/interpreter/ghc/libraries/Cabal/Distribution/Simple/Program/HcPkg.hs
https://github.com/khskrede/mehh · Haskell · 277 lines · 189 code · 43 blank · 45 comment · 13 complexity · 96fe6afc42313f034e404553c16d4e23 MD5 · raw file
- -----------------------------------------------------------------------------
- -- |
- -- Module : Distribution.Simple.Program.HcPkg
- -- Copyright : Duncan Coutts 2009
- --
- -- Maintainer : cabal-devel@haskell.org
- -- Portability : portable
- --
- -- This module provides an library interface to the @hc-pkg@ program.
- -- Currently only GHC and LHC have hc-pkg programs.
- module Distribution.Simple.Program.HcPkg (
- register,
- reregister,
- unregister,
- expose,
- hide,
- dump,
- -- * Program invocations
- registerInvocation,
- reregisterInvocation,
- unregisterInvocation,
- exposeInvocation,
- hideInvocation,
- dumpInvocation,
- ) where
- import Distribution.Package
- ( PackageId, InstalledPackageId(..) )
- import Distribution.InstalledPackageInfo
- ( InstalledPackageInfo, InstalledPackageInfo_(..)
- , showInstalledPackageInfo, parseInstalledPackageInfo )
- import Distribution.ParseUtils
- ( ParseResult(..) )
- import Distribution.Simple.Compiler
- ( PackageDB(..), PackageDBStack )
- import Distribution.Simple.Program.Types
- ( ConfiguredProgram(programId, programVersion) )
- import Distribution.Simple.Program.Run
- ( ProgramInvocation(..), IOEncoding(..), programInvocation
- , runProgramInvocation, getProgramInvocationOutput )
- import Distribution.Version
- ( Version(..) )
- import Distribution.Text
- ( display )
- import Distribution.Simple.Utils
- ( die )
- import Distribution.Verbosity
- ( Verbosity, deafening, silent )
- import Distribution.Compat.Exception
- ( catchExit )
- import Data.Char
- ( isSpace )
- import Control.Monad
- ( liftM )
- -- | Call @hc-pkg@ to register a package.
- --
- -- > hc-pkg register {filename | -} [--user | --global | --package-conf]
- --
- register :: Verbosity -> ConfiguredProgram -> PackageDBStack
- -> Either FilePath
- InstalledPackageInfo
- -> IO ()
- register verbosity hcPkg packagedb pkgFile =
- runProgramInvocation verbosity
- (registerInvocation hcPkg verbosity packagedb pkgFile)
- -- | Call @hc-pkg@ to re-register a package.
- --
- -- > hc-pkg register {filename | -} [--user | --global | --package-conf]
- --
- reregister :: Verbosity -> ConfiguredProgram -> PackageDBStack
- -> Either FilePath
- InstalledPackageInfo
- -> IO ()
- reregister verbosity hcPkg packagedb pkgFile =
- runProgramInvocation verbosity
- (reregisterInvocation hcPkg verbosity packagedb pkgFile)
- -- | Call @hc-pkg@ to unregister a package
- --
- -- > hc-pkg unregister [pkgid] [--user | --global | --package-conf]
- --
- unregister :: Verbosity -> ConfiguredProgram -> PackageDB -> PackageId -> IO ()
- unregister verbosity hcPkg packagedb pkgid =
- runProgramInvocation verbosity
- (unregisterInvocation hcPkg verbosity packagedb pkgid)
- -- | Call @hc-pkg@ to expose a package.
- --
- -- > hc-pkg expose [pkgid] [--user | --global | --package-conf]
- --
- expose :: Verbosity -> ConfiguredProgram -> PackageDB -> PackageId -> IO ()
- expose verbosity hcPkg packagedb pkgid =
- runProgramInvocation verbosity
- (exposeInvocation hcPkg verbosity packagedb pkgid)
- -- | Call @hc-pkg@ to expose a package.
- --
- -- > hc-pkg expose [pkgid] [--user | --global | --package-conf]
- --
- hide :: Verbosity -> ConfiguredProgram -> PackageDB -> PackageId -> IO ()
- hide verbosity hcPkg packagedb pkgid =
- runProgramInvocation verbosity
- (hideInvocation hcPkg verbosity packagedb pkgid)
- -- | Call @hc-pkg@ to get all the installed packages.
- --
- dump :: Verbosity -> ConfiguredProgram -> PackageDB -> IO [InstalledPackageInfo]
- dump verbosity hcPkg packagedb = do
- output <- getProgramInvocationOutput verbosity
- (dumpInvocation hcPkg verbosity packagedb)
- `catchExit` \_ -> die $ programId hcPkg ++ " dump failed"
- case parsePackages output of
- Left ok -> return ok
- _ -> die $ "failed to parse output of '"
- ++ programId hcPkg ++ " dump'"
- where
- parsePackages str =
- let parse = liftM setInstalledPackageId . parseInstalledPackageInfo
- parsed = map parse (splitPkgs str)
- in case [ msg | ParseFailed msg <- parsed ] of
- [] -> Left [ pkg | ParseOk _ pkg <- parsed ]
- msgs -> Right msgs
- --TODO: this could be a lot faster. We're doing normaliseLineEndings twice
- -- and converting back and forth with lines/unlines.
- splitPkgs :: String -> [String]
- splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines
- where
- -- Handle the case of there being no packages at all.
- checkEmpty [s] | all isSpace s = []
- checkEmpty ss = ss
- splitWith :: (a -> Bool) -> [a] -> [[a]]
- splitWith p xs = ys : case zs of
- [] -> []
- _:ws -> splitWith p ws
- where (ys,zs) = break p xs
- -- Older installed package info files did not have the installedPackageId
- -- field, so if it is missing then we fill it as the source package ID.
- setInstalledPackageId :: InstalledPackageInfo -> InstalledPackageInfo
- setInstalledPackageId pkginfo@InstalledPackageInfo {
- installedPackageId = InstalledPackageId "",
- sourcePackageId = pkgid
- }
- = pkginfo {
- --TODO use a proper named function for the conversion
- -- from source package id to installed package id
- installedPackageId = InstalledPackageId (display pkgid)
- }
- setInstalledPackageId pkginfo = pkginfo
- --------------------------
- -- The program invocations
- --
- registerInvocation, reregisterInvocation
- :: ConfiguredProgram -> Verbosity -> PackageDBStack
- -> Either FilePath InstalledPackageInfo
- -> ProgramInvocation
- registerInvocation = registerInvocation' "register"
- reregisterInvocation = registerInvocation' "update"
- registerInvocation' :: String
- -> ConfiguredProgram -> Verbosity -> PackageDBStack
- -> Either FilePath InstalledPackageInfo
- -> ProgramInvocation
- registerInvocation' cmdname hcPkg verbosity packagedbs (Left pkgFile) =
- programInvocation hcPkg args
- where
- args = [cmdname, pkgFile]
- ++ (if legacyVersion hcPkg
- then [packageDbOpts (last packagedbs)]
- else packageDbStackOpts packagedbs)
- ++ verbosityOpts hcPkg verbosity
- registerInvocation' cmdname hcPkg verbosity packagedbs (Right pkgInfo) =
- (programInvocation hcPkg args) {
- progInvokeInput = Just (showInstalledPackageInfo pkgInfo),
- progInvokeInputEncoding = IOEncodingUTF8
- }
- where
- args = [cmdname, "-"]
- ++ (if legacyVersion hcPkg
- then [packageDbOpts (last packagedbs)]
- else packageDbStackOpts packagedbs)
- ++ verbosityOpts hcPkg verbosity
- unregisterInvocation :: ConfiguredProgram
- -> Verbosity -> PackageDB -> PackageId
- -> ProgramInvocation
- unregisterInvocation hcPkg verbosity packagedb pkgid =
- programInvocation hcPkg $
- ["unregister", packageDbOpts packagedb, display pkgid]
- ++ verbosityOpts hcPkg verbosity
- exposeInvocation :: ConfiguredProgram
- -> Verbosity -> PackageDB -> PackageId -> ProgramInvocation
- exposeInvocation hcPkg verbosity packagedb pkgid =
- programInvocation hcPkg $
- ["expose", packageDbOpts packagedb, display pkgid]
- ++ verbosityOpts hcPkg verbosity
- hideInvocation :: ConfiguredProgram
- -> Verbosity -> PackageDB -> PackageId -> ProgramInvocation
- hideInvocation hcPkg verbosity packagedb pkgid =
- programInvocation hcPkg $
- ["hide", packageDbOpts packagedb, display pkgid]
- ++ verbosityOpts hcPkg verbosity
- dumpInvocation :: ConfiguredProgram
- -> Verbosity -> PackageDB -> ProgramInvocation
- dumpInvocation hcPkg verbosity packagedb =
- (programInvocation hcPkg args) {
- progInvokeOutputEncoding = IOEncodingUTF8
- }
- where
- args = ["dump", packageDbOpts packagedb]
- ++ verbosityOpts hcPkg verbosity
- packageDbStackOpts :: PackageDBStack -> [String]
- packageDbStackOpts dbstack = case dbstack of
- (GlobalPackageDB:UserPackageDB:dbs) -> "--global"
- : "--user"
- : map specific dbs
- (GlobalPackageDB:dbs) -> "--global"
- : "--no-user-package-conf"
- : map specific dbs
- _ -> ierror
- where
- specific (SpecificPackageDB db) = "--package-conf=" ++ db
- specific _ = ierror
- ierror :: a
- ierror = error ("internal error: unexpected package db stack: " ++ show dbstack)
- packageDbOpts :: PackageDB -> String
- packageDbOpts GlobalPackageDB = "--global"
- packageDbOpts UserPackageDB = "--user"
- packageDbOpts (SpecificPackageDB db) = "--package-conf=" ++ db
- verbosityOpts :: ConfiguredProgram -> Verbosity -> [String]
- verbosityOpts hcPkg v
- -- ghc-pkg < 6.11 does not support -v
- | programId hcPkg == "ghc-pkg"
- && programVersion hcPkg < Just (Version [6,11] [])
- = []
- | v >= deafening = ["-v2"]
- | v == silent = ["-v0"]
- | otherwise = []
- -- Handle quirks in ghc-pkg 6.8 and older
- legacyVersion :: ConfiguredProgram -> Bool
- legacyVersion hcPkg = programId hcPkg == "ghc-pkg"
- && programVersion hcPkg < Just (Version [6,9] [])