Commit 0094c582 authored by Duncan Coutts's avatar Duncan Coutts
Browse files

Generalise the constraint set ADT in a couple ways

We now track target packages and only require constraints on those
targets to be satisfiable. This allows us to overconstrain packages
that we do not care about, which is useful for excluding broken
packages.
We also now have a more general way of specifying constraints.
Previously constraints were specified as the conjunction of a version
range predicate and an optional installed constraint. This form made
it impossible to express constraints such as "exclude this source
package". Constraints for a package name are now specified simply by
a function predicate on the package version and installed/source state.
parent 91ec765e
......@@ -32,7 +32,7 @@ import qualified Distribution.Client.PackageIndex as PackageIndex
import Distribution.Client.PackageIndex (PackageIndex)
import Distribution.Package
( PackageName(..), PackageId, Package(..), packageVersion, packageName
, Dependency(Dependency), thisPackageVersion, notThisPackageVersion
, Dependency(Dependency), thisPackageVersion
, simplifyDependency, PackageFixedDeps(depends) )
import Distribution.PackageDescription
( PackageDescription(buildDepends) )
......@@ -566,51 +566,57 @@ improvePlan installed constraints0 selected0 =
addPackageSelectConstraint :: PackageId -> Constraints
-> Satisfiable Constraints
[PackageId] ExclusionReason
addPackageSelectConstraint pkgid constraints =
Constraints.constrain dep reason constraints
addPackageSelectConstraint pkgid =
Constraints.constrain pkgname constraint reason
where
dep = TaggedDependency NoInstalledConstraint (thisPackageVersion pkgid)
reason = SelectedOther pkgid
pkgname = packageName pkgid
constraint ver _ = ver == packageVersion pkgid
reason = SelectedOther pkgid
addPackageExcludeConstraint :: PackageId -> Constraints
-> Satisfiable Constraints
[PackageId] ExclusionReason
addPackageExcludeConstraint pkgid constraints =
Constraints.constrain dep reason constraints
addPackageExcludeConstraint pkgid =
Constraints.constrain pkgname constraint reason
where
dep = TaggedDependency NoInstalledConstraint
(notThisPackageVersion pkgid)
pkgname = packageName pkgid
constraint ver installed
| ver == packageVersion pkgid = installed
| otherwise = True
reason = ExcludedByConfigureFail
addPackageDependencyConstraint :: PackageId -> TaggedDependency -> Constraints
-> Satisfiable Constraints
[PackageId] ExclusionReason
addPackageDependencyConstraint pkgid dep constraints =
Constraints.constrain dep reason constraints
addPackageDependencyConstraint pkgid dep =
Constraints.constrain pkgname constraint reason
where
constraint ver installed = ver `withinRange` verrange
&& case installedConstraint of
InstalledConstraint -> installed
NoInstalledConstraint -> True
reason = ExcludedByPackageDependency pkgid dep
TaggedDependency installedConstraint (Dependency pkgname verrange) = dep
addTopLevelVersionConstraint :: PackageName -> VersionRange
-> Constraints
-> Satisfiable Constraints
[PackageId] ExclusionReason
addTopLevelVersionConstraint pkg ver constraints =
Constraints.constrain taggedDep reason constraints
addTopLevelVersionConstraint pkgname verrange =
Constraints.constrain pkgname constraint reason
where
dep = Dependency pkg ver
taggedDep = TaggedDependency NoInstalledConstraint dep
reason = ExcludedByTopLevelDependency dep
constraint ver _installed = ver `withinRange` verrange
reason = ExcludedByTopLevelDependency (Dependency pkgname verrange)
addTopLevelInstalledConstraint :: PackageName
-> Constraints
-> Satisfiable Constraints
[PackageId] ExclusionReason
addTopLevelInstalledConstraint pkg constraints =
Constraints.constrain taggedDep reason constraints
addTopLevelInstalledConstraint pkgname =
Constraints.constrain pkgname constraint reason
where
dep = Dependency pkg anyVersion
taggedDep = TaggedDependency InstalledConstraint dep
reason = ExcludedByTopLevelDependency dep
constraint _ver installed = installed
reason = ExcludedByTopLevelDependency (Dependency pkgname anyVersion)
-- ------------------------------------------------------------
-- * Reasons for constraints
......
......@@ -31,10 +31,11 @@ type SelectablePackage
type SelectedPackage
= InstalledOrSource InstalledPackageEx SemiConfiguredPackage
data InstalledOrSource installed available
data InstalledOrSource installed source
= InstalledOnly installed
| SourceOnly available
| InstalledAndSource installed available
| SourceOnly source
| InstalledAndSource installed source
deriving Eq
type TopologicalSortNumber = Int
......
......@@ -27,6 +27,8 @@ module Distribution.Client.PackageIndex (
-- * Queries
-- ** Precise lookups
elemByPackageId,
elemByPackageName,
lookupPackageName,
lookupPackageId,
lookupDependency,
......@@ -61,7 +63,7 @@ import qualified Data.Array as Array
import Data.Array ((!))
import Data.List (groupBy, sortBy, nub, isInfixOf)
import Data.Monoid (Monoid(..))
import Data.Maybe (isNothing, fromMaybe)
import Data.Maybe (isJust, isNothing, fromMaybe)
import Distribution.Package
( PackageName(..), PackageIdentifier(..)
......@@ -236,6 +238,13 @@ allPackagesByName (PackageIndex m) = Map.elems m
-- * Lookups
--
elemByPackageId :: Package pkg => PackageIndex pkg -> PackageIdentifier -> Bool
elemByPackageId index = isJust . lookupPackageId index
elemByPackageName :: Package pkg => PackageIndex pkg -> PackageName -> Bool
elemByPackageName index = not . null . lookupPackageName index
-- | Does a lookup by package id (name & version).
--
-- Since multiple package DBs mask each other case-sensitively by package name,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment