module Distribution.Simple.PackageIndex (
PackageIndex,
fromList,
merge,
insert,
deleteInstalledPackageId,
deleteSourcePackageId,
deletePackageName,
lookupInstalledPackageId,
lookupSourcePackageId,
lookupPackageName,
lookupDependency,
searchByName,
SearchResult(..),
searchByNameSubstring,
allPackages,
allPackagesByName,
brokenPackages,
dependencyClosure,
reverseDependencyClosure,
topologicalOrder,
reverseTopologicalOrder,
dependencyInconsistencies,
dependencyCycles,
dependencyGraph,
moduleNameIndex,
) where
import Prelude hiding (lookup)
import Control.Exception (assert)
import qualified Data.Map as Map
import Data.Map (Map)
import qualified Data.Tree as Tree
import qualified Data.Graph as Graph
import qualified Data.Array as Array
import Data.Array ((!))
import Data.List as List
( null, foldl', sort
, groupBy, sortBy, find, isInfixOf, nubBy, deleteBy, deleteFirstsBy )
import Data.Monoid (Monoid(..))
import Data.Maybe (isNothing, fromMaybe)
import Distribution.Package
( PackageName(..), PackageId
, Package(..), packageName, packageVersion
, Dependency(Dependency)
, InstalledPackageId(..) )
import Distribution.ModuleName
( ModuleName )
import Distribution.InstalledPackageInfo
( InstalledPackageInfo, installedPackageId )
import qualified Distribution.InstalledPackageInfo as IPI
import Distribution.Version
( Version, withinRange )
import Distribution.Simple.Utils (lowercase, comparing, equating)
data PackageIndex = PackageIndex
!(Map InstalledPackageId InstalledPackageInfo)
!(Map PackageName (Map Version [InstalledPackageInfo]))
deriving (D:Show ::
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> T:Show aShow, D:Read ::
(Int -> ReadS a)
-> ReadS [a]
-> ReadPrec a
-> ReadPrec [a]
-> T:Read aRead)
instance ($cmappend) :: PackageIndex -> PackageIndex -> PackageIndexMonoid PackageIndex where
mempty = ($WPackageIndex) ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexPackageIndex empty :: Map k aMap.empty empty :: Map k aMap.empty
mappend = merge :: PackageIndex -> PackageIndex -> PackageIndexmerge
mconcat [] = mempty :: Monoid a => amempty
mconcat xs = foldr1 :: (a -> a -> a) -> [a] -> afoldr1 mappend :: Monoid a => a -> a -> amappend xs :: [PackageIndex]xs
invariant :: PackageIndex -> Bool
invariant (PackageIndex pids pnames) =
map :: (a -> b) -> [a] -> [b]map installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId (elems :: Map k a -> [a]Map.elems pids :: Map InstalledPackageId InstalledPackageInfopids)
(==) :: Eq a => a -> a -> Bool== sort :: Ord a => [a] -> [a]sort
[ assertError :: Addr# -> Bool -> a -> aassert pinstOk :: BoolpinstOk (installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pinst :: InstalledPackageInfo_ ModuleNamepinst)
| (pname, pvers) <- toList :: Map k a -> [(k, a)]Map.toList pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames
, let pversOk = not :: Bool -> Boolnot (null :: Map k a -> BoolMap.null pvers :: Map Version [InstalledPackageInfo]pvers)
, (pver, pinsts) <- assertError :: Addr# -> Bool -> a -> aassert pversOk :: BoolpversOk ($) :: (a -> b) -> a -> b$ toList :: Map k a -> [(k, a)]Map.toList pvers :: Map Version [InstalledPackageInfo]pvers
, let pinsts' = sortBy :: (a -> a -> Ordering) -> [a] -> [a]sortBy (comparing :: Ord a => (b -> a) -> b -> b -> Orderingcomparing installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId) pinsts :: [InstalledPackageInfo]pinsts
pinstsOk = all :: (a -> Bool) -> [a] -> Boolall (\g -> length :: [a] -> Intlength g :: [InstalledPackageInfo_ ModuleName]g (==) :: Eq a => a -> a -> Bool== 1)
(groupBy :: (a -> a -> Bool) -> [a] -> [[a]]groupBy (equating :: Eq a => (b -> a) -> b -> b -> Boolequating installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId) pinsts' :: [InstalledPackageInfo_ ModuleName]pinsts')
, pinst <- assertError :: Addr# -> Bool -> a -> aassert pinstsOk :: BoolpinstsOk ($) :: (a -> b) -> a -> b$ pinsts' :: [InstalledPackageInfo_ ModuleName]pinsts'
, let pinstOk = packageName :: Package pkg => pkg -> PackageNamepackageName pinst :: InstalledPackageInfo_ ModuleNamepinst (==) :: Eq a => a -> a -> Bool== pname :: PackageNamepname
(&&) :: Bool -> Bool -> Bool&& packageVersion :: Package pkg => pkg -> VersionpackageVersion pinst :: InstalledPackageInfo_ ModuleNamepinst (==) :: Eq a => a -> a -> Bool== pver :: Versionpver
]
mkPackageIndex :: Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndex
mkPackageIndex pids pnames = assertError :: Addr# -> Bool -> a -> aassert (invariant :: PackageIndex -> Boolinvariant index :: PackageIndexindex) index :: PackageIndexindex
where index = ($WPackageIndex) ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexPackageIndex pids :: Map InstalledPackageId InstalledPackageInfopids pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames
fromList :: [InstalledPackageInfo] -> PackageIndex
fromList pkgs = mkPackageIndex ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexmkPackageIndex pids :: Map InstalledPackageId InstalledPackageInfopids pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames
where
pids = fromList :: Ord k => [(k, a)] -> Map k aMap.fromList [ (installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pkg :: InstalledPackageInfo_ mpkg, pkg :: InstalledPackageInfo_ mpkg) | pkg <- pkgs :: [InstalledPackageInfo]pkgs ]
pnames =
fromList :: Ord k => [(k, a)] -> Map k aMap.fromList
[ (packageName :: Package pkg => pkg -> PackageNamepackageName (head :: [a] -> ahead pkgsN :: [InstalledPackageInfo]pkgsN), pvers :: Map Version [InstalledPackageInfo]pvers)
| pkgsN <- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]groupBy (equating :: Eq a => (b -> a) -> b -> b -> Boolequating packageName :: Package pkg => pkg -> PackageNamepackageName)
(.) :: (b -> c) -> (a -> b) -> a -> c. sortBy :: (a -> a -> Ordering) -> [a] -> [a]sortBy (comparing :: Ord a => (b -> a) -> b -> b -> Orderingcomparing packageId :: Package pkg => pkg -> PackageIdentifierpackageId)
($) :: (a -> b) -> a -> b$ pkgs :: [InstalledPackageInfo]pkgs
, let pvers =
fromList :: Ord k => [(k, a)] -> Map k aMap.fromList
[ (packageVersion :: Package pkg => pkg -> VersionpackageVersion (head :: [a] -> ahead pkgsNV :: [InstalledPackageInfo]pkgsNV),
nubBy :: (a -> a -> Bool) -> [a] -> [a]nubBy (equating :: Eq a => (b -> a) -> b -> b -> Boolequating installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId) (reverse :: [a] -> [a]reverse pkgsNV :: [InstalledPackageInfo]pkgsNV))
| pkgsNV <- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]groupBy (equating :: Eq a => (b -> a) -> b -> b -> Boolequating packageVersion :: Package pkg => pkg -> VersionpackageVersion) pkgsN :: [InstalledPackageInfo]pkgsN
]
]
merge :: PackageIndex -> PackageIndex -> PackageIndex
merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) =
mkPackageIndex ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexmkPackageIndex (union :: Ord k => Map k a -> Map k a -> Map k aMap.union pids1 :: Map InstalledPackageId InstalledPackageInfopids1 pids2 :: Map InstalledPackageId InstalledPackageInfopids2)
(unionWith ::
Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k aMap.unionWith (unionWith ::
Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k aMap.unionWith mergeBuckets ::
[InstalledPackageInfo_ m]
-> [InstalledPackageInfo_ m]
-> [InstalledPackageInfo_ m]mergeBuckets) pnames1 :: Map PackageName (Map Version [InstalledPackageInfo])pnames1 pnames2 :: Map PackageName (Map Version [InstalledPackageInfo])pnames2)
where
mergeBuckets xs ys = ys :: [InstalledPackageInfo_ m]ys (++) :: [a] -> [a] -> [a]++ (xs :: [PackageIndex]xs (\\) ::
[InstalledPackageInfo_ m]
-> [InstalledPackageInfo_ m]
-> [InstalledPackageInfo_ m]\\ ys :: [InstalledPackageInfo_ m]ys)
(\\) = deleteFirstsBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]deleteFirstsBy (equating :: Eq a => (b -> a) -> b -> b -> Boolequating installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId)
insert :: InstalledPackageInfo -> PackageIndex -> PackageIndex
insert pkg (PackageIndex pids pnames) =
mkPackageIndex ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexmkPackageIndex pids' :: Map InstalledPackageId InstalledPackageInfopids' pnames' :: Map PackageName (Map Version [InstalledPackageInfo])pnames'
where
pids' = insert :: Ord k => k -> a -> Map k a -> Map k aMap.insert (installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pkg :: InstalledPackageInfo_ mpkg) pkg :: InstalledPackageInfo_ mpkg pids :: Map InstalledPackageId InstalledPackageInfopids
pnames' = insertPackageName ::
Map PackageName (Map Version [InstalledPackageInfo])
-> Map PackageName (Map Version [InstalledPackageInfo])insertPackageName pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames
insertPackageName =
insertWith' ::
Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k aMap.insertWith' (\_ -> insertPackageVersion ::
Map Version [InstalledPackageInfo]
-> Map Version [InstalledPackageInfo]insertPackageVersion)
(packageName :: Package pkg => pkg -> PackageNamepackageName pkg :: InstalledPackageInfo_ mpkg)
(singleton :: k -> a -> Map k aMap.singleton (packageVersion :: Package pkg => pkg -> VersionpackageVersion pkg :: InstalledPackageInfo_ mpkg) [pkg :: InstalledPackageInfo_ mpkg])
insertPackageVersion =
insertWith' ::
Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k aMap.insertWith' (\_ -> insertPackageInstance ::
[InstalledPackageInfo] -> [InstalledPackageInfo]insertPackageInstance)
(packageVersion :: Package pkg => pkg -> VersionpackageVersion pkg :: InstalledPackageInfo_ mpkg) [pkg :: InstalledPackageInfo_ mpkg]
insertPackageInstance pkgs =
pkg :: InstalledPackageInfo_ mpkg (:) :: a -> [a] -> [a]: deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]deleteBy (equating :: Eq a => (b -> a) -> b -> b -> Boolequating installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId) pkg :: InstalledPackageInfo_ mpkg pkgs :: [InstalledPackageInfo]pkgs
deleteInstalledPackageId :: InstalledPackageId -> PackageIndex -> PackageIndex
deleteInstalledPackageId ipkgid original@(PackageIndex pids pnames) =
case updateLookupWithKey ::
Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a, Map k a)Map.updateLookupWithKey (\_ _ -> Nothing :: Maybe aNothing) ipkgid :: InstalledPackageIdipkgid pids :: Map InstalledPackageId InstalledPackageInfopids of
(Nothing, _) -> original :: PackageIndexoriginal
(Just spkgid, pids') -> mkPackageIndex ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexmkPackageIndex pids' :: Map InstalledPackageId InstalledPackageInfopids'
(deletePkgName ::
Map PackageName (Map Version a) -> Map PackageName (Map Version a)deletePkgName spkgid :: pkgspkgid pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames)
where
deletePkgName spkgid =
update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k aMap.update (deletePkgVersion :: Map Version a -> Maybe (Map Version a)deletePkgVersion spkgid :: pkgspkgid) (packageName :: Package pkg => pkg -> PackageNamepackageName spkgid :: pkgspkgid)
deletePkgVersion spkgid =
(\m -> if null :: Map k a -> BoolMap.null m :: Map Version am then Nothing :: Maybe aNothing else Just :: a -> Maybe aJust m :: Map Version am)
(.) :: (b -> c) -> (a -> b) -> a -> c. update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k aMap.update deletePkgInstance ::
[InstalledPackageInfo_ m] -> Maybe [InstalledPackageInfo_ m]deletePkgInstance (packageVersion :: Package pkg => pkg -> VersionpackageVersion spkgid :: pkgspkgid)
deletePkgInstance =
(\xs -> if null :: [a] -> BoolList.null xs :: [PackageIndex]xs then Nothing :: Maybe aNothing else Just :: a -> Maybe aJust xs :: [PackageIndex]xs)
(.) :: (b -> c) -> (a -> b) -> a -> c. deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]List.deleteBy (\_ pkg -> installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pkg :: InstalledPackageInfo_ mpkg (==) :: Eq a => a -> a -> Bool== ipkgid :: InstalledPackageIdipkgid) undefined :: aundefined
deleteSourcePackageId :: PackageId -> PackageIndex -> PackageIndex
deleteSourcePackageId pkgid original@(PackageIndex pids pnames) =
case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup (packageName :: Package pkg => pkg -> PackageNamepackageName pkgid :: PackageIdpkgid) pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames of
Nothing -> original :: PackageIndexoriginal
Just pvers -> case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup (packageVersion :: Package pkg => pkg -> VersionpackageVersion pkgid :: PackageIdpkgid) pvers :: Map Version [InstalledPackageInfo]pvers of
Nothing -> original :: PackageIndexoriginal
Just pkgs -> mkPackageIndex ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexmkPackageIndex
(foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' (flip :: (a -> b -> c) -> b -> a -> cflip (delete :: Ord k => k -> Map k a -> Map k aMap.delete (.) :: (b -> c) -> (a -> b) -> a -> c. installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId)) pids :: Map InstalledPackageId InstalledPackageInfopids pkgs :: [InstalledPackageInfo]pkgs)
(deletePkgName ::
Map PackageName (Map Version a) -> Map PackageName (Map Version a)deletePkgName pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames)
where
deletePkgName =
update :: Ord k => (a -> Maybe a) -> k -> Map k a -> Map k aMap.update deletePkgVersion :: Map Version a -> Maybe (Map Version a)deletePkgVersion (packageName :: Package pkg => pkg -> PackageNamepackageName pkgid :: PackageIdpkgid)
deletePkgVersion =
(\m -> if null :: Map k a -> BoolMap.null m :: Map Version am then Nothing :: Maybe aNothing else Just :: a -> Maybe aJust m :: Map Version am)
(.) :: (b -> c) -> (a -> b) -> a -> c. delete :: Ord k => k -> Map k a -> Map k aMap.delete (packageVersion :: Package pkg => pkg -> VersionpackageVersion pkgid :: PackageIdpkgid)
deletePackageName :: PackageName -> PackageIndex -> PackageIndex
deletePackageName name original@(PackageIndex pids pnames) =
case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup name :: PackageNamename pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames of
Nothing -> original :: PackageIndexoriginal
Just pvers -> mkPackageIndex ::
Map InstalledPackageId InstalledPackageInfo
-> Map PackageName (Map Version [InstalledPackageInfo])
-> PackageIndexmkPackageIndex
(foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' (flip :: (a -> b -> c) -> b -> a -> cflip (delete :: Ord k => k -> Map k a -> Map k aMap.delete (.) :: (b -> c) -> (a -> b) -> a -> c. installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId)) pids :: Map InstalledPackageId InstalledPackageInfopids
(concat :: [[a]] -> [a]concat (elems :: Map k a -> [a]Map.elems pvers :: Map Version [InstalledPackageInfo]pvers)))
(delete :: Ord k => k -> Map k a -> Map k aMap.delete name :: PackageNamename pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames)
allPackages :: PackageIndex -> [InstalledPackageInfo]
allPackages (PackageIndex pids _) = elems :: Map k a -> [a]Map.elems pids :: Map InstalledPackageId InstalledPackageInfopids
allPackagesByName :: PackageIndex -> [[InstalledPackageInfo]]
allPackagesByName (PackageIndex _ pnames) =
concatMap :: (a -> [b]) -> [a] -> [b]concatMap elems :: Map k a -> [a]Map.elems (elems :: Map k a -> [a]Map.elems pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames)
lookupInstalledPackageId :: PackageIndex -> InstalledPackageId
-> Maybe InstalledPackageInfo
lookupInstalledPackageId (PackageIndex pids _) pid = lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup pid :: PackageIdpid pids :: Map InstalledPackageId InstalledPackageInfopids
lookupSourcePackageId :: PackageIndex -> PackageId -> [InstalledPackageInfo]
lookupSourcePackageId (PackageIndex _ pnames) pkgid =
case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup (packageName :: Package pkg => pkg -> PackageNamepackageName pkgid :: PackageIdpkgid) pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames of
Nothing -> [] :: [a][]
Just pvers -> case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup (packageVersion :: Package pkg => pkg -> VersionpackageVersion pkgid :: PackageIdpkgid) pvers :: Map Version [InstalledPackageInfo]pvers of
Nothing -> [] :: [a][]
Just pkgs -> pkgs :: [InstalledPackageInfo]pkgs
lookupPackageName :: PackageIndex -> PackageName
-> [(Version, [InstalledPackageInfo])]
lookupPackageName (PackageIndex _ pnames) name =
case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup name :: PackageNamename pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames of
Nothing -> [] :: [a][]
Just pvers -> toList :: Map k a -> [(k, a)]Map.toList pvers :: Map Version [InstalledPackageInfo]pvers
lookupDependency :: PackageIndex -> Dependency
-> [(Version, [InstalledPackageInfo])]
lookupDependency (PackageIndex _ pnames) (Dependency name versionRange) =
case lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup name :: PackageNamename pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames of
Nothing -> [] :: [a][]
Just pvers -> [ entry :: (Version, [InstalledPackageInfo])entry
| entry@(ver, _) <- toList :: Map k a -> [(k, a)]Map.toList pvers :: Map Version [InstalledPackageInfo]pvers
, ver :: Versionver withinRange :: Version -> VersionRange -> Bool`withinRange` versionRange :: VersionRangeversionRange ]
searchByName :: PackageIndex -> String -> SearchResult [InstalledPackageInfo]
searchByName (PackageIndex _ pnames) name =
case [ pkgs :: [InstalledPackageInfo]pkgs | pkgs@(PackageName name',_) <- toList :: Map k a -> [(k, a)]Map.toList pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames
, lowercase :: String -> Stringlowercase name' :: Stringname' (==) :: Eq a => a -> a -> Bool== lname :: Stringlname ] of
[] -> None :: SearchResult aNone
[(_,pvers)] -> Unambiguous :: a -> SearchResult aUnambiguous (concat :: [[a]] -> [a]concat (elems :: Map k a -> [a]Map.elems pvers :: Map Version [InstalledPackageInfo]pvers))
pkgss -> case find :: (a -> Bool) -> [a] -> Maybe afind ((PackageName :: String -> PackageNamePackageName name :: PackageNamename(==) :: Eq a => a -> a -> Bool==) (.) :: (b -> c) -> (a -> b) -> a -> c. fst :: (a, b) -> afst) pkgss :: [(PackageName, Map Version [InstalledPackageInfo])]pkgss of
Just (_,pvers) -> Unambiguous :: a -> SearchResult aUnambiguous (concat :: [[a]] -> [a]concat (elems :: Map k a -> [a]Map.elems pvers :: Map Version [InstalledPackageInfo]pvers))
Nothing -> Ambiguous :: [a] -> SearchResult aAmbiguous (map :: (a -> b) -> [a] -> [b]map (concat :: [[a]] -> [a]concat (.) :: (b -> c) -> (a -> b) -> a -> c. elems :: Map k a -> [a]Map.elems (.) :: (b -> c) -> (a -> b) -> a -> c. snd :: (a, b) -> bsnd) pkgss :: [(PackageName, Map Version [InstalledPackageInfo])]pkgss)
where lname = lowercase :: String -> Stringlowercase name :: PackageNamename
data SearchResult a = None | Unambiguous a | Ambiguous [a]
searchByNameSubstring :: PackageIndex -> String -> [InstalledPackageInfo]
searchByNameSubstring (PackageIndex _ pnames) searchterm =
[ pkg :: InstalledPackageInfo_ mpkg
| (PackageName name, pvers) <- toList :: Map k a -> [(k, a)]Map.toList pnames :: Map PackageName (Map Version [InstalledPackageInfo])pnames
, lsearchterm :: Stringlsearchterm isInfixOf :: Eq a => [a] -> [a] -> Bool`isInfixOf` lowercase :: String -> Stringlowercase name :: PackageNamename
, pkgs <- elems :: Map k a -> [a]Map.elems pvers :: Map Version [InstalledPackageInfo]pvers
, pkg <- pkgs :: [InstalledPackageInfo]pkgs ]
where lsearchterm = lowercase :: String -> Stringlowercase searchterm :: Stringsearchterm
dependencyCycles :: PackageIndex -> [[InstalledPackageInfo]]
dependencyCycles index =
[ vs :: [InstalledPackageInfo]vs | Graph.CyclicSCC vs <- stronglyConnComp :: Ord key => [(node, key, [key])] -> [SCC node]Graph.stronglyConnComp adjacencyList ::
[(InstalledPackageInfo, InstalledPackageId, [InstalledPackageId])]adjacencyList ]
where
adjacencyList = [ (pkg :: InstalledPackageInfo_ mpkg, installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pkg :: InstalledPackageInfo_ mpkg, depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends pkg :: InstalledPackageInfo_ mpkg)
| pkg <- allPackages :: PackageIndex -> [InstalledPackageInfo]allPackages index :: PackageIndexindex ]
brokenPackages :: PackageIndex -> [(InstalledPackageInfo, [InstalledPackageId])]
brokenPackages index =
[ (pkg :: InstalledPackageInfo_ mpkg, missing :: [InstalledPackageId]missing)
| pkg <- allPackages :: PackageIndex -> [InstalledPackageInfo]allPackages index :: PackageIndexindex
, let missing = [ pkg' :: InstalledPackageIdpkg' | pkg' <- depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends pkg :: InstalledPackageInfo_ mpkg
, isNothing :: Maybe a -> BoolisNothing (lookupInstalledPackageId ::
PackageIndex -> InstalledPackageId -> Maybe InstalledPackageInfolookupInstalledPackageId index :: PackageIndexindex pkg' :: InstalledPackageIdpkg') ]
, not :: Bool -> Boolnot (null :: [a] -> Boolnull missing :: [InstalledPackageId]missing) ]
dependencyClosure :: PackageIndex
-> [InstalledPackageId]
-> Either PackageIndex
[(InstalledPackageInfo, [InstalledPackageId])]
dependencyClosure index pkgids0 = case closure ::
PackageIndex
-> [InstalledPackageId]
-> [InstalledPackageId]
-> (PackageIndex, [InstalledPackageId])closure mempty :: Monoid a => amempty [] :: [a][] pkgids0 :: [InstalledPackageId]pkgids0 of
(completed, []) -> Left :: a -> Either a bLeft completed :: PackageIndexcompleted
(completed, _) -> Right :: b -> Either a bRight (brokenPackages ::
PackageIndex -> [(InstalledPackageInfo, [InstalledPackageId])]brokenPackages completed :: PackageIndexcompleted)
where
closure completed failed [] = (completed :: PackageIndexcompleted, failed :: [InstalledPackageId]failed)
closure completed failed (pkgid:pkgids) = case lookupInstalledPackageId ::
PackageIndex -> InstalledPackageId -> Maybe InstalledPackageInfolookupInstalledPackageId index :: PackageIndexindex pkgid :: PackageIdpkgid of
Nothing -> closure ::
PackageIndex
-> [InstalledPackageId]
-> [InstalledPackageId]
-> (PackageIndex, [InstalledPackageId])closure completed :: PackageIndexcompleted (pkgid :: PackageIdpkgid(:) :: a -> [a] -> [a]:failed :: [InstalledPackageId]failed) pkgids :: [InstalledPackageId]pkgids
Just pkg -> case lookupInstalledPackageId ::
PackageIndex -> InstalledPackageId -> Maybe InstalledPackageInfolookupInstalledPackageId completed :: PackageIndexcompleted (installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pkg :: InstalledPackageInfo_ mpkg) of
Just _ -> closure ::
PackageIndex
-> [InstalledPackageId]
-> [InstalledPackageId]
-> (PackageIndex, [InstalledPackageId])closure completed :: PackageIndexcompleted failed :: [InstalledPackageId]failed pkgids :: [InstalledPackageId]pkgids
Nothing -> closure ::
PackageIndex
-> [InstalledPackageId]
-> [InstalledPackageId]
-> (PackageIndex, [InstalledPackageId])closure completed' :: PackageIndexcompleted' failed :: [InstalledPackageId]failed pkgids' :: [InstalledPackageId]pkgids'
where completed' = insert :: InstalledPackageInfo -> PackageIndex -> PackageIndexinsert pkg :: InstalledPackageInfo_ mpkg completed :: PackageIndexcompleted
pkgids' = depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends pkg :: InstalledPackageInfo_ mpkg (++) :: [a] -> [a] -> [a]++ pkgids :: [InstalledPackageId]pkgids
reverseDependencyClosure :: PackageIndex
-> [InstalledPackageId]
-> [InstalledPackageInfo]
reverseDependencyClosure index =
map :: (a -> b) -> [a] -> [b]map vertexToPkg :: Vertex -> InstalledPackageInfovertexToPkg
(.) :: (b -> c) -> (a -> b) -> a -> c. concatMap :: (a -> [b]) -> [a] -> [b]concatMap flatten :: Tree a -> [a]Tree.flatten
(.) :: (b -> c) -> (a -> b) -> a -> c. dfs :: Graph -> [Vertex] -> Forest VertexGraph.dfs reverseDepGraph :: GraphreverseDepGraph
(.) :: (b -> c) -> (a -> b) -> a -> c. map :: (a -> b) -> [a] -> [b]map (fromMaybe :: a -> Maybe a -> afromMaybe noSuchPkgId :: tnoSuchPkgId (.) :: (b -> c) -> (a -> b) -> a -> c. pkgIdToVertex :: InstalledPackageId -> Maybe VertexpkgIdToVertex)
where
(depGraph, vertexToPkg, pkgIdToVertex) = dependencyGraph ::
PackageIndex
-> (Graph,
Vertex -> InstalledPackageInfo,
InstalledPackageId -> Maybe Vertex)dependencyGraph index :: PackageIndexindex
reverseDepGraph = transposeG :: Graph -> GraphGraph.transposeG depGraph :: GraphdepGraph
noSuchPkgId = error :: [Char] -> aerror "reverseDependencyClosure: package is not in the graph"
topologicalOrder :: PackageIndex -> [InstalledPackageInfo]
topologicalOrder index = map :: (a -> b) -> [a] -> [b]map toPkgId :: Vertex -> InstalledPackageInfotoPkgId
(.) :: (b -> c) -> (a -> b) -> a -> c. topSort :: Graph -> [Vertex]Graph.topSort
($) :: (a -> b) -> a -> b$ graph :: Graphgraph
where (graph, toPkgId, _) = dependencyGraph ::
PackageIndex
-> (Graph,
Vertex -> InstalledPackageInfo,
InstalledPackageId -> Maybe Vertex)dependencyGraph index :: PackageIndexindex
reverseTopologicalOrder :: PackageIndex -> [InstalledPackageInfo]
reverseTopologicalOrder index = map :: (a -> b) -> [a] -> [b]map toPkgId :: Vertex -> InstalledPackageInfotoPkgId
(.) :: (b -> c) -> (a -> b) -> a -> c. topSort :: Graph -> [Vertex]Graph.topSort
(.) :: (b -> c) -> (a -> b) -> a -> c. transposeG :: Graph -> GraphGraph.transposeG
($) :: (a -> b) -> a -> b$ graph :: Graphgraph
where (graph, toPkgId, _) = dependencyGraph ::
PackageIndex
-> (Graph,
Vertex -> InstalledPackageInfo,
InstalledPackageId -> Maybe Vertex)dependencyGraph index :: PackageIndexindex
dependencyGraph :: PackageIndex
-> (Graph.Graph,
Graph.Vertex -> InstalledPackageInfo,
InstalledPackageId -> Maybe Graph.Vertex)
dependencyGraph index = (graph :: Graphgraph, vertex_to_pkg :: Int -> InstalledPackageInfovertex_to_pkg, id_to_vertex :: InstalledPackageId -> Maybe Vertexid_to_vertex)
where
graph = listArray :: Ix i => (i, i) -> [e] -> Array i eArray.listArray bounds :: (Int, Int)bounds
[ [ v :: Vertexv | Just v <- map :: (a -> b) -> [a] -> [b]map id_to_vertex :: InstalledPackageId -> Maybe Vertexid_to_vertex (depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends pkg :: InstalledPackageInfo_ mpkg) ]
| pkg <- pkgs :: [InstalledPackageInfo]pkgs ]
pkgs = sortBy :: (a -> a -> Ordering) -> [a] -> [a]sortBy (comparing :: Ord a => (b -> a) -> b -> b -> Orderingcomparing packageId :: Package pkg => pkg -> PackageIdentifierpackageId) (allPackages :: PackageIndex -> [InstalledPackageInfo]allPackages index :: PackageIndexindex)
vertices = zip :: [a] -> [b] -> [(a, b)]zip (map :: (a -> b) -> [a] -> [b]map installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId pkgs :: [InstalledPackageInfo]pkgs) [0..]
vertex_map = fromList :: Ord k => [(k, a)] -> Map k aMap.fromList vertices :: [(InstalledPackageId, Vertex)]vertices
id_to_vertex pid = lookup :: Ord k => k -> Map k a -> Maybe aMap.lookup pid :: PackageIdpid vertex_map :: Map InstalledPackageId Vertexvertex_map
vertex_to_pkg vertex = pkgTable :: Array Int InstalledPackageInfopkgTable (!) :: Ix i => Array i e -> i -> e! vertex :: Intvertex
pkgTable = listArray :: Ix i => (i, i) -> [e] -> Array i eArray.listArray bounds :: (Int, Int)bounds pkgs :: [InstalledPackageInfo]pkgs
topBound = length :: [a] -> Intlength pkgs :: [InstalledPackageInfo]pkgs (-) :: Num a => a -> a -> a 1
bounds = (0, topBound :: InttopBound)
dependencyInconsistencies :: PackageIndex
-> [(PackageName, [(PackageId, Version)])]
dependencyInconsistencies index =
[ (name :: PackageNamename, [ (pid :: PackageIdpid,packageVersion :: Package pkg => pkg -> VersionpackageVersion dep :: InstalledPackageInfodep) | (dep,pids) <- uses :: [(InstalledPackageInfo, [PackageId])]uses, pid <- pids :: Map InstalledPackageId InstalledPackageInfopids])
| (name, ipid_map) <- toList :: Map k a -> [(k, a)]Map.toList inverseIndex ::
Map
PackageName
(Map InstalledPackageId (InstalledPackageInfo, [PackageId]))inverseIndex
, let uses = elems :: Map k a -> [a]Map.elems ipid_map ::
Map InstalledPackageId (InstalledPackageInfo, [PackageId])ipid_map
, reallyIsInconsistent :: [InstalledPackageInfo] -> BoolreallyIsInconsistent (map :: (a -> b) -> [a] -> [b]map fst :: (a, b) -> afst uses :: [(InstalledPackageInfo, [PackageId])]uses) ]
where
inverseIndex :: Map PackageName
(Map InstalledPackageId
(InstalledPackageInfo, [PackageId]))
inverseIndex = fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> Map k aMap.fromListWith (unionWith ::
Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k aMap.unionWith (\(a,b) (_,b') -> (a :: Inta,b :: [PackageId]b(++) :: [a] -> [a] -> [a]++b' :: [PackageId]b')))
[ (packageName :: Package pkg => pkg -> PackageNamepackageName dep :: InstalledPackageInfodep,
fromList :: Ord k => [(k, a)] -> Map k aMap.fromList [(ipid :: InstalledPackageIdipid,(dep :: InstalledPackageInfodep,[packageId :: Package pkg => pkg -> PackageIdentifierpackageId pkg :: InstalledPackageInfo_ mpkg]))])
| pkg <- allPackages :: PackageIndex -> [InstalledPackageInfo]allPackages index :: PackageIndexindex
, ipid <- depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends pkg :: InstalledPackageInfo_ mpkg
, Just dep <- [lookupInstalledPackageId ::
PackageIndex -> InstalledPackageId -> Maybe InstalledPackageInfolookupInstalledPackageId index :: PackageIndexindex ipid :: InstalledPackageIdipid]
]
reallyIsInconsistent :: [InstalledPackageInfo] -> Bool
reallyIsInconsistent [] = False :: BoolFalse
reallyIsInconsistent [_p] = False :: BoolFalse
reallyIsInconsistent [p1, p2] =
installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId p1 :: InstalledPackageInfop1 notElem :: Eq a => a -> [a] -> Bool`notElem` depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends p2 :: InstalledPackageInfop2
(&&) :: Bool -> Bool -> Bool&& installedPackageId :: InstalledPackageInfo_ m -> InstalledPackageIdinstalledPackageId p2 :: InstalledPackageInfop2 notElem :: Eq a => a -> [a] -> Bool`notElem` depends :: InstalledPackageInfo_ m -> [InstalledPackageId]IPI.depends p1 :: InstalledPackageInfop1
reallyIsInconsistent _ = True :: BoolTrue
moduleNameIndex :: PackageIndex -> Map ModuleName [InstalledPackageInfo]
moduleNameIndex index =
fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> Map k aMap.fromListWith (++) :: [a] -> [a] -> [a](++)
[ (moduleName :: ModuleNamemoduleName, [pkg :: InstalledPackageInfo_ mpkg])
| pkg <- allPackages :: PackageIndex -> [InstalledPackageInfo]allPackages index :: PackageIndexindex
, moduleName <- exposedModules :: InstalledPackageInfo_ m -> [m]IPI.exposedModules pkg :: InstalledPackageInfo_ mpkg ]