summaryrefslogtreecommitdiff
path: root/utils/ghc-pkg/Main.hs
diff options
context:
space:
mode:
authorGabor Greif <ggreif@gmail.com>2014-08-08 18:01:19 +0200
committerGabor Greif <ggreif@gmail.com>2014-08-08 18:01:19 +0200
commit5f003d228340c3ce8e500f9053f353c58dc1dc94 (patch)
treea855b0f173ff635b48354e1136ef6cbb2a1214a4 /utils/ghc-pkg/Main.hs
parentff9c5570395bcacf8963149b3a8475f5644ce694 (diff)
parentdff0623d5ab13222c06b3ff6b32793e05b417970 (diff)
downloadhaskell-wip/generics-propeq.tar.gz
Merge branch 'master' into wip/generics-propeqwip/generics-propeq
Conflicts: compiler/typecheck/TcGenGenerics.lhs
Diffstat (limited to 'utils/ghc-pkg/Main.hs')
-rw-r--r--utils/ghc-pkg/Main.hs289
1 files changed, 221 insertions, 68 deletions
diff --git a/utils/ghc-pkg/Main.hs b/utils/ghc-pkg/Main.hs
index 290fb82a22..970ab67083 100644
--- a/utils/ghc-pkg/Main.hs
+++ b/utils/ghc-pkg/Main.hs
@@ -16,6 +16,7 @@ import Distribution.ModuleName hiding (main)
import Distribution.InstalledPackageInfo
import Distribution.Compat.ReadP
import Distribution.ParseUtils
+import Distribution.ModuleExport
import Distribution.Package hiding (depends)
import Distribution.Text
import Distribution.Version
@@ -32,6 +33,8 @@ import System.Console.GetOpt
import qualified Control.Exception as Exception
import Data.Maybe
+import qualified Data.Set as Set
+
import Data.Char ( isSpace, toLower )
import Data.Ord (comparing)
import Control.Applicative (Applicative(..))
@@ -111,9 +114,11 @@ data Flag
| FlagVersion
| FlagConfig FilePath
| FlagGlobalConfig FilePath
+ | FlagUserConfig FilePath
| FlagForce
| FlagForceFiles
| FlagAutoGHCiLibs
+ | FlagMultiInstance
| FlagExpandEnvVars
| FlagExpandPkgroot
| FlagNoExpandPkgroot
@@ -122,6 +127,7 @@ data Flag
| FlagIgnoreCase
| FlagNoUserDb
| FlagVerbosity (Maybe String)
+ | FlagIPId
deriving Eq
flags :: [OptDescr Flag]
@@ -138,6 +144,8 @@ flags = [
"location of the global package database",
Option [] ["no-user-package-db"] (NoArg FlagNoUserDb)
"never read the user package database",
+ Option [] ["user-package-db"] (ReqArg FlagUserConfig "DIR")
+ "location of the user package database (use instead of default)",
Option [] ["no-user-package-conf"] (NoArg FlagNoUserDb)
"never read the user package database (DEPRECATED)",
Option [] ["force"] (NoArg FlagForce)
@@ -146,6 +154,8 @@ flags = [
"ignore missing directories and libraries only",
Option ['g'] ["auto-ghci-libs"] (NoArg FlagAutoGHCiLibs)
"automatically build libs for GHCi (with register)",
+ Option [] ["enable-multi-instance"] (NoArg FlagMultiInstance)
+ "allow registering multiple instances of the same package version",
Option [] ["expand-env-vars"] (NoArg FlagExpandEnvVars)
"expand environment variables (${name}-style) in input package descriptions",
Option [] ["expand-pkgroot"] (NoArg FlagExpandPkgroot)
@@ -162,6 +172,8 @@ flags = [
"only print package names, not versions; can only be used with list --simple-output",
Option [] ["ignore-case"] (NoArg FlagIgnoreCase)
"ignore case for substring matching",
+ Option [] ["ipid"] (NoArg FlagIPId)
+ "interpret package arguments as installed package IDs",
Option ['v'] ["verbose"] (OptArg FlagVerbosity "Verbosity")
"verbosity level (0-2, default 1)"
]
@@ -270,7 +282,8 @@ usageHeader prog = substProg prog $
"\n" ++
" Substring matching is supported for {module} in find-module and\n" ++
" for {pkg} in list, describe, and field, where a '*' indicates\n" ++
- " open substring ends (prefix*, *suffix, *infix*).\n" ++
+ " open substring ends (prefix*, *suffix, *infix*). Use --ipid to\n" ++
+ " match against the installed package ID instead.\n" ++
"\n" ++
" When asked to modify a database (register, unregister, update,\n"++
" hide, expose, and also check), ghc-pkg modifies the global database by\n"++
@@ -297,7 +310,17 @@ substProg prog (c:xs) = c : substProg prog xs
data Force = NoForce | ForceFiles | ForceAll | CannotForce
deriving (Eq,Ord)
-data PackageArg = Id PackageIdentifier | Substring String (String->Bool)
+-- | Represents how a package may be specified by a user on the command line.
+data PackageArg
+ -- | A package identifier foo-0.1; the version might be a glob.
+ = Id PackageIdentifier
+ -- | An installed package ID foo-0.1-HASH. This is guaranteed to uniquely
+ -- match a single entry in the package database.
+ | IPId InstalledPackageId
+ -- | A glob against the package name. The first string is the literal
+ -- glob, the second is a function which returns @True@ if the the argument
+ -- matches.
+ | Substring String (String->Bool)
runit :: Verbosity -> [Flag] -> [String] -> IO ()
runit verbosity cli nonopts = do
@@ -308,7 +331,9 @@ runit verbosity cli nonopts = do
| FlagForce `elem` cli = ForceAll
| FlagForceFiles `elem` cli = ForceFiles
| otherwise = NoForce
+ as_ipid = FlagIPId `elem` cli
auto_ghci_libs = FlagAutoGHCiLibs `elem` cli
+ multi_instance = FlagMultiInstance `elem` cli
expand_env_vars= FlagExpandEnvVars `elem` cli
mexpand_pkgroot= foldl' accumExpandPkgroot Nothing cli
where accumExpandPkgroot _ FlagExpandPkgroot = Just True
@@ -319,6 +344,28 @@ runit verbosity cli nonopts = do
where splitComma "" = Nothing
splitComma fs = Just $ break (==',') (tail fs)
+ -- | Parses a glob into a predicate which tests if a string matches
+ -- the glob. Returns Nothing if the string in question is not a glob.
+ -- At the moment, we only support globs at the beginning and/or end of
+ -- strings. This function respects case sensitivity.
+ --
+ -- >>> fromJust (substringCheck "*") "anything"
+ -- True
+ --
+ -- >>> fromJust (substringCheck "string") "string"
+ -- True
+ --
+ -- >>> fromJust (substringCheck "*bar") "foobar"
+ -- True
+ --
+ -- >>> fromJust (substringCheck "foo*") "foobar"
+ -- True
+ --
+ -- >>> fromJust (substringCheck "*ooba*") "foobar"
+ -- True
+ --
+ -- >>> fromJust (substringCheck "f*bar") "foobar"
+ -- False
substringCheck :: String -> Maybe (String -> Bool)
substringCheck "" = Nothing
substringCheck "*" = Just (const True)
@@ -355,32 +402,35 @@ runit verbosity cli nonopts = do
initPackageDB filename verbosity cli
["register", filename] ->
registerPackage filename verbosity cli
- auto_ghci_libs expand_env_vars False force
+ auto_ghci_libs multi_instance
+ expand_env_vars False force
["update", filename] ->
registerPackage filename verbosity cli
- auto_ghci_libs expand_env_vars True force
- ["unregister", pkgid_str] -> do
- pkgid <- readGlobPkgId pkgid_str
- unregisterPackage pkgid verbosity cli force
- ["expose", pkgid_str] -> do
- pkgid <- readGlobPkgId pkgid_str
- exposePackage pkgid verbosity cli force
- ["hide", pkgid_str] -> do
- pkgid <- readGlobPkgId pkgid_str
- hidePackage pkgid verbosity cli force
- ["trust", pkgid_str] -> do
- pkgid <- readGlobPkgId pkgid_str
- trustPackage pkgid verbosity cli force
- ["distrust", pkgid_str] -> do
- pkgid <- readGlobPkgId pkgid_str
- distrustPackage pkgid verbosity cli force
+ auto_ghci_libs multi_instance
+ expand_env_vars True force
+ ["unregister", pkgarg_str] -> do
+ pkgarg <- readPackageArg as_ipid pkgarg_str
+ unregisterPackage pkgarg verbosity cli force
+ ["expose", pkgarg_str] -> do
+ pkgarg <- readPackageArg as_ipid pkgarg_str
+ exposePackage pkgarg verbosity cli force
+ ["hide", pkgarg_str] -> do
+ pkgarg <- readPackageArg as_ipid pkgarg_str
+ hidePackage pkgarg verbosity cli force
+ ["trust", pkgarg_str] -> do
+ pkgarg <- readPackageArg as_ipid pkgarg_str
+ trustPackage pkgarg verbosity cli force
+ ["distrust", pkgarg_str] -> do
+ pkgarg <- readPackageArg as_ipid pkgarg_str
+ distrustPackage pkgarg verbosity cli force
["list"] -> do
listPackages verbosity cli Nothing Nothing
- ["list", pkgid_str] ->
- case substringCheck pkgid_str of
- Nothing -> do pkgid <- readGlobPkgId pkgid_str
- listPackages verbosity cli (Just (Id pkgid)) Nothing
- Just m -> listPackages verbosity cli (Just (Substring pkgid_str m)) Nothing
+ ["list", pkgarg_str] ->
+ case substringCheck pkgarg_str of
+ Nothing -> do pkgarg <- readPackageArg as_ipid pkgarg_str
+ listPackages verbosity cli (Just pkgarg) Nothing
+ Just m -> listPackages verbosity cli
+ (Just (Substring pkgarg_str m)) Nothing
["dot"] -> do
showPackageDot verbosity cli
["find-module", moduleName] -> do
@@ -391,13 +441,13 @@ runit verbosity cli nonopts = do
latestPackage verbosity cli pkgid
["describe", pkgid_str] -> do
pkgarg <- case substringCheck pkgid_str of
- Nothing -> liftM Id (readGlobPkgId pkgid_str)
+ Nothing -> readPackageArg as_ipid pkgid_str
Just m -> return (Substring pkgid_str m)
describePackage verbosity cli pkgarg (fromMaybe False mexpand_pkgroot)
["field", pkgid_str, fields] -> do
pkgarg <- case substringCheck pkgid_str of
- Nothing -> liftM Id (readGlobPkgId pkgid_str)
+ Nothing -> readPackageArg as_ipid pkgid_str
Just m -> return (Substring pkgid_str m)
describeField verbosity cli pkgarg
(splitFields fields) (fromMaybe True mexpand_pkgroot)
@@ -433,6 +483,11 @@ parseGlobPackageId =
_ <- string "-*"
return (PackageIdentifier{ pkgName = n, pkgVersion = globVersion }))
+readPackageArg :: Bool -> String -> IO PackageArg
+readPackageArg True str =
+ parseCheck (IPId `fmap` parse) str "installed package id"
+readPackageArg False str = Id `fmap` readGlobPkgId str
+
-- globVersion means "all versions"
globVersion :: Version
globVersion = Version{ versionBranch=[], versionTags=["*"] }
@@ -515,16 +570,18 @@ getPkgDatabases verbosity modify use_cache expand_vars my_flags = do
e_appdir <- tryIO $ getAppUserDataDirectory "ghc"
mb_user_conf <-
- if no_user_db then return Nothing else
- case e_appdir of
- Left _ -> return Nothing
- Right appdir -> do
- let subdir = targetARCH ++ '-':targetOS ++ '-':Version.version
- dir = appdir </> subdir
- r <- lookForPackageDBIn dir
- case r of
- Nothing -> return (Just (dir </> "package.conf.d", False))
- Just f -> return (Just (f, True))
+ case [ f | FlagUserConfig f <- my_flags ] of
+ _ | no_user_db -> return Nothing
+ [] -> case e_appdir of
+ Left _ -> return Nothing
+ Right appdir -> do
+ let subdir = targetARCH ++ '-':targetOS ++ '-':Version.version
+ dir = appdir </> subdir
+ r <- lookForPackageDBIn dir
+ case r of
+ Nothing -> return (Just (dir </> "package.conf.d", False))
+ Just f -> return (Just (f, True))
+ fs -> return (Just (last fs, True))
-- If the user database doesn't exist, and this command isn't a
-- "modify" command, then we won't attempt to create or use it.
@@ -585,6 +642,11 @@ getPkgDatabases verbosity modify use_cache expand_vars my_flags = do
let flag_db_stack = [ db | db_name <- flag_db_names,
db <- db_stack, location db == db_name ]
+ when (verbosity > Normal) $ do
+ infoLn ("db stack: " ++ show (map location db_stack))
+ infoLn ("modifying: " ++ show to_modify)
+ infoLn ("flag db stack: " ++ show (map location flag_db_stack))
+
return (db_stack, to_modify, flag_db_stack)
@@ -782,11 +844,13 @@ registerPackage :: FilePath
-> Verbosity
-> [Flag]
-> Bool -- auto_ghci_libs
+ -> Bool -- multi_instance
-> Bool -- expand_env_vars
-> Bool -- update
-> Force
-> IO ()
-registerPackage input verbosity my_flags auto_ghci_libs expand_env_vars update force = do
+registerPackage input verbosity my_flags auto_ghci_libs multi_instance
+ expand_env_vars update force = do
(db_stack, Just to_modify, _flag_dbs) <-
getPkgDatabases verbosity True True False{-expand vars-} my_flags
@@ -829,13 +893,23 @@ registerPackage input verbosity my_flags auto_ghci_libs expand_env_vars update f
let truncated_stack = dropWhile ((/= to_modify).location) db_stack
-- truncate the stack for validation, because we don't allow
-- packages lower in the stack to refer to those higher up.
- validatePackageConfig pkg_expanded verbosity truncated_stack auto_ghci_libs update force
+ validatePackageConfig pkg_expanded verbosity truncated_stack
+ auto_ghci_libs multi_instance update force
+
+ -- postprocess the package
+ pkg' <- resolveReexports truncated_stack pkg
+
let
+ -- In the normal mode, we only allow one version of each package, so we
+ -- remove all instances with the same source package id as the one we're
+ -- adding. In the multi instance mode we don't do that, thus allowing
+ -- multiple instances with the same source package id.
removes = [ RemovePackage p
- | p <- packages db_to_operate_on,
+ | not multi_instance,
+ p <- packages db_to_operate_on,
sourcePackageId p == sourcePackageId pkg ]
--
- changeDB verbosity (removes ++ [AddPackage pkg]) db_to_operate_on
+ changeDB verbosity (removes ++ [AddPackage pkg']) db_to_operate_on
parsePackageInfo
:: String
@@ -850,6 +924,47 @@ parsePackageInfo str =
(Nothing, s) -> die s
(Just l, s) -> die (show l ++ ": " ++ s)
+-- | Takes the "reexported-modules" field of an InstalledPackageInfo
+-- and resolves the references so they point to the original exporter
+-- of a module (i.e. the module is in exposed-modules, not
+-- reexported-modules). This is done by maintaining an invariant on
+-- the installed package database that a reexported-module field always
+-- points to the original exporter.
+resolveReexports :: PackageDBStack
+ -> InstalledPackageInfo
+ -> IO InstalledPackageInfo
+resolveReexports db_stack pkg = do
+ let dep_mask = Set.fromList (depends pkg)
+ deps = filter (flip Set.member dep_mask . installedPackageId)
+ (allPackagesInStack db_stack)
+ matchExposed pkg_dep m = map ((,) (installedPackageId pkg_dep))
+ (filter (==m) (exposedModules pkg_dep))
+ worker ModuleExport{ exportOrigPackageName = Just pnm } pkg_dep
+ | pnm /= packageName (sourcePackageId pkg_dep) = []
+ -- Now, either the package matches, *or* we were asked to search the
+ -- true location ourselves.
+ worker ModuleExport{ exportOrigName = m } pkg_dep =
+ matchExposed pkg_dep m ++
+ map (fromMaybe (error $ "Impossible! Missing true location in " ++
+ display (installedPackageId pkg_dep))
+ . exportCachedTrueOrig)
+ (filter ((==m) . exportName) (reexportedModules pkg_dep))
+ self_reexports ModuleExport{ exportOrigPackageName = Just pnm }
+ | pnm /= packageName (sourcePackageId pkg) = []
+ self_reexports ModuleExport{ exportName = m', exportOrigName = m }
+ -- Self-reexport without renaming doesn't make sense
+ | m == m' = []
+ -- *Only* match against exposed modules!
+ | otherwise = matchExposed pkg m
+
+ r <- forM (reexportedModules pkg) $ \me -> do
+ case nub (concatMap (worker me) deps ++ self_reexports me) of
+ [c] -> return me { exportCachedTrueOrig = Just c }
+ [] -> die $ "Couldn't resolve reexport " ++ display me
+ cs -> die $ "Found multiple possible ways to resolve reexport " ++
+ display me ++ ": " ++ show cs
+ return (pkg { reexportedModules = r })
+
-- -----------------------------------------------------------------------------
-- Making changes to a package database
@@ -911,52 +1026,60 @@ updateDBCache verbosity db = do
-- -----------------------------------------------------------------------------
-- Exposing, Hiding, Trusting, Distrusting, Unregistering are all similar
-exposePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
+exposePackage :: PackageArg -> Verbosity -> [Flag] -> Force -> IO ()
exposePackage = modifyPackage (\p -> ModifyPackage p{exposed=True})
-hidePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
+hidePackage :: PackageArg -> Verbosity -> [Flag] -> Force -> IO ()
hidePackage = modifyPackage (\p -> ModifyPackage p{exposed=False})
-trustPackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
+trustPackage :: PackageArg -> Verbosity -> [Flag] -> Force -> IO ()
trustPackage = modifyPackage (\p -> ModifyPackage p{trusted=True})
-distrustPackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
+distrustPackage :: PackageArg -> Verbosity -> [Flag] -> Force -> IO ()
distrustPackage = modifyPackage (\p -> ModifyPackage p{trusted=False})
-unregisterPackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
+unregisterPackage :: PackageArg -> Verbosity -> [Flag] -> Force -> IO ()
unregisterPackage = modifyPackage RemovePackage
modifyPackage
:: (InstalledPackageInfo -> DBOp)
- -> PackageIdentifier
+ -> PackageArg
-> Verbosity
-> [Flag]
-> Force
-> IO ()
-modifyPackage fn pkgid verbosity my_flags force = do
- (db_stack, Just _to_modify, _flag_dbs) <-
+modifyPackage fn pkgarg verbosity my_flags force = do
+ (db_stack, Just _to_modify, flag_dbs) <-
getPkgDatabases verbosity True{-modify-} True{-use cache-} False{-expand vars-} my_flags
- (db, ps) <- fmap head $ findPackagesByDB db_stack (Id pkgid)
+ -- Do the search for the package respecting flags...
+ (db, ps) <- fmap head $ findPackagesByDB flag_dbs pkgarg
let
db_name = location db
pkgs = packages db
- pids = map sourcePackageId ps
+ pks = map packageKey ps
- cmds = [ fn pkg | pkg <- pkgs, sourcePackageId pkg `elem` pids ]
+ cmds = [ fn pkg | pkg <- pkgs, packageKey pkg `elem` pks ]
new_db = updateInternalDB db cmds
+ -- ...but do consistency checks with regards to the full stack
old_broken = brokenPackages (allPackagesInStack db_stack)
rest_of_stack = filter ((/= db_name) . location) db_stack
new_stack = new_db : rest_of_stack
- new_broken = map sourcePackageId (brokenPackages (allPackagesInStack new_stack))
- newly_broken = filter (`notElem` map sourcePackageId old_broken) new_broken
+ new_broken = brokenPackages (allPackagesInStack new_stack)
+ newly_broken = filter ((`notElem` map packageKey old_broken)
+ . packageKey) new_broken
--
+ let displayQualPkgId pkg
+ | [_] <- filter ((== pkgid) . sourcePackageId)
+ (allPackagesInStack db_stack)
+ = display pkgid
+ | otherwise = display pkgid ++ "@" ++ display (packageKey pkg)
+ where pkgid = sourcePackageId pkg
when (not (null newly_broken)) $
- dieOrForceAll force ("unregistering " ++ display pkgid ++
- " would break the following packages: "
- ++ unwords (map display newly_broken))
+ dieOrForceAll force ("unregistering would break the following packages: "
+ ++ unwords (map displayQualPkgId newly_broken))
changeDB verbosity cmds db
@@ -998,7 +1121,10 @@ listPackages verbosity my_flags mPackageName mModuleName = do
case pkgName p1 `compare` pkgName p2 of
LT -> LT
GT -> GT
- EQ -> pkgVersion p1 `compare` pkgVersion p2
+ EQ -> case pkgVersion p1 `compare` pkgVersion p2 of
+ LT -> LT
+ GT -> GT
+ EQ -> packageKey pkg1 `compare` packageKey pkg2
where (p1,p2) = (sourcePackageId pkg1, sourcePackageId pkg2)
stack = reverse db_stack_sorted
@@ -1006,7 +1132,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do
match `exposedInPkg` pkg = any match (map display $ exposedModules pkg)
pkg_map = allPackagesInStack db_stack
- broken = map sourcePackageId (brokenPackages pkg_map)
+ broken = map packageKey (brokenPackages pkg_map)
show_normal PackageDB{ location = db_name, packages = pkg_confs } =
do hPutStrLn stdout (db_name ++ ":")
@@ -1017,7 +1143,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do
-- Sort using instance Ord PackageId
pp_pkgs = map pp_pkg . sortBy (comparing installedPackageId) $ pkg_confs
pp_pkg p
- | sourcePackageId p `elem` broken = printf "{%s}" doc
+ | packageKey p `elem` broken = printf "{%s}" doc
| exposed p = doc
| otherwise = printf "(%s)" doc
where doc | verbosity >= Verbose = printf "%s (%s)" pkg ipid
@@ -1044,7 +1170,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do
map (termText " " <#>) (map pp_pkg (packages db)))
where
pp_pkg p
- | sourcePackageId p `elem` broken = withF Red doc
+ | packageKey p `elem` broken = withF Red doc
| exposed p = doc
| otherwise = withF Blue doc
where doc | verbosity >= Verbose
@@ -1096,6 +1222,8 @@ showPackageDot verbosity myflags = do
-- -----------------------------------------------------------------------------
-- Prints the highest (hidden or exposed) version of a package
+-- ToDo: This is no longer well-defined with package keys, because the
+-- dependencies may be varying versions
latestPackage :: Verbosity -> [Flag] -> PackageIdentifier -> IO ()
latestPackage verbosity my_flags pkgid = do
(_, _, flag_db_stack) <-
@@ -1155,6 +1283,7 @@ findPackagesByDB db_stack pkgarg
ps -> return ps
where
pkg_msg (Id pkgid) = display pkgid
+ pkg_msg (IPId ipid) = display ipid
pkg_msg (Substring pkgpat _) = "matching " ++ pkgpat
matches :: PackageIdentifier -> PackageIdentifier -> Bool
@@ -1168,6 +1297,7 @@ realVersion pkgid = versionBranch (pkgVersion pkgid) /= []
matchesPkg :: PackageArg -> InstalledPackageInfo -> Bool
(Id pid) `matchesPkg` pkg = pid `matches` sourcePackageId pkg
+(IPId ipid) `matchesPkg` pkg = ipid == installedPackageId pkg
(Substring _ m) `matchesPkg` pkg = m (display (sourcePackageId pkg))
-- -----------------------------------------------------------------------------
@@ -1204,7 +1334,8 @@ checkConsistency verbosity my_flags = do
let pkgs = allPackagesInStack db_stack
checkPackage p = do
- (_,es,ws) <- runValidate $ checkPackageConfig p verbosity db_stack False True
+ (_,es,ws) <- runValidate $ checkPackageConfig p verbosity db_stack
+ False True True
if null es
then do when (not simple_output) $ do
_ <- reportValidateErrors [] ws "" Nothing
@@ -1267,15 +1398,19 @@ type InstalledPackageInfoString = InstalledPackageInfo_ String
convertPackageInfoOut :: InstalledPackageInfo -> InstalledPackageInfoString
convertPackageInfoOut
(pkgconf@(InstalledPackageInfo { exposedModules = e,
+ reexportedModules = r,
hiddenModules = h })) =
pkgconf{ exposedModules = map display e,
+ reexportedModules = map (fmap display) r,
hiddenModules = map display h }
convertPackageInfoIn :: InstalledPackageInfoString -> InstalledPackageInfo
convertPackageInfoIn
(pkgconf@(InstalledPackageInfo { exposedModules = e,
+ reexportedModules = r,
hiddenModules = h })) =
pkgconf{ exposedModules = map convert e,
+ reexportedModules = map (fmap convert) r,
hiddenModules = map convert h }
where convert = fromJust . simpleParse
@@ -1354,11 +1489,15 @@ validatePackageConfig :: InstalledPackageInfo
-> Verbosity
-> PackageDBStack
-> Bool -- auto-ghc-libs
+ -> Bool -- multi_instance
-> Bool -- update, or check
-> Force
-> IO ()
-validatePackageConfig pkg verbosity db_stack auto_ghci_libs update force = do
- (_,es,ws) <- runValidate $ checkPackageConfig pkg verbosity db_stack auto_ghci_libs update
+validatePackageConfig pkg verbosity db_stack auto_ghci_libs
+ multi_instance update force = do
+ (_,es,ws) <- runValidate $
+ checkPackageConfig pkg verbosity db_stack
+ auto_ghci_libs multi_instance update
ok <- reportValidateErrors es ws (display (sourcePackageId pkg) ++ ": ") (Just force)
when (not ok) $ exitWith (ExitFailure 1)
@@ -1366,12 +1505,15 @@ checkPackageConfig :: InstalledPackageInfo
-> Verbosity
-> PackageDBStack
-> Bool -- auto-ghc-libs
+ -> Bool -- multi_instance
-> Bool -- update, or check
-> Validate ()
-checkPackageConfig pkg verbosity db_stack auto_ghci_libs update = do
+checkPackageConfig pkg verbosity db_stack auto_ghci_libs
+ multi_instance update = do
checkInstalledPackageId pkg db_stack update
checkPackageId pkg
- checkDuplicates db_stack pkg update
+ checkPackageKey pkg
+ checkDuplicates db_stack pkg multi_instance update
mapM_ (checkDep db_stack) (depends pkg)
checkDuplicateDepends (depends pkg)
mapM_ (checkDir False "import-dirs") (importDirs pkg)
@@ -1410,15 +1552,25 @@ checkPackageId ipi =
[] -> verror CannotForce ("invalid package identifier: " ++ str)
_ -> verror CannotForce ("ambiguous package identifier: " ++ str)
-checkDuplicates :: PackageDBStack -> InstalledPackageInfo -> Bool -> Validate ()
-checkDuplicates db_stack pkg update = do
+checkPackageKey :: InstalledPackageInfo -> Validate ()
+checkPackageKey ipi =
+ let str = display (packageKey ipi) in
+ case [ x :: PackageKey | (x,ys) <- readP_to_S parse str, all isSpace ys ] of
+ [_] -> return ()
+ [] -> verror CannotForce ("invalid package key: " ++ str)
+ _ -> verror CannotForce ("ambiguous package key: " ++ str)
+
+checkDuplicates :: PackageDBStack -> InstalledPackageInfo
+ -> Bool -> Bool-> Validate ()
+checkDuplicates db_stack pkg multi_instance update = do
let
pkgid = sourcePackageId pkg
pkgs = packages (head db_stack)
--
-- Check whether this package id already exists in this DB
--
- when (not update && (pkgid `elem` map sourcePackageId pkgs)) $
+ when (not update && not multi_instance
+ && (pkgid `elem` map sourcePackageId pkgs)) $
verror CannotForce $
"package " ++ display pkgid ++ " is already installed"
@@ -1504,6 +1656,7 @@ doesFileExistOnPath filenames paths = go fullFilenames
go ((p, fp) : xs) = do b <- doesFileExist fp
if b then return (Just p) else go xs
+-- XXX maybe should check reexportedModules too
checkModules :: InstalledPackageInfo -> Validate ()
checkModules pkg = do
mapM_ findModule (exposedModules pkg ++ hiddenModules pkg)