1 {-# LANGUAGE PatternGuards, CPP, ForeignFunctionInterface #-}
2 -----------------------------------------------------------------------------
4 -- (c) The University of Glasgow 2004-2009.
6 -- Package management tool
8 -----------------------------------------------------------------------------
10 module Main (main) where
12 import Version ( version, targetOS, targetARCH )
13 import Distribution.InstalledPackageInfo.Binary()
14 import qualified Distribution.Simple.PackageIndex as PackageIndex
15 import Distribution.ModuleName hiding (main)
16 import Distribution.InstalledPackageInfo
17 import Distribution.Compat.ReadP
18 import Distribution.ParseUtils
19 import Distribution.Package hiding (depends)
20 import Distribution.Text
21 import Distribution.Version
22 import System.FilePath
23 import System.Cmd ( rawSystem )
24 import System.Directory ( getAppUserDataDirectory, createDirectoryIfMissing,
30 import System.Console.GetOpt
31 import qualified Control.Exception as Exception
34 import Data.Char ( isSpace, toLower )
36 import System.Directory ( doesDirectoryExist, getDirectoryContents,
37 doesFileExist, renameFile, removeFile )
38 import System.Exit ( exitWith, ExitCode(..) )
39 import System.Environment ( getArgs, getProgName, getEnv )
41 import System.IO.Error
43 import Control.Concurrent
45 import qualified Data.ByteString.Lazy as B
46 import qualified Data.Binary as Bin
47 import qualified Data.Binary.Get as Bin
49 #if defined(mingw32_HOST_OS)
50 -- mingw32 needs these for getExecDir, GHC <6.12 needs them for openNewFile
55 #ifdef mingw32_HOST_OS
56 import GHC.ConsoleHandler
58 import System.Posix hiding (fdToHandle)
62 import System.Process(runInteractiveCommand)
63 import qualified System.Info(os)
66 #if !defined(mingw32_HOST_OS) && !defined(BOOTSTRAPPING)
67 import System.Console.Terminfo as Terminfo
70 -- -----------------------------------------------------------------------------
77 case getOpt Permute (flags ++ deprecFlags) args of
78 (cli,_,[]) | FlagHelp `elem` cli -> do
79 prog <- getProgramName
80 bye (usageInfo (usageHeader prog) flags)
81 (cli,_,[]) | FlagVersion `elem` cli ->
84 case getVerbosity Normal cli of
85 Right v -> runit v cli nonopts
88 prog <- getProgramName
89 die (concat errors ++ usageInfo (usageHeader prog) flags)
91 -- -----------------------------------------------------------------------------
92 -- Command-line syntax
100 | FlagGlobalConfig FilePath
109 | FlagVerbosity (Maybe String)
112 flags :: [OptDescr Flag]
114 Option [] ["user"] (NoArg FlagUser)
115 "use the current user's package database",
116 Option [] ["global"] (NoArg FlagGlobal)
117 "use the global package database",
118 Option ['f'] ["package-conf"] (ReqArg FlagConfig "FILE")
119 "use the specified package config file",
120 Option [] ["global-conf"] (ReqArg FlagGlobalConfig "FILE")
121 "location of the global package config",
122 Option [] ["no-user-package-conf"] (NoArg FlagNoUserDb)
123 "never read the user package database",
124 Option [] ["force"] (NoArg FlagForce)
125 "ignore missing dependencies, directories, and libraries",
126 Option [] ["force-files"] (NoArg FlagForceFiles)
127 "ignore missing directories and libraries only",
128 Option ['g'] ["auto-ghci-libs"] (NoArg FlagAutoGHCiLibs)
129 "automatically build libs for GHCi (with register)",
130 Option [] ["expand-env-vars"] (NoArg FlagExpandEnvVars)
131 "expand environment variables (${name}-style) in input package descriptions",
132 Option ['?'] ["help"] (NoArg FlagHelp)
133 "display this help and exit",
134 Option ['V'] ["version"] (NoArg FlagVersion)
135 "output version information and exit",
136 Option [] ["simple-output"] (NoArg FlagSimpleOutput)
137 "print output in easy-to-parse format for some commands",
138 Option [] ["names-only"] (NoArg FlagNamesOnly)
139 "only print package names, not versions; can only be used with list --simple-output",
140 Option [] ["ignore-case"] (NoArg FlagIgnoreCase)
141 "ignore case for substring matching",
142 Option ['v'] ["verbose"] (OptArg FlagVerbosity "Verbosity")
143 "verbosity level (0-2, default 1)"
146 data Verbosity = Silent | Normal | Verbose
147 deriving (Show, Eq, Ord)
149 getVerbosity :: Verbosity -> [Flag] -> Either String Verbosity
150 getVerbosity v [] = Right v
151 getVerbosity _ (FlagVerbosity Nothing : fs) = getVerbosity Verbose fs
152 getVerbosity _ (FlagVerbosity (Just "0") : fs) = getVerbosity Silent fs
153 getVerbosity _ (FlagVerbosity (Just "1") : fs) = getVerbosity Normal fs
154 getVerbosity _ (FlagVerbosity (Just "2") : fs) = getVerbosity Verbose fs
155 getVerbosity _ (FlagVerbosity v : _) = Left ("Bad verbosity: " ++ show v)
156 getVerbosity v (_ : fs) = getVerbosity v fs
158 deprecFlags :: [OptDescr Flag]
160 -- put deprecated flags here
163 ourCopyright :: String
164 ourCopyright = "GHC package manager version " ++ Version.version ++ "\n"
166 usageHeader :: String -> String
167 usageHeader prog = substProg prog $
169 " $p init {path}\n" ++
170 " Create and initialise a package database at the location {path}.\n" ++
171 " Packages can be registered in the new database using the register\n" ++
172 " command with --package-conf={path}. To use the new database with GHC,\n" ++
173 " use GHC's -package-conf flag.\n" ++
175 " $p register {filename | -}\n" ++
176 " Register the package using the specified installed package\n" ++
177 " description. The syntax for the latter is given in the $p\n" ++
178 " documentation. The input file should be encoded in UTF-8.\n" ++
180 " $p update {filename | -}\n" ++
181 " Register the package, overwriting any other package with the\n" ++
182 " same name. The input file should be encoded in UTF-8.\n" ++
184 " $p unregister {pkg-id}\n" ++
185 " Unregister the specified package.\n" ++
187 " $p expose {pkg-id}\n" ++
188 " Expose the specified package.\n" ++
190 " $p hide {pkg-id}\n" ++
191 " Hide the specified package.\n" ++
193 " $p list [pkg]\n" ++
194 " List registered packages in the global database, and also the\n" ++
195 " user database if --user is given. If a package name is given\n" ++
196 " all the registered versions will be listed in ascending order.\n" ++
197 " Accepts the --simple-output flag.\n" ++
200 " Generate a graph of the package dependencies in a form suitable\n" ++
201 " for input for the graphviz tools. For example, to generate a PDF" ++
202 " of the dependency graph: ghc-pkg dot | tred | dot -Tpdf >pkgs.pdf" ++
204 " $p find-module {module}\n" ++
205 " List registered packages exposing module {module} in the global\n" ++
206 " database, and also the user database if --user is given.\n" ++
207 " All the registered versions will be listed in ascending order.\n" ++
208 " Accepts the --simple-output flag.\n" ++
210 " $p latest {pkg-id}\n" ++
211 " Prints the highest registered version of a package.\n" ++
214 " Check the consistency of package depenencies and list broken packages.\n" ++
215 " Accepts the --simple-output flag.\n" ++
217 " $p describe {pkg}\n" ++
218 " Give the registered description for the specified package. The\n" ++
219 " description is returned in precisely the syntax required by $p\n" ++
222 " $p field {pkg} {field}\n" ++
223 " Extract the specified field of the package description for the\n" ++
224 " specified package. Accepts comma-separated multiple fields.\n" ++
227 " Dump the registered description for every package. This is like\n" ++
228 " \"ghc-pkg describe '*'\", except that it is intended to be used\n" ++
229 " by tools that parse the results, rather than humans. The output is\n" ++
230 " always encoded in UTF-8, regardless of the current locale.\n" ++
233 " Regenerate the package database cache. This command should only be\n" ++
234 " necessary if you added a package to the database by dropping a file\n" ++
235 " into the database directory manually. By default, the global DB\n" ++
236 " is recached; to recache a different DB use --user or --package-conf\n" ++
237 " as appropriate.\n" ++
239 " Substring matching is supported for {module} in find-module and\n" ++
240 " for {pkg} in list, describe, and field, where a '*' indicates\n" ++
241 " open substring ends (prefix*, *suffix, *infix*).\n" ++
243 " When asked to modify a database (register, unregister, update,\n"++
244 " hide, expose, and also check), ghc-pkg modifies the global database by\n"++
245 " default. Specifying --user causes it to act on the user database,\n"++
246 " or --package-conf can be used to act on another database\n"++
247 " entirely. When multiple of these options are given, the rightmost\n"++
248 " one is used as the database to act upon.\n"++
250 " Commands that query the package database (list, tree, latest, describe,\n"++
251 " field) operate on the list of databases specified by the flags\n"++
252 " --user, --global, and --package-conf. If none of these flags are\n"++
253 " given, the default is --global --user.\n"++
255 " The following optional flags are also accepted:\n"
257 substProg :: String -> String -> String
259 substProg prog ('$':'p':xs) = prog ++ substProg prog xs
260 substProg prog (c:xs) = c : substProg prog xs
262 -- -----------------------------------------------------------------------------
265 data Force = NoForce | ForceFiles | ForceAll | CannotForce
268 data PackageArg = Id PackageIdentifier | Substring String (String->Bool)
270 runit :: Verbosity -> [Flag] -> [String] -> IO ()
271 runit verbosity cli nonopts = do
272 installSignalHandlers -- catch ^C and clean up
273 prog <- getProgramName
276 | FlagForce `elem` cli = ForceAll
277 | FlagForceFiles `elem` cli = ForceFiles
278 | otherwise = NoForce
279 auto_ghci_libs = FlagAutoGHCiLibs `elem` cli
280 expand_env_vars= FlagExpandEnvVars `elem` cli
281 splitFields fields = unfoldr splitComma (',':fields)
282 where splitComma "" = Nothing
283 splitComma fs = Just $ break (==',') (tail fs)
285 substringCheck :: String -> Maybe (String -> Bool)
286 substringCheck "" = Nothing
287 substringCheck "*" = Just (const True)
288 substringCheck [_] = Nothing
289 substringCheck (h:t) =
290 case (h, init t, last t) of
291 ('*',s,'*') -> Just (isInfixOf (f s) . f)
292 ('*',_, _ ) -> Just (isSuffixOf (f t) . f)
293 ( _ ,s,'*') -> Just (isPrefixOf (f (h:s)) . f)
295 where f | FlagIgnoreCase `elem` cli = map toLower
298 glob x | System.Info.os=="mingw32" = do
299 -- glob echoes its argument, after win32 filename globbing
300 (_,o,_,_) <- runInteractiveCommand ("glob "++x)
301 txt <- hGetContents o
303 glob x | otherwise = return [x]
306 -- first, parse the command
309 -- dummy command to demonstrate usage and permit testing
310 -- without messing things up; use glob to selectively enable
311 -- windows filename globbing for file parameters
312 -- register, update, FlagGlobalConfig, FlagConfig; others?
313 ["glob", filename] -> do
315 glob filename >>= print
317 ["init", filename] ->
318 initPackageDB filename verbosity cli
319 ["register", filename] ->
320 registerPackage filename verbosity cli
321 auto_ghci_libs expand_env_vars False force
322 ["update", filename] ->
323 registerPackage filename verbosity cli
324 auto_ghci_libs expand_env_vars True force
325 ["unregister", pkgid_str] -> do
326 pkgid <- readGlobPkgId pkgid_str
327 unregisterPackage pkgid verbosity cli force
328 ["expose", pkgid_str] -> do
329 pkgid <- readGlobPkgId pkgid_str
330 exposePackage pkgid verbosity cli force
331 ["hide", pkgid_str] -> do
332 pkgid <- readGlobPkgId pkgid_str
333 hidePackage pkgid verbosity cli force
335 listPackages verbosity cli Nothing Nothing
336 ["list", pkgid_str] ->
337 case substringCheck pkgid_str of
338 Nothing -> do pkgid <- readGlobPkgId pkgid_str
339 listPackages verbosity cli (Just (Id pkgid)) Nothing
340 Just m -> listPackages verbosity cli (Just (Substring pkgid_str m)) Nothing
342 showPackageDot verbosity cli
343 ["find-module", moduleName] -> do
344 let match = maybe (==moduleName) id (substringCheck moduleName)
345 listPackages verbosity cli Nothing (Just match)
346 ["latest", pkgid_str] -> do
347 pkgid <- readGlobPkgId pkgid_str
348 latestPackage verbosity cli pkgid
349 ["describe", pkgid_str] ->
350 case substringCheck pkgid_str of
351 Nothing -> do pkgid <- readGlobPkgId pkgid_str
352 describePackage verbosity cli (Id pkgid)
353 Just m -> describePackage verbosity cli (Substring pkgid_str m)
354 ["field", pkgid_str, fields] ->
355 case substringCheck pkgid_str of
356 Nothing -> do pkgid <- readGlobPkgId pkgid_str
357 describeField verbosity cli (Id pkgid)
359 Just m -> describeField verbosity cli (Substring pkgid_str m)
362 checkConsistency verbosity cli
365 dumpPackages verbosity cli
368 recache verbosity cli
371 die ("missing command\n" ++
372 usageInfo (usageHeader prog) flags)
374 die ("command-line syntax error\n" ++
375 usageInfo (usageHeader prog) flags)
377 parseCheck :: ReadP a a -> String -> String -> IO a
378 parseCheck parser str what =
379 case [ x | (x,ys) <- readP_to_S parser str, all isSpace ys ] of
381 _ -> die ("cannot parse \'" ++ str ++ "\' as a " ++ what)
383 readGlobPkgId :: String -> IO PackageIdentifier
384 readGlobPkgId str = parseCheck parseGlobPackageId str "package identifier"
386 parseGlobPackageId :: ReadP r PackageIdentifier
392 return (PackageIdentifier{ pkgName = n, pkgVersion = globVersion }))
394 -- globVersion means "all versions"
395 globVersion :: Version
396 globVersion = Version{ versionBranch=[], versionTags=["*"] }
398 -- -----------------------------------------------------------------------------
401 -- Some commands operate on a single database:
402 -- register, unregister, expose, hide
403 -- however these commands also check the union of the available databases
404 -- in order to check consistency. For example, register will check that
405 -- dependencies exist before registering a package.
407 -- Some commands operate on multiple databases, with overlapping semantics:
408 -- list, describe, field
411 = PackageDB { location :: FilePath,
412 packages :: [InstalledPackageInfo] }
414 type PackageDBStack = [PackageDB]
415 -- A stack of package databases. Convention: head is the topmost
418 allPackagesInStack :: PackageDBStack -> [InstalledPackageInfo]
419 allPackagesInStack = concatMap packages
421 getPkgDatabases :: Verbosity
422 -> Bool -- we are modifying, not reading
423 -> Bool -- read caches, if available
425 -> IO (PackageDBStack,
426 -- the real package DB stack: [global,user] ++
427 -- DBs specified on the command line with -f.
429 -- which one to modify, if any
431 -- the package DBs specified on the command
432 -- line, or [global,user] otherwise. This
433 -- is used as the list of package DBs for
434 -- commands that just read the DB, such as 'list'.
436 getPkgDatabases verbosity modify use_cache my_flags = do
437 -- first we determine the location of the global package config. On Windows,
438 -- this is found relative to the ghc-pkg.exe binary, whereas on Unix the
439 -- location is passed to the binary using the --global-config flag by the
441 let err_msg = "missing --global-conf option, location of global package.conf unknown\n"
443 case [ f | FlagGlobalConfig f <- my_flags ] of
444 [] -> do mb_dir <- getLibDir
446 Nothing -> die err_msg
448 r <- lookForPackageDBIn dir
450 Nothing -> die ("Can't find package database in " ++ dir)
451 Just path -> return path
452 fs -> return (last fs)
454 let no_user_db = FlagNoUserDb `elem` my_flags
456 -- get the location of the user package database, and create it if necessary
457 -- getAppUserDataDirectory can fail (e.g. if $HOME isn't set)
458 e_appdir <- tryIO $ getAppUserDataDirectory "ghc"
461 if no_user_db then return Nothing else
463 Left _ -> return Nothing
465 let subdir = targetARCH ++ '-':targetOS ++ '-':Version.version
466 dir = appdir </> subdir
467 r <- lookForPackageDBIn dir
469 Nothing -> return (Just (dir </> "package.conf.d", False))
470 Just f -> return (Just (f, True))
472 -- If the user database doesn't exist, and this command isn't a
473 -- "modify" command, then we won't attempt to create or use it.
475 | Just (user_conf,user_exists) <- mb_user_conf,
476 modify || user_exists = [user_conf, global_conf]
477 | otherwise = [global_conf]
479 e_pkg_path <- tryIO (System.Environment.getEnv "GHC_PACKAGE_PATH")
482 Left _ -> sys_databases
484 | last cs == "" -> init cs ++ sys_databases
486 where cs = parseSearchPath path
488 -- The "global" database is always the one at the bottom of the stack.
489 -- This is the database we modify by default.
490 virt_global_conf = last env_stack
492 let db_flags = [ f | Just f <- map is_db_flag my_flags ]
493 where is_db_flag FlagUser
494 | Just (user_conf, _user_exists) <- mb_user_conf
496 is_db_flag FlagGlobal = Just virt_global_conf
497 is_db_flag (FlagConfig f) = Just f
498 is_db_flag _ = Nothing
500 let flag_db_names | null db_flags = env_stack
501 | otherwise = reverse (nub db_flags)
503 -- For a "modify" command, treat all the databases as
504 -- a stack, where we are modifying the top one, but it
505 -- can refer to packages in databases further down the
508 -- -f flags on the command line add to the database
509 -- stack, unless any of them are present in the stack
511 let final_stack = filter (`notElem` env_stack)
512 [ f | FlagConfig f <- reverse my_flags ]
515 -- the database we actually modify is the one mentioned
516 -- rightmost on the command-line.
518 | not modify = Nothing
519 | null db_flags = Just virt_global_conf
520 | otherwise = Just (last db_flags)
522 db_stack <- mapM (readParseDatabase verbosity mb_user_conf use_cache) final_stack
524 let flag_db_stack = [ db | db_name <- flag_db_names,
525 db <- db_stack, location db == db_name ]
527 return (db_stack, to_modify, flag_db_stack)
530 lookForPackageDBIn :: FilePath -> IO (Maybe FilePath)
531 lookForPackageDBIn dir = do
532 let path_dir = dir </> "package.conf.d"
533 exists_dir <- doesDirectoryExist path_dir
534 if exists_dir then return (Just path_dir) else do
535 let path_file = dir </> "package.conf"
536 exists_file <- doesFileExist path_file
537 if exists_file then return (Just path_file) else return Nothing
539 readParseDatabase :: Verbosity
540 -> Maybe (FilePath,Bool)
545 readParseDatabase verbosity mb_user_conf use_cache path
546 -- the user database (only) is allowed to be non-existent
547 | Just (user_conf,False) <- mb_user_conf, path == user_conf
548 = return PackageDB { location = path, packages = [] }
550 = do e <- tryIO $ getDirectoryContents path
553 pkgs <- parseMultiPackageConf verbosity path
554 return PackageDB{ location = path, packages = pkgs }
556 | not use_cache -> ignore_cache
558 let cache = path </> cachefilename
559 tdir <- getModificationTime path
560 e_tcache <- tryIO $ getModificationTime cache
563 when (verbosity > Normal) $
564 warn ("warning: cannot read cache file " ++ cache ++ ": " ++ show ex)
567 | tcache >= tdir -> do
568 when (verbosity > Normal) $
569 putStrLn ("using cache: " ++ cache)
570 pkgs <- myReadBinPackageDB cache
571 let pkgs' = map convertPackageInfoIn pkgs
572 return PackageDB { location = path, packages = pkgs' }
574 when (verbosity >= Normal) $ do
575 warn ("WARNING: cache is out of date: " ++ cache)
576 warn " use 'ghc-pkg recache' to fix."
580 let confs = filter (".conf" `isSuffixOf`) fs
581 pkgs <- mapM (parseSingletonPackageConf verbosity) $
583 return PackageDB { location = path, packages = pkgs }
585 -- read the package.cache file strictly, to work around a problem with
586 -- bytestring 0.9.0.x (fixed in 0.9.1.x) where the file wasn't closed
587 -- after it has been completely read, leading to a sharing violation
589 myReadBinPackageDB :: FilePath -> IO [InstalledPackageInfoString]
590 myReadBinPackageDB filepath = do
591 h <- openBinaryFile filepath ReadMode
593 b <- B.hGet h (fromIntegral sz)
595 return $ Bin.runGet Bin.get b
597 parseMultiPackageConf :: Verbosity -> FilePath -> IO [InstalledPackageInfo]
598 parseMultiPackageConf verbosity file = do
599 when (verbosity > Normal) $ putStrLn ("reading package database: " ++ file)
600 str <- readUTF8File file
601 let pkgs = map convertPackageInfoIn $ read str
602 Exception.evaluate pkgs
604 die ("error while parsing " ++ file ++ ": " ++ show e)
606 parseSingletonPackageConf :: Verbosity -> FilePath -> IO InstalledPackageInfo
607 parseSingletonPackageConf verbosity file = do
608 when (verbosity > Normal) $ putStrLn ("reading package config: " ++ file)
609 readUTF8File file >>= parsePackageInfo
611 cachefilename :: FilePath
612 cachefilename = "package.cache"
614 -- -----------------------------------------------------------------------------
615 -- Creating a new package DB
617 initPackageDB :: FilePath -> Verbosity -> [Flag] -> IO ()
618 initPackageDB filename verbosity _flags = do
619 let eexist = die ("cannot create: " ++ filename ++ " already exists")
620 b1 <- doesFileExist filename
622 b2 <- doesDirectoryExist filename
624 changeDB verbosity [] PackageDB{ location = filename, packages = [] }
626 -- -----------------------------------------------------------------------------
629 registerPackage :: FilePath
632 -> Bool -- auto_ghci_libs
633 -> Bool -- expand_env_vars
637 registerPackage input verbosity my_flags auto_ghci_libs expand_env_vars update force = do
638 (db_stack, Just to_modify, _flag_dbs) <-
639 getPkgDatabases verbosity True True my_flags
642 db_to_operate_on = my_head "register" $
643 filter ((== to_modify).location) db_stack
645 when (auto_ghci_libs && verbosity >= Silent) $
646 warn "Warning: --auto-ghci-libs is deprecated and will be removed in GHC 7.4"
651 when (verbosity >= Normal) $
652 putStr "Reading package info from stdin ... "
653 -- fix the encoding to UTF-8, since this is an interchange format
654 hSetEncoding stdin utf8
657 when (verbosity >= Normal) $
658 putStr ("Reading package info from " ++ show f ++ " ... ")
661 expanded <- if expand_env_vars then expandEnvVars s force
664 pkg <- parsePackageInfo expanded
665 when (verbosity >= Normal) $
668 let truncated_stack = dropWhile ((/= to_modify).location) db_stack
669 -- truncate the stack for validation, because we don't allow
670 -- packages lower in the stack to refer to those higher up.
671 validatePackageConfig pkg truncated_stack auto_ghci_libs update force
673 removes = [ RemovePackage p
674 | p <- packages db_to_operate_on,
675 sourcePackageId p == sourcePackageId pkg ]
677 changeDB verbosity (removes ++ [AddPackage pkg]) db_to_operate_on
681 -> IO InstalledPackageInfo
682 parsePackageInfo str =
683 case parseInstalledPackageInfo str of
684 ParseOk _warns ok -> return ok
685 ParseFailed err -> case locatedErrorMsg err of
686 (Nothing, s) -> die s
687 (Just l, s) -> die (show l ++ ": " ++ s)
689 -- -----------------------------------------------------------------------------
690 -- Making changes to a package database
692 data DBOp = RemovePackage InstalledPackageInfo
693 | AddPackage InstalledPackageInfo
694 | ModifyPackage InstalledPackageInfo
696 changeDB :: Verbosity -> [DBOp] -> PackageDB -> IO ()
697 changeDB verbosity cmds db = do
698 let db' = updateInternalDB db cmds
699 isfile <- doesFileExist (location db)
701 then writeNewConfig verbosity (location db') (packages db')
703 createDirectoryIfMissing True (location db)
704 changeDBDir verbosity cmds db'
706 updateInternalDB :: PackageDB -> [DBOp] -> PackageDB
707 updateInternalDB db cmds = db{ packages = foldl do_cmd (packages db) cmds }
709 do_cmd pkgs (RemovePackage p) =
710 filter ((/= installedPackageId p) . installedPackageId) pkgs
711 do_cmd pkgs (AddPackage p) = p : pkgs
712 do_cmd pkgs (ModifyPackage p) =
713 do_cmd (do_cmd pkgs (RemovePackage p)) (AddPackage p)
716 changeDBDir :: Verbosity -> [DBOp] -> PackageDB -> IO ()
717 changeDBDir verbosity cmds db = do
719 updateDBCache verbosity db
721 do_cmd (RemovePackage p) = do
722 let file = location db </> display (installedPackageId p) <.> "conf"
723 when (verbosity > Normal) $ putStrLn ("removing " ++ file)
725 do_cmd (AddPackage p) = do
726 let file = location db </> display (installedPackageId p) <.> "conf"
727 when (verbosity > Normal) $ putStrLn ("writing " ++ file)
728 writeFileUtf8Atomic file (showInstalledPackageInfo p)
729 do_cmd (ModifyPackage p) =
730 do_cmd (AddPackage p)
732 updateDBCache :: Verbosity -> PackageDB -> IO ()
733 updateDBCache verbosity db = do
734 let filename = location db </> cachefilename
735 when (verbosity > Normal) $
736 putStrLn ("writing cache " ++ filename)
737 writeBinaryFileAtomic filename (map convertPackageInfoOut (packages db))
739 if isPermissionError e
740 then die (filename ++ ": you don't have permission to modify this file")
743 -- -----------------------------------------------------------------------------
744 -- Exposing, Hiding, Unregistering are all similar
746 exposePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
747 exposePackage = modifyPackage (\p -> ModifyPackage p{exposed=True})
749 hidePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
750 hidePackage = modifyPackage (\p -> ModifyPackage p{exposed=False})
752 unregisterPackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
753 unregisterPackage = modifyPackage RemovePackage
756 :: (InstalledPackageInfo -> DBOp)
762 modifyPackage fn pkgid verbosity my_flags force = do
763 (db_stack, Just _to_modify, _flag_dbs) <-
764 getPkgDatabases verbosity True{-modify-} True{-use cache-} my_flags
766 (db, ps) <- fmap head $ findPackagesByDB db_stack (Id pkgid)
768 db_name = location db
771 pids = map sourcePackageId ps
773 cmds = [ fn pkg | pkg <- pkgs, sourcePackageId pkg `elem` pids ]
774 new_db = updateInternalDB db cmds
776 old_broken = brokenPackages (allPackagesInStack db_stack)
777 rest_of_stack = filter ((/= db_name) . location) db_stack
778 new_stack = new_db : rest_of_stack
779 new_broken = map sourcePackageId (brokenPackages (allPackagesInStack new_stack))
780 newly_broken = filter (`notElem` map sourcePackageId old_broken) new_broken
782 when (not (null newly_broken)) $
783 dieOrForceAll force ("unregistering " ++ display pkgid ++
784 " would break the following packages: "
785 ++ unwords (map display newly_broken))
787 changeDB verbosity cmds db
789 recache :: Verbosity -> [Flag] -> IO ()
790 recache verbosity my_flags = do
791 (db_stack, Just to_modify, _flag_dbs) <-
792 getPkgDatabases verbosity True{-modify-} False{-no cache-} my_flags
794 db_to_operate_on = my_head "recache" $
795 filter ((== to_modify).location) db_stack
797 changeDB verbosity [] db_to_operate_on
799 -- -----------------------------------------------------------------------------
802 listPackages :: Verbosity -> [Flag] -> Maybe PackageArg
803 -> Maybe (String->Bool)
805 listPackages verbosity my_flags mPackageName mModuleName = do
806 let simple_output = FlagSimpleOutput `elem` my_flags
807 (db_stack, _, flag_db_stack) <-
808 getPkgDatabases verbosity False True{-use cache-} my_flags
810 let db_stack_filtered -- if a package is given, filter out all other packages
811 | Just this <- mPackageName =
812 [ db{ packages = filter (this `matchesPkg`) (packages db) }
813 | db <- flag_db_stack ]
814 | Just match <- mModuleName = -- packages which expose mModuleName
815 [ db{ packages = filter (match `exposedInPkg`) (packages db) }
816 | db <- flag_db_stack ]
817 | otherwise = flag_db_stack
820 = [ db{ packages = sort_pkgs (packages db) }
821 | db <- db_stack_filtered ]
822 where sort_pkgs = sortBy cmpPkgIds
823 cmpPkgIds pkg1 pkg2 =
824 case pkgName p1 `compare` pkgName p2 of
827 EQ -> pkgVersion p1 `compare` pkgVersion p2
828 where (p1,p2) = (sourcePackageId pkg1, sourcePackageId pkg2)
830 stack = reverse db_stack_sorted
832 match `exposedInPkg` pkg = any match (map display $ exposedModules pkg)
834 pkg_map = allPackagesInStack db_stack
835 broken = map sourcePackageId (brokenPackages pkg_map)
837 show_normal PackageDB{ location = db_name, packages = pkg_confs } =
838 hPutStrLn stdout $ unlines ((db_name ++ ":") : map (" " ++) pp_pkgs)
840 pp_pkgs = map pp_pkg pkg_confs
842 | sourcePackageId p `elem` broken = printf "{%s}" doc
844 | otherwise = printf "(%s)" doc
845 where doc | verbosity >= Verbose = printf "%s (%s)" pkg ipid
848 InstalledPackageId ipid = installedPackageId p
849 pkg = display (sourcePackageId p)
851 show_simple = simplePackageList my_flags . allPackagesInStack
853 when (not (null broken) && not simple_output && verbosity /= Silent) $ do
854 prog <- getProgramName
855 warn ("WARNING: there are broken packages. Run '" ++ prog ++ " check' for more details.")
857 if simple_output then show_simple stack else do
859 #if defined(mingw32_HOST_OS) || defined(BOOTSTRAPPING)
860 mapM_ show_normal stack
863 show_colour withF db =
864 mconcat $ map (<#> termText "\n") $
865 (termText (location db) :
866 map (termText " " <#>) (map pp_pkg (packages db)))
869 | sourcePackageId p `elem` broken = withF Red doc
871 | otherwise = withF Blue doc
872 where doc | verbosity >= Verbose
873 = termText (printf "%s (%s)" pkg ipid)
877 InstalledPackageId ipid = installedPackageId p
878 pkg = display (sourcePackageId p)
880 is_tty <- hIsTerminalDevice stdout
882 then mapM_ show_normal stack
883 else do tty <- Terminfo.setupTermFromEnv
884 case Terminfo.getCapability tty withForegroundColor of
885 Nothing -> mapM_ show_normal stack
886 Just w -> runTermOutput tty $ mconcat $
887 map (show_colour w) stack
890 simplePackageList :: [Flag] -> [InstalledPackageInfo] -> IO ()
891 simplePackageList my_flags pkgs = do
892 let showPkg = if FlagNamesOnly `elem` my_flags then display . pkgName
894 strs = map showPkg $ sortBy compPkgIdVer $ map sourcePackageId pkgs
895 when (not (null pkgs)) $
896 hPutStrLn stdout $ concat $ intersperse " " strs
898 showPackageDot :: Verbosity -> [Flag] -> IO ()
899 showPackageDot verbosity myflags = do
900 (_, _, flag_db_stack) <-
901 getPkgDatabases verbosity False True{-use cache-} myflags
903 let all_pkgs = allPackagesInStack flag_db_stack
904 ipix = PackageIndex.fromList all_pkgs
907 let quote s = '"':s ++ "\""
908 mapM_ putStrLn [ quote from ++ " -> " ++ quote to
910 let from = display (sourcePackageId p),
912 Just dep <- [PackageIndex.lookupInstalledPackageId ipix depid],
913 let to = display (sourcePackageId dep)
917 -- -----------------------------------------------------------------------------
918 -- Prints the highest (hidden or exposed) version of a package
920 latestPackage :: Verbosity -> [Flag] -> PackageIdentifier -> IO ()
921 latestPackage verbosity my_flags pkgid = do
922 (_, _, flag_db_stack) <-
923 getPkgDatabases verbosity False True{-use cache-} my_flags
925 ps <- findPackages flag_db_stack (Id pkgid)
926 show_pkg (sortBy compPkgIdVer (map sourcePackageId ps))
928 show_pkg [] = die "no matches"
929 show_pkg pids = hPutStrLn stdout (display (last pids))
931 -- -----------------------------------------------------------------------------
934 describePackage :: Verbosity -> [Flag] -> PackageArg -> IO ()
935 describePackage verbosity my_flags pkgarg = do
936 (_, _, flag_db_stack) <-
937 getPkgDatabases verbosity False True{-use cache-} my_flags
938 ps <- findPackages flag_db_stack pkgarg
941 dumpPackages :: Verbosity -> [Flag] -> IO ()
942 dumpPackages verbosity my_flags = do
943 (_, _, flag_db_stack) <-
944 getPkgDatabases verbosity False True{-use cache-} my_flags
945 doDump (allPackagesInStack flag_db_stack)
947 doDump :: [InstalledPackageInfo] -> IO ()
949 -- fix the encoding to UTF-8, since this is an interchange format
950 hSetEncoding stdout utf8
951 mapM_ putStrLn . intersperse "---" . map showInstalledPackageInfo $ pkgs
953 -- PackageId is can have globVersion for the version
954 findPackages :: PackageDBStack -> PackageArg -> IO [InstalledPackageInfo]
955 findPackages db_stack pkgarg
956 = fmap (concatMap snd) $ findPackagesByDB db_stack pkgarg
958 findPackagesByDB :: PackageDBStack -> PackageArg
959 -> IO [(PackageDB, [InstalledPackageInfo])]
960 findPackagesByDB db_stack pkgarg
961 = case [ (db, matched)
963 let matched = filter (pkgarg `matchesPkg`) (packages db),
964 not (null matched) ] of
965 [] -> die ("cannot find package " ++ pkg_msg pkgarg)
968 pkg_msg (Id pkgid) = display pkgid
969 pkg_msg (Substring pkgpat _) = "matching " ++ pkgpat
971 matches :: PackageIdentifier -> PackageIdentifier -> Bool
973 = (pkgName pid == pkgName pid')
974 && (pkgVersion pid == pkgVersion pid' || not (realVersion pid))
976 realVersion :: PackageIdentifier -> Bool
977 realVersion pkgid = versionBranch (pkgVersion pkgid) /= []
978 -- when versionBranch == [], this is a glob
980 matchesPkg :: PackageArg -> InstalledPackageInfo -> Bool
981 (Id pid) `matchesPkg` pkg = pid `matches` sourcePackageId pkg
982 (Substring _ m) `matchesPkg` pkg = m (display (sourcePackageId pkg))
984 compPkgIdVer :: PackageIdentifier -> PackageIdentifier -> Ordering
985 compPkgIdVer p1 p2 = pkgVersion p1 `compare` pkgVersion p2
987 -- -----------------------------------------------------------------------------
990 describeField :: Verbosity -> [Flag] -> PackageArg -> [String] -> IO ()
991 describeField verbosity my_flags pkgarg fields = do
992 (_, _, flag_db_stack) <-
993 getPkgDatabases verbosity False True{-use cache-} my_flags
994 fns <- toFields fields
995 ps <- findPackages flag_db_stack pkgarg
996 let top_dir = takeDirectory (location (last flag_db_stack))
997 mapM_ (selectFields fns) (mungePackagePaths top_dir ps)
998 where toFields [] = return []
999 toFields (f:fs) = case toField f of
1000 Nothing -> die ("unknown field: " ++ f)
1001 Just fn -> do fns <- toFields fs
1003 selectFields fns info = mapM_ (\fn->putStrLn (fn info)) fns
1005 mungePackagePaths :: String -> [InstalledPackageInfo] -> [InstalledPackageInfo]
1006 -- Replace the strings "$topdir" and "$httptopdir" at the beginning of a path
1007 -- with the current topdir (obtained from the -B option).
1008 mungePackagePaths top_dir ps = map munge_pkg ps
1010 munge_pkg p = p{ importDirs = munge_paths (importDirs p),
1011 includeDirs = munge_paths (includeDirs p),
1012 libraryDirs = munge_paths (libraryDirs p),
1013 frameworkDirs = munge_paths (frameworkDirs p),
1014 haddockInterfaces = munge_paths (haddockInterfaces p),
1015 haddockHTMLs = munge_paths (haddockHTMLs p)
1018 munge_paths = map munge_path
1021 | Just p' <- maybePrefixMatch "$topdir" p = top_dir ++ p'
1022 | Just p' <- maybePrefixMatch "$httptopdir" p = toHttpPath top_dir ++ p'
1025 toHttpPath p = "file:///" ++ p
1027 maybePrefixMatch :: String -> String -> Maybe String
1028 maybePrefixMatch [] rest = Just rest
1029 maybePrefixMatch (_:_) [] = Nothing
1030 maybePrefixMatch (p:pat) (r:rest)
1031 | p == r = maybePrefixMatch pat rest
1032 | otherwise = Nothing
1034 toField :: String -> Maybe (InstalledPackageInfo -> String)
1035 -- backwards compatibility:
1036 toField "import_dirs" = Just $ strList . importDirs
1037 toField "source_dirs" = Just $ strList . importDirs
1038 toField "library_dirs" = Just $ strList . libraryDirs
1039 toField "hs_libraries" = Just $ strList . hsLibraries
1040 toField "extra_libraries" = Just $ strList . extraLibraries
1041 toField "include_dirs" = Just $ strList . includeDirs
1042 toField "c_includes" = Just $ strList . includes
1043 toField "package_deps" = Just $ strList . map display. depends
1044 toField "extra_cc_opts" = Just $ strList . ccOptions
1045 toField "extra_ld_opts" = Just $ strList . ldOptions
1046 toField "framework_dirs" = Just $ strList . frameworkDirs
1047 toField "extra_frameworks"= Just $ strList . frameworks
1048 toField s = showInstalledPackageInfoField s
1050 strList :: [String] -> String
1054 -- -----------------------------------------------------------------------------
1055 -- Check: Check consistency of installed packages
1057 checkConsistency :: Verbosity -> [Flag] -> IO ()
1058 checkConsistency verbosity my_flags = do
1059 (db_stack, _, _) <- getPkgDatabases verbosity True True{-use cache-} my_flags
1060 -- check behaves like modify for the purposes of deciding which
1061 -- databases to use, because ordering is important.
1063 let simple_output = FlagSimpleOutput `elem` my_flags
1065 let pkgs = allPackagesInStack db_stack
1068 (_,es,ws) <- runValidate $ checkPackageConfig p db_stack False True
1070 then do when (not simple_output) $ do
1071 _ <- reportValidateErrors [] ws "" Nothing
1075 when (not simple_output) $ do
1076 reportError ("There are problems in package " ++ display (sourcePackageId p) ++ ":")
1077 _ <- reportValidateErrors es ws " " Nothing
1081 broken_pkgs <- concat `fmap` mapM checkPackage pkgs
1083 let filterOut pkgs1 pkgs2 = filter not_in pkgs2
1084 where not_in p = sourcePackageId p `notElem` all_ps
1085 all_ps = map sourcePackageId pkgs1
1087 let not_broken_pkgs = filterOut broken_pkgs pkgs
1088 (_, trans_broken_pkgs) = closure [] not_broken_pkgs
1089 all_broken_pkgs = broken_pkgs ++ trans_broken_pkgs
1091 when (not (null all_broken_pkgs)) $ do
1093 then simplePackageList my_flags all_broken_pkgs
1095 reportError ("\nThe following packages are broken, either because they have a problem\n"++
1096 "listed above, or because they depend on a broken package.")
1097 mapM_ (hPutStrLn stderr . display . sourcePackageId) all_broken_pkgs
1099 when (not (null all_broken_pkgs)) $ exitWith (ExitFailure 1)
1102 closure :: [InstalledPackageInfo] -> [InstalledPackageInfo]
1103 -> ([InstalledPackageInfo], [InstalledPackageInfo])
1104 closure pkgs db_stack = go pkgs db_stack
1106 go avail not_avail =
1107 case partition (depsAvailable avail) not_avail of
1108 ([], not_avail') -> (avail, not_avail')
1109 (new_avail, not_avail') -> go (new_avail ++ avail) not_avail'
1111 depsAvailable :: [InstalledPackageInfo] -> InstalledPackageInfo
1113 depsAvailable pkgs_ok pkg = null dangling
1114 where dangling = filter (`notElem` pids) (depends pkg)
1115 pids = map installedPackageId pkgs_ok
1117 -- we want mutually recursive groups of package to show up
1118 -- as broken. (#1750)
1120 brokenPackages :: [InstalledPackageInfo] -> [InstalledPackageInfo]
1121 brokenPackages pkgs = snd (closure [] pkgs)
1123 -- -----------------------------------------------------------------------------
1124 -- Manipulating package.conf files
1126 type InstalledPackageInfoString = InstalledPackageInfo_ String
1128 convertPackageInfoOut :: InstalledPackageInfo -> InstalledPackageInfoString
1129 convertPackageInfoOut
1130 (pkgconf@(InstalledPackageInfo { exposedModules = e,
1131 hiddenModules = h })) =
1132 pkgconf{ exposedModules = map display e,
1133 hiddenModules = map display h }
1135 convertPackageInfoIn :: InstalledPackageInfoString -> InstalledPackageInfo
1136 convertPackageInfoIn
1137 (pkgconf@(InstalledPackageInfo { exposedModules = e,
1138 hiddenModules = h })) =
1139 pkgconf{ exposedModules = map convert e,
1140 hiddenModules = map convert h }
1141 where convert = fromJust . simpleParse
1143 writeNewConfig :: Verbosity -> FilePath -> [InstalledPackageInfo] -> IO ()
1144 writeNewConfig verbosity filename ipis = do
1145 when (verbosity >= Normal) $
1146 hPutStr stdout "Writing new package config file... "
1147 createDirectoryIfMissing True $ takeDirectory filename
1148 let shown = concat $ intersperse ",\n "
1149 $ map (show . convertPackageInfoOut) ipis
1150 fileContents = "[" ++ shown ++ "\n]"
1151 writeFileUtf8Atomic filename fileContents
1153 if isPermissionError e
1154 then die (filename ++ ": you don't have permission to modify this file")
1156 when (verbosity >= Normal) $
1157 hPutStrLn stdout "done."
1159 -----------------------------------------------------------------------------
1160 -- Sanity-check a new package config, and automatically build GHCi libs
1163 type ValidateError = (Force,String)
1164 type ValidateWarning = String
1166 newtype Validate a = V { runValidate :: IO (a, [ValidateError],[ValidateWarning]) }
1168 instance Monad Validate where
1169 return a = V $ return (a, [], [])
1171 (a, es, ws) <- runValidate m
1172 (b, es', ws') <- runValidate (k a)
1173 return (b,es++es',ws++ws')
1175 verror :: Force -> String -> Validate ()
1176 verror f s = V (return ((),[(f,s)],[]))
1178 vwarn :: String -> Validate ()
1179 vwarn s = V (return ((),[],["Warning: " ++ s]))
1181 liftIO :: IO a -> Validate a
1182 liftIO k = V (k >>= \a -> return (a,[],[]))
1184 -- returns False if we should die
1185 reportValidateErrors :: [ValidateError] -> [ValidateWarning]
1186 -> String -> Maybe Force -> IO Bool
1187 reportValidateErrors es ws prefix mb_force = do
1188 mapM_ (warn . (prefix++)) ws
1189 oks <- mapM report es
1193 | Just force <- mb_force
1195 then do reportError (prefix ++ s ++ " (ignoring)")
1197 else if f < CannotForce
1198 then do reportError (prefix ++ s ++ " (use --force to override)")
1200 else do reportError err
1202 | otherwise = do reportError err
1207 validatePackageConfig :: InstalledPackageInfo
1209 -> Bool -- auto-ghc-libs
1210 -> Bool -- update, or check
1213 validatePackageConfig pkg db_stack auto_ghci_libs update force = do
1214 (_,es,ws) <- runValidate $ checkPackageConfig pkg db_stack auto_ghci_libs update
1215 ok <- reportValidateErrors es ws (display (sourcePackageId pkg) ++ ": ") (Just force)
1216 when (not ok) $ exitWith (ExitFailure 1)
1218 checkPackageConfig :: InstalledPackageInfo
1220 -> Bool -- auto-ghc-libs
1221 -> Bool -- update, or check
1223 checkPackageConfig pkg db_stack auto_ghci_libs update = do
1224 checkInstalledPackageId pkg db_stack update
1226 checkDuplicates db_stack pkg update
1227 mapM_ (checkDep db_stack) (depends pkg)
1228 checkDuplicateDepends (depends pkg)
1229 mapM_ (checkDir False "import-dirs") (importDirs pkg)
1230 mapM_ (checkDir True "library-dirs") (libraryDirs pkg)
1231 mapM_ (checkDir True "include-dirs") (includeDirs pkg)
1233 mapM_ (checkHSLib (libraryDirs pkg) auto_ghci_libs) (hsLibraries pkg)
1234 -- ToDo: check these somehow?
1235 -- extra_libraries :: [String],
1236 -- c_includes :: [String],
1238 checkInstalledPackageId :: InstalledPackageInfo -> PackageDBStack -> Bool
1240 checkInstalledPackageId ipi db_stack update = do
1241 let ipid@(InstalledPackageId str) = installedPackageId ipi
1242 when (null str) $ verror CannotForce "missing id field"
1243 let dups = [ p | p <- allPackagesInStack db_stack,
1244 installedPackageId p == ipid ]
1245 when (not update && not (null dups)) $
1246 verror CannotForce $
1247 "package(s) with this id already exist: " ++
1248 unwords (map (display.packageId) dups)
1250 -- When the package name and version are put together, sometimes we can
1251 -- end up with a package id that cannot be parsed. This will lead to
1252 -- difficulties when the user wants to refer to the package later, so
1253 -- we check that the package id can be parsed properly here.
1254 checkPackageId :: InstalledPackageInfo -> Validate ()
1255 checkPackageId ipi =
1256 let str = display (sourcePackageId ipi) in
1257 case [ x :: PackageIdentifier | (x,ys) <- readP_to_S parse str, all isSpace ys ] of
1259 [] -> verror CannotForce ("invalid package identifier: " ++ str)
1260 _ -> verror CannotForce ("ambiguous package identifier: " ++ str)
1262 checkDuplicates :: PackageDBStack -> InstalledPackageInfo -> Bool -> Validate ()
1263 checkDuplicates db_stack pkg update = do
1265 pkgid = sourcePackageId pkg
1266 pkgs = packages (head db_stack)
1268 -- Check whether this package id already exists in this DB
1270 when (not update && (pkgid `elem` map sourcePackageId pkgs)) $
1271 verror CannotForce $
1272 "package " ++ display pkgid ++ " is already installed"
1275 uncasep = map toLower . display
1276 dups = filter ((== uncasep pkgid) . uncasep) (map sourcePackageId pkgs)
1278 when (not update && not (null dups)) $ verror ForceAll $
1279 "Package names may be treated case-insensitively in the future.\n"++
1280 "Package " ++ display pkgid ++
1281 " overlaps with: " ++ unwords (map display dups)
1284 checkDir :: Bool -> String -> String -> Validate ()
1285 checkDir warn_only thisfield d
1286 | "$topdir" `isPrefixOf` d = return ()
1287 | "$httptopdir" `isPrefixOf` d = return ()
1288 -- can't check these, because we don't know what $(http)topdir is
1289 | isRelative d = verror ForceFiles $
1290 thisfield ++ ": " ++ d ++ " is a relative path"
1291 -- relative paths don't make any sense; #4134
1293 there <- liftIO $ doesDirectoryExist d
1295 let msg = thisfield ++ ": " ++ d ++ " doesn't exist or isn't a directory"
1299 else verror ForceFiles msg
1301 checkDep :: PackageDBStack -> InstalledPackageId -> Validate ()
1302 checkDep db_stack pkgid
1303 | pkgid `elem` pkgids = return ()
1304 | otherwise = verror ForceAll ("dependency \"" ++ display pkgid
1305 ++ "\" doesn't exist")
1307 all_pkgs = allPackagesInStack db_stack
1308 pkgids = map installedPackageId all_pkgs
1310 checkDuplicateDepends :: [InstalledPackageId] -> Validate ()
1311 checkDuplicateDepends deps
1312 | null dups = return ()
1313 | otherwise = verror ForceAll ("package has duplicate dependencies: " ++
1314 unwords (map display dups))
1316 dups = [ p | (p:_:_) <- group (sort deps) ]
1318 checkHSLib :: [String] -> Bool -> String -> Validate ()
1319 checkHSLib dirs auto_ghci_libs lib = do
1320 let batch_lib_file = "lib" ++ lib ++ ".a"
1321 m <- liftIO $ doesFileExistOnPath batch_lib_file dirs
1323 Nothing -> verror ForceFiles ("cannot find " ++ batch_lib_file ++
1325 Just dir -> liftIO $ checkGHCiLib dir batch_lib_file lib auto_ghci_libs
1327 doesFileExistOnPath :: String -> [FilePath] -> IO (Maybe FilePath)
1328 doesFileExistOnPath file path = go path
1329 where go [] = return Nothing
1330 go (p:ps) = do b <- doesFileExistIn file p
1331 if b then return (Just p) else go ps
1333 doesFileExistIn :: String -> String -> IO Bool
1334 doesFileExistIn lib d
1335 | "$topdir" `isPrefixOf` d = return True
1336 | "$httptopdir" `isPrefixOf` d = return True
1337 | otherwise = doesFileExist (d </> lib)
1339 checkModules :: InstalledPackageInfo -> Validate ()
1340 checkModules pkg = do
1341 mapM_ findModule (exposedModules pkg ++ hiddenModules pkg)
1343 findModule modl = do
1344 -- there's no .hi file for GHC.Prim
1345 if modl == fromString "GHC.Prim" then return () else do
1346 let file = toFilePath modl <.> "hi"
1347 m <- liftIO $ doesFileExistOnPath file (importDirs pkg)
1348 when (isNothing m) $
1349 verror ForceFiles ("file " ++ file ++ " is missing")
1351 checkGHCiLib :: String -> String -> String -> Bool -> IO ()
1352 checkGHCiLib batch_lib_dir batch_lib_file lib auto_build
1353 | auto_build = autoBuildGHCiLib batch_lib_dir batch_lib_file ghci_lib_file
1354 | otherwise = return ()
1356 ghci_lib_file = lib <.> "o"
1358 -- automatically build the GHCi version of a batch lib,
1359 -- using ld --whole-archive.
1361 autoBuildGHCiLib :: String -> String -> String -> IO ()
1362 autoBuildGHCiLib dir batch_file ghci_file = do
1363 let ghci_lib_file = dir ++ '/':ghci_file
1364 batch_lib_file = dir ++ '/':batch_file
1365 hPutStr stderr ("building GHCi library " ++ ghci_lib_file ++ "...")
1366 #if defined(darwin_HOST_OS)
1367 r <- rawSystem "ld" ["-r","-x","-o",ghci_lib_file,"-all_load",batch_lib_file]
1368 #elif defined(mingw32_HOST_OS)
1369 execDir <- getLibDir
1370 r <- rawSystem (maybe "" (++"/gcc-lib/") execDir++"ld") ["-r","-x","-o",ghci_lib_file,"--whole-archive",batch_lib_file]
1372 r <- rawSystem "ld" ["-r","-x","-o",ghci_lib_file,"--whole-archive",batch_lib_file]
1374 when (r /= ExitSuccess) $ exitWith r
1375 hPutStrLn stderr (" done.")
1377 -- -----------------------------------------------------------------------------
1378 -- Searching for modules
1382 findModules :: [FilePath] -> IO [String]
1384 mms <- mapM searchDir paths
1387 searchDir path prefix = do
1388 fs <- getDirectoryEntries path `catchIO` \_ -> return []
1389 searchEntries path prefix fs
1391 searchEntries path prefix [] = return []
1392 searchEntries path prefix (f:fs)
1393 | looks_like_a_module = do
1394 ms <- searchEntries path prefix fs
1395 return (prefix `joinModule` f : ms)
1396 | looks_like_a_component = do
1397 ms <- searchDir (path </> f) (prefix `joinModule` f)
1398 ms' <- searchEntries path prefix fs
1401 searchEntries path prefix fs
1404 (base,suffix) = splitFileExt f
1405 looks_like_a_module =
1406 suffix `elem` haskell_suffixes &&
1407 all okInModuleName base
1408 looks_like_a_component =
1409 null suffix && all okInModuleName base
1415 -- ---------------------------------------------------------------------------
1416 -- expanding environment variables in the package configuration
1418 expandEnvVars :: String -> Force -> IO String
1419 expandEnvVars str0 force = go str0 ""
1421 go "" acc = return $! reverse acc
1422 go ('$':'{':str) acc | (var, '}':rest) <- break close str
1423 = do value <- lookupEnvVar var
1424 go rest (reverse value ++ acc)
1425 where close c = c == '}' || c == '\n' -- don't span newlines
1429 lookupEnvVar :: String -> IO String
1431 catchIO (System.Environment.getEnv nm)
1432 (\ _ -> do dieOrForceAll force ("Unable to expand variable " ++
1436 -----------------------------------------------------------------------------
1438 getProgramName :: IO String
1439 getProgramName = liftM (`withoutSuffix` ".bin") getProgName
1440 where str `withoutSuffix` suff
1441 | suff `isSuffixOf` str = take (length str - length suff) str
1444 bye :: String -> IO a
1445 bye s = putStr s >> exitWith ExitSuccess
1447 die :: String -> IO a
1450 dieWith :: Int -> String -> IO a
1453 prog <- getProgramName
1454 hPutStrLn stderr (prog ++ ": " ++ s)
1455 exitWith (ExitFailure ec)
1457 dieOrForceAll :: Force -> String -> IO ()
1458 dieOrForceAll ForceAll s = ignoreError s
1459 dieOrForceAll _other s = dieForcible s
1461 warn :: String -> IO ()
1464 ignoreError :: String -> IO ()
1465 ignoreError s = reportError (s ++ " (ignoring)")
1467 reportError :: String -> IO ()
1468 reportError s = do hFlush stdout; hPutStrLn stderr s
1470 dieForcible :: String -> IO ()
1471 dieForcible s = die (s ++ " (use --force to override)")
1473 my_head :: String -> [a] -> a
1474 my_head s [] = error s
1475 my_head _ (x : _) = x
1477 -----------------------------------------
1478 -- Cut and pasted from ghc/compiler/main/SysTools
1480 #if defined(mingw32_HOST_OS)
1481 subst :: Char -> Char -> String -> String
1482 subst a b ls = map (\ x -> if x == a then b else x) ls
1484 unDosifyPath :: FilePath -> FilePath
1485 unDosifyPath xs = subst '\\' '/' xs
1487 getLibDir :: IO (Maybe String)
1488 getLibDir = fmap (fmap (</> "lib")) $ getExecDir "/bin/ghc-pkg.exe"
1490 -- (getExecDir cmd) returns the directory in which the current
1491 -- executable, which should be called 'cmd', is running
1492 -- So if the full path is /a/b/c/d/e, and you pass "d/e" as cmd,
1493 -- you'll get "/a/b/c" back as the result
1494 getExecDir :: String -> IO (Maybe String)
1496 getExecPath >>= maybe (return Nothing) removeCmdSuffix
1497 where initN n = reverse . drop n . reverse
1498 removeCmdSuffix = return . Just . initN (length cmd) . unDosifyPath
1500 getExecPath :: IO (Maybe String)
1501 getExecPath = try_size 2048 -- plenty, PATH_MAX is 512 under Win32.
1503 try_size size = allocaArray (fromIntegral size) $ \buf -> do
1504 ret <- c_GetModuleFileName nullPtr buf size
1507 _ | ret < size -> fmap Just $ peekCWString buf
1508 | otherwise -> try_size (size * 2)
1510 foreign import stdcall unsafe "windows.h GetModuleFileNameW"
1511 c_GetModuleFileName :: Ptr () -> CWString -> Word32 -> IO Word32
1513 getLibDir :: IO (Maybe String)
1514 getLibDir = return Nothing
1517 -----------------------------------------
1518 -- Adapted from ghc/compiler/utils/Panic
1520 installSignalHandlers :: IO ()
1521 installSignalHandlers = do
1522 threadid <- myThreadId
1524 interrupt = Exception.throwTo threadid
1525 (Exception.ErrorCall "interrupted")
1527 #if !defined(mingw32_HOST_OS)
1528 _ <- installHandler sigQUIT (Catch interrupt) Nothing
1529 _ <- installHandler sigINT (Catch interrupt) Nothing
1532 -- GHC 6.3+ has support for console events on Windows
1533 -- NOTE: running GHCi under a bash shell for some reason requires
1534 -- you to press Ctrl-Break rather than Ctrl-C to provoke
1535 -- an interrupt. Ctrl-C is getting blocked somewhere, I don't know
1536 -- why --SDM 17/12/2004
1537 let sig_handler ControlC = interrupt
1538 sig_handler Break = interrupt
1539 sig_handler _ = return ()
1541 _ <- installHandler (Catch sig_handler)
1545 #if mingw32_HOST_OS || mingw32_TARGET_OS
1546 throwIOIO :: Exception.IOException -> IO a
1547 throwIOIO = Exception.throwIO
1550 catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a
1551 catchIO = Exception.catch
1553 catchError :: IO a -> (String -> IO a) -> IO a
1554 catchError io handler = io `Exception.catch` handler'
1555 where handler' (Exception.ErrorCall err) = handler err
1557 tryIO :: IO a -> IO (Either Exception.IOException a)
1558 tryIO = Exception.try
1560 writeBinaryFileAtomic :: Bin.Binary a => FilePath -> a -> IO ()
1561 writeBinaryFileAtomic targetFile obj =
1562 withFileAtomic targetFile $ \h -> do
1563 hSetBinaryMode h True
1564 B.hPutStr h (Bin.encode obj)
1566 writeFileUtf8Atomic :: FilePath -> String -> IO ()
1567 writeFileUtf8Atomic targetFile content =
1568 withFileAtomic targetFile $ \h -> do
1572 -- copied from Cabal's Distribution.Simple.Utils, except that we want
1573 -- to use text files here, rather than binary files.
1574 withFileAtomic :: FilePath -> (Handle -> IO ()) -> IO ()
1575 withFileAtomic targetFile write_content = do
1576 (newFile, newHandle) <- openNewFile targetDir template
1577 do write_content newHandle
1579 #if mingw32_HOST_OS || mingw32_TARGET_OS
1580 renameFile newFile targetFile
1581 -- If the targetFile exists then renameFile will fail
1582 `catchIO` \err -> do
1583 exists <- doesFileExist targetFile
1585 then do removeFileSafe targetFile
1586 -- Big fat hairy race condition
1587 renameFile newFile targetFile
1588 -- If the removeFile succeeds and the renameFile fails
1589 -- then we've lost the atomic property.
1592 renameFile newFile targetFile
1594 `Exception.onException` do hClose newHandle
1595 removeFileSafe newFile
1597 template = targetName <.> "tmp"
1598 targetDir | null targetDir_ = "."
1599 | otherwise = targetDir_
1600 --TODO: remove this when takeDirectory/splitFileName is fixed
1601 -- to always return a valid dir
1602 (targetDir_,targetName) = splitFileName targetFile
1604 openNewFile :: FilePath -> String -> IO (FilePath, Handle)
1605 openNewFile dir template = do
1606 -- this was added to System.IO in 6.12.1
1607 -- we must use this version because the version below opens the file
1609 openTempFileWithDefaultPermissions dir template
1611 -- | The function splits the given string to substrings
1612 -- using 'isSearchPathSeparator'.
1613 parseSearchPath :: String -> [FilePath]
1614 parseSearchPath path = split path
1616 split :: String -> [String]
1620 _:rest -> chunk : split rest
1624 #ifdef mingw32_HOST_OS
1625 ('\"':xs@(_:_)) | last xs == '\"' -> init xs
1629 (chunk', rest') = break isSearchPathSeparator s
1631 readUTF8File :: FilePath -> IO String
1632 readUTF8File file = do
1633 h <- openFile file ReadMode
1634 -- fix the encoding to UTF-8
1638 -- removeFileSave doesn't throw an exceptions, if the file is already deleted
1639 removeFileSafe :: FilePath -> IO ()
1641 removeFile fn `catchIO` \ e ->
1642 when (not $ isDoesNotExistError e) $ ioError e