stackage/Stackage/InstallInfo.hs
2013-05-24 06:17:40 +03:00

150 lines
5.6 KiB
Haskell

{-# LANGUAGE RecordWildCards #-}
module Stackage.InstallInfo
( getInstallInfo
, bpPackageList
) where
import Control.Monad (forM_)
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Version (showVersion)
import qualified Distribution.Text
import Distribution.Version (simplifyVersionRange, withinRange)
import Stackage.HaskellPlatform
import Stackage.LoadDatabase
import Stackage.NarrowDatabase
import Stackage.Types
import Stackage.Util
import Stackage.GhcPkg
dropExcluded :: SelectSettings
-> Map PackageName (VersionRange, Maintainer)
-> Map PackageName (VersionRange, Maintainer)
dropExcluded bs m0 =
Set.foldl' (flip Map.delete) m0 (excludedPackages bs)
getInstallInfo :: SelectSettings -> IO InstallInfo
getInstallInfo settings = do
putStrLn "Loading Haskell Platform"
hp <- loadHaskellPlatform settings
core <-
if useGlobalDatabase settings
then do
putStrLn "Loading core packages from global database"
getGlobalPackages
else return $ hpcore hp
let coreMap = Map.unions
$ map (\(PackageIdentifier k v) -> Map.singleton k v)
$ Set.toList core
let allPackages'
| requireHaskellPlatform settings = Map.union (stablePackages settings) $ identsToRanges (hplibs hp)
| otherwise = stablePackages settings
allPackages = dropExcluded settings allPackages'
let totalCore = extraCore settings `Set.union` Set.map (\(PackageIdentifier p _) -> p) core
putStrLn "Loading package database"
pdb <- loadPackageDB settings coreMap totalCore allPackages
putStrLn "Narrowing package database"
final <- narrowPackageDB settings totalCore pdb $ Set.fromList $ Map.toList $ Map.map snd $ allPackages
putStrLn "Printing build plan to build-plan.log"
writeFile "build-plan.log" $ unlines $ map showDep $ Map.toList final
putStrLn "Checking for bad versions"
case checkBadVersions settings coreMap pdb final of
badVersions
| Map.null badVersions -> return ()
| otherwise -> do
forM_ (Map.toList badVersions) $ \(user, badDeps) -> do
putStrLn $ user ++ " cannot use: "
forM_ (Map.toList badDeps) $ \(name, (version, range)) -> do
putStrLn $ concat
[ "- "
, packageVersionString (name, version)
, " -- "
, Distribution.Text.display $ simplifyVersionRange range
]
putStrLn ""
error "Conflicting build plan, exiting"
return InstallInfo
{ iiCore = totalCore
, iiPackages = Map.map biToSPI final
, iiOptionalCore = Map.fromList $ map (\(PackageIdentifier p v) -> (p, v)) $ Set.toList $ hplibs hp
, iiPackageDB = pdb
}
biToSPI :: BuildInfo -> SelectedPackageInfo
biToSPI BuildInfo {..} = SelectedPackageInfo
{ spiVersion = biVersion
, spiMaintainer = biMaintainer
, spiGithubUser = biGithubUser
, spiHasTests = biHasTests
}
showDep :: (PackageName, BuildInfo) -> String
showDep (PackageName name, BuildInfo {..}) =
concat
[ name
, "-"
, showVersion biVersion
, " ("
, unMaintainer biMaintainer
, case biGithubUser of
Nothing -> ""
Just x -> " @" ++ x
, ")"
, ": "
, unwords $ map unP biUsers
]
where
unP (PackageName p) = p
bpPackageList :: BuildPlan -> [String]
bpPackageList = map packageVersionString . Map.toList . Map.map spiVersion . bpPackages
-- | Check for internal mismatches in required and actual package versions.
checkBadVersions :: SelectSettings
-> Map PackageName Version -- ^ core
-> PackageDB
-> Map PackageName BuildInfo
-> Map String (Map PackageName (Version, VersionRange))
checkBadVersions settings core (PackageDB pdb) buildPlan =
Map.unions $ map getBadVersions $ Map.toList $ Map.filterWithKey unexpectedFailure buildPlan
where
unexpectedFailure name _ = name `Set.notMember` expectedFailuresSelect settings
getBadVersions :: (PackageName, BuildInfo) -> Map String (Map PackageName (Version, VersionRange))
getBadVersions (name, bi)
| Map.null badVersions = Map.empty
| otherwise = Map.singleton display badVersions
where
badVersions = Map.unions $ map (uncurry checkPackage) $ Map.toList $ biDeps bi
display = concat
[ packageVersionString (name, biVersion bi)
, " ("
, unMaintainer $ biMaintainer bi
, case Map.lookup name pdb of
Just PackageInfo { piGithubUser = Just gu } -> " @" ++ gu
_ -> ""
, ")"
]
checkPackage :: PackageName -> VersionRange -> Map PackageName (Version, VersionRange)
checkPackage name vr =
case Map.lookup name buildPlan of
Nothing ->
case Map.lookup name core of
-- Might be part of extra-core
Nothing -> Map.empty
Just version
| version `withinRange` vr -> Map.empty
| otherwise -> Map.singleton name (version, vr)
Just bi
| biVersion bi `withinRange` vr -> Map.empty
| otherwise -> Map.singleton name (biVersion bi, vr)