2013-05-17 01:00:01 +00:00
|
|
|
module Language.Haskell.GhcMod.Cradle (findCradle) where
|
2013-03-02 03:18:55 +00:00
|
|
|
|
2013-09-20 06:48:50 +00:00
|
|
|
import Data.Char (isSpace)
|
2013-03-02 03:18:55 +00:00
|
|
|
import Control.Applicative ((<$>))
|
2013-09-20 06:48:50 +00:00
|
|
|
import Control.Exception as E (catch, throwIO, SomeException)
|
|
|
|
import Control.Monad (filterM)
|
|
|
|
import Data.List (isPrefixOf, isSuffixOf)
|
2013-05-17 01:00:01 +00:00
|
|
|
import Language.Haskell.GhcMod.Types
|
2013-09-20 06:48:50 +00:00
|
|
|
import System.Directory (getCurrentDirectory, getDirectoryContents, doesFileExist)
|
2013-03-02 03:18:55 +00:00
|
|
|
import System.FilePath ((</>),takeDirectory)
|
|
|
|
|
2013-09-05 07:38:17 +00:00
|
|
|
----------------------------------------------------------------
|
|
|
|
|
2013-05-20 05:28:56 +00:00
|
|
|
-- | Finding 'Cradle'.
|
2013-09-20 06:53:51 +00:00
|
|
|
-- Find a cabal file by tracing ancestor directories.
|
|
|
|
-- Find a sandbox according to a cabal sandbox config
|
|
|
|
-- in a cabal directory.
|
2013-09-20 06:48:50 +00:00
|
|
|
findCradle :: IO Cradle
|
|
|
|
findCradle = do
|
2013-03-02 03:18:55 +00:00
|
|
|
wdir <- getCurrentDirectory
|
2013-09-20 06:48:50 +00:00
|
|
|
findCradle' wdir `E.catch` handler wdir
|
|
|
|
where
|
|
|
|
handler :: FilePath -> SomeException -> IO Cradle
|
|
|
|
handler wdir _ = return Cradle {
|
|
|
|
cradleCurrentDir = wdir
|
|
|
|
, cradleCabalDir = Nothing
|
|
|
|
, cradleCabalFile = Nothing
|
|
|
|
, cradlePackageConf = Nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
findCradle' :: FilePath -> IO Cradle
|
|
|
|
findCradle' wdir = do
|
|
|
|
(cdir,cfile) <- cabalDir wdir
|
|
|
|
mPkgConf <- getPackageDbDir cdir
|
|
|
|
return Cradle {
|
|
|
|
cradleCurrentDir = wdir
|
|
|
|
, cradleCabalDir = Just cdir
|
|
|
|
, cradleCabalFile = Just cfile
|
|
|
|
, cradlePackageConf = mPkgConf
|
|
|
|
}
|
2013-03-02 03:18:55 +00:00
|
|
|
|
2013-09-05 07:38:17 +00:00
|
|
|
----------------------------------------------------------------
|
|
|
|
|
|
|
|
cabalSuffix :: String
|
|
|
|
cabalSuffix = ".cabal"
|
|
|
|
|
|
|
|
cabalSuffixLength :: Int
|
|
|
|
cabalSuffixLength = length cabalSuffix
|
|
|
|
|
|
|
|
-- Finding a Cabal file up to the root directory
|
|
|
|
-- Input: a directly to investigate
|
|
|
|
-- Output: (the path to the directory containing a Cabal file
|
2013-09-20 06:48:50 +00:00
|
|
|
-- ,the path to the Cabal file)
|
|
|
|
cabalDir :: FilePath -> IO (FilePath,FilePath)
|
2013-03-02 03:18:55 +00:00
|
|
|
cabalDir dir = do
|
2013-09-20 06:48:50 +00:00
|
|
|
cnts <- getCabalFiles dir
|
2013-03-02 03:18:55 +00:00
|
|
|
case cnts of
|
2013-09-20 06:48:50 +00:00
|
|
|
[] | dir' == dir -> throwIO $ userError "cabal files not found"
|
2013-03-02 03:18:55 +00:00
|
|
|
| otherwise -> cabalDir dir'
|
2013-09-20 06:48:50 +00:00
|
|
|
cfile:_ -> return (dir,dir </> cfile)
|
|
|
|
where
|
|
|
|
dir' = takeDirectory dir
|
|
|
|
|
|
|
|
getCabalFiles :: FilePath -> IO [FilePath]
|
|
|
|
getCabalFiles dir = getFiles >>= filterM doesCabalFileExist
|
2013-03-02 03:18:55 +00:00
|
|
|
where
|
2013-09-05 07:38:17 +00:00
|
|
|
isCabal name = cabalSuffix `isSuffixOf` name
|
|
|
|
&& length name > cabalSuffixLength
|
2013-09-20 06:48:50 +00:00
|
|
|
getFiles = filter isCabal <$> getDirectoryContents dir
|
|
|
|
doesCabalFileExist file = doesFileExist $ dir </> file
|
2013-09-05 07:38:17 +00:00
|
|
|
|
|
|
|
----------------------------------------------------------------
|
|
|
|
|
2013-09-20 06:48:50 +00:00
|
|
|
configFile :: String
|
|
|
|
configFile = "cabal.sandbox.config"
|
2013-03-02 03:18:55 +00:00
|
|
|
|
2013-09-20 06:48:50 +00:00
|
|
|
pkgDbKey :: String
|
|
|
|
pkgDbKey = "package-db:"
|
2013-03-02 03:18:55 +00:00
|
|
|
|
2013-09-20 06:48:50 +00:00
|
|
|
pkgDbKeyLen :: Int
|
|
|
|
pkgDbKeyLen = length pkgDbKey
|
2013-09-05 07:38:17 +00:00
|
|
|
|
2013-09-20 06:48:50 +00:00
|
|
|
-- | Extract a package db directory from the sandbox config file.
|
|
|
|
getPackageDbDir :: FilePath -> IO (Maybe FilePath)
|
|
|
|
getPackageDbDir cdir = (Just <$> getPkgDb) `E.catch` handler
|
|
|
|
where
|
|
|
|
getPkgDb = extractValue . parse <$> readFile (cdir </> configFile)
|
|
|
|
parse = head . filter ("package-db:" `isPrefixOf`) . lines
|
|
|
|
extractValue = fst . break isSpace . dropWhile isSpace . drop pkgDbKeyLen
|
|
|
|
handler :: SomeException -> IO (Maybe FilePath)
|
|
|
|
handler _ = return Nothing
|