2015-08-19 06:46:56 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
module Language.Haskell.GhcMod.Cradle
|
|
|
|
#ifndef SPEC
|
|
|
|
(
|
2013-09-21 09:37:33 +00:00
|
|
|
findCradle
|
2014-05-18 01:32:09 +00:00
|
|
|
, findCradle'
|
2015-11-25 15:06:24 +00:00
|
|
|
, findCradleNoLog
|
2015-03-03 20:12:43 +00:00
|
|
|
, findSpecCradle
|
2014-10-14 17:52:58 +00:00
|
|
|
, cleanupCradle
|
2015-08-19 06:46:56 +00:00
|
|
|
)
|
|
|
|
#endif
|
|
|
|
where
|
2013-03-02 03:18:55 +00:00
|
|
|
|
2014-11-01 21:02:47 +00:00
|
|
|
import Language.Haskell.GhcMod.PathsAndFiles
|
2015-03-03 20:12:43 +00:00
|
|
|
import Language.Haskell.GhcMod.Monad.Types
|
2014-11-01 21:02:47 +00:00
|
|
|
import Language.Haskell.GhcMod.Types
|
2014-11-02 18:00:25 +00:00
|
|
|
import Language.Haskell.GhcMod.Utils
|
2015-09-15 03:25:00 +00:00
|
|
|
import Language.Haskell.GhcMod.Stack
|
2015-10-30 18:05:41 +00:00
|
|
|
import Language.Haskell.GhcMod.Logging
|
2016-01-08 16:14:10 +00:00
|
|
|
import Language.Haskell.GhcMod.Error
|
2015-10-30 18:05:41 +00:00
|
|
|
|
2016-01-13 03:49:38 +00:00
|
|
|
import Safe
|
2015-03-03 20:12:43 +00:00
|
|
|
import Control.Applicative
|
|
|
|
import Control.Monad.Trans.Maybe
|
|
|
|
import Data.Maybe
|
|
|
|
import System.Directory
|
|
|
|
import System.FilePath
|
2016-07-11 03:43:21 +00:00
|
|
|
import System.Environment
|
2015-08-03 01:09:56 +00:00
|
|
|
import Prelude
|
2015-11-25 15:06:24 +00:00
|
|
|
import Control.Monad.Trans.Journal (runJournalT)
|
2013-03-02 03:18:55 +00:00
|
|
|
|
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.
|
2016-05-14 18:18:06 +00:00
|
|
|
findCradle :: (GmLog m, IOish m, GmOut m) => Programs -> m Cradle
|
|
|
|
findCradle progs = findCradle' progs =<< liftIO getCurrentDirectory
|
2015-09-01 08:27:12 +00:00
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
findCradleNoLog :: forall m. (IOish m, GmOut m) => Programs -> m Cradle
|
|
|
|
findCradleNoLog progs =
|
|
|
|
fst <$> (runJournalT (findCradle progs) :: m (Cradle, GhcModLog))
|
2016-01-08 16:17:21 +00:00
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
findCradle' :: (GmLog m, IOish m, GmOut m) => Programs -> FilePath -> m Cradle
|
|
|
|
findCradle' Programs { stackProgram, cabalProgram } dir = run $
|
|
|
|
msum [ stackCradle stackProgram dir
|
|
|
|
, cabalCradle cabalProgram dir
|
2015-09-01 08:27:12 +00:00
|
|
|
, sandboxCradle dir
|
|
|
|
, plainCradle dir
|
|
|
|
]
|
2016-01-13 03:49:38 +00:00
|
|
|
where run a = fillTempDir =<< (fromJustNote "findCradle'" <$> runMaybeT a)
|
2015-03-03 20:12:43 +00:00
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
findSpecCradle ::
|
|
|
|
(GmLog m, IOish m, GmOut m) => Programs -> FilePath -> m Cradle
|
|
|
|
findSpecCradle Programs { stackProgram, cabalProgram } dir = do
|
|
|
|
let cfs = [ stackCradleSpec stackProgram
|
|
|
|
, cabalCradle cabalProgram
|
|
|
|
, sandboxCradle
|
|
|
|
]
|
2015-03-03 20:12:43 +00:00
|
|
|
cs <- catMaybes <$> mapM (runMaybeT . ($ dir)) cfs
|
|
|
|
gcs <- filterM isNotGmCradle cs
|
|
|
|
fillTempDir =<< case gcs of
|
|
|
|
[] -> fromJust <$> runMaybeT (plainCradle dir)
|
|
|
|
c:_ -> return c
|
|
|
|
where
|
2015-09-14 03:59:01 +00:00
|
|
|
isNotGmCradle crdl =
|
|
|
|
liftIO $ not <$> doesFileExist (cradleRootDir crdl </> "ghc-mod.cabal")
|
2014-03-30 08:28:57 +00:00
|
|
|
|
2014-10-14 17:52:58 +00:00
|
|
|
cleanupCradle :: Cradle -> IO ()
|
|
|
|
cleanupCradle crdl = removeDirectoryRecursive $ cradleTempDir crdl
|
|
|
|
|
2015-09-01 08:27:12 +00:00
|
|
|
fillTempDir :: IOish m => Cradle -> m Cradle
|
2015-03-03 20:12:43 +00:00
|
|
|
fillTempDir crdl = do
|
|
|
|
tmpDir <- liftIO $ newTempDir (cradleRootDir crdl)
|
|
|
|
return crdl { cradleTempDir = tmpDir }
|
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
cabalCradle ::
|
|
|
|
(IOish m, GmLog m, GmOut m) => FilePath -> FilePath -> MaybeT m Cradle
|
|
|
|
cabalCradle cabalProg wdir = do
|
2016-07-11 03:43:21 +00:00
|
|
|
cabalFile <- MaybeT $ liftIO $ findCabalFile wdir
|
|
|
|
let cabalDir = takeDirectory cabalFile
|
|
|
|
|
|
|
|
gmLog GmInfo "" $ text "Found Cabal project at" <+>: text cabalDir
|
|
|
|
|
2016-05-11 13:10:00 +00:00
|
|
|
-- If cabal doesn't exist the user probably wants to use something else
|
2016-05-14 18:18:06 +00:00
|
|
|
whenM ((==Nothing) <$> liftIO (findExecutable cabalProg)) $ do
|
2016-07-11 03:43:21 +00:00
|
|
|
gmLog GmInfo "" $ text "'cabal' executable wasn't found, trying next project type"
|
2016-05-11 13:10:00 +00:00
|
|
|
mzero
|
|
|
|
|
2016-07-11 03:43:21 +00:00
|
|
|
gmLog GmInfo "" $ text "Using Cabal project at" <+>: text cabalDir
|
2014-03-30 08:28:57 +00:00
|
|
|
return Cradle {
|
2015-09-11 01:48:52 +00:00
|
|
|
cradleProject = CabalProject
|
2015-08-12 07:25:13 +00:00
|
|
|
, cradleCurrentDir = wdir
|
2014-11-01 21:02:47 +00:00
|
|
|
, cradleRootDir = cabalDir
|
2015-03-03 20:12:43 +00:00
|
|
|
, cradleTempDir = error "tmpDir"
|
2014-11-01 21:02:47 +00:00
|
|
|
, cradleCabalFile = Just cabalFile
|
2015-08-18 09:41:14 +00:00
|
|
|
, cradleDistDir = "dist"
|
2013-09-20 06:48:50 +00:00
|
|
|
}
|
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
stackCradle ::
|
|
|
|
(IOish m, GmLog m, GmOut m) => FilePath -> FilePath -> MaybeT m Cradle
|
|
|
|
stackCradle stackProg wdir = do
|
2016-07-17 20:32:35 +00:00
|
|
|
#if __GLASGOW_HASKELL__ < 708
|
2015-11-26 18:21:15 +00:00
|
|
|
-- GHC < 7.8 is not supported by stack
|
|
|
|
mzero
|
|
|
|
#endif
|
2016-05-14 18:18:06 +00:00
|
|
|
|
2015-09-01 08:27:12 +00:00
|
|
|
cabalFile <- MaybeT $ liftIO $ findCabalFile wdir
|
2015-08-17 05:41:46 +00:00
|
|
|
let cabalDir = takeDirectory cabalFile
|
2015-09-01 08:27:12 +00:00
|
|
|
_stackConfigFile <- MaybeT $ liftIO $ findStackConfigFile cabalDir
|
2015-08-20 06:43:36 +00:00
|
|
|
|
2016-07-11 03:43:21 +00:00
|
|
|
gmLog GmInfo "" $ text "Found Stack project at" <+>: text cabalDir
|
|
|
|
|
|
|
|
stackExeSet <- liftIO $ isJust <$> lookupEnv "STACK_EXE"
|
|
|
|
stackExeExists <- liftIO $ isJust <$> findExecutable stackProg
|
|
|
|
setupCfgExists <- liftIO $ doesFileExist $ cabalDir </> setupConfigPath "dist"
|
|
|
|
|
|
|
|
case (stackExeExists, stackExeSet) of
|
|
|
|
(False, True) -> do
|
|
|
|
gmLog GmWarning "" $ text "'stack' executable wasn't found but STACK_EXE is set, trying next project type"
|
|
|
|
mzero
|
|
|
|
|
|
|
|
(False, False) -> do
|
|
|
|
gmLog GmInfo "" $ text "'stack' executable wasn't found, trying next project type"
|
|
|
|
mzero
|
|
|
|
|
|
|
|
(True, True) -> do
|
2017-02-26 18:40:45 +00:00
|
|
|
gmLog GmInfo "" $ text "STACK_EXE set, preferring Stack project"
|
2016-07-11 03:43:21 +00:00
|
|
|
|
|
|
|
(True, False) | setupCfgExists -> do
|
|
|
|
gmLog GmWarning "" $ text "'dist/setup-config' exists, ignoring Stack project"
|
|
|
|
mzero
|
|
|
|
|
|
|
|
(True, False) -> return ()
|
2016-01-09 22:21:59 +00:00
|
|
|
|
2016-08-27 12:05:44 +00:00
|
|
|
senv <- MaybeT $ getStackEnv cabalDir stackProg
|
2015-08-17 05:41:46 +00:00
|
|
|
|
2016-07-11 03:43:21 +00:00
|
|
|
gmLog GmInfo "" $ text "Using Stack project at" <+>: text cabalDir
|
2015-08-17 05:41:46 +00:00
|
|
|
return Cradle {
|
2015-09-11 01:48:52 +00:00
|
|
|
cradleProject = StackProject senv
|
2015-08-17 05:41:46 +00:00
|
|
|
, cradleCurrentDir = wdir
|
|
|
|
, cradleRootDir = cabalDir
|
|
|
|
, cradleTempDir = error "tmpDir"
|
|
|
|
, cradleCabalFile = Just cabalFile
|
2015-09-11 01:48:52 +00:00
|
|
|
, cradleDistDir = seDistDir senv
|
2015-08-17 05:41:46 +00:00
|
|
|
}
|
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
stackCradleSpec ::
|
|
|
|
(IOish m, GmLog m, GmOut m) => FilePath -> FilePath -> MaybeT m Cradle
|
|
|
|
stackCradleSpec stackProg wdir = do
|
|
|
|
crdl <- stackCradle stackProg wdir
|
2015-09-14 05:11:45 +00:00
|
|
|
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")
|
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
sandboxCradle :: (IOish m, GmLog m, GmOut m) => FilePath -> MaybeT m Cradle
|
2014-03-30 08:28:57 +00:00
|
|
|
sandboxCradle wdir = do
|
2015-09-01 08:27:12 +00:00
|
|
|
sbDir <- MaybeT $ liftIO $ findCabalSandboxDir wdir
|
2016-07-11 03:43:21 +00:00
|
|
|
gmLog GmInfo "" $ text "Using sandbox project at" <+>: text sbDir
|
2013-09-20 06:48:50 +00:00
|
|
|
return Cradle {
|
2015-09-11 01:48:52 +00:00
|
|
|
cradleProject = SandboxProject
|
2015-08-12 07:25:13 +00:00
|
|
|
, cradleCurrentDir = wdir
|
2014-11-01 21:02:47 +00:00
|
|
|
, cradleRootDir = sbDir
|
2015-03-03 20:12:43 +00:00
|
|
|
, cradleTempDir = error "tmpDir"
|
2014-03-30 08:28:57 +00:00
|
|
|
, cradleCabalFile = Nothing
|
2015-08-18 09:41:14 +00:00
|
|
|
, cradleDistDir = "dist"
|
2013-09-20 06:48:50 +00:00
|
|
|
}
|
2013-03-02 03:18:55 +00:00
|
|
|
|
2016-05-14 18:18:06 +00:00
|
|
|
plainCradle :: (IOish m, GmLog m, GmOut m) => FilePath -> MaybeT m Cradle
|
2014-10-14 17:52:58 +00:00
|
|
|
plainCradle wdir = do
|
2016-05-14 18:18:06 +00:00
|
|
|
gmLog GmInfo "" $ text "Found no other project type, falling back to plain GHC project"
|
2015-03-03 20:12:43 +00:00
|
|
|
return $ Cradle {
|
2015-09-11 01:48:52 +00:00
|
|
|
cradleProject = PlainProject
|
2015-08-12 07:25:13 +00:00
|
|
|
, cradleCurrentDir = wdir
|
2014-03-30 08:28:57 +00:00
|
|
|
, cradleRootDir = wdir
|
2015-03-03 20:12:43 +00:00
|
|
|
, cradleTempDir = error "tmpDir"
|
2014-03-30 08:28:57 +00:00
|
|
|
, cradleCabalFile = Nothing
|
2015-08-18 09:41:14 +00:00
|
|
|
, cradleDistDir = "dist"
|
2014-03-30 08:28:57 +00:00
|
|
|
}
|