Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
-----------------------------------------------------------------------------
-- |
-- Module : Hackage.DependencySet
-- Copyright : (c) Duncan Coutts 2008
-- License : BSD-like
--
-- Maintainer : duncan@haskell.org
-- Stability : provisional
-- Portability : portable
--
-- A set of satisfiable dependencies (package version constraints).
--
-----------------------------------------------------------------------------
module Hackage.DependencySet (
DependencySet,
empty,
insert,
Satisfiable(..),
) where
import Distribution.Package
import Distribution.Version
import Distribution.Simple.PackageIndex (PackageIndex)
import qualified Distribution.Simple.PackageIndex as PackageIndex
import Data.Map (Map)
import qualified Data.Map as Map
import Control.Exception (assert)
-- | A set of constraints on package versions. For each package name we record
-- what other packages depends on it and what constraints they impose on the
-- version of the package.
--
data Package pkg => DependencySet pkg =
DependencySet
(PackageIndex pkg)
(Map String [(PackageIdentifier, VersionRange)])
invariant :: Package pkg => DependencySet pkg -> Bool
invariant (DependencySet pkgs constraints) =
all satisfiable
[ Dependency pkgname (foldr1 IntersectVersionRanges (map snd constraints'))
| (pkgname, constraints') <- Map.toList constraints ]
where
satisfiable = not . null . PackageIndex.lookupDependency pkgs
-- | We construct a 'DependencySet' with an initial 'PackageIndex'
-- of all the packages available. This will enable us to determine when adding
-- constraints wether the new constraint is satisfiable or not.
--
empty :: Package pkg
=> PackageIndex pkg
-> DependencySet pkg
empty pkgs = DependencySet pkgs Map.empty
data Satisfiable a
= Satisfiable a
| Unsatisfiable
| ConflictsWith [(PackageIdentifier, VersionRange)]
insert :: Package pkg
=> Dependency -- ^ The subject of the dependency
-> PackageIdentifier -- ^ The package imposing the dependency.
-- We record this merely so we can report better errors.
-> DependencySet pkg
-> Satisfiable (DependencySet pkg)
insert dep@(Dependency pkgid constraint) pkgid'
depset@(DependencySet pkgs constraints) =
assert (invariant depset) $
case PackageIndex.lookupDependency pkgs dep of
[] -> Unsatisfiable
pkgs' -> case Map.lookup pkgid constraints of
Just existingConstraints
-- We have some existing constraints on the version of pkg. We check
-- if our new constraint conflicts with any of the existing ones:
| constraint `confilctsWith` foldr1 IntersectVersionRanges
(map snd existingConstraints)
-- Since we know none of the existing constraints conflicted with each
-- other then we know our new constraint must conflict with one or more
-- of the existing ones:
-> assert (not (null conflicts)) $
ConflictsWith conflicts
where conflicts = filter (confilctsWith constraint . snd)
existingConstraints
_ -> assert (invariant depset') $
Satisfiable depset'
where depset' = DependencySet pkgs constraints'
constraints' = Map.insertWith (++)
pkgid [(pkgid', constraint)] constraints
where
confilctsWith vr1 vr2 =
not . any (`withinRange` IntersectVersionRanges vr1 vr2)
. map (pkgVersion . packageId) $ pkgs'