"""
Check summary of changes shown to the user when modifying dependencies
"""

import os
import re

from drivers.alr import alr_with, run_alr
from drivers.asserts import assert_match

# Initialize a workspace for the test
run_alr('init', '--bin', 'xxx')
os.chdir('xxx')

###############################################################################
# Add a regular solvable dependency
p = run_alr('with', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   + libhello ^2.0.0 (add)

Changes to dependency solution:

   + libhello 2.0.0 (new)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Check adding a missing crate (with forcing)
p = run_alr('with', 'unobtanium', quiet=False, force=True)
assert_match(".*" +
             re.escape("""\
Requested changes:

   + unobtanium * (add)

Changes to dependency solution:

   New solution is incomplete.
   Missing:
   +!       unobtanium * (new,missing:unknown)\
""") + ".*",
             p.out, flags=re.S)

# Remove the missing crate for following tests
run_alr("with", "--del", "unobtanium")

# Check adding without forcing for simpler error message
p = run_alr('with', 'unobtanium', force=False, complain_on_error=False)
assert_match(".*Cannot add crate 'unobtanium' not found in index",
             p.out)

###############################################################################
# Check adding a missing crate manually, then running `alr with` without args
alr_with("unobtanium", update=False, manual=True)
p = run_alr('with', quiet=False)
assert_match(".*" +
             re.escape("""\
Dependencies automatically updated as follows:

   New solution is incomplete.
   Missing:
   +!       unobtanium * (new,missing:unknown)\
""") + ".*",
             p.out, flags=re.S)

# Remove the missing crate for following tests
run_alr("with", "--del", "unobtanium")

###############################################################################
# Check adding a pinned dir (the dir must exist)
os.mkdir("local_crate")
p = run_alr('with', 'local_crate', '--use=local_crate', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   + local_crate * (add)

Changes to dependency solution:

   +. local_crate unknown (new,path=local_crate)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Pinning a crate to a version
p = run_alr('pin', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Changes to dependency solution:

   . libhello 2.0.0 (pin=2.0.0)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Unpinning
p = run_alr('pin', '--unpin', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Changes to dependency solution:

   o libhello 2.0.0 (unpinned)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Pinning a crate to a non-existent version
p = run_alr('pin', 'libhello=2.999.0', quiet=False)
assert_match(".*" +
             re.escape("""\
Changes to dependency solution:

   New solution is incomplete.
   Missing:
   .!       libhello (=2.999.0) & (^2.0.0) (pin=2.999.0,missing:unavailable)\
""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Removal
p = run_alr('with', '--del', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   - libhello ^2.0.0 (remove)

Changes to dependency solution:

   - libhello 2.0.0 (removed)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Indirect dependency
p = run_alr('with', 'hello', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   + hello ^1.0.1 (add)

Changes to dependency solution:

   + hello    1.0.1 (new)""") + "\s*\n\s*" +
             re.escape("+ libhello 1.1.0 (new,indirect)") + ".*",
             p.out, flags=re.S)

###############################################################################
# Going from indirect to direct. Since the dependency is already in the
# solution, there is no version change (=).
p = run_alr('with', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   + libhello ^1.1.0 (add)

Changes to dependency solution:

   = libhello 1.1.0 (direct)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Going from direct to indirect. Likewise, removing the dependency leaves it in
# the solution because is still needed indirectly via 'hello'
p = run_alr('with', '--del', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   - libhello ^1.1.0 (remove)

Changes to dependency solution:

   = libhello 1.1.0 (indirect)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Display of downgrades. Forcing libhello=1, it results in a downgrade.
p = run_alr('with', 'libhello=1', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   + libhello =1 (add)

Changes to dependency solution:

   v libhello 1.0.0 (direct,downgraded from 1.1.0)""") + ".*",
             p.out, flags=re.S)

###############################################################################
# Display of upgrades. By removing libhello=1, it can be upgraded.
p = run_alr('with', '--del', 'libhello', quiet=False)
assert_match(".*" +
             re.escape("""Requested changes:

   - libhello =1 (remove)

Changes to dependency solution:

   ^ libhello 1.1.0 (indirect,upgraded from 1.0.0)""") + ".*",
             p.out, flags=re.S)


print('SUCCESS')
