{-# LANGUAGE DeriveGeneric #-}{-# LANGUAGE FlexibleContexts #-}{-# LANGUAGE FlexibleInstances #-}------------------------------------------------------------------------------- |-- Module : Distribution.Simple.PackageIndex-- Copyright : (c) David Himmelstrup 2005,-- Bjorn Bringert 2007,-- Duncan Coutts 2008-2009---- Maintainer : cabal-devel@haskell.org-- Portability : portable---- An index of packages whose primary key is 'UnitId'. Public libraries-- are additionally indexed by 'PackageName' and 'Version'.-- Technically, these are an index of *units* (so we should eventually-- rename it to 'UnitIndex'); but in the absence of internal libraries-- or Backpack each unit is equivalent to a package.---- While 'PackageIndex' is parametric over what it actually records,-- it is in fact only ever instantiated with a single element:-- The 'InstalledPackageIndex' (defined here) contains a graph of-- 'InstalledPackageInfo's representing the packages in a-- package database stack. It is used in a variety of ways:---- * The primary use to let Cabal access the same installed-- package database which is used by GHC during compilation.-- For example, this data structure is used by 'ghc-pkg'-- and 'Cabal' to do consistency checks on the database-- (are the references closed).---- * Given a set of dependencies, we can compute the transitive-- closure of dependencies. This is to check if the versions-- of packages are consistent, and also needed by multiple-- tools (Haddock must be explicitly told about the every-- transitive package to do cross-package linking;-- preprocessors must know about the include paths of all-- transitive dependencies.)---- This 'PackageIndex' is NOT to be confused with-- 'Distribution.Client.PackageIndex', which indexes packages only by-- 'PackageName' (this makes it suitable for indexing source packages,-- for which we don't know 'UnitId's.)moduleDistribution.Simple.PackageIndex(-- * Package index data typeInstalledPackageIndex ,PackageIndex -- * Creating an index,fromList -- * Updates,merge ,insert ,deleteUnitId ,deleteSourcePackageId ,deletePackageName -- deleteDependency,-- * Queries-- ** Precise lookups,lookupUnitId ,lookupComponentId ,lookupSourcePackageId ,lookupPackageId ,lookupPackageName ,lookupInternalPackageName ,lookupDependency ,lookupInternalDependency -- ** Case-insensitive searches,searchByName ,SearchResult (..),searchByNameSubstring ,searchWithPredicate -- ** Bulk queries,allPackages ,allPackagesByName ,allPackagesBySourcePackageId ,allPackagesBySourcePackageIdAndLibName -- ** Special queries,brokenPackages ,dependencyClosure ,reverseDependencyClosure ,topologicalOrder ,reverseTopologicalOrder ,dependencyInconsistencies ,dependencyCycles ,dependencyGraph ,moduleNameIndex -- ** Filters on lookup results,eligibleDependencies ,matchingDependencies )whereimportqualifiedData.Map.StrictasMapimportDistribution.Compat.Preludehiding(lookup)importPrelude()importDistribution.BackpackimportqualifiedDistribution.InstalledPackageInfoasIPIimportDistribution.ModuleNameimportDistribution.PackageimportDistribution.Simple.Utils importDistribution.Types.LibraryNameimportDistribution.VersionimportControl.Exception(assert)importControl.MonadimportData.Array((!))importqualifiedData.ArrayasArrayimportqualifiedData.GraphasGraphimportData.ListasList(deleteBy,deleteFirstsBy,groupBy)importqualifiedData.List.NonEmptyasNEimportqualifiedData.TreeasTreeimportDistribution.Compat.Stack importqualifiedPrelude(foldr1)-- | The collection of information about packages from one or more 'PackageDB's.-- These packages generally should have an instance of 'PackageInstalled'---- Packages are uniquely identified in by their 'UnitId', they can-- also be efficiently looked up by package name or by name and version.dataPackageIndex a =PackageIndex {-- The primary index. Each InstalledPackageInfo record is uniquely identified-- by its UnitId.--forall a. PackageIndex a -> Map UnitId a unitIdIndex ::!(MapUnitIda ),-- This auxiliary index maps package names (case-sensitively) to all the-- versions and instances of that package. This allows us to find all-- versions satisfying a dependency.---- It is a three-level index. The first level is the package name,-- the second is the package version and the final level is instances-- of the same package version. These are unique by UnitId-- and are kept in preference order.---- FIXME: Clarify what "preference order" means. Check that this invariant is-- preserved. See #1463 for discussion.forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex ::!(Map(PackageName,LibraryName)(MapVersion[a ]))}deriving(PackageIndex a -> PackageIndex a -> Bool (PackageIndex a -> PackageIndex a -> Bool) -> (PackageIndex a -> PackageIndex a -> Bool) -> Eq (PackageIndex a) forall a. Eq a => PackageIndex a -> PackageIndex a -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $c== :: forall a. Eq a => PackageIndex a -> PackageIndex a -> Bool == :: PackageIndex a -> PackageIndex a -> Bool $c/= :: forall a. Eq a => PackageIndex a -> PackageIndex a -> Bool /= :: PackageIndex a -> PackageIndex a -> Bool Eq,(forall x. PackageIndex a -> Rep (PackageIndex a) x) -> (forall x. Rep (PackageIndex a) x -> PackageIndex a) -> Generic (PackageIndex a) forall x. Rep (PackageIndex a) x -> PackageIndex a forall x. PackageIndex a -> Rep (PackageIndex a) x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall a x. Rep (PackageIndex a) x -> PackageIndex a forall a x. PackageIndex a -> Rep (PackageIndex a) x $cfrom :: forall a x. PackageIndex a -> Rep (PackageIndex a) x from :: forall x. PackageIndex a -> Rep (PackageIndex a) x $cto :: forall a x. Rep (PackageIndex a) x -> PackageIndex a to :: forall x. Rep (PackageIndex a) x -> PackageIndex a Generic,Int -> PackageIndex a -> ShowS [PackageIndex a] -> ShowS PackageIndex a -> String (Int -> PackageIndex a -> ShowS) -> (PackageIndex a -> String) -> ([PackageIndex a] -> ShowS) -> Show (PackageIndex a) forall a. Show a => Int -> PackageIndex a -> ShowS forall a. Show a => [PackageIndex a] -> ShowS forall a. Show a => PackageIndex a -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: forall a. Show a => Int -> PackageIndex a -> ShowS showsPrec :: Int -> PackageIndex a -> ShowS $cshow :: forall a. Show a => PackageIndex a -> String show :: PackageIndex a -> String $cshowList :: forall a. Show a => [PackageIndex a] -> ShowS showList :: [PackageIndex a] -> ShowS Show,ReadPrec [PackageIndex a] ReadPrec (PackageIndex a) Int -> ReadS (PackageIndex a) ReadS [PackageIndex a] (Int -> ReadS (PackageIndex a)) -> ReadS [PackageIndex a] -> ReadPrec (PackageIndex a) -> ReadPrec [PackageIndex a] -> Read (PackageIndex a) forall a. Read a => ReadPrec [PackageIndex a] forall a. Read a => ReadPrec (PackageIndex a) forall a. Read a => Int -> ReadS (PackageIndex a) forall a. Read a => ReadS [PackageIndex a] forall a. (Int -> ReadS a) -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a $creadsPrec :: forall a. Read a => Int -> ReadS (PackageIndex a) readsPrec :: Int -> ReadS (PackageIndex a) $creadList :: forall a. Read a => ReadS [PackageIndex a] readList :: ReadS [PackageIndex a] $creadPrec :: forall a. Read a => ReadPrec (PackageIndex a) readPrec :: ReadPrec (PackageIndex a) $creadListPrec :: forall a. Read a => ReadPrec [PackageIndex a] readListPrec :: ReadPrec [PackageIndex a] Read)instanceBinarya =>Binary(PackageIndex a )instanceStructureda =>Structured(PackageIndex a )-- | The default package index which contains 'InstalledPackageInfo'. Normally-- use this.typeInstalledPackageIndex =PackageIndex IPI.InstalledPackageInfoinstanceMonoid(PackageIndex IPI.InstalledPackageInfo)wheremempty :: PackageIndex InstalledPackageInfo mempty=Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo forall a. Map UnitId a -> Map (PackageName, LibraryName) (Map Version [a]) -> PackageIndex a PackageIndex Map UnitId InstalledPackageInfo forall k a. Map k a Map.emptyMap (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall k a. Map k a Map.emptymappend :: PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo mappend=PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo forall a. Semigroup a => a -> a -> a (<>)-- save one mappend with empty in the common case:mconcat :: [PackageIndex InstalledPackageInfo] -> PackageIndex InstalledPackageInfo mconcat[]=PackageIndex InstalledPackageInfo forall a. Monoid a => a memptymconcat[PackageIndex InstalledPackageInfo] xs =(PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo) -> [PackageIndex InstalledPackageInfo] -> PackageIndex InstalledPackageInfo forall a. (a -> a -> a) -> [a] -> a forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a Prelude.foldr1PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo forall a. Monoid a => a -> a -> a mappend[PackageIndex InstalledPackageInfo] xs instanceSemigroup(PackageIndex IPI.InstalledPackageInfo)where<> :: PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo (<>)=PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo merge {-# NOINLINEinvariant #-}invariant ::WithCallStack (InstalledPackageIndex ->Bool)invariant :: WithCallStack (PackageIndex InstalledPackageInfo -> Bool) invariant (PackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )=-- trace (show pids' ++ "\n" ++ show pnames') $[UnitId] pids' [UnitId] -> [UnitId] -> Bool forall a. Eq a => a -> a -> Bool ==[UnitId] pnames' wherepids' :: [UnitId] pids' =(InstalledPackageInfo -> UnitId) -> [InstalledPackageInfo] -> [UnitId] forall a b. (a -> b) -> [a] -> [b] mapInstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId(Map UnitId InstalledPackageInfo -> [InstalledPackageInfo] forall k a. Map k a -> [a] Map.elemsMap UnitId InstalledPackageInfo pids )pnames' :: [UnitId] pnames' =[UnitId] -> [UnitId] forall a. Ord a => [a] -> [a] sort[Bool -> UnitId -> UnitId forall a. HasCallStack => Bool -> a -> a assertBool pinstOk (InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitIdInstalledPackageInfo pinst )|((PackageName pname ,LibraryName plib ),Map Version [InstalledPackageInfo] pvers )<-Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> [((PackageName, LibraryName), Map Version [InstalledPackageInfo])] forall k a. Map k a -> [(k, a)] Map.toListMap (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames ,letpversOk :: Bool pversOk =Bool -> Bool not(Map Version [InstalledPackageInfo] -> Bool forall k a. Map k a -> Bool Map.nullMap Version [InstalledPackageInfo] pvers ),(Version pver ,[InstalledPackageInfo] pinsts )<-Bool -> [(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] forall a. HasCallStack => Bool -> a -> a assertBool pversOk ([(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])]) -> [(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] forall a b. (a -> b) -> a -> b $Map Version [InstalledPackageInfo] -> [(Version, [InstalledPackageInfo])] forall k a. Map k a -> [(k, a)] Map.toListMap Version [InstalledPackageInfo] pvers ,letpinsts' :: [InstalledPackageInfo] pinsts' =(InstalledPackageInfo -> InstalledPackageInfo -> Ordering) -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. (a -> a -> Ordering) -> [a] -> [a] sortBy((InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> InstalledPackageInfo -> Ordering forall a b. Ord a => (b -> a) -> b -> b -> Ordering comparingInstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId)[InstalledPackageInfo] pinsts pinstsOk :: Bool pinstsOk =([InstalledPackageInfo] -> Bool) -> [[InstalledPackageInfo]] -> Bool forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool all(\[InstalledPackageInfo] g ->[InstalledPackageInfo] -> Int forall a. [a] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length[InstalledPackageInfo] g Int -> Int -> Bool forall a. Eq a => a -> a -> Bool ==Int 1)((InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> [InstalledPackageInfo] -> [[InstalledPackageInfo]] forall a. (a -> a -> Bool) -> [a] -> [[a]] groupBy((InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> InstalledPackageInfo -> Bool forall a b. Eq a => (b -> a) -> b -> b -> Bool equatingInstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId)[InstalledPackageInfo] pinsts' ),InstalledPackageInfo pinst <-Bool -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. HasCallStack => Bool -> a -> a assertBool pinstsOk ([InstalledPackageInfo] -> [InstalledPackageInfo]) -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a b. (a -> b) -> a -> b $[InstalledPackageInfo] pinsts' ,letpinstOk :: Bool pinstOk =InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo pinst PackageName -> PackageName -> Bool forall a. Eq a => a -> a -> Bool ==PackageName pname Bool -> Bool -> Bool &&InstalledPackageInfo -> Version forall pkg. Package pkg => pkg -> Version packageVersionInstalledPackageInfo pinst Version -> Version -> Bool forall a. Eq a => a -> a -> Bool ==Version pver Bool -> Bool -> Bool &&InstalledPackageInfo -> LibraryName IPI.sourceLibNameInstalledPackageInfo pinst LibraryName -> LibraryName -> Bool forall a. Eq a => a -> a -> Bool ==LibraryName plib ]-- If you see this invariant failing (ie the assert in mkPackageIndex below)-- then one thing to check is if it is happening in fromList. Check if the-- second list above (the sort [...] bit) is ending up with duplicates. This-- has been observed in practice once due to a messed up ghc-pkg db. How/why-- it became messed up was not discovered.---- * Internal helpers--mkPackageIndex ::WithCallStack (MapUnitIdIPI.InstalledPackageInfo->Map(PackageName,LibraryName)(MapVersion[IPI.InstalledPackageInfo])->InstalledPackageIndex )mkPackageIndex :: WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) mkPackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames =Bool -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo forall a. HasCallStack => Bool -> a -> a assert(WithCallStack (PackageIndex InstalledPackageInfo -> Bool) PackageIndex InstalledPackageInfo -> Bool invariant PackageIndex InstalledPackageInfo index )PackageIndex InstalledPackageInfo index whereindex :: PackageIndex InstalledPackageInfo index =Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo forall a. Map UnitId a -> Map (PackageName, LibraryName) (Map Version [a]) -> PackageIndex a PackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames ---- * Construction---- | Build an index out of a bunch of packages.---- If there are duplicates by 'UnitId' then later ones mask earlier-- ones.fromList ::[IPI.InstalledPackageInfo]->InstalledPackageIndex fromList :: [InstalledPackageInfo] -> PackageIndex InstalledPackageInfo fromList [InstalledPackageInfo] pkgs =WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo mkPackageIndex Map UnitId InstalledPackageInfo pids (((Map Version (NonEmpty InstalledPackageInfo) -> Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version (NonEmpty InstalledPackageInfo)) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall a b. (a -> b) -> Map (PackageName, LibraryName) a -> Map (PackageName, LibraryName) b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap((Map Version (NonEmpty InstalledPackageInfo) -> Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version (NonEmpty InstalledPackageInfo)) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo])) -> ((NonEmpty InstalledPackageInfo -> [InstalledPackageInfo]) -> Map Version (NonEmpty InstalledPackageInfo) -> Map Version [InstalledPackageInfo]) -> (NonEmpty InstalledPackageInfo -> [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version (NonEmpty InstalledPackageInfo)) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall b c a. (b -> c) -> (a -> b) -> a -> c .(NonEmpty InstalledPackageInfo -> [InstalledPackageInfo]) -> Map Version (NonEmpty InstalledPackageInfo) -> Map Version [InstalledPackageInfo] forall a b. (a -> b) -> Map Version a -> Map Version b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap)NonEmpty InstalledPackageInfo -> [InstalledPackageInfo] forall a. NonEmpty a -> [a] forall (t :: * -> *) a. Foldable t => t a -> [a] toListMap (PackageName, LibraryName) (Map Version (NonEmpty InstalledPackageInfo)) pnames )wherepids :: Map UnitId InstalledPackageInfo pids =[(UnitId, InstalledPackageInfo)] -> Map UnitId InstalledPackageInfo forall k a. Ord k => [(k, a)] -> Map k a Map.fromList[(InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitIdInstalledPackageInfo pkg ,InstalledPackageInfo pkg )|InstalledPackageInfo pkg <-[InstalledPackageInfo] pkgs ]pnames :: Map (PackageName, LibraryName) (Map Version (NonEmpty InstalledPackageInfo)) pnames =[((PackageName, LibraryName), Map Version (NonEmpty InstalledPackageInfo))] -> Map (PackageName, LibraryName) (Map Version (NonEmpty InstalledPackageInfo)) forall k a. Ord k => [(k, a)] -> Map k a Map.fromList[((PackageName -> LibraryName -> (PackageName, LibraryName)) -> (InstalledPackageInfo -> PackageName) -> (InstalledPackageInfo -> LibraryName) -> InstalledPackageInfo -> (PackageName, LibraryName) forall (m :: * -> *) a1 a2 r. Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r liftM2(,)InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo -> LibraryName IPI.sourceLibName(NonEmpty InstalledPackageInfo -> InstalledPackageInfo forall a. NonEmpty a -> a NE.headNonEmpty InstalledPackageInfo pkgsN ),Map Version (NonEmpty InstalledPackageInfo) pvers )|NonEmpty InstalledPackageInfo pkgsN <-(InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> [InstalledPackageInfo] -> [NonEmpty InstalledPackageInfo] forall (f :: * -> *) a. Foldable f => (a -> a -> Bool) -> f a -> [NonEmpty a] NE.groupBy((InstalledPackageInfo -> (PackageName, LibraryName)) -> InstalledPackageInfo -> InstalledPackageInfo -> Bool forall a b. Eq a => (b -> a) -> b -> b -> Bool equating((PackageName -> LibraryName -> (PackageName, LibraryName)) -> (InstalledPackageInfo -> PackageName) -> (InstalledPackageInfo -> LibraryName) -> InstalledPackageInfo -> (PackageName, LibraryName) forall (m :: * -> *) a1 a2 r. Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r liftM2(,)InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo -> LibraryName IPI.sourceLibName))([InstalledPackageInfo] -> [NonEmpty InstalledPackageInfo]) -> ([InstalledPackageInfo] -> [InstalledPackageInfo]) -> [InstalledPackageInfo] -> [NonEmpty InstalledPackageInfo] forall b c a. (b -> c) -> (a -> b) -> a -> c .(InstalledPackageInfo -> InstalledPackageInfo -> Ordering) -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. (a -> a -> Ordering) -> [a] -> [a] sortBy((InstalledPackageInfo -> (PackageName, LibraryName, Version)) -> InstalledPackageInfo -> InstalledPackageInfo -> Ordering forall a b. Ord a => (b -> a) -> b -> b -> Ordering comparing((PackageName -> LibraryName -> Version -> (PackageName, LibraryName, Version)) -> (InstalledPackageInfo -> PackageName) -> (InstalledPackageInfo -> LibraryName) -> (InstalledPackageInfo -> Version) -> InstalledPackageInfo -> (PackageName, LibraryName, Version) forall (m :: * -> *) a1 a2 a3 r. Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r liftM3(,,)InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo -> LibraryName IPI.sourceLibNameInstalledPackageInfo -> Version forall pkg. Package pkg => pkg -> Version packageVersion))([InstalledPackageInfo] -> [NonEmpty InstalledPackageInfo]) -> [InstalledPackageInfo] -> [NonEmpty InstalledPackageInfo] forall a b. (a -> b) -> a -> b $[InstalledPackageInfo] pkgs ,letpvers :: Map Version (NonEmpty InstalledPackageInfo) pvers =[(Version, NonEmpty InstalledPackageInfo)] -> Map Version (NonEmpty InstalledPackageInfo) forall k a. Ord k => [(k, a)] -> Map k a Map.fromList[(InstalledPackageInfo -> Version forall pkg. Package pkg => pkg -> Version packageVersion(NonEmpty InstalledPackageInfo -> InstalledPackageInfo forall a. NonEmpty a -> a NE.headNonEmpty InstalledPackageInfo pkgsNV ),(InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> NonEmpty InstalledPackageInfo -> NonEmpty InstalledPackageInfo forall a. (a -> a -> Bool) -> NonEmpty a -> NonEmpty a NE.nubBy((InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> InstalledPackageInfo -> Bool forall a b. Eq a => (b -> a) -> b -> b -> Bool equatingInstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId)(NonEmpty InstalledPackageInfo -> NonEmpty InstalledPackageInfo forall a. NonEmpty a -> NonEmpty a NE.reverseNonEmpty InstalledPackageInfo pkgsNV ))|NonEmpty InstalledPackageInfo pkgsNV <-(InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> NonEmpty InstalledPackageInfo -> [NonEmpty InstalledPackageInfo] forall (f :: * -> *) a. Foldable f => (a -> a -> Bool) -> f a -> [NonEmpty a] NE.groupBy((InstalledPackageInfo -> Version) -> InstalledPackageInfo -> InstalledPackageInfo -> Bool forall a b. Eq a => (b -> a) -> b -> b -> Bool equatingInstalledPackageInfo -> Version forall pkg. Package pkg => pkg -> Version packageVersion)NonEmpty InstalledPackageInfo pkgsN ]]---- * Updates---- | Merge two indexes.---- Packages from the second mask packages from the first if they have the exact-- same 'UnitId'.---- For packages with the same source 'PackageId', packages from the second are-- \"preferred\" over those from the first. Being preferred means they are top-- result when we do a lookup by source 'PackageId'. This is the mechanism we-- use to prefer user packages over global packages.merge ::InstalledPackageIndex ->InstalledPackageIndex ->InstalledPackageIndex merge :: PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo merge (PackageIndex Map UnitId InstalledPackageInfo pids1 Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames1 )(PackageIndex Map UnitId InstalledPackageInfo pids2 Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames2 )=WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo mkPackageIndex ((InstalledPackageInfo -> InstalledPackageInfo -> InstalledPackageInfo) -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a Map.unionWith(\InstalledPackageInfo _InstalledPackageInfo y ->InstalledPackageInfo y )Map UnitId InstalledPackageInfo pids1 Map UnitId InstalledPackageInfo pids2 )((Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a Map.unionWith(([InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo]) -> Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a Map.unionWith[InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] mergeBuckets )Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames1 Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames2 )where-- Packages in the second list mask those in the first, however preferred-- packages go first in the list.mergeBuckets :: [InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] mergeBuckets [InstalledPackageInfo] xs [InstalledPackageInfo] ys =[InstalledPackageInfo] ys [InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. [a] -> [a] -> [a] ++([InstalledPackageInfo] xs [InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] \\ [InstalledPackageInfo] ys )\\ :: [InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] (\\) =(InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> [InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. (a -> a -> Bool) -> [a] -> [a] -> [a] deleteFirstsBy((InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> InstalledPackageInfo -> Bool forall a b. Eq a => (b -> a) -> b -> b -> Bool equatingInstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId)-- | Inserts a single package into the index.---- This is equivalent to (but slightly quicker than) using 'mappend' or-- 'merge' with a singleton index.insert ::IPI.InstalledPackageInfo->InstalledPackageIndex ->InstalledPackageIndex insert :: InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo insert InstalledPackageInfo pkg (PackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )=WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo mkPackageIndex Map UnitId InstalledPackageInfo pids' Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames' wherepids' :: Map UnitId InstalledPackageInfo pids' =UnitId -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall k a. Ord k => k -> a -> Map k a -> Map k a Map.insert(InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitIdInstalledPackageInfo pkg )InstalledPackageInfo pkg Map UnitId InstalledPackageInfo pids pnames' :: Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames' =Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) insertPackageName Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames insertPackageName :: Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) insertPackageName =(Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo]) -> (PackageName, LibraryName) -> Map Version [InstalledPackageInfo] -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a Map.insertWith(\Map Version [InstalledPackageInfo] _->Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] insertPackageVersion )(InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo pkg ,InstalledPackageInfo -> LibraryName IPI.sourceLibNameInstalledPackageInfo pkg )(Version -> [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] forall k a. k -> a -> Map k a Map.singleton(InstalledPackageInfo -> Version forall pkg. Package pkg => pkg -> Version packageVersionInstalledPackageInfo pkg )[InstalledPackageInfo pkg ])insertPackageVersion :: Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] insertPackageVersion =([InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo]) -> Version -> [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a Map.insertWith(\[InstalledPackageInfo] _->[InstalledPackageInfo] -> [InstalledPackageInfo] insertPackageInstance )(InstalledPackageInfo -> Version forall pkg. Package pkg => pkg -> Version packageVersionInstalledPackageInfo pkg )[InstalledPackageInfo pkg ]insertPackageInstance :: [InstalledPackageInfo] -> [InstalledPackageInfo] insertPackageInstance [InstalledPackageInfo] pkgs =InstalledPackageInfo pkg InstalledPackageInfo -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. a -> [a] -> [a] :(InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> InstalledPackageInfo -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. (a -> a -> Bool) -> a -> [a] -> [a] deleteBy((InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> InstalledPackageInfo -> Bool forall a b. Eq a => (b -> a) -> b -> b -> Bool equatingInstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId)InstalledPackageInfo pkg [InstalledPackageInfo] pkgs -- | Removes a single installed package from the index.deleteUnitId ::UnitId->InstalledPackageIndex ->InstalledPackageIndex deleteUnitId :: UnitId -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo deleteUnitId UnitId ipkgid original :: PackageIndex InstalledPackageInfo original @(PackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )=case(UnitId -> InstalledPackageInfo -> Maybe InstalledPackageInfo) -> UnitId -> Map UnitId InstalledPackageInfo -> (Maybe InstalledPackageInfo, Map UnitId InstalledPackageInfo) forall k a. Ord k => (k -> a -> Maybe a) -> k -> Map k a -> (Maybe a, Map k a) Map.updateLookupWithKey(\UnitId _InstalledPackageInfo _->Maybe InstalledPackageInfo forall a. Maybe a Nothing)UnitId ipkgid Map UnitId InstalledPackageInfo pids of(Maybe InstalledPackageInfo Nothing,Map UnitId InstalledPackageInfo _)->PackageIndex InstalledPackageInfo original (JustInstalledPackageInfo spkgid ,Map UnitId InstalledPackageInfo pids' )->WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo mkPackageIndex Map UnitId InstalledPackageInfo pids' (InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) deletePkgName InstalledPackageInfo spkgid Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )wheredeletePkgName :: InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) deletePkgName InstalledPackageInfo spkgid =(Map Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo])) -> (PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a Map.update(InstalledPackageInfo -> Map Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo]) forall {pkg}. Package pkg => pkg -> Map Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo]) deletePkgVersion InstalledPackageInfo spkgid )(InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo spkgid ,InstalledPackageInfo -> LibraryName IPI.sourceLibNameInstalledPackageInfo spkgid )deletePkgVersion :: pkg -> Map Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo]) deletePkgVersion pkg spkgid =(\Map Version [InstalledPackageInfo] m ->ifMap Version [InstalledPackageInfo] -> Bool forall k a. Map k a -> Bool Map.nullMap Version [InstalledPackageInfo] m thenMaybe (Map Version [InstalledPackageInfo]) forall a. Maybe a NothingelseMap Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo]) forall a. a -> Maybe a JustMap Version [InstalledPackageInfo] m )(Map Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo])) -> (Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo]) -> Map Version [InstalledPackageInfo] -> Maybe (Map Version [InstalledPackageInfo]) forall b c a. (b -> c) -> (a -> b) -> a -> c .([InstalledPackageInfo] -> Maybe [InstalledPackageInfo]) -> Version -> Map Version [InstalledPackageInfo] -> Map Version [InstalledPackageInfo] forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a Map.update[InstalledPackageInfo] -> Maybe [InstalledPackageInfo] deletePkgInstance (pkg -> Version forall pkg. Package pkg => pkg -> Version packageVersionpkg spkgid )deletePkgInstance :: [InstalledPackageInfo] -> Maybe [InstalledPackageInfo] deletePkgInstance =(\[InstalledPackageInfo] xs ->if[InstalledPackageInfo] -> Bool forall a. [a] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null[InstalledPackageInfo] xs thenMaybe [InstalledPackageInfo] forall a. Maybe a Nothingelse[InstalledPackageInfo] -> Maybe [InstalledPackageInfo] forall a. a -> Maybe a Just[InstalledPackageInfo] xs )([InstalledPackageInfo] -> Maybe [InstalledPackageInfo]) -> ([InstalledPackageInfo] -> [InstalledPackageInfo]) -> [InstalledPackageInfo] -> Maybe [InstalledPackageInfo] forall b c a. (b -> c) -> (a -> b) -> a -> c .(InstalledPackageInfo -> InstalledPackageInfo -> Bool) -> InstalledPackageInfo -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. (a -> a -> Bool) -> a -> [a] -> [a] List.deleteBy(\InstalledPackageInfo _InstalledPackageInfo pkg ->InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitIdInstalledPackageInfo pkg UnitId -> UnitId -> Bool forall a. Eq a => a -> a -> Bool ==UnitId ipkgid )InstalledPackageInfo forall a. HasCallStack => a undefined-- | Removes all packages with this source 'PackageId' from the index.deleteSourcePackageId ::PackageId->InstalledPackageIndex ->InstalledPackageIndex deleteSourcePackageId :: PackageId -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo deleteSourcePackageId PackageId pkgid original :: PackageIndex InstalledPackageInfo original @(PackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )=-- NB: Doesn't delete internal packagescase(PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Maybe (Map Version [InstalledPackageInfo]) forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(PackageId -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNamePackageId pkgid ,LibraryName LMainLibName)Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames ofMaybe (Map Version [InstalledPackageInfo]) Nothing->PackageIndex InstalledPackageInfo original JustMap Version [InstalledPackageInfo] pvers ->caseVersion -> Map Version [InstalledPackageInfo] -> Maybe [InstalledPackageInfo] forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(PackageId -> Version forall pkg. Package pkg => pkg -> Version packageVersionPackageId pkgid )Map Version [InstalledPackageInfo] pvers ofMaybe [InstalledPackageInfo] Nothing->PackageIndex InstalledPackageInfo original Just[InstalledPackageInfo] pkgs ->WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo mkPackageIndex ((Map UnitId InstalledPackageInfo -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo) -> Map UnitId InstalledPackageInfo -> [InstalledPackageInfo] -> Map UnitId InstalledPackageInfo forall b a. (b -> a -> b) -> b -> [a] -> b forall (t :: * -> *) b a. Foldable t => (b -> a -> b) -> b -> t a -> b foldl'((InstalledPackageInfo -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo) -> Map UnitId InstalledPackageInfo -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall a b c. (a -> b -> c) -> b -> a -> c flip(UnitId -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall k a. Ord k => k -> Map k a -> Map k a Map.delete(UnitId -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo) -> (InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall b c a. (b -> c) -> (a -> b) -> a -> c .InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId))Map UnitId InstalledPackageInfo pids [InstalledPackageInfo] pkgs )(Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall {a}. Map (PackageName, LibraryName) (Map Version a) -> Map (PackageName, LibraryName) (Map Version a) deletePkgName Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )wheredeletePkgName :: Map (PackageName, LibraryName) (Map Version a) -> Map (PackageName, LibraryName) (Map Version a) deletePkgName =(Map Version a -> Maybe (Map Version a)) -> (PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version a) -> Map (PackageName, LibraryName) (Map Version a) forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a Map.updateMap Version a -> Maybe (Map Version a) forall {a}. Map Version a -> Maybe (Map Version a) deletePkgVersion (PackageId -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNamePackageId pkgid ,LibraryName LMainLibName)deletePkgVersion :: Map Version a -> Maybe (Map Version a) deletePkgVersion =(\Map Version a m ->ifMap Version a -> Bool forall k a. Map k a -> Bool Map.nullMap Version a m thenMaybe (Map Version a) forall a. Maybe a NothingelseMap Version a -> Maybe (Map Version a) forall a. a -> Maybe a JustMap Version a m )(Map Version a -> Maybe (Map Version a)) -> (Map Version a -> Map Version a) -> Map Version a -> Maybe (Map Version a) forall b c a. (b -> c) -> (a -> b) -> a -> c .Version -> Map Version a -> Map Version a forall k a. Ord k => k -> Map k a -> Map k a Map.delete(PackageId -> Version forall pkg. Package pkg => pkg -> Version packageVersionPackageId pkgid )-- | Removes all packages with this (case-sensitive) name from the index.---- NB: Does NOT delete internal libraries from this package.deletePackageName ::PackageName->InstalledPackageIndex ->InstalledPackageIndex deletePackageName :: PackageName -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo deletePackageName PackageName name original :: PackageIndex InstalledPackageInfo original @(PackageIndex Map UnitId InstalledPackageInfo pids Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames )=case(PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Maybe (Map Version [InstalledPackageInfo]) forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(PackageName name ,LibraryName LMainLibName)Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames ofMaybe (Map Version [InstalledPackageInfo]) Nothing->PackageIndex InstalledPackageInfo original JustMap Version [InstalledPackageInfo] pvers ->WithCallStack (Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo) Map UnitId InstalledPackageInfo -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> PackageIndex InstalledPackageInfo mkPackageIndex ((Map UnitId InstalledPackageInfo -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo) -> Map UnitId InstalledPackageInfo -> [InstalledPackageInfo] -> Map UnitId InstalledPackageInfo forall b a. (b -> a -> b) -> b -> [a] -> b forall (t :: * -> *) b a. Foldable t => (b -> a -> b) -> b -> t a -> b foldl'((InstalledPackageInfo -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo) -> Map UnitId InstalledPackageInfo -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall a b c. (a -> b -> c) -> b -> a -> c flip(UnitId -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall k a. Ord k => k -> Map k a -> Map k a Map.delete(UnitId -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo) -> (InstalledPackageInfo -> UnitId) -> InstalledPackageInfo -> Map UnitId InstalledPackageInfo -> Map UnitId InstalledPackageInfo forall b c a. (b -> c) -> (a -> b) -> a -> c .InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId))Map UnitId InstalledPackageInfo pids ([[InstalledPackageInfo]] -> [InstalledPackageInfo] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat(Map Version [InstalledPackageInfo] -> [[InstalledPackageInfo]] forall k a. Map k a -> [a] Map.elemsMap Version [InstalledPackageInfo] pvers )))((PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) -> Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) forall k a. Ord k => k -> Map k a -> Map k a Map.delete(PackageName name ,LibraryName LMainLibName)Map (PackageName, LibraryName) (Map Version [InstalledPackageInfo]) pnames ){- -- | Removes all packages satisfying this dependency from the index. -- deleteDependency :: Dependency -> PackageIndex -> PackageIndex deleteDependency (Dependency name verstionRange) = delete' name (\pkg -> packageVersion pkg `withinRange` verstionRange) -}---- * Bulk queries---- | Get all the packages from the index.allPackages ::PackageIndex a ->[a ]allPackages :: forall a. PackageIndex a -> [a] allPackages =Map UnitId a -> [a] forall k a. Map k a -> [a] Map.elems(Map UnitId a -> [a]) -> (PackageIndex a -> Map UnitId a) -> PackageIndex a -> [a] forall b c a. (b -> c) -> (a -> b) -> a -> c .PackageIndex a -> Map UnitId a forall a. PackageIndex a -> Map UnitId a unitIdIndex -- | Get all the packages from the index.---- They are grouped by package name (case-sensitively).---- (Doesn't include private libraries.)allPackagesByName ::PackageIndex a ->[(PackageName,[a ])]allPackagesByName :: forall a. PackageIndex a -> [(PackageName, [a])] allPackagesByName PackageIndex a index =[(PackageName pkgname ,[[a]] -> [a] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat(Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elemsMap Version [a] pvers ))|((PackageName pkgname ,LibraryName LMainLibName),Map Version [a] pvers )<-Map (PackageName, LibraryName) (Map Version [a]) -> [((PackageName, LibraryName), Map Version [a])] forall k a. Map k a -> [(k, a)] Map.toList(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index )]-- | Get all the packages from the index.---- They are grouped by source package id (package name and version).---- (Doesn't include private libraries)allPackagesBySourcePackageId ::HasUnitIda =>PackageIndex a ->[(PackageId,[a ])]allPackagesBySourcePackageId :: forall a. HasUnitId a => PackageIndex a -> [(PackageId, [a])] allPackagesBySourcePackageId PackageIndex a index =[(a -> PackageId forall pkg. Package pkg => pkg -> PackageId packageIda ipkg ,[a] ipkgs )|((PackageName _,LibraryName LMainLibName),Map Version [a] pvers )<-Map (PackageName, LibraryName) (Map Version [a]) -> [((PackageName, LibraryName), Map Version [a])] forall k a. Map k a -> [(k, a)] Map.toList(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index ),ipkgs :: [a] ipkgs @(a ipkg :[a] _)<-Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elemsMap Version [a] pvers ]-- | Get all the packages from the index.---- They are grouped by source package id and library name.---- This DOES include internal libraries.allPackagesBySourcePackageIdAndLibName ::HasUnitIda =>PackageIndex a ->[((PackageId,LibraryName),[a ])]allPackagesBySourcePackageIdAndLibName :: forall a. HasUnitId a => PackageIndex a -> [((PackageId, LibraryName), [a])] allPackagesBySourcePackageIdAndLibName PackageIndex a index =[((a -> PackageId forall pkg. Package pkg => pkg -> PackageId packageIda ipkg ,LibraryName ln ),[a] ipkgs )|((PackageName _,LibraryName ln ),Map Version [a] pvers )<-Map (PackageName, LibraryName) (Map Version [a]) -> [((PackageName, LibraryName), Map Version [a])] forall k a. Map k a -> [(k, a)] Map.toList(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index ),ipkgs :: [a] ipkgs @(a ipkg :[a] _)<-Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elemsMap Version [a] pvers ]---- * Lookups---- | Does a lookup by unit identifier.---- Since multiple package DBs mask each other by 'UnitId',-- then we get back at most one package.lookupUnitId ::PackageIndex a ->UnitId->Maybea lookupUnitId :: forall a. PackageIndex a -> UnitId -> Maybe a lookupUnitId PackageIndex a index UnitId uid =UnitId -> Map UnitId a -> Maybe a forall k a. Ord k => k -> Map k a -> Maybe a Map.lookupUnitId uid (PackageIndex a -> Map UnitId a forall a. PackageIndex a -> Map UnitId a unitIdIndex PackageIndex a index )-- | Does a lookup by component identifier. In the absence-- of Backpack, this is just a 'lookupUnitId'.lookupComponentId ::PackageIndex a ->ComponentId->Maybea lookupComponentId :: forall a. PackageIndex a -> ComponentId -> Maybe a lookupComponentId PackageIndex a index ComponentId cid =UnitId -> Map UnitId a -> Maybe a forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(ComponentId -> UnitId newSimpleUnitIdComponentId cid )(PackageIndex a -> Map UnitId a forall a. PackageIndex a -> Map UnitId a unitIdIndex PackageIndex a index )-- | Does a lookup by source package id (name & version).---- There can be multiple installed packages with the same source 'PackageId'-- but different 'UnitId'. They are returned in order of-- preference, with the most preferred first.lookupSourcePackageId ::PackageIndex a ->PackageId->[a ]lookupSourcePackageId :: forall a. PackageIndex a -> PackageId -> [a] lookupSourcePackageId PackageIndex a index PackageId pkgid =-- Do not lookup internal librariescase(PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version [a]) -> Maybe (Map Version [a]) forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(PackageId -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNamePackageId pkgid ,LibraryName LMainLibName)(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index )ofMaybe (Map Version [a]) Nothing->[]JustMap Version [a] pvers ->caseVersion -> Map Version [a] -> Maybe [a] forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(PackageId -> Version forall pkg. Package pkg => pkg -> Version packageVersionPackageId pkgid )Map Version [a] pvers ofMaybe [a] Nothing->[]Just[a] pkgs ->[a] pkgs -- in preference order-- | Convenient alias of 'lookupSourcePackageId', but assuming only-- one package per package ID.lookupPackageId ::PackageIndex a ->PackageId->Maybea lookupPackageId :: forall a. PackageIndex a -> PackageId -> Maybe a lookupPackageId PackageIndex a index PackageId pkgid =casePackageIndex a -> PackageId -> [a] forall a. PackageIndex a -> PackageId -> [a] lookupSourcePackageId PackageIndex a index PackageId pkgid of[]->Maybe a forall a. Maybe a Nothing[a pkg ]->a -> Maybe a forall a. a -> Maybe a Justa pkg [a] _->String -> Maybe a forall a. HasCallStack => String -> a errorString "Distribution.Simple.PackageIndex: multiple matches found"-- | Does a lookup by source package name.lookupPackageName ::PackageIndex a ->PackageName->[(Version,[a ])]lookupPackageName :: forall a. PackageIndex a -> PackageName -> [(Version, [a])] lookupPackageName PackageIndex a index PackageName name =-- Do not match internal librariesPackageIndex a -> PackageName -> LibraryName -> [(Version, [a])] forall a. PackageIndex a -> PackageName -> LibraryName -> [(Version, [a])] lookupInternalPackageName PackageIndex a index PackageName name LibraryName LMainLibName-- | Does a lookup by source package name and library name.---- Also looks up internal packages.lookupInternalPackageName ::PackageIndex a ->PackageName->LibraryName->[(Version,[a ])]lookupInternalPackageName :: forall a. PackageIndex a -> PackageName -> LibraryName -> [(Version, [a])] lookupInternalPackageName PackageIndex a index PackageName name LibraryName library =case(PackageName, LibraryName) -> Map (PackageName, LibraryName) (Map Version [a]) -> Maybe (Map Version [a]) forall k a. Ord k => k -> Map k a -> Maybe a Map.lookup(PackageName name ,LibraryName library )(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index )ofMaybe (Map Version [a]) Nothing->[]JustMap Version [a] pvers ->Map Version [a] -> [(Version, [a])] forall k a. Map k a -> [(k, a)] Map.toListMap Version [a] pvers -- | Does a lookup by source package name and a range of versions.---- We get back any number of versions of the specified package name, all-- satisfying the version range constraint.---- This does NOT work for internal dependencies, DO NOT use this-- function on those; use 'lookupInternalDependency' instead.---- INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.lookupDependency ::InstalledPackageIndex ->PackageName->VersionRange->[(Version,[IPI.InstalledPackageInfo])]lookupDependency :: PackageIndex InstalledPackageInfo -> PackageName -> VersionRange -> [(Version, [InstalledPackageInfo])] lookupDependency PackageIndex InstalledPackageInfo index PackageName pn VersionRange vr =-- Yes, a little bit of a misnomer here!PackageIndex InstalledPackageInfo -> PackageName -> VersionRange -> LibraryName -> [(Version, [InstalledPackageInfo])] lookupInternalDependency PackageIndex InstalledPackageInfo index PackageName pn VersionRange vr LibraryName LMainLibName-- | Does a lookup by source package name and a range of versions.---- We get back any number of versions of the specified package name, all-- satisfying the version range constraint.---- INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.lookupInternalDependency ::InstalledPackageIndex ->PackageName->VersionRange->LibraryName->[(Version,[IPI.InstalledPackageInfo])]lookupInternalDependency :: PackageIndex InstalledPackageInfo -> PackageName -> VersionRange -> LibraryName -> [(Version, [InstalledPackageInfo])] lookupInternalDependency PackageIndex InstalledPackageInfo index PackageName name VersionRange versionRange LibraryName libn =VersionRange -> [(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] matchingDependencies VersionRange versionRange ([(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])]) -> [(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] forall a b. (a -> b) -> a -> b $PackageIndex InstalledPackageInfo -> PackageName -> LibraryName -> [(Version, [InstalledPackageInfo])] forall a. PackageIndex a -> PackageName -> LibraryName -> [(Version, [a])] lookupInternalPackageName PackageIndex InstalledPackageInfo index PackageName name LibraryName libn -- | Filter a set of installed packages to ones eligible as dependencies.---- When we select for dependencies, we ONLY want to pick up indefinite-- packages, or packages with no instantiations. We'll do mix-in linking to-- improve any such package into an instantiated one later.---- INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.eligibleDependencies ::[(Version,[IPI.InstalledPackageInfo])]->[(Version,[IPI.InstalledPackageInfo])]eligibleDependencies :: [(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] eligibleDependencies [(Version, [InstalledPackageInfo])] versions =[(Version ver ,[InstalledPackageInfo] pkgs' )|(Version ver ,[InstalledPackageInfo] pkgs )<-[(Version, [InstalledPackageInfo])] versions ,letpkgs' :: [InstalledPackageInfo] pkgs' =(InstalledPackageInfo -> Bool) -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. (a -> Bool) -> [a] -> [a] filterInstalledPackageInfo -> Bool eligible [InstalledPackageInfo] pkgs ,-- Enforce the invariantBool -> Bool not([InstalledPackageInfo] -> Bool forall a. [a] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null[InstalledPackageInfo] pkgs' )]whereeligible :: InstalledPackageInfo -> Bool eligible InstalledPackageInfo pkg =InstalledPackageInfo -> Bool IPI.indefiniteInstalledPackageInfo pkg Bool -> Bool -> Bool ||[(ModuleName, OpenModule)] -> Bool forall a. [a] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null(InstalledPackageInfo -> [(ModuleName, OpenModule)] IPI.instantiatedWithInstalledPackageInfo pkg )-- | Get eligible dependencies from a list of versions.---- This can be used to filter the output of 'lookupPackageName' or-- 'lookupInternalPackageName'.---- INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.matchingDependencies ::VersionRange->[(Version,[IPI.InstalledPackageInfo])]->[(Version,[IPI.InstalledPackageInfo])]matchingDependencies :: VersionRange -> [(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] matchingDependencies VersionRange versionRange [(Version, [InstalledPackageInfo])] versions =leteligibleVersions :: [(Version, [InstalledPackageInfo])] eligibleVersions =[(Version, [InstalledPackageInfo])] -> [(Version, [InstalledPackageInfo])] eligibleDependencies [(Version, [InstalledPackageInfo])] versions in[(Version ver ,[InstalledPackageInfo] pkgs )|(Version ver ,[InstalledPackageInfo] pkgs )<-[(Version, [InstalledPackageInfo])] eligibleVersions ,Version ver Version -> VersionRange -> Bool `withinRange`VersionRange versionRange ]---- * Case insensitive name lookups---- | Does a case-insensitive search by package name.---- If there is only one package that compares case-insensitively to this name-- then the search is unambiguous and we get back all versions of that package.-- If several match case-insensitively but one matches exactly then it is also-- unambiguous.---- If however several match case-insensitively and none match exactly then we-- have an ambiguous result, and we get back all the versions of all the-- packages. The list of ambiguous results is split by exact package name. So-- it is a non-empty list of non-empty lists.searchByName ::PackageIndex a ->String->SearchResult [a ]searchByName :: forall a. PackageIndex a -> String -> SearchResult [a] searchByName PackageIndex a index String name =-- Don't match internal packagescase[((PackageName, LibraryName), Map Version [a]) pkgs |pkgs :: ((PackageName, LibraryName), Map Version [a]) pkgs @((PackageName pname ,LibraryName LMainLibName),Map Version [a] _)<-Map (PackageName, LibraryName) (Map Version [a]) -> [((PackageName, LibraryName), Map Version [a])] forall k a. Map k a -> [(k, a)] Map.toList(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index ),ShowS lowercase(PackageName -> String unPackageNamePackageName pname )String -> String -> Bool forall a. Eq a => a -> a -> Bool ==String lname ]of[]->SearchResult [a] forall a. SearchResult a None [((PackageName, LibraryName) _,Map Version [a] pvers )]->[a] -> SearchResult [a] forall a. a -> SearchResult a Unambiguous ([[a]] -> [a] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat(Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elemsMap Version [a] pvers ))[((PackageName, LibraryName), Map Version [a])] pkgss ->case(((PackageName, LibraryName), Map Version [a]) -> Bool) -> [((PackageName, LibraryName), Map Version [a])] -> Maybe ((PackageName, LibraryName), Map Version [a]) forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a find((String -> PackageName mkPackageNameString name PackageName -> PackageName -> Bool forall a. Eq a => a -> a -> Bool ==)(PackageName -> Bool) -> (((PackageName, LibraryName), Map Version [a]) -> PackageName) -> ((PackageName, LibraryName), Map Version [a]) -> Bool forall b c a. (b -> c) -> (a -> b) -> a -> c .(PackageName, LibraryName) -> PackageName forall a b. (a, b) -> a fst((PackageName, LibraryName) -> PackageName) -> (((PackageName, LibraryName), Map Version [a]) -> (PackageName, LibraryName)) -> ((PackageName, LibraryName), Map Version [a]) -> PackageName forall b c a. (b -> c) -> (a -> b) -> a -> c .((PackageName, LibraryName), Map Version [a]) -> (PackageName, LibraryName) forall a b. (a, b) -> a fst)[((PackageName, LibraryName), Map Version [a])] pkgss ofJust((PackageName, LibraryName) _,Map Version [a] pvers )->[a] -> SearchResult [a] forall a. a -> SearchResult a Unambiguous ([[a]] -> [a] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat(Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elemsMap Version [a] pvers ))Maybe ((PackageName, LibraryName), Map Version [a]) Nothing->[[a]] -> SearchResult [a] forall a. [a] -> SearchResult a Ambiguous ((((PackageName, LibraryName), Map Version [a]) -> [a]) -> [((PackageName, LibraryName), Map Version [a])] -> [[a]] forall a b. (a -> b) -> [a] -> [b] map([[a]] -> [a] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat([[a]] -> [a]) -> (((PackageName, LibraryName), Map Version [a]) -> [[a]]) -> ((PackageName, LibraryName), Map Version [a]) -> [a] forall b c a. (b -> c) -> (a -> b) -> a -> c .Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elems(Map Version [a] -> [[a]]) -> (((PackageName, LibraryName), Map Version [a]) -> Map Version [a]) -> ((PackageName, LibraryName), Map Version [a]) -> [[a]] forall b c a. (b -> c) -> (a -> b) -> a -> c .((PackageName, LibraryName), Map Version [a]) -> Map Version [a] forall a b. (a, b) -> b snd)[((PackageName, LibraryName), Map Version [a])] pkgss )wherelname :: String lname =ShowS lowercaseString name dataSearchResult a =None |Unambiguous a |Ambiguous [a ]-- | Does a case-insensitive substring search by package name.---- That is, all packages that contain the given string in their name.searchByNameSubstring ::PackageIndex a ->String->[a ]searchByNameSubstring :: forall a. PackageIndex a -> String -> [a] searchByNameSubstring PackageIndex a index String searchterm =PackageIndex a -> (String -> Bool) -> [a] forall a. PackageIndex a -> (String -> Bool) -> [a] searchWithPredicate PackageIndex a index (\String n ->String lsearchterm String -> String -> Bool forall a. Eq a => [a] -> [a] -> Bool `isInfixOf`ShowS lowercaseString n )wherelsearchterm :: String lsearchterm =ShowS lowercaseString searchterm -- | @since 3.4.0.0searchWithPredicate ::PackageIndex a ->(String->Bool)->[a ]searchWithPredicate :: forall a. PackageIndex a -> (String -> Bool) -> [a] searchWithPredicate PackageIndex a index String -> Bool predicate =[a pkg |-- Don't match internal packages((PackageName pname ,LibraryName LMainLibName),Map Version [a] pvers )<-Map (PackageName, LibraryName) (Map Version [a]) -> [((PackageName, LibraryName), Map Version [a])] forall k a. Map k a -> [(k, a)] Map.toList(PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) forall a. PackageIndex a -> Map (PackageName, LibraryName) (Map Version [a]) packageIdIndex PackageIndex a index ),String -> Bool predicate (PackageName -> String unPackageNamePackageName pname ),[a] pkgs <-Map Version [a] -> [[a]] forall k a. Map k a -> [a] Map.elemsMap Version [a] pvers ,a pkg <-[a] pkgs ]---- * Special queries---- None of the stuff below depends on the internal representation of the index.---- | Find if there are any cycles in the dependency graph. If there are no-- cycles the result is @[]@.---- This actually computes the strongly connected components. So it gives us a-- list of groups of packages where within each group they all depend on each-- other, directly or indirectly.dependencyCycles ::PackageInstalleda =>PackageIndex a ->[[a ]]dependencyCycles :: forall a. PackageInstalled a => PackageIndex a -> [[a]] dependencyCycles PackageIndex a index =[[a] vs |Graph.CyclicSCC[a] vs <-[(a, UnitId, [UnitId])] -> [SCC a] forall key node. Ord key => [(node, key, [key])] -> [SCC node] Graph.stronglyConnComp[(a, UnitId, [UnitId])] adjacencyList ]whereadjacencyList :: [(a, UnitId, [UnitId])] adjacencyList =[(a pkg ,a -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitIda pkg ,a -> [UnitId] forall pkg. PackageInstalled pkg => pkg -> [UnitId] installedDependsa pkg )|a pkg <-PackageIndex a -> [a] forall a. PackageIndex a -> [a] allPackages PackageIndex a index ]-- | All packages that have immediate dependencies that are not in the index.---- Returns such packages along with the dependencies that they're missing.brokenPackages ::PackageInstalleda =>PackageIndex a ->[(a ,[UnitId])]brokenPackages :: forall a. PackageInstalled a => PackageIndex a -> [(a, [UnitId])] brokenPackages PackageIndex a index =[(a pkg ,[UnitId] missing )|a pkg <-PackageIndex a -> [a] forall a. PackageIndex a -> [a] allPackages PackageIndex a index ,letmissing :: [UnitId] missing =[UnitId pkg' |UnitId pkg' <-a -> [UnitId] forall pkg. PackageInstalled pkg => pkg -> [UnitId] installedDependsa pkg ,Maybe a -> Bool forall a. Maybe a -> Bool isNothing(PackageIndex a -> UnitId -> Maybe a forall a. PackageIndex a -> UnitId -> Maybe a lookupUnitId PackageIndex a index UnitId pkg' )],Bool -> Bool not([UnitId] -> Bool forall a. [a] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null[UnitId] missing )]-- | Tries to take the transitive closure of the package dependencies.---- If the transitive closure is complete then it returns that subset of the-- index. Otherwise it returns the broken packages as in 'brokenPackages'.---- * Note that if the result is @Right []@ it is because at least one of-- the original given 'PackageId's do not occur in the index.dependencyClosure ::InstalledPackageIndex ->[UnitId]->Either(InstalledPackageIndex )[(IPI.InstalledPackageInfo,[UnitId])]dependencyClosure :: PackageIndex InstalledPackageInfo -> [UnitId] -> Either (PackageIndex InstalledPackageInfo) [(InstalledPackageInfo, [UnitId])] dependencyClosure PackageIndex InstalledPackageInfo index [UnitId] pkgids0 =casePackageIndex InstalledPackageInfo -> [UnitId] -> [UnitId] -> (PackageIndex InstalledPackageInfo, [UnitId]) closure PackageIndex InstalledPackageInfo forall a. Monoid a => a mempty[][UnitId] pkgids0 of(PackageIndex InstalledPackageInfo completed ,[])->PackageIndex InstalledPackageInfo -> Either (PackageIndex InstalledPackageInfo) [(InstalledPackageInfo, [UnitId])] forall a b. a -> Either a b LeftPackageIndex InstalledPackageInfo completed (PackageIndex InstalledPackageInfo completed ,[UnitId] _)->[(InstalledPackageInfo, [UnitId])] -> Either (PackageIndex InstalledPackageInfo) [(InstalledPackageInfo, [UnitId])] forall a b. b -> Either a b Right(PackageIndex InstalledPackageInfo -> [(InstalledPackageInfo, [UnitId])] forall a. PackageInstalled a => PackageIndex a -> [(a, [UnitId])] brokenPackages PackageIndex InstalledPackageInfo completed )whereclosure :: PackageIndex InstalledPackageInfo -> [UnitId] -> [UnitId] -> (PackageIndex InstalledPackageInfo, [UnitId]) closure PackageIndex InstalledPackageInfo completed [UnitId] failed []=(PackageIndex InstalledPackageInfo completed ,[UnitId] failed )closure PackageIndex InstalledPackageInfo completed [UnitId] failed (UnitId pkgid :[UnitId] pkgids )=casePackageIndex InstalledPackageInfo -> UnitId -> Maybe InstalledPackageInfo forall a. PackageIndex a -> UnitId -> Maybe a lookupUnitId PackageIndex InstalledPackageInfo index UnitId pkgid ofMaybe InstalledPackageInfo Nothing->PackageIndex InstalledPackageInfo -> [UnitId] -> [UnitId] -> (PackageIndex InstalledPackageInfo, [UnitId]) closure PackageIndex InstalledPackageInfo completed (UnitId pkgid UnitId -> [UnitId] -> [UnitId] forall a. a -> [a] -> [a] :[UnitId] failed )[UnitId] pkgids JustInstalledPackageInfo pkg ->casePackageIndex InstalledPackageInfo -> UnitId -> Maybe InstalledPackageInfo forall a. PackageIndex a -> UnitId -> Maybe a lookupUnitId PackageIndex InstalledPackageInfo completed (InstalledPackageInfo -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitIdInstalledPackageInfo pkg )ofJustInstalledPackageInfo _->PackageIndex InstalledPackageInfo -> [UnitId] -> [UnitId] -> (PackageIndex InstalledPackageInfo, [UnitId]) closure PackageIndex InstalledPackageInfo completed [UnitId] failed [UnitId] pkgids Maybe InstalledPackageInfo Nothing->PackageIndex InstalledPackageInfo -> [UnitId] -> [UnitId] -> (PackageIndex InstalledPackageInfo, [UnitId]) closure PackageIndex InstalledPackageInfo completed' [UnitId] failed [UnitId] pkgids' wherecompleted' :: PackageIndex InstalledPackageInfo completed' =InstalledPackageInfo -> PackageIndex InstalledPackageInfo -> PackageIndex InstalledPackageInfo insert InstalledPackageInfo pkg PackageIndex InstalledPackageInfo completed pkgids' :: [UnitId] pkgids' =InstalledPackageInfo -> [UnitId] forall pkg. PackageInstalled pkg => pkg -> [UnitId] installedDependsInstalledPackageInfo pkg [UnitId] -> [UnitId] -> [UnitId] forall a. [a] -> [a] -> [a] ++[UnitId] pkgids -- | Takes the transitive closure of the packages reverse dependencies.---- * The given 'PackageId's must be in the index.reverseDependencyClosure ::PackageInstalleda =>PackageIndex a ->[UnitId]->[a ]reverseDependencyClosure :: forall a. PackageInstalled a => PackageIndex a -> [UnitId] -> [a] reverseDependencyClosure PackageIndex a index =(Int -> a) -> [Int] -> [a] forall a b. (a -> b) -> [a] -> [b] mapInt -> a vertexToPkg ([Int] -> [a]) -> ([UnitId] -> [Int]) -> [UnitId] -> [a] forall b c a. (b -> c) -> (a -> b) -> a -> c .(Tree Int -> [Int]) -> [Tree Int] -> [Int] forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b] concatMapTree Int -> [Int] forall a. Tree a -> [a] Tree.flatten([Tree Int] -> [Int]) -> ([UnitId] -> [Tree Int]) -> [UnitId] -> [Int] forall b c a. (b -> c) -> (a -> b) -> a -> c .Graph -> [Int] -> [Tree Int] Graph.dfsGraph reverseDepGraph ([Int] -> [Tree Int]) -> ([UnitId] -> [Int]) -> [UnitId] -> [Tree Int] forall b c a. (b -> c) -> (a -> b) -> a -> c .(UnitId -> Int) -> [UnitId] -> [Int] forall a b. (a -> b) -> [a] -> [b] map(Int -> Maybe Int -> Int forall a. a -> Maybe a -> a fromMaybeInt forall {a}. a noSuchPkgId (Maybe Int -> Int) -> (UnitId -> Maybe Int) -> UnitId -> Int forall b c a. (b -> c) -> (a -> b) -> a -> c .UnitId -> Maybe Int pkgIdToVertex )where(Graph depGraph ,Int -> a vertexToPkg ,UnitId -> Maybe Int pkgIdToVertex )=PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) forall a. PackageInstalled a => PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) dependencyGraph PackageIndex a index reverseDepGraph :: Graph reverseDepGraph =Graph -> Graph Graph.transposeGGraph depGraph noSuchPkgId :: a noSuchPkgId =String -> a forall a. HasCallStack => String -> a errorString "reverseDependencyClosure: package is not in the graph"topologicalOrder ::PackageInstalleda =>PackageIndex a ->[a ]topologicalOrder :: forall a. PackageInstalled a => PackageIndex a -> [a] topologicalOrder PackageIndex a index =(Int -> a) -> [Int] -> [a] forall a b. (a -> b) -> [a] -> [b] mapInt -> a toPkgId ([Int] -> [a]) -> (Graph -> [Int]) -> Graph -> [a] forall b c a. (b -> c) -> (a -> b) -> a -> c .Graph -> [Int] Graph.topSort(Graph -> [a]) -> Graph -> [a] forall a b. (a -> b) -> a -> b $Graph graph where(Graph graph ,Int -> a toPkgId ,UnitId -> Maybe Int _)=PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) forall a. PackageInstalled a => PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) dependencyGraph PackageIndex a index reverseTopologicalOrder ::PackageInstalleda =>PackageIndex a ->[a ]reverseTopologicalOrder :: forall a. PackageInstalled a => PackageIndex a -> [a] reverseTopologicalOrder PackageIndex a index =(Int -> a) -> [Int] -> [a] forall a b. (a -> b) -> [a] -> [b] mapInt -> a toPkgId ([Int] -> [a]) -> (Graph -> [Int]) -> Graph -> [a] forall b c a. (b -> c) -> (a -> b) -> a -> c .Graph -> [Int] Graph.topSort(Graph -> [Int]) -> (Graph -> Graph) -> Graph -> [Int] forall b c a. (b -> c) -> (a -> b) -> a -> c .Graph -> Graph Graph.transposeG(Graph -> [a]) -> Graph -> [a] forall a b. (a -> b) -> a -> b $Graph graph where(Graph graph ,Int -> a toPkgId ,UnitId -> Maybe Int _)=PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) forall a. PackageInstalled a => PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) dependencyGraph PackageIndex a index -- | Builds a graph of the package dependencies.---- Dependencies on other packages that are not in the index are discarded.-- You can check if there are any such dependencies with 'brokenPackages'.dependencyGraph ::PackageInstalleda =>PackageIndex a ->(Graph.Graph,Graph.Vertex->a ,UnitId->MaybeGraph.Vertex)dependencyGraph :: forall a. PackageInstalled a => PackageIndex a -> (Graph, Int -> a, UnitId -> Maybe Int) dependencyGraph PackageIndex a index =(Graph graph ,Int -> a vertex_to_pkg ,UnitId -> Maybe Int id_to_vertex )wheregraph :: Graph graph =(Int, Int) -> [[Int]] -> Graph forall i e. Ix i => (i, i) -> [e] -> Array i e Array.listArray(Int, Int) bounds [[Int v |JustInt v <-(UnitId -> Maybe Int) -> [UnitId] -> [Maybe Int] forall a b. (a -> b) -> [a] -> [b] mapUnitId -> Maybe Int id_to_vertex (a -> [UnitId] forall pkg. PackageInstalled pkg => pkg -> [UnitId] installedDependsa pkg )]|a pkg <-[a] pkgs ]pkgs :: [a] pkgs =(a -> a -> Ordering) -> [a] -> [a] forall a. (a -> a -> Ordering) -> [a] -> [a] sortBy((a -> PackageId) -> a -> a -> Ordering forall a b. Ord a => (b -> a) -> b -> b -> Ordering comparinga -> PackageId forall pkg. Package pkg => pkg -> PackageId packageId)(PackageIndex a -> [a] forall a. PackageIndex a -> [a] allPackages PackageIndex a index )vertices :: [(UnitId, Int)] vertices =[UnitId] -> [Int] -> [(UnitId, Int)] forall a b. [a] -> [b] -> [(a, b)] zip((a -> UnitId) -> [a] -> [UnitId] forall a b. (a -> b) -> [a] -> [b] mapa -> UnitId forall pkg. HasUnitId pkg => pkg -> UnitId installedUnitId[a] pkgs )[Int 0..]vertex_map :: Map UnitId Int vertex_map =[(UnitId, Int)] -> Map UnitId Int forall k a. Ord k => [(k, a)] -> Map k a Map.fromList[(UnitId, Int)] vertices id_to_vertex :: UnitId -> Maybe Int id_to_vertex UnitId pid =UnitId -> Map UnitId Int -> Maybe Int forall k a. Ord k => k -> Map k a -> Maybe a Map.lookupUnitId pid Map UnitId Int vertex_map vertex_to_pkg :: Int -> a vertex_to_pkg Int vertex =Array Int a pkgTable Array Int a -> Int -> a forall i e. Ix i => Array i e -> i -> e !Int vertex pkgTable :: Array Int a pkgTable =(Int, Int) -> [a] -> Array Int a forall i e. Ix i => (i, i) -> [e] -> Array i e Array.listArray(Int, Int) bounds [a] pkgs topBound :: Int topBound =[a] -> Int forall a. [a] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length[a] pkgs Int -> Int -> Int forall a. Num a => a -> a -> a -Int 1bounds :: (Int, Int) bounds =(Int 0,Int topBound )-- | We maintain the invariant that, for any 'DepUniqueKey', there-- is only one instance of the package in our database.typeDepUniqueKey =(PackageName,LibraryName,MapModuleNameOpenModule)-- | Given a package index where we assume we want to use all the packages-- (use 'dependencyClosure' if you need to get such a index subset) find out-- if the dependencies within it use consistent versions of each package.-- Return all cases where multiple packages depend on different versions of-- some other package.---- Each element in the result is a package name along with the packages that-- depend on it and the versions they require. These are guaranteed to be-- distinct.dependencyInconsistencies ::InstalledPackageIndex -- At DepUniqueKey...->[(DepUniqueKey ,-- There were multiple packages (BAD!)[(UnitId,-- And here are the packages which-- immediately depended on it[IPI.InstalledPackageInfo])])]dependencyInconsistencies :: PackageIndex InstalledPackageInfo -> [(DepUniqueKey, [(UnitId, [InstalledPackageInfo])])] dependencyInconsistencies PackageIndex InstalledPackageInfo index =do(DepUniqueKey dep_key ,Map UnitId [InstalledPackageInfo] insts_map )<-Map DepUniqueKey (Map UnitId [InstalledPackageInfo]) -> [(DepUniqueKey, Map UnitId [InstalledPackageInfo])] forall k a. Map k a -> [(k, a)] Map.toListMap DepUniqueKey (Map UnitId [InstalledPackageInfo]) inverseIndex letinsts :: [(UnitId, [InstalledPackageInfo])] insts =Map UnitId [InstalledPackageInfo] -> [(UnitId, [InstalledPackageInfo])] forall k a. Map k a -> [(k, a)] Map.toListMap UnitId [InstalledPackageInfo] insts_map Bool -> [()] forall (f :: * -> *). Alternative f => Bool -> f () guard([(UnitId, [InstalledPackageInfo])] -> Int forall a. [a] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length[(UnitId, [InstalledPackageInfo])] insts Int -> Int -> Bool forall a. Ord a => a -> a -> Bool >=Int 2)(DepUniqueKey, [(UnitId, [InstalledPackageInfo])]) -> [(DepUniqueKey, [(UnitId, [InstalledPackageInfo])])] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return(DepUniqueKey dep_key ,[(UnitId, [InstalledPackageInfo])] insts )whereinverseIndex ::MapDepUniqueKey (MapUnitId[IPI.InstalledPackageInfo])inverseIndex :: Map DepUniqueKey (Map UnitId [InstalledPackageInfo]) inverseIndex =(Map UnitId [InstalledPackageInfo] -> Map UnitId [InstalledPackageInfo] -> Map UnitId [InstalledPackageInfo]) -> [(DepUniqueKey, Map UnitId [InstalledPackageInfo])] -> Map DepUniqueKey (Map UnitId [InstalledPackageInfo]) forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a Map.fromListWith(([InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo]) -> Map UnitId [InstalledPackageInfo] -> Map UnitId [InstalledPackageInfo] -> Map UnitId [InstalledPackageInfo] forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a Map.unionWith[InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. [a] -> [a] -> [a] (++))([(DepUniqueKey, Map UnitId [InstalledPackageInfo])] -> Map DepUniqueKey (Map UnitId [InstalledPackageInfo])) -> [(DepUniqueKey, Map UnitId [InstalledPackageInfo])] -> Map DepUniqueKey (Map UnitId [InstalledPackageInfo]) forall a b. (a -> b) -> a -> b $doInstalledPackageInfo pkg <-PackageIndex InstalledPackageInfo -> [InstalledPackageInfo] forall a. PackageIndex a -> [a] allPackages PackageIndex InstalledPackageInfo index UnitId dep_ipid <-InstalledPackageInfo -> [UnitId] forall pkg. PackageInstalled pkg => pkg -> [UnitId] installedDependsInstalledPackageInfo pkg JustInstalledPackageInfo dep <-[PackageIndex InstalledPackageInfo -> UnitId -> Maybe InstalledPackageInfo forall a. PackageIndex a -> UnitId -> Maybe a lookupUnitId PackageIndex InstalledPackageInfo index UnitId dep_ipid ]letdep_key :: DepUniqueKey dep_key =(InstalledPackageInfo -> PackageName forall pkg. Package pkg => pkg -> PackageName packageNameInstalledPackageInfo dep ,InstalledPackageInfo -> LibraryName IPI.sourceLibNameInstalledPackageInfo dep ,[(ModuleName, OpenModule)] -> Map ModuleName OpenModule forall k a. Ord k => [(k, a)] -> Map k a Map.fromList(InstalledPackageInfo -> [(ModuleName, OpenModule)] IPI.instantiatedWithInstalledPackageInfo dep ))(DepUniqueKey, Map UnitId [InstalledPackageInfo]) -> [(DepUniqueKey, Map UnitId [InstalledPackageInfo])] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return(DepUniqueKey dep_key ,UnitId -> [InstalledPackageInfo] -> Map UnitId [InstalledPackageInfo] forall k a. k -> a -> Map k a Map.singletonUnitId dep_ipid [InstalledPackageInfo pkg ])-- | A rough approximation of GHC's module finder, takes a-- 'InstalledPackageIndex' and turns it into a map from module names to their-- source packages. It's used to initialize the @build-deps@ field in @cabal-- init@.moduleNameIndex ::InstalledPackageIndex ->MapModuleName[IPI.InstalledPackageInfo]moduleNameIndex :: PackageIndex InstalledPackageInfo -> Map ModuleName [InstalledPackageInfo] moduleNameIndex PackageIndex InstalledPackageInfo index =([InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo]) -> [(ModuleName, [InstalledPackageInfo])] -> Map ModuleName [InstalledPackageInfo] forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a Map.fromListWith[InstalledPackageInfo] -> [InstalledPackageInfo] -> [InstalledPackageInfo] forall a. [a] -> [a] -> [a] (++)([(ModuleName, [InstalledPackageInfo])] -> Map ModuleName [InstalledPackageInfo]) -> [(ModuleName, [InstalledPackageInfo])] -> Map ModuleName [InstalledPackageInfo] forall a b. (a -> b) -> a -> b $doInstalledPackageInfo pkg <-PackageIndex InstalledPackageInfo -> [InstalledPackageInfo] forall a. PackageIndex a -> [a] allPackages PackageIndex InstalledPackageInfo index IPI.ExposedModuleModuleName m Maybe OpenModule reexport <-InstalledPackageInfo -> [ExposedModule] IPI.exposedModulesInstalledPackageInfo pkg caseMaybe OpenModule reexport ofMaybe OpenModule Nothing->(ModuleName, [InstalledPackageInfo]) -> [(ModuleName, [InstalledPackageInfo])] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return(ModuleName m ,[InstalledPackageInfo pkg ])Just(OpenModuleVarModuleName _)->[]Just(OpenModuleOpenUnitId _ModuleName m' )|ModuleName m ModuleName -> ModuleName -> Bool forall a. Eq a => a -> a -> Bool ==ModuleName m' ->[]|Bool otherwise->(ModuleName, [InstalledPackageInfo]) -> [(ModuleName, [InstalledPackageInfo])] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return(ModuleName m' ,[InstalledPackageInfo pkg ])-- The heuristic is this: we want to prefer the original package-- which originally exported a module. However, if a reexport-- also *renamed* the module (m /= m'), then we have to use the-- downstream package, since the upstream package has the wrong-- module name!