2015-02-07 22:55:57 +00:00
|
|
|
{-# LANGUAGE RecordWildCards, CPP #-}
|
2014-11-01 21:02:47 +00:00
|
|
|
module Language.Haskell.GhcMod.World where
|
|
|
|
{-(
|
|
|
|
, World
|
|
|
|
, getCurrentWorld
|
|
|
|
, isWorldChanged
|
|
|
|
) where
|
|
|
|
-}
|
|
|
|
|
|
|
|
import Language.Haskell.GhcMod.GhcPkg
|
|
|
|
import Language.Haskell.GhcMod.PathsAndFiles
|
|
|
|
import Language.Haskell.GhcMod.Types
|
|
|
|
import Language.Haskell.GhcMod.Utils
|
|
|
|
|
2015-02-07 22:55:57 +00:00
|
|
|
import Control.Applicative (pure, (<$>), (<*>))
|
|
|
|
import Control.Monad
|
2014-11-01 21:02:47 +00:00
|
|
|
import Data.Maybe
|
|
|
|
import Data.Traversable (traverse)
|
|
|
|
import System.Directory (getModificationTime)
|
|
|
|
import System.FilePath ((</>))
|
|
|
|
|
|
|
|
import GHC.Paths (libdir)
|
|
|
|
|
|
|
|
#if __GLASGOW_HASKELL__ <= 704
|
|
|
|
import System.Time (ClockTime)
|
|
|
|
#else
|
|
|
|
import Data.Time (UTCTime)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if __GLASGOW_HASKELL__ <= 704
|
|
|
|
type ModTime = ClockTime
|
|
|
|
#else
|
|
|
|
type ModTime = UTCTime
|
|
|
|
#endif
|
|
|
|
|
|
|
|
data TimedFile = TimedFile FilePath ModTime deriving (Eq, Show)
|
|
|
|
|
|
|
|
instance Ord TimedFile where
|
|
|
|
compare (TimedFile _ a) (TimedFile _ b) = compare a b
|
|
|
|
|
|
|
|
timeFile :: FilePath -> IO TimedFile
|
|
|
|
timeFile f = TimedFile <$> pure f <*> getModificationTime f
|
|
|
|
|
|
|
|
data World = World {
|
|
|
|
worldPackageCaches :: [TimedFile]
|
|
|
|
, worldCabalFile :: Maybe TimedFile
|
|
|
|
, worldCabalConfig :: Maybe TimedFile
|
2015-02-07 22:55:57 +00:00
|
|
|
, worldSymbolCache :: Maybe TimedFile
|
|
|
|
, worldPrettyCabalConfigCache :: Maybe TimedFile
|
2014-11-01 21:02:47 +00:00
|
|
|
} deriving (Eq, Show)
|
|
|
|
|
|
|
|
timedPackageCache :: Cradle -> IO [TimedFile]
|
|
|
|
timedPackageCache crdl = do
|
|
|
|
fs <- mapM mightExist . map (</> packageCache)
|
|
|
|
=<< getPackageCachePaths libdir crdl
|
|
|
|
timeFile `mapM` catMaybes fs
|
|
|
|
|
|
|
|
getCurrentWorld :: Cradle -> IO World
|
|
|
|
getCurrentWorld crdl = do
|
|
|
|
pkgCaches <- timedPackageCache crdl
|
|
|
|
mCabalFile <- timeFile `traverse` cradleCabalFile crdl
|
2015-02-07 22:55:57 +00:00
|
|
|
mCabalConfig <- timeMaybe (setupConfigFile crdl)
|
|
|
|
mSymbolCache <- timeMaybe (symbolCache crdl)
|
|
|
|
mPrettyConfigCache <- timeMaybe prettyConfigCache
|
2014-11-01 21:02:47 +00:00
|
|
|
|
|
|
|
return World {
|
|
|
|
worldPackageCaches = pkgCaches
|
|
|
|
, worldCabalFile = mCabalFile
|
|
|
|
, worldCabalConfig = mCabalConfig
|
2015-02-07 22:55:57 +00:00
|
|
|
, worldSymbolCache = mSymbolCache
|
|
|
|
, worldPrettyCabalConfigCache = mPrettyConfigCache
|
2014-11-01 21:02:47 +00:00
|
|
|
}
|
|
|
|
|
2015-02-07 22:55:57 +00:00
|
|
|
where
|
|
|
|
timeMaybe :: FilePath -> IO (Maybe TimedFile)
|
|
|
|
timeMaybe f = do
|
|
|
|
join $ (timeFile `traverse`) <$> mightExist f
|
|
|
|
|
2014-11-01 21:02:47 +00:00
|
|
|
didWorldChange :: World -> Cradle -> IO Bool
|
|
|
|
didWorldChange world crdl = do
|
|
|
|
(world /=) <$> getCurrentWorld crdl
|
|
|
|
|
|
|
|
-- * Neither file exists -> should return False:
|
|
|
|
-- @Nothing < Nothing = False@
|
|
|
|
-- (since we don't need to @cabal configure@ when no cabal file exists.)
|
|
|
|
--
|
|
|
|
-- * Cabal file doesn't exist (unlikely case) -> should return False
|
|
|
|
-- @Just cc < Nothing = False@
|
|
|
|
-- TODO: should we delete dist/setup-config?
|
|
|
|
--
|
|
|
|
-- * dist/setup-config doesn't exist yet -> should return True:
|
|
|
|
-- @Nothing < Just cf = True@
|
|
|
|
--
|
|
|
|
-- * Both files exist
|
|
|
|
-- @Just cc < Just cf = cc < cf = cc `olderThan` cf@
|
2015-02-07 22:55:57 +00:00
|
|
|
isSetupConfigOutOfDate :: World -> Bool
|
|
|
|
isSetupConfigOutOfDate World {..} = do
|
|
|
|
worldCabalConfig < worldCabalFile
|
|
|
|
|
|
|
|
isYoungerThanSetupConfig :: FilePath -> World -> IO Bool
|
|
|
|
isYoungerThanSetupConfig file World {..} = do
|
|
|
|
tfile <- timeFile file
|
|
|
|
return $ worldCabalConfig < Just tfile
|