ghc-mod/Language/Haskell/GhcMod/GhcPkg.hs

108 lines
3.7 KiB
Haskell
Raw Normal View History

2014-05-09 18:37:15 +00:00
{-# LANGUAGE CPP, BangPatterns, ScopedTypeVariables, TupleSections #-}
module Language.Haskell.GhcMod.GhcPkg (
ghcPkgDbOpt
, ghcPkgDbStackOpts
, ghcDbStackOpts
, ghcDbOpt
2014-04-30 23:48:49 +00:00
, fromInstalledPackageId
, fromInstalledPackageId'
, getSandboxDb
, getPackageDbStack
) where
2014-05-16 00:27:23 +00:00
#ifndef MIN_VERSION_Cabal
#define MIN_VERSION_Cabal(x,y,z) 1
#endif
import Config (cProjectVersionInt)
import Control.Applicative ((<$>))
2014-05-09 18:37:15 +00:00
#if MIN_VERSION_Cabal(1,18,0)
2014-05-09 19:12:52 +00:00
import qualified Control.Exception as E
2014-05-09 18:37:15 +00:00
#endif
import Data.Char (isSpace)
import Data.List (isPrefixOf, intercalate)
2014-04-30 23:48:49 +00:00
import Data.List.Split (splitOn)
import Distribution.Package (InstalledPackageId(..))
2014-04-16 02:50:31 +00:00
import Language.Haskell.GhcMod.Types
2014-04-19 06:20:16 +00:00
import Language.Haskell.GhcMod.Utils
2014-04-16 02:32:36 +00:00
import System.FilePath ((</>))
ghcVersion :: Int
ghcVersion = read cProjectVersionInt
-- | Get path to sandbox package db
getSandboxDb :: FilePath -- ^ Path to the cabal package root directory
-- (containing the @cabal.sandbox.config@ file)
-> IO FilePath
2014-04-16 02:50:31 +00:00
getSandboxDb cdir = getSandboxDbDir (cdir </> "cabal.sandbox.config")
-- | Extract the sandbox package db directory from the cabal.sandbox.config file.
-- Exception is thrown if the sandbox config file is broken.
getSandboxDbDir :: FilePath -- ^ Path to the @cabal.sandbox.config@ file
-> IO FilePath
getSandboxDbDir sconf = do
-- Be strict to ensure that an error can be caught.
!path <- extractValue . parse <$> readFile sconf
return path
where
key = "package-db:"
keyLen = length key
parse = head . filter (key `isPrefixOf`) . lines
extractValue = dropWhileEnd isSpace . dropWhile isSpace . drop keyLen
getPackageDbStack :: FilePath -- ^ Project Directory (where the
-- cabal.sandbox.config file would be if it
-- exists)
-> IO [GhcPkgDb]
2014-05-09 18:37:15 +00:00
#if MIN_VERSION_Cabal(1,18,0)
2014-05-09 18:38:35 +00:00
getPackageDbStack cdir =
(getSandboxDb cdir >>= \db -> return [GlobalDb, PackageDb db])
2014-05-09 19:12:52 +00:00
`E.catch` \(_ :: E.SomeException) -> return [GlobalDb, UserDb]
2014-05-09 18:37:15 +00:00
#else
2014-05-09 18:38:35 +00:00
getPackageDbStack _ =
2014-05-09 18:37:15 +00:00
return [GlobalDb, UserDb]
#endif
fromInstalledPackageId' :: InstalledPackageId -> Maybe Package
fromInstalledPackageId' pid = let
2014-04-30 23:48:49 +00:00
InstalledPackageId pkg = pid
in case reverse $ splitOn "-" pkg of
i:v:rest -> Just (intercalate "-" (reverse rest), v, i)
_ -> Nothing
fromInstalledPackageId :: InstalledPackageId -> Package
fromInstalledPackageId pid =
case fromInstalledPackageId' pid of
Just p -> p
Nothing -> error $
"fromInstalledPackageId: `"++show pid++"' is not a valid package-id"
-- | Get options needed to add a list of package dbs to ghc-pkg's db stack
ghcPkgDbStackOpts :: [GhcPkgDb] -- ^ Package db stack
-> [String]
2014-04-16 02:52:49 +00:00
ghcPkgDbStackOpts dbs = ghcPkgDbOpt `concatMap` dbs
-- | Get options needed to add a list of package dbs to ghc's db stack
ghcDbStackOpts :: [GhcPkgDb] -- ^ Package db stack
2014-04-16 02:50:31 +00:00
-> [String]
2014-04-16 02:52:49 +00:00
ghcDbStackOpts dbs = ghcDbOpt `concatMap` dbs
ghcPkgDbOpt :: GhcPkgDb -> [String]
ghcPkgDbOpt GlobalDb = ["--global"]
ghcPkgDbOpt UserDb = ["--user"]
ghcPkgDbOpt (PackageDb pkgDb)
2014-04-16 02:50:31 +00:00
| ghcVersion < 706 = ["--no-user-package-conf", "--package-conf=" ++ pkgDb]
| otherwise = ["--no-user-package-db", "--package-db=" ++ pkgDb]
ghcDbOpt :: GhcPkgDb -> [String]
2014-04-16 02:50:31 +00:00
ghcDbOpt GlobalDb
| ghcVersion < 706 = ["-global-package-conf"]
| otherwise = ["-global-package-db"]
ghcDbOpt UserDb
| ghcVersion < 706 = ["-user-package-conf"]
| otherwise = ["-user-package-db"]
ghcDbOpt (PackageDb pkgDb)
2014-04-16 02:50:31 +00:00
| ghcVersion < 706 = ["-no-user-package-conf", "-package-conf", pkgDb]
| otherwise = ["-no-user-package-db", "-package-db", pkgDb]