1 {-# OPTIONS -fglasgow-exts -cpp #-}
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 #include "../../includes/ghcconfig.h"
32 import System.Console.GetOpt
33 #if __GLASGOW_HASKELL__ >= 609
34 import qualified Control.Exception as Exception
36 import qualified Control.Exception.Extensible as Exception
40 import Data.Char ( isSpace, toLower )
42 import System.Directory ( doesDirectoryExist, getDirectoryContents,
43 doesFileExist, renameFile, removeFile )
44 import System.Exit ( exitWith, ExitCode(..) )
45 import System.Environment ( getArgs, getProgName, getEnv )
47 import System.IO.Error (try)
49 import Control.Concurrent
51 import qualified Data.ByteString.Lazy as B
52 import qualified Data.Binary as Bin
53 import qualified Data.Binary.Get as Bin
57 #ifdef mingw32_HOST_OS
58 import GHC.ConsoleHandler
60 import System.Posix hiding (fdToHandle)
63 import IO ( isPermissionError )
64 import System.Posix.Internals
65 #if __GLASGOW_HASKELL__ >= 611
66 import GHC.IO.Handle.FD (fdToHandle)
68 import GHC.Handle (fdToHandle)
72 import System.Process(runInteractiveCommand)
73 import qualified System.Info(os)
76 #if !defined(mingw32_HOST_OS) && __GLASGOW_HASKELL__ >= 611 && !defined(BOOTSTRAPPING)
77 import System.Console.Terminfo as Terminfo
80 -- -----------------------------------------------------------------------------
87 case getOpt Permute (flags ++ deprecFlags) args of
88 (cli,_,[]) | FlagHelp `elem` cli -> do
89 prog <- getProgramName
90 bye (usageInfo (usageHeader prog) flags)
91 (cli,_,[]) | FlagVersion `elem` cli ->
94 case getVerbosity Normal cli of
95 Right v -> runit v cli nonopts
98 prog <- getProgramName
99 die (concat errors ++ usageInfo (usageHeader prog) flags)
101 -- -----------------------------------------------------------------------------
102 -- Command-line syntax
109 | FlagConfig FilePath
110 | FlagGlobalConfig FilePath
118 | FlagVerbosity (Maybe String)
121 flags :: [OptDescr Flag]
123 Option [] ["user"] (NoArg FlagUser)
124 "use the current user's package database",
125 Option [] ["global"] (NoArg FlagGlobal)
126 "use the global package database",
127 Option ['f'] ["package-conf"] (ReqArg FlagConfig "FILE")
128 "use the specified package config file",
129 Option [] ["global-conf"] (ReqArg FlagGlobalConfig "FILE")
130 "location of the global package config",
131 Option [] ["no-user-package-conf"] (NoArg FlagNoUserDb)
132 "never read the user package database",
133 Option [] ["force"] (NoArg FlagForce)
134 "ignore missing dependencies, directories, and libraries",
135 Option [] ["force-files"] (NoArg FlagForceFiles)
136 "ignore missing directories and libraries only",
137 Option ['g'] ["auto-ghci-libs"] (NoArg FlagAutoGHCiLibs)
138 "automatically build libs for GHCi (with register)",
139 Option ['?'] ["help"] (NoArg FlagHelp)
140 "display this help and exit",
141 Option ['V'] ["version"] (NoArg FlagVersion)
142 "output version information and exit",
143 Option [] ["simple-output"] (NoArg FlagSimpleOutput)
144 "print output in easy-to-parse format for some commands",
145 Option [] ["names-only"] (NoArg FlagNamesOnly)
146 "only print package names, not versions; can only be used with list --simple-output",
147 Option [] ["ignore-case"] (NoArg FlagIgnoreCase)
148 "ignore case for substring matching",
149 Option ['v'] ["verbose"] (OptArg FlagVerbosity "Verbosity")
150 "verbosity level (0-2, default 1)"
153 data Verbosity = Silent | Normal | Verbose
154 deriving (Show, Eq, Ord)
156 getVerbosity :: Verbosity -> [Flag] -> Either String Verbosity
157 getVerbosity v [] = Right v
158 getVerbosity _ (FlagVerbosity Nothing : fs) = getVerbosity Verbose fs
159 getVerbosity _ (FlagVerbosity (Just "0") : fs) = getVerbosity Silent fs
160 getVerbosity _ (FlagVerbosity (Just "1") : fs) = getVerbosity Normal fs
161 getVerbosity _ (FlagVerbosity (Just "2") : fs) = getVerbosity Verbose fs
162 getVerbosity _ (FlagVerbosity v : _) = Left ("Bad verbosity: " ++ show v)
163 getVerbosity v (_ : fs) = getVerbosity v fs
165 deprecFlags :: [OptDescr Flag]
167 -- put deprecated flags here
170 ourCopyright :: String
171 ourCopyright = "GHC package manager version " ++ Version.version ++ "\n"
173 usageHeader :: String -> String
174 usageHeader prog = substProg prog $
176 " $p init {path}\n" ++
177 " Create and initialise a package database at the location {path}.\n" ++
178 " Packages can be registered in the new database using the register\n" ++
179 " command with --package-conf={path}. To use the new database with GHC,\n" ++
180 " use GHC's -package-conf flag.\n" ++
182 " $p register {filename | -}\n" ++
183 " Register the package using the specified installed package\n" ++
184 " description. The syntax for the latter is given in the $p\n" ++
185 " documentation. The input file should be encoded in UTF-8.\n" ++
187 " $p update {filename | -}\n" ++
188 " Register the package, overwriting any other package with the\n" ++
189 " same name. The input file should be encoded in UTF-8.\n" ++
191 " $p unregister {pkg-id}\n" ++
192 " Unregister the specified package.\n" ++
194 " $p expose {pkg-id}\n" ++
195 " Expose the specified package.\n" ++
197 " $p hide {pkg-id}\n" ++
198 " Hide the specified package.\n" ++
200 " $p list [pkg]\n" ++
201 " List registered packages in the global database, and also the\n" ++
202 " user database if --user is given. If a package name is given\n" ++
203 " all the registered versions will be listed in ascending order.\n" ++
204 " Accepts the --simple-output flag.\n" ++
207 " Generate a graph of the package dependencies in a form suitable\n" ++
208 " for input for the graphviz tools. For example, to generate a PDF" ++
209 " of the dependency graph: ghc-pkg dot | tred | dot -Tpdf >pkgs.pdf" ++
211 " $p find-module {module}\n" ++
212 " List registered packages exposing module {module} in the global\n" ++
213 " database, and also the user database if --user is given.\n" ++
214 " All the registered versions will be listed in ascending order.\n" ++
215 " Accepts the --simple-output flag.\n" ++
217 " $p latest {pkg-id}\n" ++
218 " Prints the highest registered version of a package.\n" ++
221 " Check the consistency of package depenencies and list broken packages.\n" ++
222 " Accepts the --simple-output flag.\n" ++
224 " $p describe {pkg}\n" ++
225 " Give the registered description for the specified package. The\n" ++
226 " description is returned in precisely the syntax required by $p\n" ++
229 " $p field {pkg} {field}\n" ++
230 " Extract the specified field of the package description for the\n" ++
231 " specified package. Accepts comma-separated multiple fields.\n" ++
234 " Dump the registered description for every package. This is like\n" ++
235 " \"ghc-pkg describe '*'\", except that it is intended to be used\n" ++
236 " by tools that parse the results, rather than humans. The output is\n" ++
237 " always encoded in UTF-8, regardless of the current locale.\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 splitFields fields = unfoldr splitComma (',':fields)
281 where splitComma "" = Nothing
282 splitComma fs = Just $ break (==',') (tail fs)
284 substringCheck :: String -> Maybe (String -> Bool)
285 substringCheck "" = Nothing
286 substringCheck "*" = Just (const True)
287 substringCheck [_] = Nothing
288 substringCheck (h:t) =
289 case (h, init t, last t) of
290 ('*',s,'*') -> Just (isInfixOf (f s) . f)
291 ('*',_, _ ) -> Just (isSuffixOf (f t) . f)
292 ( _ ,s,'*') -> Just (isPrefixOf (f (h:s)) . f)
294 where f | FlagIgnoreCase `elem` cli = map toLower
297 glob x | System.Info.os=="mingw32" = do
298 -- glob echoes its argument, after win32 filename globbing
299 (_,o,_,_) <- runInteractiveCommand ("glob "++x)
300 txt <- hGetContents o
302 glob x | otherwise = return [x]
305 -- first, parse the command
308 -- dummy command to demonstrate usage and permit testing
309 -- without messing things up; use glob to selectively enable
310 -- windows filename globbing for file parameters
311 -- register, update, FlagGlobalConfig, FlagConfig; others?
312 ["glob", filename] -> do
314 glob filename >>= print
316 ["init", filename] ->
317 initPackageDB filename verbosity cli
318 ["register", filename] ->
319 registerPackage filename verbosity cli auto_ghci_libs False force
320 ["update", filename] ->
321 registerPackage filename verbosity cli auto_ghci_libs True force
322 ["unregister", pkgid_str] -> do
323 pkgid <- readGlobPkgId pkgid_str
324 unregisterPackage pkgid verbosity cli force
325 ["expose", pkgid_str] -> do
326 pkgid <- readGlobPkgId pkgid_str
327 exposePackage pkgid verbosity cli force
328 ["hide", pkgid_str] -> do
329 pkgid <- readGlobPkgId pkgid_str
330 hidePackage pkgid verbosity cli force
332 listPackages verbosity cli Nothing Nothing
333 ["list", pkgid_str] ->
334 case substringCheck pkgid_str of
335 Nothing -> do pkgid <- readGlobPkgId pkgid_str
336 listPackages verbosity cli (Just (Id pkgid)) Nothing
337 Just m -> listPackages verbosity cli (Just (Substring pkgid_str m)) Nothing
339 showPackageDot verbosity cli
340 ["find-module", moduleName] -> do
341 let match = maybe (==moduleName) id (substringCheck moduleName)
342 listPackages verbosity cli Nothing (Just match)
343 ["latest", pkgid_str] -> do
344 pkgid <- readGlobPkgId pkgid_str
345 latestPackage verbosity cli pkgid
346 ["describe", pkgid_str] ->
347 case substringCheck pkgid_str of
348 Nothing -> do pkgid <- readGlobPkgId pkgid_str
349 describePackage verbosity cli (Id pkgid)
350 Just m -> describePackage verbosity cli (Substring pkgid_str m)
351 ["field", pkgid_str, fields] ->
352 case substringCheck pkgid_str of
353 Nothing -> do pkgid <- readGlobPkgId pkgid_str
354 describeField verbosity cli (Id pkgid)
356 Just m -> describeField verbosity cli (Substring pkgid_str m)
359 checkConsistency verbosity cli
362 dumpPackages verbosity cli
365 recache verbosity cli
368 die ("missing command\n" ++
369 usageInfo (usageHeader prog) flags)
371 die ("command-line syntax error\n" ++
372 usageInfo (usageHeader prog) flags)
374 parseCheck :: ReadP a a -> String -> String -> IO a
375 parseCheck parser str what =
376 case [ x | (x,ys) <- readP_to_S parser str, all isSpace ys ] of
378 _ -> die ("cannot parse \'" ++ str ++ "\' as a " ++ what)
380 readGlobPkgId :: String -> IO PackageIdentifier
381 readGlobPkgId str = parseCheck parseGlobPackageId str "package identifier"
383 parseGlobPackageId :: ReadP r PackageIdentifier
389 return (PackageIdentifier{ pkgName = n, pkgVersion = globVersion }))
391 -- globVersion means "all versions"
392 globVersion :: Version
393 globVersion = Version{ versionBranch=[], versionTags=["*"] }
395 -- -----------------------------------------------------------------------------
398 -- Some commands operate on a single database:
399 -- register, unregister, expose, hide
400 -- however these commands also check the union of the available databases
401 -- in order to check consistency. For example, register will check that
402 -- dependencies exist before registering a package.
404 -- Some commands operate on multiple databases, with overlapping semantics:
405 -- list, describe, field
408 = PackageDB { location :: FilePath,
409 packages :: [InstalledPackageInfo] }
411 type PackageDBStack = [PackageDB]
412 -- A stack of package databases. Convention: head is the topmost
415 allPackagesInStack :: PackageDBStack -> [InstalledPackageInfo]
416 allPackagesInStack = concatMap packages
418 getPkgDatabases :: Verbosity
419 -> Bool -- we are modifying, not reading
420 -> Bool -- read caches, if available
422 -> IO (PackageDBStack,
423 -- the real package DB stack: [global,user] ++
424 -- DBs specified on the command line with -f.
426 -- which one to modify, if any
428 -- the package DBs specified on the command
429 -- line, or [global,user] otherwise. This
430 -- is used as the list of package DBs for
431 -- commands that just read the DB, such as 'list'.
433 getPkgDatabases verbosity modify use_cache my_flags = do
434 -- first we determine the location of the global package config. On Windows,
435 -- this is found relative to the ghc-pkg.exe binary, whereas on Unix the
436 -- location is passed to the binary using the --global-config flag by the
438 let err_msg = "missing --global-conf option, location of global package.conf unknown\n"
440 case [ f | FlagGlobalConfig f <- my_flags ] of
441 [] -> do mb_dir <- getLibDir
443 Nothing -> die err_msg
445 r <- lookForPackageDBIn dir
447 Nothing -> die ("Can't find package database in " ++ dir)
448 Just path -> return path
449 fs -> return (last fs)
451 let no_user_db = FlagNoUserDb `elem` my_flags
453 -- get the location of the user package database, and create it if necessary
454 -- getAppUserDataDirectory can fail (e.g. if $HOME isn't set)
455 e_appdir <- try $ getAppUserDataDirectory "ghc"
458 if no_user_db then return Nothing else
460 Left _ -> return Nothing
462 let subdir = targetARCH ++ '-':targetOS ++ '-':Version.version
463 dir = appdir </> subdir
464 r <- lookForPackageDBIn dir
466 Nothing -> return (Just (dir </> "package.conf.d", False))
467 Just f -> return (Just (f, True))
469 -- If the user database doesn't exist, and this command isn't a
470 -- "modify" command, then we won't attempt to create or use it.
472 | Just (user_conf,user_exists) <- mb_user_conf,
473 modify || user_exists = [user_conf, global_conf]
474 | otherwise = [global_conf]
476 e_pkg_path <- try (System.Environment.getEnv "GHC_PACKAGE_PATH")
479 Left _ -> sys_databases
481 | last cs == "" -> init cs ++ sys_databases
483 where cs = parseSearchPath path
485 -- The "global" database is always the one at the bottom of the stack.
486 -- This is the database we modify by default.
487 virt_global_conf = last env_stack
489 let db_flags = [ f | Just f <- map is_db_flag my_flags ]
490 where is_db_flag FlagUser
491 | Just (user_conf, _user_exists) <- mb_user_conf
493 is_db_flag FlagGlobal = Just virt_global_conf
494 is_db_flag (FlagConfig f) = Just f
495 is_db_flag _ = Nothing
497 let flag_db_names | null db_flags = env_stack
498 | otherwise = reverse (nub db_flags)
500 -- For a "modify" command, treat all the databases as
501 -- a stack, where we are modifying the top one, but it
502 -- can refer to packages in databases further down the
505 -- -f flags on the command line add to the database
506 -- stack, unless any of them are present in the stack
508 let final_stack = filter (`notElem` env_stack)
509 [ f | FlagConfig f <- reverse my_flags ]
512 -- the database we actually modify is the one mentioned
513 -- rightmost on the command-line.
515 | not modify = Nothing
516 | null db_flags = Just virt_global_conf
517 | otherwise = Just (last db_flags)
519 db_stack <- mapM (readParseDatabase verbosity mb_user_conf use_cache) final_stack
521 let flag_db_stack = [ db | db_name <- flag_db_names,
522 db <- db_stack, location db == db_name ]
524 return (db_stack, to_modify, flag_db_stack)
527 lookForPackageDBIn :: FilePath -> IO (Maybe FilePath)
528 lookForPackageDBIn dir = do
529 let path_dir = dir </> "package.conf.d"
530 exists_dir <- doesDirectoryExist path_dir
531 if exists_dir then return (Just path_dir) else do
532 let path_file = dir </> "package.conf"
533 exists_file <- doesFileExist path_file
534 if exists_file then return (Just path_file) else return Nothing
536 readParseDatabase :: Verbosity
537 -> Maybe (FilePath,Bool)
542 readParseDatabase verbosity mb_user_conf use_cache path
543 -- the user database (only) is allowed to be non-existent
544 | Just (user_conf,False) <- mb_user_conf, path == user_conf
545 = return PackageDB { location = path, packages = [] }
547 = do e <- try $ getDirectoryContents path
550 pkgs <- parseMultiPackageConf verbosity path
551 return PackageDB{ location = path, packages = pkgs }
553 | not use_cache -> ignore_cache
555 let cache = path </> cachefilename
556 tdir <- getModificationTime path
557 e_tcache <- try $ getModificationTime cache
560 when (verbosity > Normal) $
561 putStrLn ("warning: cannot read cache file " ++ cache ++ ": " ++ show ex)
564 | tcache >= tdir -> do
565 when (verbosity > Normal) $
566 putStrLn ("using cache: " ++ cache)
567 pkgs <- myReadBinPackageDB cache
568 let pkgs' = map convertPackageInfoIn pkgs
569 return PackageDB { location = path, packages = pkgs' }
571 when (verbosity >= Normal) $ do
572 putStrLn ("WARNING: cache is out of date: " ++ cache)
573 putStrLn " use 'ghc-pkg recache' to fix."
577 let confs = filter (".conf" `isSuffixOf`) fs
578 pkgs <- mapM (parseSingletonPackageConf verbosity) $
580 return PackageDB { location = path, packages = pkgs }
582 -- read the package.cache file strictly, to work around a problem with
583 -- bytestring 0.9.0.x (fixed in 0.9.1.x) where the file wasn't closed
584 -- after it has been completely read, leading to a sharing violation
586 myReadBinPackageDB :: FilePath -> IO [InstalledPackageInfoString]
587 myReadBinPackageDB filepath = do
588 h <- openBinaryFile filepath ReadMode
590 b <- B.hGet h (fromIntegral sz)
592 return $ Bin.runGet Bin.get b
594 parseMultiPackageConf :: Verbosity -> FilePath -> IO [InstalledPackageInfo]
595 parseMultiPackageConf verbosity file = do
596 when (verbosity > Normal) $ putStrLn ("reading package database: " ++ file)
597 str <- readUTF8File file
598 let pkgs = map convertPackageInfoIn $ read str
599 Exception.evaluate pkgs
601 die ("error while parsing " ++ file ++ ": " ++ show e)
603 parseSingletonPackageConf :: Verbosity -> FilePath -> IO InstalledPackageInfo
604 parseSingletonPackageConf verbosity file = do
605 when (verbosity > Normal) $ putStrLn ("reading package config: " ++ file)
606 readUTF8File file >>= parsePackageInfo
608 cachefilename :: FilePath
609 cachefilename = "package.cache"
611 -- -----------------------------------------------------------------------------
612 -- Creating a new package DB
614 initPackageDB :: FilePath -> Verbosity -> [Flag] -> IO ()
615 initPackageDB filename verbosity _flags = do
616 let eexist = die ("cannot create: " ++ filename ++ " already exists")
617 b1 <- doesFileExist filename
619 b2 <- doesDirectoryExist filename
621 changeDB verbosity [] PackageDB{ location = filename, packages = [] }
623 -- -----------------------------------------------------------------------------
626 registerPackage :: FilePath
629 -> Bool -- auto_ghci_libs
633 registerPackage input verbosity my_flags auto_ghci_libs update force = do
634 (db_stack, Just to_modify, _flag_dbs) <-
635 getPkgDatabases verbosity True True my_flags
638 db_to_operate_on = my_head "register" $
639 filter ((== to_modify).location) db_stack
644 when (verbosity >= Normal) $
645 putStr "Reading package info from stdin ... "
646 #if __GLASGOW_HASKELL__ >= 612
647 -- fix the encoding to UTF-8, since this is an interchange format
648 hSetEncoding stdin utf8
652 when (verbosity >= Normal) $
653 putStr ("Reading package info from " ++ show f ++ " ... ")
656 expanded <- expandEnvVars s force
658 pkg <- parsePackageInfo expanded
659 when (verbosity >= Normal) $
662 let truncated_stack = dropWhile ((/= to_modify).location) db_stack
663 -- truncate the stack for validation, because we don't allow
664 -- packages lower in the stack to refer to those higher up.
665 validatePackageConfig pkg truncated_stack auto_ghci_libs update force
667 removes = [ RemovePackage p
668 | p <- packages db_to_operate_on,
669 sourcePackageId p == sourcePackageId pkg ]
671 changeDB verbosity (removes ++ [AddPackage pkg]) db_to_operate_on
675 -> IO InstalledPackageInfo
676 parsePackageInfo str =
677 case parseInstalledPackageInfo str of
678 ParseOk _warns ok -> return ok
679 ParseFailed err -> case locatedErrorMsg err of
680 (Nothing, s) -> die s
681 (Just l, s) -> die (show l ++ ": " ++ s)
683 -- -----------------------------------------------------------------------------
684 -- Making changes to a package database
686 data DBOp = RemovePackage InstalledPackageInfo
687 | AddPackage InstalledPackageInfo
688 | ModifyPackage InstalledPackageInfo
690 changeDB :: Verbosity -> [DBOp] -> PackageDB -> IO ()
691 changeDB verbosity cmds db = do
692 let db' = updateInternalDB db cmds
693 isfile <- doesFileExist (location db)
695 then writeNewConfig verbosity (location db') (packages db')
697 createDirectoryIfMissing True (location db)
698 changeDBDir verbosity cmds db'
700 updateInternalDB :: PackageDB -> [DBOp] -> PackageDB
701 updateInternalDB db cmds = db{ packages = foldl do_cmd (packages db) cmds }
703 do_cmd pkgs (RemovePackage p) =
704 filter ((/= installedPackageId p) . installedPackageId) pkgs
705 do_cmd pkgs (AddPackage p) = p : pkgs
706 do_cmd pkgs (ModifyPackage p) =
707 do_cmd (do_cmd pkgs (RemovePackage p)) (AddPackage p)
710 changeDBDir :: Verbosity -> [DBOp] -> PackageDB -> IO ()
711 changeDBDir verbosity cmds db = do
713 updateDBCache verbosity db
715 do_cmd (RemovePackage p) = do
716 let file = location db </> display (installedPackageId p) <.> "conf"
717 when (verbosity > Normal) $ putStrLn ("removing " ++ file)
719 do_cmd (AddPackage p) = do
720 let file = location db </> display (installedPackageId p) <.> "conf"
721 when (verbosity > Normal) $ putStrLn ("writing " ++ file)
722 writeFileAtomic file (showInstalledPackageInfo p)
723 do_cmd (ModifyPackage p) =
724 do_cmd (AddPackage p)
726 updateDBCache :: Verbosity -> PackageDB -> IO ()
727 updateDBCache verbosity db = do
728 let filename = location db </> cachefilename
729 when (verbosity > Normal) $
730 putStrLn ("writing cache " ++ filename)
731 writeBinPackageDB filename (map convertPackageInfoOut (packages db))
733 if isPermissionError e
734 then die (filename ++ ": you don't have permission to modify this file")
737 -- -----------------------------------------------------------------------------
738 -- Exposing, Hiding, Unregistering are all similar
740 exposePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
741 exposePackage = modifyPackage (\p -> ModifyPackage p{exposed=True})
743 hidePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
744 hidePackage = modifyPackage (\p -> ModifyPackage p{exposed=False})
746 unregisterPackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO ()
747 unregisterPackage = modifyPackage RemovePackage
750 :: (InstalledPackageInfo -> DBOp)
756 modifyPackage fn pkgid verbosity my_flags force = do
757 (db_stack, Just _to_modify, _flag_dbs) <-
758 getPkgDatabases verbosity True{-modify-} True{-use cache-} my_flags
760 (db, ps) <- fmap head $ findPackagesByDB db_stack (Id pkgid)
762 db_name = location db
765 pids = map sourcePackageId ps
767 cmds = [ fn pkg | pkg <- pkgs, sourcePackageId pkg `elem` pids ]
768 new_db = updateInternalDB db cmds
770 old_broken = brokenPackages (allPackagesInStack db_stack)
771 rest_of_stack = filter ((/= db_name) . location) db_stack
772 new_stack = new_db : rest_of_stack
773 new_broken = map sourcePackageId (brokenPackages (allPackagesInStack new_stack))
774 newly_broken = filter (`notElem` map sourcePackageId old_broken) new_broken
776 when (not (null newly_broken)) $
777 dieOrForceAll force ("unregistering " ++ display pkgid ++
778 " would break the following packages: "
779 ++ unwords (map display newly_broken))
781 changeDB verbosity cmds db
783 recache :: Verbosity -> [Flag] -> IO ()
784 recache verbosity my_flags = do
785 (db_stack, Just to_modify, _flag_dbs) <-
786 getPkgDatabases verbosity True{-modify-} False{-no cache-} my_flags
788 db_to_operate_on = my_head "recache" $
789 filter ((== to_modify).location) db_stack
791 changeDB verbosity [] db_to_operate_on
793 -- -----------------------------------------------------------------------------
796 listPackages :: Verbosity -> [Flag] -> Maybe PackageArg
797 -> Maybe (String->Bool)
799 listPackages verbosity my_flags mPackageName mModuleName = do
800 let simple_output = FlagSimpleOutput `elem` my_flags
801 (db_stack, _, flag_db_stack) <-
802 getPkgDatabases verbosity False True{-use cache-} my_flags
804 let db_stack_filtered -- if a package is given, filter out all other packages
805 | Just this <- mPackageName =
806 [ db{ packages = filter (this `matchesPkg`) (packages db) }
807 | db <- flag_db_stack ]
808 | Just match <- mModuleName = -- packages which expose mModuleName
809 [ db{ packages = filter (match `exposedInPkg`) (packages db) }
810 | db <- flag_db_stack ]
811 | otherwise = flag_db_stack
814 = [ db{ packages = sort_pkgs (packages db) }
815 | db <- db_stack_filtered ]
816 where sort_pkgs = sortBy cmpPkgIds
817 cmpPkgIds pkg1 pkg2 =
818 case pkgName p1 `compare` pkgName p2 of
821 EQ -> pkgVersion p1 `compare` pkgVersion p2
822 where (p1,p2) = (sourcePackageId pkg1, sourcePackageId pkg2)
824 stack = reverse db_stack_sorted
826 match `exposedInPkg` pkg = any match (map display $ exposedModules pkg)
828 pkg_map = allPackagesInStack db_stack
829 broken = map sourcePackageId (brokenPackages pkg_map)
831 show_normal PackageDB{ location = db_name, packages = pkg_confs } =
832 hPutStrLn stdout $ unlines ((db_name ++ ":") : map (" " ++) pp_pkgs)
834 pp_pkgs = map pp_pkg pkg_confs
836 | sourcePackageId p `elem` broken = printf "{%s}" doc
838 | otherwise = printf "(%s)" doc
839 where doc | verbosity >= Verbose = printf "%s (%s)" pkg ipid
842 InstalledPackageId ipid = installedPackageId p
843 pkg = display (sourcePackageId p)
845 show_simple = simplePackageList my_flags . allPackagesInStack
847 when (not (null broken) && not simple_output && verbosity /= Silent) $ do
848 prog <- getProgramName
849 putStrLn ("WARNING: there are broken packages. Run '" ++ prog ++ " check' for more details.")
851 if simple_output then show_simple stack else do
853 #if defined(mingw32_HOST_OS) || __GLASGOW_HASKELL__ < 611 || defined(BOOTSTRAPPING)
854 mapM_ show_normal stack
857 show_colour withF db =
858 mconcat $ map (<#> termText "\n") $
859 (termText (location db) :
860 map (termText " " <#>) (map pp_pkg (packages db)))
863 | sourcePackageId p `elem` broken = withF Red doc
865 | otherwise = withF Blue doc
866 where doc | verbosity >= Verbose
867 = termText (printf "%s (%s)" pkg ipid)
871 InstalledPackageId ipid = installedPackageId p
872 pkg = display (sourcePackageId p)
874 is_tty <- hIsTerminalDevice stdout
876 then mapM_ show_normal stack
877 else do tty <- Terminfo.setupTermFromEnv
878 case Terminfo.getCapability tty withForegroundColor of
879 Nothing -> mapM_ show_normal stack
880 Just w -> runTermOutput tty $ mconcat $
881 map (show_colour w) stack
884 simplePackageList :: [Flag] -> [InstalledPackageInfo] -> IO ()
885 simplePackageList my_flags pkgs = do
886 let showPkg = if FlagNamesOnly `elem` my_flags then display . pkgName
888 strs = map showPkg $ sortBy compPkgIdVer $ map sourcePackageId pkgs
889 when (not (null pkgs)) $
890 hPutStrLn stdout $ concat $ intersperse " " strs
892 showPackageDot :: Verbosity -> [Flag] -> IO ()
893 showPackageDot verbosity myflags = do
894 (_, _, flag_db_stack) <-
895 getPkgDatabases verbosity False True{-use cache-} myflags
897 let all_pkgs = allPackagesInStack flag_db_stack
898 ipix = PackageIndex.fromList all_pkgs
901 let quote s = '"':s ++ "\""
902 mapM_ putStrLn [ quote from ++ " -> " ++ quote to
904 let from = display (sourcePackageId p),
906 Just dep <- [PackageIndex.lookupInstalledPackageId ipix depid],
907 let to = display (sourcePackageId dep)
911 -- -----------------------------------------------------------------------------
912 -- Prints the highest (hidden or exposed) version of a package
914 latestPackage :: Verbosity -> [Flag] -> PackageIdentifier -> IO ()
915 latestPackage verbosity my_flags pkgid = do
916 (_, _, flag_db_stack) <-
917 getPkgDatabases verbosity False True{-use cache-} my_flags
919 ps <- findPackages flag_db_stack (Id pkgid)
920 show_pkg (sortBy compPkgIdVer (map sourcePackageId ps))
922 show_pkg [] = die "no matches"
923 show_pkg pids = hPutStrLn stdout (display (last pids))
925 -- -----------------------------------------------------------------------------
928 describePackage :: Verbosity -> [Flag] -> PackageArg -> IO ()
929 describePackage verbosity my_flags pkgarg = do
930 (_, _, flag_db_stack) <-
931 getPkgDatabases verbosity False True{-use cache-} my_flags
932 ps <- findPackages flag_db_stack pkgarg
935 dumpPackages :: Verbosity -> [Flag] -> IO ()
936 dumpPackages verbosity my_flags = do
937 (_, _, flag_db_stack) <-
938 getPkgDatabases verbosity False True{-use cache-} my_flags
939 doDump (allPackagesInStack flag_db_stack)
941 doDump :: [InstalledPackageInfo] -> IO ()
943 #if __GLASGOW_HASKELL__ >= 612
944 -- fix the encoding to UTF-8, since this is an interchange format
945 hSetEncoding stdout utf8
947 mapM_ putStrLn . intersperse "---" . map showInstalledPackageInfo $ pkgs
949 -- PackageId is can have globVersion for the version
950 findPackages :: PackageDBStack -> PackageArg -> IO [InstalledPackageInfo]
951 findPackages db_stack pkgarg
952 = fmap (concatMap snd) $ findPackagesByDB db_stack pkgarg
954 findPackagesByDB :: PackageDBStack -> PackageArg
955 -> IO [(PackageDB, [InstalledPackageInfo])]
956 findPackagesByDB db_stack pkgarg
957 = case [ (db, matched)
959 let matched = filter (pkgarg `matchesPkg`) (packages db),
960 not (null matched) ] of
961 [] -> die ("cannot find package " ++ pkg_msg pkgarg)
964 pkg_msg (Id pkgid) = display pkgid
965 pkg_msg (Substring pkgpat _) = "matching " ++ pkgpat
967 matches :: PackageIdentifier -> PackageIdentifier -> Bool
969 = (pkgName pid == pkgName pid')
970 && (pkgVersion pid == pkgVersion pid' || not (realVersion pid))
972 realVersion :: PackageIdentifier -> Bool
973 realVersion pkgid = versionBranch (pkgVersion pkgid) /= []
974 -- when versionBranch == [], this is a glob
976 matchesPkg :: PackageArg -> InstalledPackageInfo -> Bool
977 (Id pid) `matchesPkg` pkg = pid `matches` sourcePackageId pkg
978 (Substring _ m) `matchesPkg` pkg = m (display (sourcePackageId pkg))
980 compPkgIdVer :: PackageIdentifier -> PackageIdentifier -> Ordering
981 compPkgIdVer p1 p2 = pkgVersion p1 `compare` pkgVersion p2
983 -- -----------------------------------------------------------------------------
986 describeField :: Verbosity -> [Flag] -> PackageArg -> [String] -> IO ()
987 describeField verbosity my_flags pkgarg fields = do
988 (_, _, flag_db_stack) <-
989 getPkgDatabases verbosity False True{-use cache-} my_flags
990 fns <- toFields fields
991 ps <- findPackages flag_db_stack pkgarg
992 let top_dir = takeDirectory (location (last flag_db_stack))
993 mapM_ (selectFields fns) (mungePackagePaths top_dir ps)
994 where toFields [] = return []
995 toFields (f:fs) = case toField f of
996 Nothing -> die ("unknown field: " ++ f)
997 Just fn -> do fns <- toFields fs
999 selectFields fns info = mapM_ (\fn->putStrLn (fn info)) fns
1001 mungePackagePaths :: String -> [InstalledPackageInfo] -> [InstalledPackageInfo]
1002 -- Replace the strings "$topdir" and "$httptopdir" at the beginning of a path
1003 -- with the current topdir (obtained from the -B option).
1004 mungePackagePaths top_dir ps = map munge_pkg ps
1006 munge_pkg p = p{ importDirs = munge_paths (importDirs p),
1007 includeDirs = munge_paths (includeDirs p),
1008 libraryDirs = munge_paths (libraryDirs p),
1009 frameworkDirs = munge_paths (frameworkDirs p),
1010 haddockInterfaces = munge_paths (haddockInterfaces p),
1011 haddockHTMLs = munge_paths (haddockHTMLs p)
1014 munge_paths = map munge_path
1017 | Just p' <- maybePrefixMatch "$topdir" p = top_dir ++ p'
1018 | Just p' <- maybePrefixMatch "$httptopdir" p = toHttpPath top_dir ++ p'
1021 toHttpPath p = "file:///" ++ p
1023 maybePrefixMatch :: String -> String -> Maybe String
1024 maybePrefixMatch [] rest = Just rest
1025 maybePrefixMatch (_:_) [] = Nothing
1026 maybePrefixMatch (p:pat) (r:rest)
1027 | p == r = maybePrefixMatch pat rest
1028 | otherwise = Nothing
1030 toField :: String -> Maybe (InstalledPackageInfo -> String)
1031 -- backwards compatibility:
1032 toField "import_dirs" = Just $ strList . importDirs
1033 toField "source_dirs" = Just $ strList . importDirs
1034 toField "library_dirs" = Just $ strList . libraryDirs
1035 toField "hs_libraries" = Just $ strList . hsLibraries
1036 toField "extra_libraries" = Just $ strList . extraLibraries
1037 toField "include_dirs" = Just $ strList . includeDirs
1038 toField "c_includes" = Just $ strList . includes
1039 toField "package_deps" = Just $ strList . map display. depends
1040 toField "extra_cc_opts" = Just $ strList . ccOptions
1041 toField "extra_ld_opts" = Just $ strList . ldOptions
1042 toField "framework_dirs" = Just $ strList . frameworkDirs
1043 toField "extra_frameworks"= Just $ strList . frameworks
1044 toField s = showInstalledPackageInfoField s
1046 strList :: [String] -> String
1050 -- -----------------------------------------------------------------------------
1051 -- Check: Check consistency of installed packages
1053 checkConsistency :: Verbosity -> [Flag] -> IO ()
1054 checkConsistency verbosity my_flags = do
1055 (db_stack, _, _) <- getPkgDatabases verbosity True True{-use cache-} my_flags
1056 -- check behaves like modify for the purposes of deciding which
1057 -- databases to use, because ordering is important.
1059 let simple_output = FlagSimpleOutput `elem` my_flags
1061 let pkgs = allPackagesInStack db_stack
1064 (_,es) <- runValidate $ checkPackageConfig p db_stack False True
1068 when (not simple_output) $ do
1069 reportError ("There are problems in package " ++ display (sourcePackageId p) ++ ":")
1070 _ <- reportValidateErrors es " " Nothing
1074 broken_pkgs <- concat `fmap` mapM checkPackage pkgs
1076 let filterOut pkgs1 pkgs2 = filter not_in pkgs2
1077 where not_in p = sourcePackageId p `notElem` all_ps
1078 all_ps = map sourcePackageId pkgs1
1080 let not_broken_pkgs = filterOut broken_pkgs pkgs
1081 (_, trans_broken_pkgs) = closure [] not_broken_pkgs
1082 all_broken_pkgs = broken_pkgs ++ trans_broken_pkgs
1084 when (not (null all_broken_pkgs)) $ do
1086 then simplePackageList my_flags all_broken_pkgs
1088 reportError ("\nThe following packages are broken, either because they have a problem\n"++
1089 "listed above, or because they depend on a broken package.")
1090 mapM_ (hPutStrLn stderr . display . sourcePackageId) all_broken_pkgs
1092 when (not (null all_broken_pkgs)) $ exitWith (ExitFailure 1)
1095 closure :: [InstalledPackageInfo] -> [InstalledPackageInfo]
1096 -> ([InstalledPackageInfo], [InstalledPackageInfo])
1097 closure pkgs db_stack = go pkgs db_stack
1099 go avail not_avail =
1100 case partition (depsAvailable avail) not_avail of
1101 ([], not_avail') -> (avail, not_avail')
1102 (new_avail, not_avail') -> go (new_avail ++ avail) not_avail'
1104 depsAvailable :: [InstalledPackageInfo] -> InstalledPackageInfo
1106 depsAvailable pkgs_ok pkg = null dangling
1107 where dangling = filter (`notElem` pids) (depends pkg)
1108 pids = map installedPackageId pkgs_ok
1110 -- we want mutually recursive groups of package to show up
1111 -- as broken. (#1750)
1113 brokenPackages :: [InstalledPackageInfo] -> [InstalledPackageInfo]
1114 brokenPackages pkgs = snd (closure [] pkgs)
1116 -- -----------------------------------------------------------------------------
1117 -- Manipulating package.conf files
1119 type InstalledPackageInfoString = InstalledPackageInfo_ String
1121 convertPackageInfoOut :: InstalledPackageInfo -> InstalledPackageInfoString
1122 convertPackageInfoOut
1123 (pkgconf@(InstalledPackageInfo { exposedModules = e,
1124 hiddenModules = h })) =
1125 pkgconf{ exposedModules = map display e,
1126 hiddenModules = map display h }
1128 convertPackageInfoIn :: InstalledPackageInfoString -> InstalledPackageInfo
1129 convertPackageInfoIn
1130 (pkgconf@(InstalledPackageInfo { exposedModules = e,
1131 hiddenModules = h })) =
1132 pkgconf{ exposedModules = map convert e,
1133 hiddenModules = map convert h }
1134 where convert = fromJust . simpleParse
1136 writeNewConfig :: Verbosity -> FilePath -> [InstalledPackageInfo] -> IO ()
1137 writeNewConfig verbosity filename ipis = do
1138 when (verbosity >= Normal) $
1139 hPutStr stdout "Writing new package config file... "
1140 createDirectoryIfMissing True $ takeDirectory filename
1141 let shown = concat $ intersperse ",\n "
1142 $ map (show . convertPackageInfoOut) ipis
1143 fileContents = "[" ++ shown ++ "\n]"
1144 writeFileAtomic filename fileContents
1146 if isPermissionError e
1147 then die (filename ++ ": you don't have permission to modify this file")
1149 when (verbosity >= Normal) $
1150 hPutStrLn stdout "done."
1152 -----------------------------------------------------------------------------
1153 -- Sanity-check a new package config, and automatically build GHCi libs
1156 type ValidateError = (Force,String)
1158 newtype Validate a = V { runValidate :: IO (a, [ValidateError]) }
1160 instance Monad Validate where
1161 return a = V $ return (a, [])
1163 (a, es) <- runValidate m
1164 (b, es') <- runValidate (k a)
1167 verror :: Force -> String -> Validate ()
1168 verror f s = V (return ((),[(f,s)]))
1170 liftIO :: IO a -> Validate a
1171 liftIO k = V (k >>= \a -> return (a,[]))
1173 -- returns False if we should die
1174 reportValidateErrors :: [ValidateError] -> String -> Maybe Force -> IO Bool
1175 reportValidateErrors es prefix mb_force = do
1176 oks <- mapM report es
1180 | Just force <- mb_force
1182 then do reportError (prefix ++ s ++ " (ignoring)")
1184 else if f < CannotForce
1185 then do reportError (prefix ++ s ++ " (use --force to override)")
1187 else do reportError err
1189 | otherwise = do reportError err
1194 validatePackageConfig :: InstalledPackageInfo
1196 -> Bool -- auto-ghc-libs
1197 -> Bool -- update, or check
1200 validatePackageConfig pkg db_stack auto_ghci_libs update force = do
1201 (_,es) <- runValidate $ checkPackageConfig pkg db_stack auto_ghci_libs update
1202 ok <- reportValidateErrors es (display (sourcePackageId pkg) ++ ": ") (Just force)
1203 when (not ok) $ exitWith (ExitFailure 1)
1205 checkPackageConfig :: InstalledPackageInfo
1207 -> Bool -- auto-ghc-libs
1208 -> Bool -- update, or check
1210 checkPackageConfig pkg db_stack auto_ghci_libs update = do
1211 checkInstalledPackageId pkg db_stack update
1213 checkDuplicates db_stack pkg update
1214 mapM_ (checkDep db_stack) (depends pkg)
1215 checkDuplicateDepends (depends pkg)
1216 mapM_ (checkDir "import-dirs") (importDirs pkg)
1217 mapM_ (checkDir "library-dirs") (libraryDirs pkg)
1218 mapM_ (checkDir "include-dirs") (includeDirs pkg)
1220 mapM_ (checkHSLib (libraryDirs pkg) auto_ghci_libs) (hsLibraries pkg)
1221 -- ToDo: check these somehow?
1222 -- extra_libraries :: [String],
1223 -- c_includes :: [String],
1225 checkInstalledPackageId :: InstalledPackageInfo -> PackageDBStack -> Bool
1227 checkInstalledPackageId ipi db_stack update = do
1228 let ipid@(InstalledPackageId str) = installedPackageId ipi
1229 when (null str) $ verror CannotForce "missing id field"
1230 let dups = [ p | p <- allPackagesInStack db_stack,
1231 installedPackageId p == ipid ]
1232 when (not update && not (null dups)) $
1233 verror CannotForce $
1234 "package(s) with this id already exist: " ++
1235 unwords (map (display.packageId) dups)
1237 -- When the package name and version are put together, sometimes we can
1238 -- end up with a package id that cannot be parsed. This will lead to
1239 -- difficulties when the user wants to refer to the package later, so
1240 -- we check that the package id can be parsed properly here.
1241 checkPackageId :: InstalledPackageInfo -> Validate ()
1242 checkPackageId ipi =
1243 let str = display (sourcePackageId ipi) in
1244 case [ x :: PackageIdentifier | (x,ys) <- readP_to_S parse str, all isSpace ys ] of
1246 [] -> verror CannotForce ("invalid package identifier: " ++ str)
1247 _ -> verror CannotForce ("ambiguous package identifier: " ++ str)
1249 checkDuplicates :: PackageDBStack -> InstalledPackageInfo -> Bool -> Validate ()
1250 checkDuplicates db_stack pkg update = do
1252 pkgid = sourcePackageId pkg
1253 pkgs = packages (head db_stack)
1255 -- Check whether this package id already exists in this DB
1257 when (not update && (pkgid `elem` map sourcePackageId pkgs)) $
1258 verror CannotForce $
1259 "package " ++ display pkgid ++ " is already installed"
1262 uncasep = map toLower . display
1263 dups = filter ((== uncasep pkgid) . uncasep) (map sourcePackageId pkgs)
1265 when (not update && not (null dups)) $ verror ForceAll $
1266 "Package names may be treated case-insensitively in the future.\n"++
1267 "Package " ++ display pkgid ++
1268 " overlaps with: " ++ unwords (map display dups)
1271 checkDir :: String -> String -> Validate ()
1272 checkDir thisfield d
1273 | "$topdir" `isPrefixOf` d = return ()
1274 | "$httptopdir" `isPrefixOf` d = return ()
1275 -- can't check these, because we don't know what $(http)topdir is
1277 there <- liftIO $ doesDirectoryExist d
1279 verror ForceFiles (thisfield ++ ": " ++ d ++ " doesn't exist or isn't a directory")
1281 checkDep :: PackageDBStack -> InstalledPackageId -> Validate ()
1282 checkDep db_stack pkgid
1283 | pkgid `elem` pkgids = return ()
1284 | otherwise = verror ForceAll ("dependency \"" ++ display pkgid
1285 ++ "\" doesn't exist")
1287 all_pkgs = allPackagesInStack db_stack
1288 pkgids = map installedPackageId all_pkgs
1290 checkDuplicateDepends :: [InstalledPackageId] -> Validate ()
1291 checkDuplicateDepends deps
1292 | null dups = return ()
1293 | otherwise = verror ForceAll ("package has duplicate dependencies: " ++
1294 unwords (map display dups))
1296 dups = [ p | (p:_:_) <- group (sort deps) ]
1298 checkHSLib :: [String] -> Bool -> String -> Validate ()
1299 checkHSLib dirs auto_ghci_libs lib = do
1300 let batch_lib_file = "lib" ++ lib ++ ".a"
1301 m <- liftIO $ doesFileExistOnPath batch_lib_file dirs
1303 Nothing -> verror ForceFiles ("cannot find " ++ batch_lib_file ++
1305 Just dir -> liftIO $ checkGHCiLib dirs dir batch_lib_file lib auto_ghci_libs
1307 doesFileExistOnPath :: String -> [FilePath] -> IO (Maybe FilePath)
1308 doesFileExistOnPath file path = go path
1309 where go [] = return Nothing
1310 go (p:ps) = do b <- doesFileExistIn file p
1311 if b then return (Just p) else go ps
1313 doesFileExistIn :: String -> String -> IO Bool
1314 doesFileExistIn lib d
1315 | "$topdir" `isPrefixOf` d = return True
1316 | "$httptopdir" `isPrefixOf` d = return True
1317 | otherwise = doesFileExist (d </> lib)
1319 checkModules :: InstalledPackageInfo -> Validate ()
1320 checkModules pkg = do
1321 mapM_ findModule (exposedModules pkg ++ hiddenModules pkg)
1323 findModule modl = do
1324 -- there's no .hi file for GHC.Prim
1325 if modl == fromString "GHC.Prim" then return () else do
1326 let file = toFilePath modl <.> "hi"
1327 m <- liftIO $ doesFileExistOnPath file (importDirs pkg)
1328 when (isNothing m) $
1329 verror ForceFiles ("file " ++ file ++ " is missing")
1331 checkGHCiLib :: [String] -> String -> String -> String -> Bool -> IO ()
1332 checkGHCiLib dirs batch_lib_dir batch_lib_file lib auto_build
1333 | auto_build = autoBuildGHCiLib batch_lib_dir batch_lib_file ghci_lib_file
1335 m <- doesFileExistOnPath ghci_lib_file dirs
1336 when (isNothing m && ghci_lib_file /= "HSrts.o") $
1337 hPutStrLn stderr ("warning: can't find GHCi lib " ++ ghci_lib_file)
1339 ghci_lib_file = lib <.> "o"
1341 -- automatically build the GHCi version of a batch lib,
1342 -- using ld --whole-archive.
1344 autoBuildGHCiLib :: String -> String -> String -> IO ()
1345 autoBuildGHCiLib dir batch_file ghci_file = do
1346 let ghci_lib_file = dir ++ '/':ghci_file
1347 batch_lib_file = dir ++ '/':batch_file
1348 hPutStr stderr ("building GHCi library " ++ ghci_lib_file ++ "...")
1349 #if defined(darwin_HOST_OS)
1350 r <- rawSystem "ld" ["-r","-x","-o",ghci_lib_file,"-all_load",batch_lib_file]
1351 #elif defined(mingw32_HOST_OS)
1352 execDir <- getLibDir
1353 r <- rawSystem (maybe "" (++"/gcc-lib/") execDir++"ld") ["-r","-x","-o",ghci_lib_file,"--whole-archive",batch_lib_file]
1355 r <- rawSystem "ld" ["-r","-x","-o",ghci_lib_file,"--whole-archive",batch_lib_file]
1357 when (r /= ExitSuccess) $ exitWith r
1358 hPutStrLn stderr (" done.")
1360 -- -----------------------------------------------------------------------------
1361 -- Searching for modules
1365 findModules :: [FilePath] -> IO [String]
1367 mms <- mapM searchDir paths
1370 searchDir path prefix = do
1371 fs <- getDirectoryEntries path `catch` \_ -> return []
1372 searchEntries path prefix fs
1374 searchEntries path prefix [] = return []
1375 searchEntries path prefix (f:fs)
1376 | looks_like_a_module = do
1377 ms <- searchEntries path prefix fs
1378 return (prefix `joinModule` f : ms)
1379 | looks_like_a_component = do
1380 ms <- searchDir (path </> f) (prefix `joinModule` f)
1381 ms' <- searchEntries path prefix fs
1384 searchEntries path prefix fs
1387 (base,suffix) = splitFileExt f
1388 looks_like_a_module =
1389 suffix `elem` haskell_suffixes &&
1390 all okInModuleName base
1391 looks_like_a_component =
1392 null suffix && all okInModuleName base
1398 -- ---------------------------------------------------------------------------
1399 -- expanding environment variables in the package configuration
1401 expandEnvVars :: String -> Force -> IO String
1402 expandEnvVars str0 force = go str0 ""
1404 go "" acc = return $! reverse acc
1405 go ('$':'{':str) acc | (var, '}':rest) <- break close str
1406 = do value <- lookupEnvVar var
1407 go rest (reverse value ++ acc)
1408 where close c = c == '}' || c == '\n' -- don't span newlines
1412 lookupEnvVar :: String -> IO String
1414 catch (System.Environment.getEnv nm)
1415 (\ _ -> do dieOrForceAll force ("Unable to expand variable " ++
1419 -----------------------------------------------------------------------------
1421 getProgramName :: IO String
1422 getProgramName = liftM (`withoutSuffix` ".bin") getProgName
1423 where str `withoutSuffix` suff
1424 | suff `isSuffixOf` str = take (length str - length suff) str
1427 bye :: String -> IO a
1428 bye s = putStr s >> exitWith ExitSuccess
1430 die :: String -> IO a
1433 dieWith :: Int -> String -> IO a
1436 prog <- getProgramName
1437 hPutStrLn stderr (prog ++ ": " ++ s)
1438 exitWith (ExitFailure ec)
1440 dieOrForceAll :: Force -> String -> IO ()
1441 dieOrForceAll ForceAll s = ignoreError s
1442 dieOrForceAll _other s = dieForcible s
1444 ignoreError :: String -> IO ()
1445 ignoreError s = reportError (s ++ " (ignoring)")
1447 reportError :: String -> IO ()
1448 reportError s = do hFlush stdout; hPutStrLn stderr s
1450 dieForcible :: String -> IO ()
1451 dieForcible s = die (s ++ " (use --force to override)")
1453 my_head :: String -> [a] -> a
1454 my_head s [] = error s
1455 my_head _ (x : _) = x
1457 -----------------------------------------
1458 -- Cut and pasted from ghc/compiler/main/SysTools
1460 #if defined(mingw32_HOST_OS)
1461 subst :: Char -> Char -> String -> String
1462 subst a b ls = map (\ x -> if x == a then b else x) ls
1464 unDosifyPath :: FilePath -> FilePath
1465 unDosifyPath xs = subst '\\' '/' xs
1467 getLibDir :: IO (Maybe String)
1468 getLibDir = fmap (fmap (</> "lib")) $ getExecDir "/bin/ghc-pkg.exe"
1470 -- (getExecDir cmd) returns the directory in which the current
1471 -- executable, which should be called 'cmd', is running
1472 -- So if the full path is /a/b/c/d/e, and you pass "d/e" as cmd,
1473 -- you'll get "/a/b/c" back as the result
1474 getExecDir :: String -> IO (Maybe String)
1476 getExecPath >>= maybe (return Nothing) removeCmdSuffix
1477 where initN n = reverse . drop n . reverse
1478 removeCmdSuffix = return . Just . initN (length cmd) . unDosifyPath
1480 getExecPath :: IO (Maybe String)
1482 allocaArray len $ \buf -> do
1483 ret <- getModuleFileName nullPtr buf len
1484 if ret == 0 then return Nothing
1485 else liftM Just $ peekCString buf
1486 where len = 2048 -- Plenty, PATH_MAX is 512 under Win32.
1488 foreign import stdcall unsafe "GetModuleFileNameA"
1489 getModuleFileName :: Ptr () -> CString -> Int -> IO Int32
1492 getLibDir :: IO (Maybe String)
1493 getLibDir = return Nothing
1496 -----------------------------------------
1497 -- Adapted from ghc/compiler/utils/Panic
1499 installSignalHandlers :: IO ()
1500 installSignalHandlers = do
1501 threadid <- myThreadId
1503 interrupt = Exception.throwTo threadid
1504 (Exception.ErrorCall "interrupted")
1506 #if !defined(mingw32_HOST_OS)
1507 _ <- installHandler sigQUIT (Catch interrupt) Nothing
1508 _ <- installHandler sigINT (Catch interrupt) Nothing
1510 #elif __GLASGOW_HASKELL__ >= 603
1511 -- GHC 6.3+ has support for console events on Windows
1512 -- NOTE: running GHCi under a bash shell for some reason requires
1513 -- you to press Ctrl-Break rather than Ctrl-C to provoke
1514 -- an interrupt. Ctrl-C is getting blocked somewhere, I don't know
1515 -- why --SDM 17/12/2004
1516 let sig_handler ControlC = interrupt
1517 sig_handler Break = interrupt
1518 sig_handler _ = return ()
1520 _ <- installHandler (Catch sig_handler)
1523 return () -- nothing
1526 #if __GLASGOW_HASKELL__ <= 604
1527 isInfixOf :: (Eq a) => [a] -> [a] -> Bool
1528 isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack)
1531 #if mingw32_HOST_OS || mingw32_TARGET_OS
1532 throwIOIO :: Exception.IOException -> IO a
1533 throwIOIO = Exception.throwIO
1535 catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a
1536 catchIO = Exception.catch
1539 catchError :: IO a -> (String -> IO a) -> IO a
1540 catchError io handler = io `Exception.catch` handler'
1541 where handler' (Exception.ErrorCall err) = handler err
1544 -- copied from Cabal's Distribution.Simple.Utils, except that we want
1545 -- to use text files here, rather than binary files.
1546 writeFileAtomic :: FilePath -> String -> IO ()
1547 writeFileAtomic targetFile content = do
1548 (newFile, newHandle) <- openNewFile targetDir template
1549 do hPutStr newHandle content
1551 #if mingw32_HOST_OS || mingw32_TARGET_OS
1552 renameFile newFile targetFile
1553 -- If the targetFile exists then renameFile will fail
1554 `catchIO` \err -> do
1555 exists <- doesFileExist targetFile
1557 then do removeFile targetFile
1558 -- Big fat hairy race condition
1559 renameFile newFile targetFile
1560 -- If the removeFile succeeds and the renameFile fails
1561 -- then we've lost the atomic property.
1564 renameFile newFile targetFile
1566 `Exception.onException` do hClose newHandle
1569 template = targetName <.> "tmp"
1570 targetDir | null targetDir_ = "."
1571 | otherwise = targetDir_
1572 --TODO: remove this when takeDirectory/splitFileName is fixed
1573 -- to always return a valid dir
1574 (targetDir_,targetName) = splitFileName targetFile
1576 -- Ugh, this is a copy/paste of code from the base library, but
1577 -- if uses 666 rather than 600 for the permissions.
1578 openNewFile :: FilePath -> String -> IO (FilePath, Handle)
1579 openNewFile dir template = do
1583 -- We split off the last extension, so we can use .foo.ext files
1584 -- for temporary files (hidden on Unix OSes). Unfortunately we're
1585 -- below filepath in the hierarchy here.
1587 case break (== '.') $ reverse template of
1588 -- First case: template contains no '.'s. Just re-reverse it.
1589 (rev_suffix, "") -> (reverse rev_suffix, "")
1590 -- Second case: template contains at least one '.'. Strip the
1591 -- dot from the prefix and prepend it to the suffix (if we don't
1592 -- do this, the unique number will get added after the '.' and
1593 -- thus be part of the extension, which is wrong.)
1594 (rev_suffix, '.':rest) -> (reverse rest, '.':reverse rev_suffix)
1595 -- Otherwise, something is wrong, because (break (== '.')) should
1596 -- always return a pair with either the empty string or a string
1597 -- beginning with '.' as the second component.
1598 _ -> error "bug in System.IO.openTempFile"
1600 oflags = rw_flags .|. o_EXCL
1602 #if __GLASGOW_HASKELL__ < 611
1603 withFilePath = withCString
1607 fd <- withFilePath filepath $ \ f ->
1608 c_open f oflags 0o666
1613 then findTempName (x+1)
1614 else ioError (errnoToIOError "openNewBinaryFile" errno Nothing (Just dir))
1616 -- XXX We want to tell fdToHandle what the filepath is,
1617 -- as any exceptions etc will only be able to report the
1620 #if __GLASGOW_HASKELL__ >= 609
1623 fdToHandle (fromIntegral fd)
1625 `Exception.onException` c_close fd
1626 return (filepath, h)
1628 filename = prefix ++ show x ++ suffix
1629 filepath = dir `combine` filename
1631 -- XXX Copied from GHC.Handle
1632 std_flags, output_flags, rw_flags :: CInt
1633 std_flags = o_NONBLOCK .|. o_NOCTTY
1634 output_flags = std_flags .|. o_CREAT
1635 rw_flags = output_flags .|. o_RDWR
1637 -- | The function splits the given string to substrings
1638 -- using 'isSearchPathSeparator'.
1639 parseSearchPath :: String -> [FilePath]
1640 parseSearchPath path = split path
1642 split :: String -> [String]
1646 _:rest -> chunk : split rest
1650 #ifdef mingw32_HOST_OS
1651 ('\"':xs@(_:_)) | last xs == '\"' -> init xs
1655 (chunk', rest') = break isSearchPathSeparator s
1657 readUTF8File :: FilePath -> IO String
1658 readUTF8File file = do
1659 h <- openFile file ReadMode
1660 #if __GLASGOW_HASKELL__ >= 612
1661 -- fix the encoding to UTF-8