Module CPM.Resolution

This module contains the dependency resolution algorithm.

Summary of exported operations:

resolveDependenciesFromLookupSet :: Config -> Package -> LookupSet -> IO ([LogEntry],Either LogEntry ResolutionResult)   
Resolves the dependencies of a package using packages from a lookup set, inside an error logger.
resolve :: Config -> Package -> LookupSet -> ResolutionResult   
Resolves the dependencies of a package using packages from a lookup set.
resolvedPackages :: ResolutionResult -> [Package]   
Gives a list of all activated packages for a successful resolution.
resolutionSuccess :: ResolutionResult -> Bool   
Was a resolution successful?
showDependencies :: ResolutionResult -> String   
Renders a dependency tree from a successful resolution.
showConflict :: ResolutionResult -> String   
Renders a conflict resolution into a textual representation.
showResult :: ResolutionResult -> String   
Renders a resolution result into a textual representation for the user.
allTransitiveDependencies :: LookupSet -> String -> [String]   
transitiveDependencies :: LookupSet -> Package -> [String]   
isCompatibleToCompiler :: Config -> Package -> Bool   
isDisjunctionCompatible :: (Int,Int,Int,Maybe String) -> [[VersionConstraint]] -> Bool   

Exported datatypes:


ResolutionResult

Result of a resolution run. In case of success, it contains the original package as well as a list of resolved packages. If the resolution failed, it contains the conflict tree.

Constructors:


Exported operations:

resolveDependenciesFromLookupSet :: Config -> Package -> LookupSet -> IO ([LogEntry],Either LogEntry ResolutionResult)   

Resolves the dependencies of a package using packages from a lookup set, inside an error logger.

resolve :: Config -> Package -> LookupSet -> ResolutionResult   

Resolves the dependencies of a package using packages from a lookup set. The base package of the current compiler is removed from the result set.

resolvedPackages :: ResolutionResult -> [Package]   

Gives a list of all activated packages for a successful resolution.

resolutionSuccess :: ResolutionResult -> Bool   

Was a resolution successful?

Further infos:
  • solution complete, i.e., able to compute all solutions

showDependencies :: ResolutionResult -> String   

Renders a dependency tree from a successful resolution.

showConflict :: ResolutionResult -> String   

Renders a conflict resolution into a textual representation.

showResult :: ResolutionResult -> String   

Renders a resolution result into a textual representation for the user. In case of success, the dependency tree is shown. In case of failure, information on the cause of the conflict is shown.

allTransitiveDependencies :: LookupSet -> String -> [String]   

transitiveDependencies :: LookupSet -> Package -> [String]   

Properties:

transitiveDependencies db pkg -=- ["B","C"] where pkg = cPackage "A" (0,0,1,Nothing) [cDep "B" ">= 1.0.0",cDep "C" "= 1.2.0"] b = cPackage "B" (1,0,9,Nothing) [] c = cPackage "C" (1,2,0,Nothing) [] db = cDB [b,c] (test_transitiveDependencies_simpleCase)
transitiveDependencies db pkg -=- ["B","C"] where pkg = cPackage "A" (0,0,1,Nothing) [cDep "B" ">= 1.0.0",cDep "C" "= 1.2.0"] b = cPackage "B" (1,0,0,Nothing) [cDep "C" "= 1.2.0"] c = cPackage "C" (1,2,0,Nothing) [cDep "B" ">= 1.0.0"] db = cDB [b,c] (test_transitiveDependencies_loop)
transitiveDependencies db pkg -=- ["B","D","C"] where pkg = cPackage "A" (0,0,1,Nothing) [cDep "B" ">= 1.0.0"] b100 = cPackage "B" (1,0,0,Nothing) [cDep "C" "= 1.0.0"] b110 = cPackage "B" (1,1,0,Nothing) [cDep "D" "= 1.0.0"] c = cPackage "C" (1,0,0,Nothing) [] d = cPackage "D" (1,0,0,Nothing) [] db = cDB [b100,b110,c,d] (test_transitiveDependencies_multipleVersions)

isCompatibleToCompiler :: Config -> Package -> Bool   

isDisjunctionCompatible :: (Int,Int,Int,Maybe String) -> [[VersionConstraint]] -> Bool   

Properties:

isDisjunctionCompatible ver dis -=- True where dis = cDisj "= 1.0.0" ver = (1,0,0,Nothing) (test_onlyConjunctionCompatible)
isDisjunctionCompatible ver dis -=- True where dis = cDisj ">= 1.0.0 || = 1.2.0" ver = (1,2,0,Nothing) (test_allConjunctionsCompatible)
isDisjunctionCompatible ver dis -=- True where ver = (1,0,0,Nothing) dis = cDisj "> 2.0.0 || = 1.0.0" (test_oneConjunctionCompatible)
isDisjunctionCompatible ver dis -=- True where ver = (1,0,0,Nothing) dis = cDisj ">= 1.0.0, < 2.0.0" (test_conjunctionWithMultipleParts)
isDisjunctionCompatible ver dis -=- False where ver = (1,0,0,Nothing) dis = cDisj "> 1.0.0" (test_reportsSimpleFailure)
isDisjunctionCompatible ver dis -=- False where ver = (1,0,0,Nothing) dis = cDisj "< 1.0.0 || > 1.0.0" (test_reportsAllConjunctionsAsFailure)
isDisjunctionCompatible ver dis -=- False where ver = (1,0,0,Nothing) dis = cDisj "< 1.0.0, > 0.5.0" (test_reportsRelevantPartOfConjunction)
isDisjunctionCompatible ver dis -=- True where ver = (0,5,9,Nothing) dis = cDisj "~> 0.5.0" (test_semverCompatible)
isDisjunctionCompatible ver dis -=- False where ver = (0,7,1,Nothing) dis = cDisj "~> 0.6.0" (test_semverIncompatible)
isDisjunctionCompatible ver dis -=- False where ver = (0,7,0,Nothing) dis = cDisj "~> 0.7.2" (test_semverMinimum)
maybeResolvedPackages (resolve defaultConfig pkg db) -=- Just [json100,pkg] where pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "=1.0.0"] json100 = cPackage "json" (1,0,0,Nothing) [] json101 = cPackage "json" (1,0,1,Nothing) [] db = cDB [json100,json101] (test_resolvesSimpleDependency)
showResult result -=- "There seems to be no version of package json that can satisfy the constraint json = 1.0.0" where result = resolve defaultConfig pkg db pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "= 1.0.0"] db = cDB [pkg] (test_reportsUnknownPackage)
showResult result -=- "There seems to be no version of package json that can satisfy the constraint json = 1.2.0" where result = resolve defaultConfig pkg db pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "=1.2.0"] json = cPackage "json" (1,0,0,Nothing) [] db = cDB [json] (test_reportsMissingPackageVersion)
showResult result -=- expectedMessage where result = resolve defaultConfig pkg db pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "= 1.0.0",cDep "b" ">= 0.0.1"] b = cPackage "b" (0,0,2,Nothing) [cDep "json" "~> 1.0.4"] json100 = cPackage "json" (1,0,0,Nothing) [] json105 = cPackage "json" (1,0,5,Nothing) [] db = cDB [pkg,b,json100,json105] expectedMessage = "There was a conflict for package json\n" ++ ("sample\n" ++ (" |- json (json = 1.0.0)\n" ++ ("sample\n" ++ (" |- b (b >= 0.0.1)\n" ++ " |- json (json ~1.0.4)")))) (test_reportsSecondaryConflict)
showResult result -=- expectedMessage where result = resolve defaultConfig pkg db pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "= 1.0.0",cDep "b" ">= 0.0.5"] b001 = cPackage "b" (0,0,1,Nothing) [] b002 = cPackage "b" (0,0,2,Nothing) [] b003 = cPackage "b" (0,0,3,Nothing) [] b006 = cPackage "b" (0,0,6,Nothing) [cDep "json" "~> 1.0.4"] json100 = cPackage "json" (1,0,0,Nothing) [] json105 = cPackage "json" (1,0,5,Nothing) [] db = cDB [pkg,b001,b002,b003,b006,json100,json105] expectedMessage = "There was a conflict for package json\n" ++ ("sample\n" ++ (" |- json (json = 1.0.0)\n" ++ ("sample\n" ++ (" |- b (b >= 0.0.5)\n" ++ " |- json (json ~1.0.4)")))) (test_reportsSecondaryConflictInsteadOfPrimary)
showResult result -=- expectedMessage where result = resolve defaultConfig pkg db pkg = cPackage "sample" (0,0,1,Nothing) [cDep "a" "= 0.0.1",cDep "b" "> 0.0.1"] a001 = cPackage "a" (0,0,1,Nothing) [cDep "b" "= 0.0.1"] b001 = cPackage "b" (0,0,1,Nothing) [] b002 = cPackage "b" (0,0,2,Nothing) [] db = cDB [pkg,a001,b001,b002] expectedMessage = "There was a conflict for package b\n" ++ ("sample\n" ++ (" |- a (a = 0.0.1)\n" ++ (" |- b (b = 0.0.1)\n" ++ ("sample\n" ++ " |- b (b > 0.0.1)")))) (test_detectsSecondaryOnFirstActivation)
maybeResolvedPackages (resolve defaultConfig pkg db) -=- Just [json150,pkg] where pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "> 1.0.0, < 2.0.0 || >= 4.0.0"] json150 = cPackage "json" (1,5,0,Nothing) [] json320 = cPackage "json" (3,2,0,Nothing) [] db = cDB [json150,json320] (test_makesDecisionBetweenAlternatives)
maybeResolvedPackages (resolve defaultConfig pkg db) -=- Just [json420,pkg] where pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "> 1.0.0, < 2.0.0 || >= 4.0.0"] json150 = cPackage "json" (1,5,0,Nothing) [] json420 = cPackage "json" (4,2,0,Nothing) [] db = cDB [json150,json420] (test_alwaysChoosesNewestAlternative)
maybeResolvedPackages (resolve defaultConfig pkg db) -=- Just [b109,pkg] where pkg = cPackage "A" (0,0,1,Nothing) [cDep "B" ">= 1.0.0"] b109 = cPackage "B" (1,0,9,Nothing) [] b110b1 = cPackage "B" (1,1,0,Just "b1") [] db = cDB [b109,b110b1] (test_doesNotChoosePrereleaseByDefault)
maybeResolvedPackages (resolve defaultConfig pkg db) -=- Just [b110b1,c,pkg] where pkg = cPackage "A" (0,0,1,Nothing) [cDep "C" "= 1.2.0"] b109 = cPackage "B" (1,0,9,Nothing) [] b110b1 = cPackage "B" (1,1,0,Just "b1") [] c = cPackage "C" (1,2,0,Nothing) [cDep "B" ">= 1.1.0-b1"] db = cDB [b109,b110b1,c] (test_upgradesPackageToPrereleaseWhenNeccesary)
maybeResolvedPackages (resolve defaultConfig pkg db) -=- Just [b101,pkg] where pkg = cPackage "A" (0,0,1,Nothing) [cDep "B" ">= 1.0.0"] b101 = cPackage "B" (1,0,1,Nothing) [] b105 = cPackage "B" (1,0,5,Nothing) [] db = addPackage (addPackage emptySet b101 FromLocalCache) b105 FromRepository (test_prefersLocalPackageCacheEvenIfOlder)
showResult result -=- "The package json-1.0.0, dependency constraint json = 1.0.0, is not compatible to the current compiler. It was activated because:\nPackage dependencies:\nsample\n |- json (json = 1.0.0)" where result = resolve defaultConfig pkg db pkg = cPackage "sample" (0,0,1,Nothing) [cDep "json" "= 1.0.0"] json = cPackageCC "json" (1,0,0,Nothing) [cCC "nocompiler" "= 1.0.0"] db = cDB [json] (test_reportsCompilerIncompatibility)