138 lines
4.1 KiB
Haskell
138 lines
4.1 KiB
Haskell
{-# LANGUAGE CPP #-}
|
|
module Language.Haskell.GhcMod.Cradle
|
|
#ifndef SPEC
|
|
(
|
|
findCradle
|
|
, findCradle'
|
|
, findSpecCradle
|
|
, cleanupCradle
|
|
)
|
|
#endif
|
|
where
|
|
|
|
import Language.Haskell.GhcMod.PathsAndFiles
|
|
import Language.Haskell.GhcMod.Monad.Types
|
|
import Language.Haskell.GhcMod.Types
|
|
import Language.Haskell.GhcMod.Utils
|
|
import Language.Haskell.GhcMod.Stack
|
|
|
|
import Control.Applicative
|
|
import Control.Monad
|
|
import Control.Monad.Trans.Maybe
|
|
import Data.Maybe
|
|
import System.Directory
|
|
import System.FilePath
|
|
import Prelude
|
|
|
|
----------------------------------------------------------------
|
|
|
|
-- | Finding 'Cradle'.
|
|
-- Find a cabal file by tracing ancestor directories.
|
|
-- Find a sandbox according to a cabal sandbox config
|
|
-- in a cabal directory.
|
|
findCradle :: (IOish m, GmOut m) => m Cradle
|
|
findCradle = findCradle' =<< liftIO getCurrentDirectory
|
|
|
|
findCradle' :: (IOish m, GmOut m) => FilePath -> m Cradle
|
|
findCradle' dir = run $
|
|
msum [ stackCradle dir
|
|
, cabalCradle dir
|
|
, sandboxCradle dir
|
|
, plainCradle dir
|
|
]
|
|
where run a = fillTempDir =<< (fromJust <$> runMaybeT a)
|
|
|
|
findSpecCradle :: (IOish m, GmOut m) => FilePath -> m Cradle
|
|
findSpecCradle dir = do
|
|
let cfs = [stackCradleSpec, cabalCradle, sandboxCradle]
|
|
cs <- catMaybes <$> mapM (runMaybeT . ($ dir)) cfs
|
|
gcs <- filterM isNotGmCradle cs
|
|
fillTempDir =<< case gcs of
|
|
[] -> fromJust <$> runMaybeT (plainCradle dir)
|
|
c:_ -> return c
|
|
where
|
|
isNotGmCradle crdl =
|
|
liftIO $ not <$> doesFileExist (cradleRootDir crdl </> "ghc-mod.cabal")
|
|
|
|
cleanupCradle :: Cradle -> IO ()
|
|
cleanupCradle crdl = removeDirectoryRecursive $ cradleTempDir crdl
|
|
|
|
fillTempDir :: IOish m => Cradle -> m Cradle
|
|
fillTempDir crdl = do
|
|
tmpDir <- liftIO $ newTempDir (cradleRootDir crdl)
|
|
return crdl { cradleTempDir = tmpDir }
|
|
|
|
cabalCradle :: IOish m => FilePath -> MaybeT m Cradle
|
|
cabalCradle wdir = do
|
|
cabalFile <- MaybeT $ liftIO $ findCabalFile wdir
|
|
|
|
let cabalDir = takeDirectory cabalFile
|
|
|
|
return Cradle {
|
|
cradleProject = CabalProject
|
|
, cradleCurrentDir = wdir
|
|
, cradleRootDir = cabalDir
|
|
, cradleTempDir = error "tmpDir"
|
|
, cradleCabalFile = Just cabalFile
|
|
, cradleDistDir = "dist"
|
|
}
|
|
|
|
stackCradle :: (IOish m, GmOut m) => FilePath -> MaybeT m Cradle
|
|
stackCradle wdir = do
|
|
cabalFile <- MaybeT $ liftIO $ findCabalFile wdir
|
|
|
|
let cabalDir = takeDirectory cabalFile
|
|
|
|
_stackConfigFile <- MaybeT $ liftIO $ findStackConfigFile cabalDir
|
|
|
|
-- If dist/setup-config already exists the user probably wants to use cabal
|
|
-- rather than stack, or maybe that's just me ;)
|
|
whenM (liftIO $ doesFileExist $ setupConfigPath "dist") $ mzero
|
|
|
|
senv <- MaybeT $ getStackEnv cabalDir
|
|
|
|
return Cradle {
|
|
cradleProject = StackProject senv
|
|
, cradleCurrentDir = wdir
|
|
, cradleRootDir = cabalDir
|
|
, cradleTempDir = error "tmpDir"
|
|
, cradleCabalFile = Just cabalFile
|
|
, cradleDistDir = seDistDir senv
|
|
}
|
|
|
|
stackCradleSpec :: (IOish m, GmOut m) => FilePath -> MaybeT m Cradle
|
|
stackCradleSpec wdir = do
|
|
crdl <- stackCradle wdir
|
|
case crdl of
|
|
Cradle { cradleProject = StackProject StackEnv { seDistDir } } -> do
|
|
b <- isGmDistDir seDistDir
|
|
when b mzero
|
|
return crdl
|
|
_ -> error "stackCradleSpec"
|
|
where
|
|
isGmDistDir dir =
|
|
liftIO $ not <$> doesFileExist (dir </> ".." </> "ghc-mod.cabal")
|
|
|
|
sandboxCradle :: IOish m => FilePath -> MaybeT m Cradle
|
|
sandboxCradle wdir = do
|
|
sbDir <- MaybeT $ liftIO $ findCabalSandboxDir wdir
|
|
return Cradle {
|
|
cradleProject = SandboxProject
|
|
, cradleCurrentDir = wdir
|
|
, cradleRootDir = sbDir
|
|
, cradleTempDir = error "tmpDir"
|
|
, cradleCabalFile = Nothing
|
|
, cradleDistDir = "dist"
|
|
}
|
|
|
|
plainCradle :: IOish m => FilePath -> MaybeT m Cradle
|
|
plainCradle wdir = do
|
|
return $ Cradle {
|
|
cradleProject = PlainProject
|
|
, cradleCurrentDir = wdir
|
|
, cradleRootDir = wdir
|
|
, cradleTempDir = error "tmpDir"
|
|
, cradleCabalFile = Nothing
|
|
, cradleDistDir = "dist"
|
|
}
|