diff --git a/cabal-install/Distribution/Client/BuildReports/Storage.hs b/cabal-install/Distribution/Client/BuildReports/Storage.hs index a4f20de32d50b494953b0a75bff2da5ad749049b..26e4b6e27266e97c5676af464934317bf29dcd7c 100644 --- a/cabal-install/Distribution/Client/BuildReports/Storage.hs +++ b/cabal-install/Distribution/Client/BuildReports/Storage.hs @@ -36,6 +36,8 @@ import Distribution.Package ( PackageId, packageId ) import Distribution.PackageDescription ( FlagAssignment ) +import Distribution.InstalledPackageInfo + ( InstalledPackageInfo ) import Distribution.Simple.InstallDirs ( PathTemplate, fromPathTemplate , initialPathTemplateEnv, substPathTemplate ) @@ -116,7 +118,10 @@ storeLocal cinfo templates reports platform = sequence_ -- * InstallPlan support -- ------------------------------------------------------------ -fromInstallPlan :: InstallPlan -> [(BuildReport, Maybe Repo)] +fromInstallPlan :: InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure + -> [(BuildReport, Maybe Repo)] fromInstallPlan plan = catMaybes . map (fromPlanPackage platform comp) . InstallPlan.toList @@ -125,18 +130,23 @@ fromInstallPlan plan = catMaybes comp = compilerInfoId (InstallPlan.planCompiler plan) fromPlanPackage :: Platform -> CompilerId - -> InstallPlan.PlanPackage + -> InstallPlan.PlanPackage InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure -> Maybe (BuildReport, Maybe Repo) fromPlanPackage (Platform arch os) comp planPackage = case planPackage of - InstallPlan.Installed (ReadyPackage srcPkg flags _ deps) result + InstallPlan.Installed (ReadyPackage (ConfiguredPackage srcPkg flags _ _) deps) + _ result -> Just $ ( BuildReport.new os arch comp - (packageId srcPkg) flags (map packageId (CD.nonSetupDeps deps)) + (packageId srcPkg) flags + (map packageId (CD.nonSetupDeps deps)) (Right result) , extractRepo srcPkg) InstallPlan.Failed (ConfiguredPackage srcPkg flags _ deps) result -> Just $ ( BuildReport.new os arch comp - (packageId srcPkg) flags (map confSrcId (CD.nonSetupDeps deps)) + (packageId srcPkg) flags + (map confSrcId (CD.nonSetupDeps deps)) (Left result) , extractRepo srcPkg ) diff --git a/cabal-install/Distribution/Client/Configure.hs b/cabal-install/Distribution/Client/Configure.hs index b106cb5ee817683834aaf67f3f5cd7137b56a1b8..52557fbf3f2486afaaf58e38864487e8cd822fa2 100644 --- a/cabal-install/Distribution/Client/Configure.hs +++ b/cabal-install/Distribution/Client/Configure.hs @@ -42,6 +42,7 @@ import Distribution.Simple.Setup import Distribution.Simple.PackageIndex (InstalledPackageIndex) import Distribution.Simple.Utils ( defaultPackageDesc ) +import Distribution.InstalledPackageInfo (InstalledPackageInfo) import qualified Distribution.InstalledPackageInfo as Installed import Distribution.Package ( Package(..), InstalledPackageId, packageName @@ -116,7 +117,10 @@ configure verbosity packageDBs repos comp platform conf configureCommand (const configFlags) extraArgs Right installPlan -> case InstallPlan.ready installPlan of - [pkg@(ReadyPackage (SourcePackage _ _ (LocalUnpackedPackage _) _) _ _ _)] -> do + [pkg@(ReadyPackage + (ConfiguredPackage (SourcePackage _ _ (LocalUnpackedPackage _) _) + _ _ _) + _)] -> do configurePackage verbosity (InstallPlan.planPlatform installPlan) (InstallPlan.planCompiler installPlan) @@ -127,7 +131,10 @@ configure verbosity packageDBs repos comp platform conf ++ "one local ready package." where - setupScriptOptions :: InstalledPackageIndex -> Maybe ReadyPackage -> SetupScriptOptions + setupScriptOptions :: InstalledPackageIndex + -> Maybe (ReadyPackage ConfiguredPackage + InstalledPackageInfo) + -> SetupScriptOptions setupScriptOptions = configureSetupScript packageDBs @@ -154,7 +161,8 @@ configureSetupScript :: PackageDBStack -> Maybe Lock -> Bool -> InstalledPackageIndex - -> Maybe ReadyPackage + -> Maybe (ReadyPackage ConfiguredPackage + InstalledPackageInfo) -> SetupScriptOptions configureSetupScript packageDBs comp @@ -206,7 +214,8 @@ configureSetupScript packageDBs explicitSetupDeps :: Maybe [(InstalledPackageId, PackageId)] explicitSetupDeps = do - ReadyPackage (SourcePackage _ gpkg _ _) _ _ deps <- mpkg + ReadyPackage (ConfiguredPackage (SourcePackage _ gpkg _ _) _ _ _) deps + <- mpkg -- Check if there is an explicit setup stanza _buildInfo <- PkgDesc.setupBuildInfo (PkgDesc.packageDescription gpkg) -- Return the setup dependencies computed by the solver @@ -224,7 +233,10 @@ planLocalPackage :: Verbosity -> Compiler -> ConfigFlags -> ConfigExFlags -> InstalledPackageIndex -> SourcePackageDb - -> IO (Progress String String InstallPlan) + -> IO (Progress String String + (InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure)) planLocalPackage verbosity comp platform configFlags configExFlags installedPkgIndex (SourcePackageDb _ packagePrefs) = do pkg <- readPackageDescription verbosity =<< defaultPackageDesc verbosity @@ -290,11 +302,14 @@ configurePackage :: Verbosity -> Platform -> CompilerInfo -> SetupScriptOptions -> ConfigFlags - -> ReadyPackage + -> ReadyPackage ConfiguredPackage InstalledPackageInfo -> [String] -> IO () configurePackage verbosity platform comp scriptOptions configFlags - (ReadyPackage (SourcePackage _ gpkg _ _) flags stanzas deps) extraArgs = + (ReadyPackage (ConfiguredPackage (SourcePackage _ gpkg _ _) + flags stanzas _) + deps) + extraArgs = setupWrapper verbosity scriptOptions (Just pkg) configureCommand configureFlags extraArgs diff --git a/cabal-install/Distribution/Client/Dependency.hs b/cabal-install/Distribution/Client/Dependency.hs index 6c431e5e395cccddbfeb05663cba9b2fc8185470..514e8fe869a433261d9bf2e1fd48931cb94f1113 100644 --- a/cabal-install/Distribution/Client/Dependency.hs +++ b/cabal-install/Distribution/Client/Dependency.hs @@ -83,6 +83,8 @@ import Distribution.Client.Targets import Distribution.Client.ComponentDeps (ComponentDeps) import qualified Distribution.Client.ComponentDeps as CD import qualified Distribution.InstalledPackageInfo as Installed +import Distribution.InstalledPackageInfo + ( InstalledPackageInfo ) import Distribution.Package ( PackageName(..), PackageIdentifier(PackageIdentifier), PackageId , Package(..), packageName, packageVersion @@ -523,7 +525,10 @@ resolveDependencies :: Platform -> CompilerInfo -> Solver -> DepResolverParams - -> Progress String String InstallPlan + -> Progress String String + (InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure) --TODO: is this needed here? see dontUpgradeNonUpgradeablePackages resolveDependencies platform comp _solver params @@ -608,7 +613,9 @@ validateSolverResult :: Platform -> CompilerInfo -> Bool -> [ResolverPackage] - -> InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure validateSolverResult platform comp indepGoals pkgs = case planPackagesProblems platform comp pkgs of [] -> case InstallPlan.new platform comp indepGoals index of diff --git a/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs b/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs index 01e2be67e716a0b24e3a57215f3c4cea728418a1..d0988c8e37badc89b5b19776e0c4c52ef99794a1 100644 --- a/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs +++ b/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs @@ -14,8 +14,7 @@ module Distribution.Client.Dependency.TopDown.Types where import Distribution.Client.Types - ( SourcePackage(..), ReadyPackage(..) - , ConfiguredPackage(..) + ( SourcePackage(..), ConfiguredPackage(..) , OptionalStanza, ConfiguredId(..) ) import Distribution.InstalledPackageInfo ( InstalledPackageInfo ) @@ -135,9 +134,6 @@ instance PackageSourceDeps InstalledPackageEx where instance PackageSourceDeps ConfiguredPackage where sourceDeps (ConfiguredPackage _ _ _ deps) = map confSrcId $ CD.nonSetupDeps deps -instance PackageSourceDeps ReadyPackage where - sourceDeps (ReadyPackage _ _ _ deps) = map packageId $ CD.nonSetupDeps deps - instance PackageSourceDeps InstalledPackage where sourceDeps (InstalledPackage _ deps) = deps diff --git a/cabal-install/Distribution/Client/Fetch.hs b/cabal-install/Distribution/Client/Fetch.hs index ecfe204667e51530958e51f5a8a3d9abb3277c4a..541e33d60baa082050705eb5ea27e56225888e9a 100644 --- a/cabal-install/Distribution/Client/Fetch.hs +++ b/cabal-install/Distribution/Client/Fetch.hs @@ -139,7 +139,7 @@ planPackages verbosity comp platform fetchFlags -- that are in the 'InstallPlan.Configured' state. return [ pkg - | (InstallPlan.Configured (InstallPlan.ConfiguredPackage pkg _ _ _)) + | (InstallPlan.Configured (ConfiguredPackage pkg _ _ _)) <- InstallPlan.toList installPlan ] | otherwise = diff --git a/cabal-install/Distribution/Client/Freeze.hs b/cabal-install/Distribution/Client/Freeze.hs index f38512dbd59c618e76727e4c97a4c9fe15b51ca8..d75a2c07c44f5b95c3e92179ef487cf016592755 100644 --- a/cabal-install/Distribution/Client/Freeze.hs +++ b/cabal-install/Distribution/Client/Freeze.hs @@ -23,7 +23,7 @@ import Distribution.Client.Dependency import Distribution.Client.IndexUtils as IndexUtils ( getSourcePackages, getInstalledPackages ) import Distribution.Client.InstallPlan - ( PlanPackage ) + ( InstallPlan, PlanPackage ) import qualified Distribution.Client.InstallPlan as InstallPlan import Distribution.Client.Setup ( GlobalFlags(..), FreezeFlags(..), ConfigExFlags(..) ) @@ -36,7 +36,10 @@ import Distribution.Client.Sandbox.Types ( SandboxPackageInfo(..) ) import Distribution.Package - ( Package, packageId, packageName, packageVersion ) + ( Package, packageId, packageName, packageVersion + , HasInstalledPackageId ) +import Distribution.InstalledPackageInfo + ( InstalledPackageInfo ) import Distribution.Simple.Compiler ( Compiler, compilerInfo, PackageDBStack ) import Distribution.Simple.PackageIndex (InstalledPackageIndex) @@ -130,7 +133,9 @@ planPackages :: Verbosity -> InstalledPackageIndex -> SourcePackageDb -> [PackageSpecifier SourcePackage] - -> IO [PlanPackage] + -> IO [PlanPackage InstalledPackageInfo + ConfiguredPackage + iresult ifailure] planPackages verbosity comp platform mSandboxPkgInfo freezeFlags installedPkgIndex sourcePkgDb pkgSpecifiers = do @@ -193,9 +198,11 @@ planPackages verbosity comp platform mSandboxPkgInfo freezeFlags -- 2) not a dependency (directly or transitively) of the package we are -- freezing. This is useful for removing previously installed packages -- which are no longer required from the install plan. -pruneInstallPlan :: InstallPlan.InstallPlan +pruneInstallPlan :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => InstallPlan ipkg srcpkg iresult ifailure -> [PackageSpecifier SourcePackage] - -> [PlanPackage] + -> [PlanPackage ipkg srcpkg iresult ifailure] pruneInstallPlan installPlan pkgSpecifiers = either (const brokenPkgsErr) (removeSelf pkgIds . PackageIndex.allPackages) $ diff --git a/cabal-install/Distribution/Client/Install.hs b/cabal-install/Distribution/Client/Install.hs index 68fa7303ad576d1d214b79b09cc07005099fba1b..9942946b8c170800eb6996a43c1dbd5e039ed3b1 100644 --- a/cabal-install/Distribution/Client/Install.hs +++ b/cabal-install/Distribution/Client/Install.hs @@ -136,13 +136,17 @@ import Distribution.Simple.InstallDirs as InstallDirs import Distribution.Package ( PackageIdentifier(..), PackageId, packageName, packageVersion , Package(..), LibraryName - , Dependency(..), thisPackageVersion, InstalledPackageId, installedPackageId ) + , Dependency(..), thisPackageVersion + , InstalledPackageId, installedPackageId + , HasInstalledPackageId(..) ) import qualified Distribution.PackageDescription as PackageDescription import Distribution.PackageDescription ( PackageDescription, GenericPackageDescription(..), Flag(..) , FlagName(..), FlagAssignment ) import Distribution.PackageDescription.Configuration ( finalizePackageDescription ) +import Distribution.InstalledPackageInfo + ( InstalledPackageInfo ) import Distribution.ParseUtils ( showPWarning ) import Distribution.Version @@ -279,7 +283,10 @@ makeInstallContext verbosity -- | Make an install plan given install context and install arguments. makeInstallPlan :: Verbosity -> InstallArgs -> InstallContext - -> IO (Progress String String InstallPlan) + -> IO (Progress String String + (InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure)) makeInstallPlan verbosity (_, _, comp, platform, _, _, mSandboxPkgInfo, _, configFlags, configExFlags, installFlags, @@ -296,13 +303,15 @@ makeInstallPlan verbosity -- | Given an install plan, perform the actual installations. processInstallPlan :: Verbosity -> InstallArgs -> InstallContext - -> InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure -> IO () processInstallPlan verbosity - args@(_,_, comp, _, _, _, _, _, _, _, installFlags, _) + args@(_,_, _, _, _, _, _, _, _, _, installFlags, _) (installedPkgIndex, sourcePkgDb, userTargets, pkgSpecifiers, _) installPlan = do - checkPrintPlan verbosity comp installedPkgIndex installPlan sourcePkgDb + checkPrintPlan verbosity installedPkgIndex installPlan sourcePkgDb installFlags pkgSpecifiers unless (dryRun || nothingToInstall) $ do @@ -327,7 +336,10 @@ planPackages :: Compiler -> InstalledPackageIndex -> SourcePackageDb -> [PackageSpecifier SourcePackage] - -> Progress String String InstallPlan + -> Progress String String + (InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure) planPackages comp platform mSandboxPkgInfo solver configFlags configExFlags installFlags installedPkgIndex sourcePkgDb pkgSpecifiers = @@ -407,8 +419,13 @@ planPackages comp platform mSandboxPkgInfo solver allowNewer = fromFlag (configAllowNewer configExFlags) -- | Remove the provided targets from the install plan. -pruneInstallPlan :: Package pkg => [PackageSpecifier pkg] -> InstallPlan - -> Progress String String InstallPlan +pruneInstallPlan :: (Package targetpkg, Package srcpkg, Package ipkg, + PackageFixedDeps srcpkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, HasInstalledPackageId ipkg) + => [PackageSpecifier targetpkg] + -> InstallPlan ipkg srcpkg iresult ifailure + -> Progress String String + (InstallPlan ipkg srcpkg iresult ifailure) pruneInstallPlan pkgSpecifiers = -- TODO: this is a general feature and should be moved to D.C.Dependency -- Also, the InstallPlan.remove should return info more precise to the @@ -416,7 +433,7 @@ pruneInstallPlan pkgSpecifiers = either (Fail . explain) Done . InstallPlan.remove (\pkg -> packageName pkg `elem` targetnames) where - explain :: [InstallPlan.PlanProblem] -> String + explain :: [InstallPlan.PlanProblem ipkg srcpkg iresult ifailure] -> String explain problems = "Cannot select only the dependencies (as requested by the " ++ "'--only-dependencies' flag), " @@ -441,14 +458,15 @@ pruneInstallPlan pkgSpecifiers = -- | Perform post-solver checks of the install plan and print it if -- either requested or needed. checkPrintPlan :: Verbosity - -> Compiler -> InstalledPackageIndex - -> InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess ifailure -> SourcePackageDb -> InstallFlags -> [PackageSpecifier SourcePackage] -> IO () -checkPrintPlan verbosity comp installed installPlan sourcePkgDb +checkPrintPlan verbosity installed installPlan sourcePkgDb installFlags pkgSpecifiers = do -- User targets that are already installed. @@ -465,7 +483,7 @@ checkPrintPlan verbosity comp installed installPlan sourcePkgDb : map (display . packageId) preExistingTargets ++ ["Use --reinstall if you want to reinstall anyway."] - let lPlan = linearizeInstallPlan comp installed installPlan + let lPlan = linearizeInstallPlan installed installPlan -- Are any packages classified as reinstalls? let reinstalledPkgs = concatMap (extractReinstalls . snd) lPlan -- Packages that are already broken. @@ -533,11 +551,13 @@ checkPrintPlan verbosity comp installed installPlan sourcePkgDb dryRun = fromFlag (installDryRun installFlags) overrideReinstall = fromFlag (installOverrideReinstall installFlags) -linearizeInstallPlan :: Compiler - -> InstalledPackageIndex - -> InstallPlan - -> [(ReadyPackage, PackageStatus)] -linearizeInstallPlan comp installedPkgIndex plan = +--TODO: this type is too specific +linearizeInstallPlan :: (PackageFixedDeps srcpkg, HasInstalledPackageId srcpkg) + => InstalledPackageIndex + -> InstallPlan InstalledPackageInfo srcpkg + BuildSuccess ifailure + -> [(ReadyPackage srcpkg InstalledPackageInfo, PackageStatus)] +linearizeInstallPlan installedPkgIndex plan = unfoldr next plan where next plan' = case InstallPlan.ready plan' of @@ -545,12 +565,13 @@ linearizeInstallPlan comp installedPkgIndex plan = (pkg:_) -> Just ((pkg, status), plan'') where pkgid = installedPackageId pkg - status = packageStatus comp installedPkgIndex pkg - plan'' = InstallPlan.completed pkgid - (BuildOk DocsNotTried TestsNotTried - (Just $ Installed.emptyInstalledPackageInfo - { Installed.sourcePackageId = packageId pkg - , Installed.installedPackageId = pkgid })) + status = packageStatus installedPkgIndex pkg + ipkg = Installed.emptyInstalledPackageInfo { + Installed.sourcePackageId = packageId pkg, + Installed.installedPackageId = pkgid + } + plan'' = InstallPlan.completed pkgid (Just ipkg) + (BuildOk DocsNotTried TestsNotTried (Just ipkg)) (InstallPlan.processing [pkg] plan') --FIXME: This is a bit of a hack, -- pretending that each package is installed @@ -567,8 +588,11 @@ extractReinstalls :: PackageStatus -> [InstalledPackageId] extractReinstalls (Reinstall ipids _) = ipids extractReinstalls _ = [] -packageStatus :: Compiler -> InstalledPackageIndex -> ReadyPackage -> PackageStatus -packageStatus _comp installedPkgIndex cpkg = +packageStatus :: (Package srcpkg, HasInstalledPackageId ipkg) + => InstalledPackageIndex + -> ReadyPackage srcpkg ipkg + -> PackageStatus +packageStatus installedPkgIndex cpkg = case PackageIndex.lookupPackageName installedPkgIndex (packageName cpkg) of [] -> NewPackage @@ -580,8 +604,9 @@ packageStatus _comp installedPkgIndex cpkg = where - changes :: Installed.InstalledPackageInfo - -> ReadyPackage + changes :: (Package srcpkg, HasInstalledPackageId ipkg) + => Installed.InstalledPackageInfo + -> ReadyPackage srcpkg ipkg -> [MergeResult PackageIdentifier PackageIdentifier] changes pkg pkg' = filter changed $ mergeBy (comparing packageName) @@ -602,7 +627,7 @@ packageStatus _comp installedPkgIndex cpkg = printPlan :: Bool -- is dry run -> Verbosity - -> [(ReadyPackage, PackageStatus)] + -> [(ReadyPackage ConfiguredPackage ipkg, PackageStatus)] -> SourcePackageDb -> IO () printPlan dryRun verbosity plan sourcePkgDb = case plan of @@ -622,7 +647,7 @@ printPlan dryRun verbosity plan sourcePkgDb = case plan of showPkg (pkg, _) = display (packageId pkg) ++ showLatest (pkg) - showPkgAndReason (pkg', pr) = display (packageId pkg') ++ + showPkgAndReason (ReadyPackage pkg' _, pr) = display (packageId pkg') ++ showLatest pkg' ++ showFlagAssignment (nonDefaultFlags pkg') ++ showStanzas (stanzas pkg') ++ " " ++ @@ -633,7 +658,7 @@ printPlan dryRun verbosity plan sourcePkgDb = case plan of [] -> "" diff -> " changes: " ++ intercalate ", " (map change diff) - showLatest :: ReadyPackage -> String + showLatest :: Package srcpkg => srcpkg -> String showLatest pkg = case mLatestVersion of Just latestVersion -> if packageVersion pkg < latestVersion @@ -651,15 +676,15 @@ printPlan dryRun verbosity plan sourcePkgDb = case plan of toFlagAssignment :: [Flag] -> FlagAssignment toFlagAssignment = map (\ f -> (flagName f, flagDefault f)) - nonDefaultFlags :: ReadyPackage -> FlagAssignment - nonDefaultFlags (ReadyPackage spkg fa _ _) = + nonDefaultFlags :: ConfiguredPackage -> FlagAssignment + nonDefaultFlags (ConfiguredPackage spkg fa _ _) = let defaultAssignment = toFlagAssignment (genPackageFlags (Source.packageDescription spkg)) in fa \\ defaultAssignment - stanzas :: ReadyPackage -> [OptionalStanza] - stanzas (ReadyPackage _ _ sts _) = sts + stanzas :: ConfiguredPackage -> [OptionalStanza] + stanzas (ConfiguredPackage _ _ sts _) = sts showStanzas :: [OptionalStanza] -> String showStanzas = concatMap ((' ' :) . showStanza) @@ -759,7 +784,9 @@ theSpecifiedPackage pkgSpec = postInstallActions :: Verbosity -> InstallArgs -> [UserTarget] - -> InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure -> IO () postInstallActions verbosity (packageDBs, _, comp, platform, conf, useSandbox, mSandboxPkgInfo @@ -837,7 +864,7 @@ regenerateHaddockIndex :: Verbosity -> UseSandbox -> ConfigFlags -> InstallFlags - -> InstallPlan + -> InstallPlan ipkg srcpkg BuildSuccess ifailure -> IO () regenerateHaddockIndex verbosity packageDBs comp platform conf useSandbox configFlags installFlags installPlan @@ -874,8 +901,8 @@ regenerateHaddockIndex verbosity packageDBs comp platform conf useSandbox normalUserInstall = (UserPackageDB `elem` packageDBs) && all (not . isSpecificPackageDB) packageDBs - installedDocs (InstallPlan.Installed _ (BuildOk DocsOk _ _)) = True - installedDocs _ = False + installedDocs (InstallPlan.Installed _ _ (BuildOk DocsOk _ _)) = True + installedDocs _ = False isSpecificPackageDB (SpecificPackageDB _) = True isSpecificPackageDB _ = False @@ -896,7 +923,10 @@ symlinkBinaries :: Verbosity -> Compiler -> ConfigFlags -> InstallFlags - -> InstallPlan -> IO () + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure + -> IO () symlinkBinaries verbosity comp configFlags installFlags plan = do failed <- InstallSymlink.symlinkBinaries comp configFlags installFlags plan case failed of @@ -920,7 +950,9 @@ symlinkBinaries verbosity comp configFlags installFlags plan = do bindir = fromFlag (installSymlinkBinDir installFlags) -printBuildFailures :: InstallPlan -> IO () +printBuildFailures :: Package srcpkg + => InstallPlan ipkg srcpkg iresult BuildFailure + -> IO () printBuildFailures plan = case [ (pkg, reason) | InstallPlan.Failed pkg reason <- InstallPlan.toList plan ] of @@ -964,15 +996,18 @@ printBuildFailures plan = -- | If we're working inside a sandbox and some add-source deps were installed, -- update the timestamps of those deps. updateSandboxTimestampsFile :: UseSandbox -> Maybe SandboxPackageInfo - -> Compiler -> Platform -> InstallPlan + -> Compiler -> Platform + -> InstallPlan ipkg ConfiguredPackage + iresult ifailure -> IO () updateSandboxTimestampsFile (UseSandbox sandboxDir) (Just (SandboxPackageInfo _ _ _ allAddSourceDeps)) comp platform installPlan = withUpdateTimestamps sandboxDir (compilerId comp) platform $ \_ -> do - let allInstalled = [ pkg | InstallPlan.Installed pkg _ + let allInstalled = [ pkg | InstallPlan.Installed pkg _ _ <- InstallPlan.toList installPlan ] - allSrcPkgs = [ pkg | ReadyPackage pkg _ _ _ <- allInstalled ] + allSrcPkgs = [ pkg | ReadyPackage (ConfiguredPackage pkg _ _ _) _ + <- allInstalled ] allPaths = [ pth | LocalUnpackedPackage pth <- map packageSource allSrcPkgs] allPathsCanonical <- mapM tryCanonicalizePath allPaths @@ -996,8 +1031,12 @@ type UseLogFile = Maybe (PackageIdentifier -> LibraryName -> FilePath, Verbosity performInstallations :: Verbosity -> InstallArgs -> InstalledPackageIndex - -> InstallPlan - -> IO InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure + -> IO (InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure) performInstallations verbosity (packageDBs, _, comp, _, conf, useSandbox, _, globalFlags, configFlags, configExFlags, installFlags, haddockFlags) @@ -1115,9 +1154,15 @@ executeInstallPlan :: Verbosity -> Compiler -> JobControl IO (PackageId, LibraryName, BuildResult) -> UseLogFile - -> InstallPlan - -> (ReadyPackage -> IO BuildResult) - -> IO InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure + -> (ReadyPackage ConfiguredPackage + InstalledPackageInfo + -> IO BuildResult) + -> IO (InstallPlan InstalledPackageInfo + ConfiguredPackage + BuildSuccess BuildFailure) executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg = tryNewTasks 0 plan0 where @@ -1147,12 +1192,18 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg = plan' = updatePlan pkgid buildResult plan tryNewTasks taskCount' plan' - updatePlan :: PackageIdentifier -> BuildResult -> InstallPlan -> InstallPlan - updatePlan pkgid (Right buildSuccess) = - InstallPlan.completed (Source.fakeInstalledPackageId pkgid) buildSuccess + updatePlan :: PackageIdentifier -> BuildResult + -> InstallPlan InstalledPackageInfo ConfiguredPackage + BuildSuccess BuildFailure + -> InstallPlan InstalledPackageInfo ConfiguredPackage + BuildSuccess BuildFailure + updatePlan pkgid (Right buildSuccess@(BuildOk _ _ mipkg)) = + InstallPlan.completed (Source.fakeInstalledPackageId pkgid) + mipkg buildSuccess updatePlan pkgid (Left buildFailure) = - InstallPlan.failed (Source.fakeInstalledPackageId pkgid) buildFailure depsFailure + InstallPlan.failed (Source.fakeInstalledPackageId pkgid) + buildFailure depsFailure where depsFailure = DependentFailed pkgid -- So this first pkgid failed for whatever reason (buildFailure). @@ -1187,16 +1238,21 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg = -- NB: when updating this function, don't forget to also update -- 'configurePackage' in D.C.Configure. installReadyPackage :: Platform -> CompilerInfo - -> ConfigFlags - -> ReadyPackage - -> (ConfigFlags -> PackageLocation (Maybe FilePath) - -> PackageDescription - -> PackageDescriptionOverride -> a) - -> a + -> ConfigFlags + -> ReadyPackage ConfiguredPackage + InstalledPackageInfo + -> (ConfigFlags -> PackageLocation (Maybe FilePath) + -> PackageDescription + -> PackageDescriptionOverride + -> a) + -> a installReadyPackage platform cinfo configFlags - (ReadyPackage (SourcePackage _ gpkg source pkgoverride) - flags stanzas deps) - installPkg = installPkg configFlags { + (ReadyPackage (ConfiguredPackage + (SourcePackage _ gpkg source pkgoverride) + flags stanzas _) + deps) + installPkg = + installPkg configFlags { configConfigurationsFlags = flags, -- We generate the legacy constraints as well as the new style precise deps. -- In the end only one set gets passed to Setup.hs configure, depending on diff --git a/cabal-install/Distribution/Client/InstallPlan.hs b/cabal-install/Distribution/Client/InstallPlan.hs index 0822ee5a39c47f30d5f21de4c30959c403b74fd4..1f6617329fd6958ff840490b9e6172341fedf2fc 100644 --- a/cabal-install/Distribution/Client/InstallPlan.hs +++ b/cabal-install/Distribution/Client/InstallPlan.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.InstallPlan @@ -13,7 +14,6 @@ ----------------------------------------------------------------------------- module Distribution.Client.InstallPlan ( InstallPlan, - ConfiguredPackage(..), PlanPackage(..), -- * Operations on 'InstallPlan's @@ -46,16 +46,11 @@ module Distribution.Client.InstallPlan ( dependencyClosure, ) where -import Distribution.Client.Types - ( ConfiguredPackage(..) - , ReadyPackage(..), readyPackageToConfiguredPackage - , BuildFailure, BuildSuccess(..) - , PackageFixedDeps(..) - , fakeInstalledPackageId - ) import Distribution.Package ( PackageIdentifier(..), PackageName(..), Package(..) , InstalledPackageId, HasInstalledPackageId(..) ) +import Distribution.Client.Types + ( PackageFixedDeps(..), ReadyPackage(..), fakeInstalledPackageId ) import Distribution.Version ( Version ) import Distribution.Client.ComponentDeps (ComponentDeps) @@ -74,9 +69,6 @@ import Distribution.Compiler ( CompilerInfo(..) ) import Distribution.Simple.Utils ( intercalate ) -import Distribution.InstalledPackageInfo - ( InstalledPackageInfo ) -import qualified Distribution.InstalledPackageInfo as Installed import Data.Maybe ( fromMaybe, maybeToList ) @@ -88,7 +80,6 @@ import Data.Maybe (catMaybes) import qualified Data.Map as Map import qualified Data.Traversable as T -type PlanIndex = PackageIndex PlanPackage -- When cabal tries to install a number of packages, including all their -- dependencies it has a non-trivial problem to solve. @@ -143,50 +134,59 @@ type PlanIndex = PackageIndex PlanPackage -- 'PackageInstalled' instance it would be too easy to get this wrong (and, -- for instance, call graph traversal functions from Cabal rather than from -- cabal-install). Instead, see 'PackageFixedDeps'. -data PlanPackage = PreExisting InstalledPackageInfo - | Configured ConfiguredPackage - | Processing ReadyPackage - | Installed ReadyPackage BuildSuccess - | Failed ConfiguredPackage BuildFailure - -- ^ NB: packages in the Failed state can be *either* Ready - -- or Configured. - -instance Package PlanPackage where - packageId (PreExisting pkg) = packageId pkg - packageId (Configured pkg) = packageId pkg - packageId (Processing pkg) = packageId pkg - packageId (Installed pkg _) = packageId pkg - packageId (Failed pkg _) = packageId pkg - -instance PackageFixedDeps PlanPackage where - depends (PreExisting pkg) = depends pkg - depends (Configured pkg) = depends pkg - depends (Processing pkg) = depends pkg - depends (Installed pkg _) = depends pkg - depends (Failed pkg _) = depends pkg - -instance HasInstalledPackageId PlanPackage where - installedPackageId (PreExisting pkg) = installedPackageId pkg - installedPackageId (Configured pkg) = installedPackageId pkg - installedPackageId (Processing pkg) = installedPackageId pkg +data PlanPackage ipkg srcpkg iresult ifailure + = PreExisting ipkg + | Configured srcpkg + | Processing (ReadyPackage srcpkg ipkg) + | Installed (ReadyPackage srcpkg ipkg) (Maybe ipkg) iresult + | Failed srcpkg ifailure + +instance (Package ipkg, Package srcpkg) => + Package (PlanPackage ipkg srcpkg iresult ifailure) where + packageId (PreExisting ipkg) = packageId ipkg + packageId (Configured spkg) = packageId spkg + packageId (Processing rpkg) = packageId rpkg + packageId (Installed rpkg _ _) = packageId rpkg + packageId (Failed spkg _) = packageId spkg + +instance (PackageFixedDeps srcpkg, + PackageFixedDeps ipkg, HasInstalledPackageId ipkg) => + PackageFixedDeps (PlanPackage ipkg srcpkg iresult ifailure) where + depends (PreExisting pkg) = depends pkg + depends (Configured pkg) = depends pkg + depends (Processing pkg) = depends pkg + depends (Installed pkg _ _) = depends pkg + depends (Failed pkg _) = depends pkg + +instance (HasInstalledPackageId ipkg, HasInstalledPackageId srcpkg) => + HasInstalledPackageId (PlanPackage ipkg srcpkg iresult ifailure) where + installedPackageId (PreExisting ipkg ) = installedPackageId ipkg + installedPackageId (Configured spkg) = installedPackageId spkg + installedPackageId (Processing rpkg) = installedPackageId rpkg -- NB: defer to the actual installed package info in this case - installedPackageId (Installed _ (BuildOk _ _ (Just ipkg))) = installedPackageId ipkg - installedPackageId (Installed pkg _) = installedPackageId pkg - installedPackageId (Failed pkg _) = installedPackageId pkg + installedPackageId (Installed _ (Just ipkg) _) = installedPackageId ipkg + installedPackageId (Installed rpkg _ _) = installedPackageId rpkg + installedPackageId (Failed spkg _) = installedPackageId spkg -data InstallPlan = InstallPlan { - planIndex :: PlanIndex, + +data InstallPlan ipkg srcpkg iresult ifailure = InstallPlan { + planIndex :: (PlanIndex ipkg srcpkg iresult ifailure), planFakeMap :: FakeMap, planGraph :: Graph, planGraphRev :: Graph, - planPkgOf :: Graph.Vertex -> PlanPackage, + planPkgOf :: Graph.Vertex -> PlanPackage ipkg srcpkg iresult ifailure, planVertexOf :: InstalledPackageId -> Graph.Vertex, planPlatform :: Platform, planCompiler :: CompilerInfo, planIndepGoals :: Bool } -invariant :: InstallPlan -> Bool +type PlanIndex ipkg srcpkg iresult ifailure = + PackageIndex (PlanPackage ipkg srcpkg iresult ifailure) + +invariant :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => InstallPlan ipkg srcpkg iresult ifailure -> Bool invariant plan = valid (planFakeMap plan) (planIndepGoals plan) @@ -195,7 +195,8 @@ invariant plan = internalError :: String -> a internalError msg = error $ "InstallPlan: internal error: " ++ msg -showPlanIndex :: PlanIndex -> String +showPlanIndex :: (HasInstalledPackageId ipkg, HasInstalledPackageId srcpkg) + => PlanIndex ipkg srcpkg iresult ifailure -> String showPlanIndex index = intercalate "\n" (map showPlanPackage (PackageIndex.allPackages index)) where showPlanPackage p = @@ -203,23 +204,28 @@ showPlanIndex index = ++ display (packageId p) ++ " (" ++ display (installedPackageId p) ++ ")" -showInstallPlan :: InstallPlan -> String +showInstallPlan :: (HasInstalledPackageId ipkg, HasInstalledPackageId srcpkg) + => InstallPlan ipkg srcpkg iresult ifailure -> String showInstallPlan plan = showPlanIndex (planIndex plan) ++ "\n" ++ "fake map:\n " ++ intercalate "\n " (map showKV (Map.toList (planFakeMap plan))) where showKV (k,v) = display k ++ " -> " ++ display v -showPlanPackageTag :: PlanPackage -> String -showPlanPackageTag (PreExisting _) = "PreExisting" -showPlanPackageTag (Configured _) = "Configured" -showPlanPackageTag (Processing _) = "Processing" -showPlanPackageTag (Installed _ _) = "Installed" -showPlanPackageTag (Failed _ _) = "Failed" +showPlanPackageTag :: PlanPackage ipkg srcpkg iresult ifailure -> String +showPlanPackageTag (PreExisting _) = "PreExisting" +showPlanPackageTag (Configured _) = "Configured" +showPlanPackageTag (Processing _) = "Processing" +showPlanPackageTag (Installed _ _ _) = "Installed" +showPlanPackageTag (Failed _ _) = "Failed" -- | Build an installation plan from a valid set of resolved packages. -- -new :: Platform -> CompilerInfo -> Bool -> PlanIndex - -> Either [PlanProblem] InstallPlan +new :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => Platform -> CompilerInfo -> Bool + -> PlanIndex ipkg srcpkg iresult ifailure + -> Either [PlanProblem ipkg srcpkg iresult ifailure] + (InstallPlan ipkg srcpkg iresult ifailure) new platform cinfo indepGoals index = -- NB: Need to pre-initialize the fake-map with pre-existing -- packages @@ -246,7 +252,8 @@ new platform cinfo indepGoals index = noSuchPkgId = internalError "package is not in the graph" probs -> Left probs -toList :: InstallPlan -> [PlanPackage] +toList :: InstallPlan ipkg srcpkg iresult ifailure + -> [PlanPackage ipkg srcpkg iresult ifailure] toList = PackageIndex.allPackages . planIndex -- | Remove packages from the install plan. This will result in an @@ -255,9 +262,12 @@ toList = PackageIndex.allPackages . planIndex -- the dependencies of a package or set of packages without actually -- installing the package itself, as when doing development. -- -remove :: (PlanPackage -> Bool) - -> InstallPlan - -> Either [PlanProblem] InstallPlan +remove :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => (PlanPackage ipkg srcpkg iresult ifailure -> Bool) + -> InstallPlan ipkg srcpkg iresult ifailure + -> Either [PlanProblem ipkg srcpkg iresult ifailure] + (InstallPlan ipkg srcpkg iresult ifailure) remove shouldRemove plan = new (planPlatform plan) (planCompiler plan) (planIndepGoals plan) newIndex where @@ -268,7 +278,9 @@ remove shouldRemove plan = -- configured state and have all their dependencies installed already. -- The plan is complete if the result is @[]@. -- -ready :: InstallPlan -> [ReadyPackage] +ready :: forall ipkg srcpkg iresult ifailure. PackageFixedDeps srcpkg + => InstallPlan ipkg srcpkg iresult ifailure + -> [ReadyPackage srcpkg ipkg] ready plan = assert check readyPackages where check = if null readyPackages && null processingPackages @@ -277,29 +289,29 @@ ready plan = assert check readyPackages configuredPackages = [ pkg | Configured pkg <- toList plan ] processingPackages = [ pkg | Processing pkg <- toList plan] - readyPackages :: [ReadyPackage] + readyPackages :: [ReadyPackage srcpkg ipkg] readyPackages = - [ ReadyPackage srcPkg flags stanzas deps - | pkg@(ConfiguredPackage srcPkg flags stanzas _) <- configuredPackages + [ ReadyPackage srcpkg deps + | srcpkg <- configuredPackages -- select only the package that have all of their deps installed: - , deps <- maybeToList (hasAllInstalledDeps pkg) + , deps <- maybeToList (hasAllInstalledDeps srcpkg) ] - hasAllInstalledDeps :: ConfiguredPackage -> Maybe (ComponentDeps [Installed.InstalledPackageInfo]) + hasAllInstalledDeps :: srcpkg -> Maybe (ComponentDeps [ipkg]) hasAllInstalledDeps = T.mapM (mapM isInstalledDep) . depends - isInstalledDep :: InstalledPackageId -> Maybe Installed.InstalledPackageInfo + isInstalledDep :: InstalledPackageId -> Maybe ipkg isInstalledDep pkgid = -- NB: Need to check if the ID has been updated in planFakeMap, in which case we -- might be dealing with an old pointer case PlanIndex.fakeLookupInstalledPackageId (planFakeMap plan) (planIndex plan) pkgid of - Just (Configured _) -> Nothing - Just (Processing _) -> Nothing - Just (Failed _ _) -> internalError depOnFailed - Just (PreExisting instPkg) -> Just instPkg - Just (Installed _ (BuildOk _ _ (Just instPkg))) -> Just instPkg - Just (Installed _ (BuildOk _ _ Nothing)) -> internalError depOnNonLib - Nothing -> internalError incomplete + Just (PreExisting ipkg) -> Just ipkg + Just (Configured _) -> Nothing + Just (Processing _) -> Nothing + Just (Installed _ (Just ipkg) _) -> Just ipkg + Just (Installed _ Nothing _) -> internalError depOnNonLib + Just (Failed _ _) -> internalError depOnFailed + Nothing -> internalError incomplete incomplete = "install plan is not closed" depOnFailed = "configured package depends on failed package" depOnNonLib = "configured package depends on a non-library package" @@ -308,7 +320,11 @@ ready plan = assert check readyPackages -- -- * The package must exist in the graph and be in the configured state. -- -processing :: [ReadyPackage] -> InstallPlan -> InstallPlan +processing :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => [ReadyPackage srcpkg ipkg] + -> InstallPlan ipkg srcpkg iresult ifailure + -> InstallPlan ipkg srcpkg iresult ifailure processing pkgs plan = assert (invariant plan') plan' where plan' = plan { @@ -322,15 +338,18 @@ processing pkgs plan = assert (invariant plan') plan' -- * The package must exist in the graph and be in the processing state. -- * The package must have had no uninstalled dependent packages. -- -completed :: InstalledPackageId - -> BuildSuccess - -> InstallPlan -> InstallPlan -completed pkgid buildResult plan = assert (invariant plan') plan' +completed :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => InstalledPackageId + -> Maybe ipkg -> iresult + -> InstallPlan ipkg srcpkg iresult ifailure + -> InstallPlan ipkg srcpkg iresult ifailure +completed pkgid mipkg buildResult plan = assert (invariant plan') plan' where plan' = plan { -- NB: installation can change the IPID, so better -- record it in the fake mapping... - planFakeMap = insert_fake_mapping buildResult + planFakeMap = insert_fake_mapping mipkg $ planFakeMap plan, planIndex = PackageIndex.insert installed . PackageIndex.deleteInstalledPackageId pkgid @@ -338,9 +357,9 @@ completed pkgid buildResult plan = assert (invariant plan') plan' } -- ...but be sure to use the *old* IPID for the lookup for the -- preexisting record - installed = Installed (lookupProcessingPackage plan pkgid) buildResult - insert_fake_mapping (BuildOk _ _ (Just ipi)) = Map.insert pkgid (installedPackageId ipi) - insert_fake_mapping _ = id + installed = Installed (lookupProcessingPackage plan pkgid) mipkg buildResult + insert_fake_mapping (Just ipkg) = Map.insert pkgid (installedPackageId ipkg) + insert_fake_mapping _ = id -- | Marks a package in the graph as having failed. It also marks all the -- packages that depended on it as having failed. @@ -348,28 +367,31 @@ completed pkgid buildResult plan = assert (invariant plan') plan' -- * The package must exist in the graph and be in the processing -- state. -- -failed :: InstalledPackageId -- ^ The id of the package that failed to install - -> BuildFailure -- ^ The build result to use for the failed package - -> BuildFailure -- ^ The build result to use for its dependencies - -> InstallPlan - -> InstallPlan +failed :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => InstalledPackageId -- ^ The id of the package that failed to install + -> ifailure -- ^ The build result to use for the failed package + -> ifailure -- ^ The build result to use for its dependencies + -> InstallPlan ipkg srcpkg iresult ifailure + -> InstallPlan ipkg srcpkg iresult ifailure failed pkgid buildResult buildResult' plan = assert (invariant plan') plan' where -- NB: failures don't update IPIDs plan' = plan { planIndex = PackageIndex.merge (planIndex plan) failures } - pkg = lookupProcessingPackage plan pkgid + ReadyPackage srcpkg _deps = lookupProcessingPackage plan pkgid failures = PackageIndex.fromList - $ Failed (readyPackageToConfiguredPackage pkg) buildResult + $ Failed srcpkg buildResult : [ Failed pkg' buildResult' | Just pkg' <- map checkConfiguredPackage $ packagesThatDependOn plan pkgid ] -- | Lookup the reachable packages in the reverse dependency graph. -- -packagesThatDependOn :: InstallPlan - -> InstalledPackageId -> [PlanPackage] +packagesThatDependOn :: InstallPlan ipkg srcpkg iresult ifailure + -> InstalledPackageId + -> [PlanPackage ipkg srcpkg iresult ifailure] packagesThatDependOn plan pkgid = map (planPkgOf plan) . tail . Graph.reachable (planGraphRev plan) @@ -378,8 +400,9 @@ packagesThatDependOn plan pkgid = map (planPkgOf plan) -- | Lookup a package that we expect to be in the processing state. -- -lookupProcessingPackage :: InstallPlan - -> InstalledPackageId -> ReadyPackage +lookupProcessingPackage :: InstallPlan ipkg srcpkg iresult ifailure + -> InstalledPackageId + -> ReadyPackage srcpkg ipkg lookupProcessingPackage plan pkgid = -- NB: processing packages are guaranteed to not indirect through -- planFakeMap @@ -389,7 +412,9 @@ lookupProcessingPackage plan pkgid = -- | Check a package that we expect to be in the configured or failed state. -- -checkConfiguredPackage :: PlanPackage -> Maybe ConfiguredPackage +checkConfiguredPackage :: (Package srcpkg, Package ipkg) + => PlanPackage ipkg srcpkg iresult ifailure + -> Maybe srcpkg checkConfiguredPackage (Configured pkg) = Just pkg checkConfiguredPackage (Failed _ _) = Nothing checkConfiguredPackage pkg = @@ -405,17 +430,24 @@ checkConfiguredPackage pkg = -- -- * if the result is @False@ use 'problems' to get a detailed list. -- -valid :: FakeMap -> Bool -> PlanIndex -> Bool +valid :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => FakeMap -> Bool + -> PlanIndex ipkg srcpkg iresult ifailure + -> Bool valid fakeMap indepGoals index = null $ problems fakeMap indepGoals index -data PlanProblem = - PackageMissingDeps PlanPackage [PackageIdentifier] - | PackageCycle [PlanPackage] +data PlanProblem ipkg srcpkg iresult ifailure = + PackageMissingDeps (PlanPackage ipkg srcpkg iresult ifailure) + [PackageIdentifier] + | PackageCycle [PlanPackage ipkg srcpkg iresult ifailure] | PackageInconsistency PackageName [(PackageIdentifier, Version)] - | PackageStateInvalid PlanPackage PlanPackage + | PackageStateInvalid (PlanPackage ipkg srcpkg iresult ifailure) + (PlanPackage ipkg srcpkg iresult ifailure) -showPlanProblem :: PlanProblem -> String +showPlanProblem :: (Package ipkg, Package srcpkg) + => PlanProblem ipkg srcpkg iresult ifailure -> String showPlanProblem (PackageMissingDeps pkg missingDeps) = "Package " ++ display (packageId pkg) ++ " depends on the following packages which are missing from the plan: " @@ -440,17 +472,21 @@ showPlanProblem (PackageStateInvalid pkg pkg') = ++ " which is in the " ++ showPlanState pkg' ++ " state" where - showPlanState (PreExisting _) = "pre-existing" - showPlanState (Configured _) = "configured" - showPlanState (Processing _) = "processing" - showPlanState (Installed _ _) = "installed" - showPlanState (Failed _ _) = "failed" + showPlanState (PreExisting _) = "pre-existing" + showPlanState (Configured _) = "configured" + showPlanState (Processing _) = "processing" + showPlanState (Installed _ _ _) = "installed" + showPlanState (Failed _ _) = "failed" -- | For an invalid plan, produce a detailed list of problems as human readable -- error messages. This is mainly intended for debugging purposes. -- Use 'showPlanProblem' for a human readable explanation. -- -problems :: FakeMap -> Bool -> PlanIndex -> [PlanProblem] +problems :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => FakeMap -> Bool + -> PlanIndex ipkg srcpkg iresult ifailure + -> [PlanProblem ipkg srcpkg iresult ifailure] problems fakeMap indepGoals index = [ PackageMissingDeps pkg (catMaybes (map (fmap packageId . PlanIndex.fakeLookupInstalledPackageId fakeMap index) missingDeps)) @@ -472,7 +508,9 @@ problems fakeMap indepGoals index = -- * if the result is @False@ use 'PackageIndex.dependencyCycles' to find out -- which packages are involved in dependency cycles. -- -acyclic :: FakeMap -> PlanIndex -> Bool +acyclic :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => FakeMap -> PlanIndex ipkg srcpkg iresult ifailure -> Bool acyclic fakeMap = null . PlanIndex.dependencyCycles fakeMap -- | An installation plan is closed if for every package in the set, all of @@ -482,7 +520,9 @@ acyclic fakeMap = null . PlanIndex.dependencyCycles fakeMap -- * if the result is @False@ use 'PackageIndex.brokenPackages' to find out -- which packages depend on packages not in the index. -- -closed :: FakeMap -> PlanIndex -> Bool +closed :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + PackageFixedDeps srcpkg) + => FakeMap -> PlanIndex ipkg srcpkg iresult ifailure -> Bool closed fakeMap = null . PlanIndex.brokenPackages fakeMap -- | An installation plan is consistent if all dependencies that target a @@ -501,46 +541,52 @@ closed fakeMap = null . PlanIndex.brokenPackages fakeMap -- * if the result is @False@ use 'PackageIndex.dependencyInconsistencies' to -- find out which packages are. -- -consistent :: FakeMap -> PlanIndex -> Bool +consistent :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => FakeMap -> PlanIndex ipkg srcpkg iresult ifailure -> Bool consistent fakeMap = null . PlanIndex.dependencyInconsistencies fakeMap False -- | The states of packages have that depend on each other must respect -- this relation. That is for very case where package @a@ depends on -- package @b@ we require that @dependencyStatesOk a b = True@. -- -stateDependencyRelation :: PlanPackage -> PlanPackage -> Bool -stateDependencyRelation (PreExisting _) (PreExisting _) = True +stateDependencyRelation :: PlanPackage ipkg srcpkg iresult ifailure + -> PlanPackage ipkg srcpkg iresult ifailure + -> Bool +stateDependencyRelation (PreExisting _) (PreExisting _) = True -stateDependencyRelation (Configured _) (PreExisting _) = True -stateDependencyRelation (Configured _) (Configured _) = True -stateDependencyRelation (Configured _) (Processing _) = True -stateDependencyRelation (Configured _) (Installed _ _) = True +stateDependencyRelation (Configured _) (PreExisting _) = True +stateDependencyRelation (Configured _) (Configured _) = True +stateDependencyRelation (Configured _) (Processing _) = True +stateDependencyRelation (Configured _) (Installed _ _ _) = True -stateDependencyRelation (Processing _) (PreExisting _) = True -stateDependencyRelation (Processing _) (Installed _ _) = True +stateDependencyRelation (Processing _) (PreExisting _) = True +stateDependencyRelation (Processing _) (Installed _ _ _) = True -stateDependencyRelation (Installed _ _) (PreExisting _) = True -stateDependencyRelation (Installed _ _) (Installed _ _) = True +stateDependencyRelation (Installed _ _ _) (PreExisting _) = True +stateDependencyRelation (Installed _ _ _) (Installed _ _ _) = True -stateDependencyRelation (Failed _ _) (PreExisting _) = True +stateDependencyRelation (Failed _ _) (PreExisting _) = True -- failed can depends on configured because a package can depend on -- several other packages and if one of the deps fail then we fail -- but we still depend on the other ones that did not fail: -stateDependencyRelation (Failed _ _) (Configured _) = True -stateDependencyRelation (Failed _ _) (Processing _) = True -stateDependencyRelation (Failed _ _) (Installed _ _) = True -stateDependencyRelation (Failed _ _) (Failed _ _) = True +stateDependencyRelation (Failed _ _) (Configured _) = True +stateDependencyRelation (Failed _ _) (Processing _) = True +stateDependencyRelation (Failed _ _) (Installed _ _ _) = True +stateDependencyRelation (Failed _ _) (Failed _ _) = True -stateDependencyRelation _ _ = False +stateDependencyRelation _ _ = False -- | Compute the dependency closure of a _source_ package in a install plan -- -- See `Distribution.Client.PlanIndex.dependencyClosure` -dependencyClosure :: InstallPlan +dependencyClosure :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg, + HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg) + => InstallPlan ipkg srcpkg iresult ifailure -> [PackageIdentifier] - -> Either [(PlanPackage, [InstalledPackageId])] - (PackageIndex PlanPackage) + -> Either [(PlanPackage ipkg srcpkg iresult ifailure, [InstalledPackageId])] + (PackageIndex (PlanPackage ipkg srcpkg iresult ifailure)) dependencyClosure installPlan pids = PlanIndex.dependencyClosure (planFakeMap installPlan) diff --git a/cabal-install/Distribution/Client/InstallSymlink.hs b/cabal-install/Distribution/Client/InstallSymlink.hs index 6a171986ea786bd3cc8a90eb9fca44cd5b4433c4..71309d1e305ae72bdcab8f8523e7329a32864e26 100644 --- a/cabal-install/Distribution/Client/InstallSymlink.hs +++ b/cabal-install/Distribution/Client/InstallSymlink.hs @@ -27,7 +27,9 @@ import Distribution.Simple.Compiler symlinkBinaries :: Compiler -> ConfigFlags -> InstallFlags - -> InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure -> IO [(PackageIdentifier, String, FilePath)] symlinkBinaries _ _ _ _ = return [] @@ -37,7 +39,8 @@ symlinkBinary _ _ _ _ = fail "Symlinking feature not available on Windows" #else import Distribution.Client.Types - ( SourcePackage(..), ReadyPackage(..), enableStanzas ) + ( SourcePackage(..), ReadyPackage(..), enableStanzas + , ConfiguredPackage(..) ) import Distribution.Client.Setup ( InstallFlags(installSymlinkBinDir) ) import qualified Distribution.Client.InstallPlan as InstallPlan @@ -57,6 +60,8 @@ import Distribution.PackageDescription.Configuration import Distribution.Simple.Setup ( ConfigFlags(..), fromFlag, fromFlagOrDefault, flagToMaybe ) import qualified Distribution.Simple.InstallDirs as InstallDirs +import Distribution.InstalledPackageInfo + ( InstalledPackageInfo ) import qualified Distribution.InstalledPackageInfo as Installed import Distribution.Simple.Compiler ( Compiler, CompilerInfo(..), packageKeySupported ) @@ -101,7 +106,9 @@ import Data.Maybe symlinkBinaries :: Compiler -> ConfigFlags -> InstallFlags - -> InstallPlan + -> InstallPlan InstalledPackageInfo + ConfiguredPackage + iresult ifailure -> IO [(PackageIdentifier, String, FilePath)] symlinkBinaries comp configFlags installFlags plan = case flagToMaybe (installSymlinkBinDir installFlags) of @@ -121,7 +128,7 @@ symlinkBinaries comp configFlags installFlags plan = then return Nothing else return (Just (pkgid, publicExeName, privateBinDir </> privateExeName)) - | (ReadyPackage _ _flags _ deps, pkg, exe) <- exes + | (ReadyPackage (ConfiguredPackage _ _flags _ _) deps, pkg, exe) <- exes , let pkgid = packageId pkg pkg_key = mkPackageKey (packageKeySupported comp) pkgid (map Installed.libraryName (CD.nonSetupDeps deps)) @@ -133,13 +140,16 @@ symlinkBinaries comp configFlags installFlags plan = where exes = [ (cpkg, pkg, exe) - | InstallPlan.Installed cpkg _ <- InstallPlan.toList plan + | InstallPlan.Installed cpkg _ _ <- InstallPlan.toList plan , let pkg = pkgDescription cpkg , exe <- PackageDescription.executables pkg , PackageDescription.buildable (PackageDescription.buildInfo exe) ] - pkgDescription :: ReadyPackage -> PackageDescription - pkgDescription (ReadyPackage (SourcePackage _ pkg _ _) flags stanzas _) = + pkgDescription :: ReadyPackage ConfiguredPackage ipkg -> PackageDescription + pkgDescription (ReadyPackage (ConfiguredPackage + (SourcePackage _ pkg _ _) + flags stanzas _) + _) = case finalizePackageDescription flags (const True) platform cinfo [] (enableStanzas stanzas pkg) of diff --git a/cabal-install/Distribution/Client/Types.hs b/cabal-install/Distribution/Client/Types.hs index 2d67b1be331136a68f43d2f502bf54d1938e4183..5eb05606c80b6493ff6ed5689068883f46719930 100644 --- a/cabal-install/Distribution/Client/Types.hs +++ b/cabal-install/Distribution/Client/Types.hs @@ -131,51 +131,42 @@ instance HasInstalledPackageId ConfiguredPackage where -- | Like 'ConfiguredPackage', but with all dependencies guaranteed to be -- installed already, hence itself ready to be installed. -data ReadyPackage = ReadyPackage - SourcePackage -- see 'ConfiguredPackage'. - FlagAssignment -- - [OptionalStanza] -- - (ComponentDeps [InstalledPackageInfo]) -- Installed dependencies. - deriving Show +data ReadyPackage srcpkg ipkg + = ReadyPackage + srcpkg -- see 'ConfiguredPackage'. + (ComponentDeps [ipkg]) -- Installed dependencies. + deriving (Eq, Show) -instance Package ReadyPackage where - packageId (ReadyPackage pkg _ _ _) = packageId pkg +instance Package srcpkg => Package (ReadyPackage srcpkg ipkg) where + packageId (ReadyPackage srcpkg _deps) = packageId srcpkg -instance PackageFixedDeps ReadyPackage where - depends (ReadyPackage _ _ _ deps) = fmap (map installedPackageId) deps +instance (Package srcpkg, HasInstalledPackageId ipkg) => + PackageFixedDeps (ReadyPackage srcpkg ipkg) where + depends (ReadyPackage _ deps) = fmap (map installedPackageId) deps -instance HasInstalledPackageId ReadyPackage where - installedPackageId = fakeInstalledPackageId . packageId +instance HasInstalledPackageId srcpkg => + HasInstalledPackageId (ReadyPackage srcpkg ipkg) where + installedPackageId (ReadyPackage pkg _) = installedPackageId pkg -- | Extracts a package key from ReadyPackage, a common operation needed -- to calculate build paths. -readyPackageKey :: Compiler -> ReadyPackage -> PackageKey -readyPackageKey comp (ReadyPackage pkg _ _ deps) = +readyPackageKey :: Compiler + -> ReadyPackage ConfiguredPackage InstalledPackageInfo + -> PackageKey +readyPackageKey comp (ReadyPackage pkg deps) = mkPackageKey (packageKeySupported comp) (packageId pkg) (map Info.libraryName (CD.nonSetupDeps deps)) -- | Extracts a library name from ReadyPackage, a common operation needed -- to calculate build paths. -readyLibraryName :: Compiler -> ReadyPackage -> LibraryName -readyLibraryName comp ready@(ReadyPackage pkg _ _ _) = +readyLibraryName :: Compiler + -> ReadyPackage ConfiguredPackage InstalledPackageInfo + -> LibraryName +readyLibraryName comp ready@(ReadyPackage pkg _) = packageKeyLibraryName (packageId pkg) (readyPackageKey comp ready) --- | Sometimes we need to convert a 'ReadyPackage' back to a --- 'ConfiguredPackage'. For example, a failed 'PlanPackage' can be *either* --- Ready or Configured. -readyPackageToConfiguredPackage :: ReadyPackage -> ConfiguredPackage -readyPackageToConfiguredPackage (ReadyPackage srcpkg flags stanzas deps) = - ConfiguredPackage srcpkg flags stanzas (fmap (map aux) deps) - where - aux :: InstalledPackageInfo -> ConfiguredId - aux info = ConfiguredId { - confSrcId = Info.sourcePackageId info - , confInstId = installedPackageId info - } - - -- | A package description along with the location of the package sources. -- data SourcePackage = SourcePackage { diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs index e5e3dd6e5825adc7446b29e6c88fed5413933cc7..b7a9e97809e0749e2f36eefcb12b2730e34baf8b 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs @@ -261,7 +261,11 @@ exInstIdx = C.PackageIndex.fromList . map exInstInfo exResolve :: ExampleDb -> [ExamplePkgName] -> Bool - -> ([String], Either String CI.InstallPlan.InstallPlan) + -> ([String], Either String + (CI.InstallPlan.InstallPlan + C.InstalledPackageInfo + ConfiguredPackage + isuccess ifailure)) exResolve db targets indepGoals = runProgress $ resolveDependencies C.buildPlatform (C.unknownCompilerInfo C.buildCompilerId C.NoAbiTag) @@ -282,11 +286,14 @@ exResolve db targets indepGoals = runProgress $ depResolverIndependentGoals = indepGoals } -extractInstallPlan :: CI.InstallPlan.InstallPlan +extractInstallPlan :: CI.InstallPlan.InstallPlan ipkg ConfiguredPackage + isuccess ifailure -> [(ExamplePkgName, ExamplePkgVersion)] extractInstallPlan = catMaybes . map confPkg . CI.InstallPlan.toList where - confPkg :: CI.InstallPlan.PlanPackage -> Maybe (String, Int) + confPkg :: CI.InstallPlan.PlanPackage ipkg ConfiguredPackage + isuccess ifailure + -> Maybe (String, Int) confPkg (CI.InstallPlan.Configured pkg) = Just $ srcPkg pkg confPkg _ = Nothing