-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Haskell suite library for package management and integration with Cabal -- -- See http://documentup.com/haskell-suite/haskell-packages @package haskell-packages @version 0.5 module Distribution.HaskellSuite.Packages type Packages = [InstalledPackageInfo] -- | Get all packages that are registered in a particular database -- -- If the database doesn't exist, the behaviour is determined by -- maybeInitDB. getInstalledPackages :: forall db. IsPackageDB db => Proxy db -> PackageDB -> IO Packages -- | Try to retrieve an InstalledPackageInfo for each of -- UnitIds from a specified set of PackageDBs. -- -- May throw a PkgInfoNotFound exception. -- -- If a database doesn't exist, the behaviour is determined by -- maybeInitDB. readPackagesInfo :: IsPackageDB db => Proxy db -> [PackageDB] -> [UnitId] -> IO Packages -- | Package database class. -- -- db will typically be a newtype-wrapped path to the database -- file, although more sophisticated setups are certainly possible. -- -- Consider using StandardDB first, and implement your own -- database type if that isn't enough. class IsPackageDB db where locateDB GlobalPackageDB = globalDB locateDB UserPackageDB = Just <$> userDB locateDB (SpecificPackageDB p) = Just <$> dbFromPath p userDB = do { let name = untag (dbName :: Tagged db String); path <- () <$> haskellPackagesDir <*> pure (name <.> "db"); dbFromPath path } -- | The name of the database. Used to construct some paths. dbName :: IsPackageDB db => Tagged db String -- | Read a package database. -- -- If the database does not exist, then the first argument tells whether -- we should create and initialize it with an empty package list. In that -- case, if Don'tInitDB is specified, a BadPkgDb -- exception is thrown. readPackageDB :: IsPackageDB db => MaybeInitDB -> db -> IO Packages -- | Write a package database writePackageDB :: IsPackageDB db => db -> Packages -> IO () -- | Get the location of a global package database (if there's one) globalDB :: IsPackageDB db => IO (Maybe db) -- | Create a db object given a database file path dbFromPath :: IsPackageDB db => FilePath -> IO db -- | Convert a package db specification to a db object locateDB :: IsPackageDB db => PackageDB -> IO (Maybe db) -- | The user database userDB :: IsPackageDB db => IO db -- | A flag which tells whether the library should create an empty package -- database if it doesn't exist yet data MaybeInitDB InitDB :: MaybeInitDB Don'tInitDB :: MaybeInitDB -- | This function determines whether a package database should be -- initialized if it doesn't exist yet. -- -- The rule is this: if it is a global or a user database, then -- initialize it; otherwise, don't. -- -- Rationale: if the database was specified by the user, she could have -- made a mistake in the path, and we'd rather report it. On the other -- hand, it is our responsibility to ensure that the user and global -- databases exist. maybeInitDB :: PackageDB -> MaybeInitDB data StandardDB name StandardDB :: FilePath -> StandardDB name class IsDBName name getDBName :: IsDBName name => Tagged name String -- | Make all paths in the package info relative to the given base -- directory. makePkgInfoRelative :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo -- | Make all relative paths in the package info absolute, interpreting -- them relative to the given base directory. makePkgInfoAbsolute :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo -- | Apply a given function to all file paths contained in the package info mapPaths :: (FilePath -> FilePath) -> (InstalledPackageInfo -> InstalledPackageInfo) writeDB :: FilePath -> Packages -> IO () readDB :: MaybeInitDB -> FilePath -> IO Packages -- | If the path does not exist, create an empty database there. Otherwise, -- do nothing. initDB :: FilePath -> IO () data PkgDBError -- | package database could not be parsed or contains errors BadPkgDB :: FilePath -> PkgDBError -- | package db file could not be read PkgDBReadError :: FilePath -> IOException -> PkgDBError -- | attempt to register an already present package id PkgExists :: UnitId -> PkgDBError -- | attempt to register in the global db when it's not present RegisterNullDB :: PkgDBError data PkgInfoError -- | requested package id could not be found in any of the package -- databases PkgInfoNotFound :: UnitId -> PkgInfoError instance Data.Aeson.Types.ToJSON.ToJSON Distribution.InstalledPackageInfo.InstalledPackageInfo instance Data.Aeson.Types.FromJSON.FromJSON Distribution.InstalledPackageInfo.InstalledPackageInfo instance Data.Aeson.Types.ToJSON.ToJSON Distribution.InstalledPackageInfo.ExposedModule instance Data.Aeson.Types.FromJSON.FromJSON Distribution.InstalledPackageInfo.ExposedModule instance Data.Aeson.Types.ToJSON.ToJSON Distribution.InstalledPackageInfo.OriginalModule instance Data.Aeson.Types.FromJSON.FromJSON Distribution.InstalledPackageInfo.OriginalModule instance Distribution.HaskellSuite.Packages.IsDBName name => Distribution.HaskellSuite.Packages.IsPackageDB (Distribution.HaskellSuite.Packages.StandardDB name) instance GHC.Show.Show Distribution.HaskellSuite.Packages.PkgDBError instance GHC.Exception.Exception Distribution.HaskellSuite.Packages.PkgDBError instance GHC.Exception.Exception Distribution.HaskellSuite.Packages.PkgInfoError instance GHC.Show.Show Distribution.HaskellSuite.Packages.PkgInfoError instance Data.Aeson.Types.ToJSON.ToJSON Distribution.License.License instance Data.Aeson.Types.FromJSON.FromJSON Distribution.License.License instance Data.Aeson.Types.ToJSON.ToJSON Distribution.ModuleName.ModuleName instance Data.Aeson.Types.FromJSON.FromJSON Distribution.ModuleName.ModuleName instance Data.Aeson.Types.ToJSON.ToJSON Distribution.Package.PackageName instance Data.Aeson.Types.FromJSON.FromJSON Distribution.Package.PackageName instance Data.Aeson.Types.ToJSON.ToJSON Distribution.Package.PackageIdentifier instance Data.Aeson.Types.FromJSON.FromJSON Distribution.Package.PackageIdentifier instance Data.Aeson.Types.ToJSON.ToJSON Distribution.Package.UnitId instance Data.Aeson.Types.FromJSON.FromJSON Distribution.Package.UnitId instance Data.Aeson.Types.ToJSON.ToJSON Distribution.Package.AbiHash instance Data.Aeson.Types.FromJSON.FromJSON Distribution.Package.AbiHash module Distribution.HaskellSuite.Modules -- | A standard module monad transformer. -- -- i is the type of module info, m is the underlying -- monad. data ModuleT i m a -- | Tries to find the module in the current set of packages, then find the -- module's info file, and reads and caches its contents. -- -- Returns Nothing if the module could not be found in the current -- set of packages. If the module is found, but something else goes wrong -- (e.g. there's no info file for it), an exception is thrown. getModuleInfo :: (MonadModule m, ModName n) => n -> m (Maybe (ModuleInfo m)) -- | Run a ModuleT action. -- -- This is a simplified version of runModuleT. evalModuleT :: MonadIO m => ModuleT i m a -> Packages -> String -> (FilePath -> m i) -> m a -- | Run a ModuleT action runModuleT :: MonadIO m => ModuleT i m a -> Packages -> String -> (FilePath -> m i) -> Map ModuleName i -> m (a, Map ModuleName i) -- | This class defines the interface that is used by getModuleInfo, -- so that you can use it in monads other than ModuleT. -- -- You don't typically have to define your own instances of this class, -- but here are a couple of cases when you might: -- -- class Monad m => MonadModule m where type ModuleInfo m where { type family ModuleInfo m; } lookupInCache :: (MonadModule m, ModName n) => n -> m (Maybe (ModuleInfo m)) insertInCache :: (MonadModule m, ModName n) => n -> ModuleInfo m -> m () getPackages :: MonadModule m => m Packages -- | Read the module info, given a list of search paths and the module name readModuleInfo :: (MonadModule m, ModName n) => [FilePath] -> n -> m (ModuleInfo m) -- | Different libraries (Cabal, haskell-src-exts, ...) use different types -- to represent module names. Hence this class. class ModName n modToString :: ModName n => n -> String -- | Convert module name from arbitrary representation to Cabal's one convertModuleName :: (ModName n) => n -> ModuleName instance GHC.Base.Monad m => GHC.Base.Monad (Distribution.HaskellSuite.Modules.ModuleT i m) instance GHC.Base.Monad m => GHC.Base.Applicative (Distribution.HaskellSuite.Modules.ModuleT i m) instance GHC.Base.Functor m => GHC.Base.Functor (Distribution.HaskellSuite.Modules.ModuleT i m) instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Distribution.HaskellSuite.Modules.ModuleT i m) instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Distribution.HaskellSuite.Modules.ModuleT i m) instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Distribution.HaskellSuite.Modules.ModuleT i m) instance Distribution.HaskellSuite.Modules.ModName GHC.Base.String instance Distribution.HaskellSuite.Modules.ModName Distribution.ModuleName.ModuleName instance Control.Monad.Trans.Class.MonadTrans (Distribution.HaskellSuite.Modules.ModuleT i) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Distribution.HaskellSuite.Modules.ModuleT i m) instance (GHC.Base.Functor m, GHC.Base.Monad m) => Distribution.HaskellSuite.Modules.MonadModule (Distribution.HaskellSuite.Modules.ModuleT i m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Distribution.HaskellSuite.Modules.ModuleT i m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Distribution.HaskellSuite.Modules.ModuleT i m) -- | This module is designed to be imported qualified: -- --
--   import qualified Distribution.HaskellSuite.Compiler as Compiler
--   
module Distribution.HaskellSuite.Compiler -- | An abstraction over a Haskell compiler. -- -- Once you've written a Compiler.Is instance, you get -- Cabal integration for free (via Compiler.main). -- -- Consider whether Compiler.Simple suits your needs — -- then you need to write even less code. -- -- Minimal definition: DB, name, version, -- fileExtensions, compile, languages, -- languageExtensions. -- -- fileExtensions are only used for installLib, so if you -- define a custom installLib, fileExtensions won't be used -- (but you'll still get a compiler warning if you do not define it). class IsPackageDB (DB compiler) => Is compiler where type DB compiler installLib t buildDir targetDir _dynlibTargetDir _pkg mods = forM_ (fileExtensions t) $ \ ext -> do { findModuleFiles [buildDir] [ext] mods >>= installOrdinaryFiles normal targetDir } register _tool dbspec pkg = do { mbDb <- locateDB dbspec; case mbDb :: Maybe (DB compiler) of { Nothing -> throwIO RegisterNullDB Just db -> do { pkgs <- readPackageDB (maybeInitDB dbspec) db; let pkgid = installedUnitId pkg; writePackageDB db $ pkg : removePackage pkgid pkgs } } } unregister _tool dbspec pkg = do { let pkgCriterion = (case pkgVersion $ packageId pkg of { Version [] _ -> ((==) `on` pkgName) pkg _ -> (==) pkg }) . sourcePackageId; mbDb <- locateDB dbspec; case mbDb :: Maybe (DB compiler) of { Nothing -> throwIO RegisterNullDB Just db -> do { pkgs <- readPackageDB (maybeInitDB dbspec) db; let (packagesRemoved, packagesLeft) = partition pkgCriterion pkgs; if null packagesRemoved then putStrLn $ "No packages removed" else do { putStrLn "Packages removed:"; forM_ packagesRemoved $ \ p -> putStrLn $ " " ++ display (installedUnitId p) }; writePackageDB db packagesLeft } } } list _tool dbspec = do { mbDb <- locateDB dbspec; case mbDb :: Maybe (DB compiler) of { Nothing -> return () Just db -> do { pkgs <- readPackageDB (maybeInitDB dbspec) db; forM_ pkgs $ putStrLn . display . installedUnitId } } } where { type family DB compiler; } -- | Compiler's name. Should not contain spaces. name :: Is compiler => compiler -> String -- | Compiler's version version :: Is compiler => compiler -> Version -- | File extensions of the files generated by the compiler. Those files -- will be copied during the install phase. fileExtensions :: Is compiler => compiler -> [String] -- | How to compile a set of modules compile :: Is compiler => compiler -> CompileFn -- | Languages supported by this compiler (such as Haskell98, -- Haskell2010 etc.) languages :: Is compiler => compiler -> [Language] -- | Extensions supported by this compiler languageExtensions :: Is compiler => compiler -> [Extension] installLib :: Is compiler => compiler -> FilePath -> FilePath -> Maybe FilePath -> PackageIdentifier -> [ModuleName] -> IO () -- | Register the package in the database. If a package with the same id is -- already installed, it should be replaced by the new one. register :: Is compiler => compiler -> PackageDB -> InstalledPackageInfo -> IO () -- | Unregister the package unregister :: Is compiler => compiler -> PackageDB -> PackageId -> IO () list :: Is compiler => compiler -> PackageDB -> IO () -- | Compilation function type CompileFn = FilePath build directory -> Maybe Language optional default language -> [Extension] default extensions -> CpphsOptions CPP options -> PackageId name and version of the package being compiled -> PackageDBStack package db stack to use -> [UnitId] dependencies -> [FilePath] list of files to compile -> IO () data Simple db simple :: String -> Version -> [Language] -> [Extension] -> CompileFn -> [String] -> Simple db main :: Is c => c -> IO () customMain :: Is c => Parser (IO ()) -> c -> IO () instance Distribution.HaskellSuite.Packages.IsPackageDB db => Distribution.HaskellSuite.Compiler.Is (Distribution.HaskellSuite.Compiler.Simple db) -- | This module re-exports all you need in order to read package -- databases and module info files created by compilers that use -- haskell-packages. -- -- If you are writing a compiler, i.e. a program that creates or writes -- package databases or module info files — then take a look at -- Distribution.HaskellSuite.Compiler. It provides command-line -- options handling and Cabal integration. module Distribution.HaskellSuite