diff --git a/src/Data/Store/VersionTagged.hs b/src/Data/Store/VersionTagged.hs index 27763ac472..1520fe89ea 100644 --- a/src/Data/Store/VersionTagged.hs +++ b/src/Data/Store/VersionTagged.hs @@ -4,12 +4,14 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE ViewPatterns #-} -- | Tag a Store instance with structural version info to ensure we're -- reading a compatible format. module Data.Store.VersionTagged - ( taggedDecodeOrLoad - , taggedEncodeFile - , decodeFileMaybe + ( versionedEncodeFile + , versionedDecodeOrLoad + , versionedDecodeFile + , storeVersionConfig ) where import Control.Applicative @@ -18,60 +20,88 @@ import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Logger import Control.Monad.Trans.Control (MonadBaseControl) import qualified Data.ByteString as BS +import Data.Data (Data) +import qualified Data.Map as M import Data.Monoid ((<>)) +import qualified Data.Set as S import Data.Store -import Data.Store.TypeHash +import Data.Store.Version import qualified Data.Text as T +import Language.Haskell.TH import Path import Path.IO (ensureDir) import Prelude --- | Write to the given file, with a binary-tagged tag. -taggedEncodeFile :: (Store a, HasTypeHash a, MonadIO m, MonadLogger m, Eq a) - => Path Abs File - -> a - -> m () -taggedEncodeFile fp x = do +versionedEncodeFile :: (Store a, Data a) => VersionConfig a -> Q Exp +versionedEncodeFile vc = [e| \fp x -> storeEncodeFile fp ($(wrapVersion vc) x) |] + +versionedDecodeOrLoad :: (Store a, Data a, Eq a) => VersionConfig a -> Q Exp +versionedDecodeOrLoad vc = [| versionedDecodeOrLoadImpl $(wrapVersion vc) $(checkVersion vc) |] + +versionedDecodeFile :: (Store a, Data a) => VersionConfig a -> Q Exp +versionedDecodeFile vc = [e| versionedDecodeFileImpl $(checkVersion vc) |] + +-- | Write to the given file. +storeEncodeFile :: (Store a, MonadIO m, MonadLogger m, Eq a) + => Path Abs File + -> a + -> m () +storeEncodeFile fp x = do let fpt = T.pack (toFilePath fp) $logDebug $ "Encoding " <> fpt ensureDir (parent fp) - let encoded = encode (Tagged x) - assert (decodeEx encoded == Tagged x) $ liftIO $ BS.writeFile (toFilePath fp) encoded + let encoded = encode x + assert (decodeEx encoded == x) $ liftIO $ BS.writeFile (toFilePath fp) encoded $logDebug $ "Finished writing " <> fpt -- | Read from the given file. If the read fails, run the given action and -- write that back to the file. Always starts the file off with the -- version tag. -taggedDecodeOrLoad :: (Store a, HasTypeHash a, Eq a, MonadIO m, MonadLogger m, MonadBaseControl IO m) - => Path Abs File - -> m a - -> m a -taggedDecodeOrLoad fp mx = do +versionedDecodeOrLoadImpl :: (Store a, Eq a, MonadIO m, MonadLogger m, MonadBaseControl IO m) + => (a -> WithVersion a) + -> (WithVersion a -> Either VersionCheckException a) + -> Path Abs File + -> m a + -> m a +versionedDecodeOrLoadImpl wrap check fp mx = do let fpt = T.pack (toFilePath fp) $logDebug $ "Trying to decode " <> fpt - mres <- decodeFileMaybe fp + mres <- versionedDecodeFileImpl check fp case mres of - Nothing -> do - $logDebug $ "Failure decoding " <> fpt - x <- mx - taggedEncodeFile fp x - return x Just x -> do $logDebug $ "Success decoding " <> fpt return x + _ -> do + $logDebug $ "Failure decoding " <> fpt + x <- mx + storeEncodeFile fp (wrap x) + return x -decodeFileMaybe :: (Store a, HasTypeHash a, MonadIO m, MonadLogger m, MonadBaseControl IO m) - => Path loc File - -> m (Maybe a) -decodeFileMaybe fp = do +versionedDecodeFileImpl :: (Store a, MonadIO m, MonadLogger m, MonadBaseControl IO m) + => (WithVersion a -> Either VersionCheckException a) + -> Path loc File + -> m (Maybe a) +versionedDecodeFileImpl check fp = do mbs <- liftIO (Just <$> BS.readFile (toFilePath fp)) `catch` \(err :: IOException) -> do $logDebug ("Exception ignored when attempting to load " <> T.pack (toFilePath fp) <> ": " <> T.pack (show err)) return Nothing case mbs of Nothing -> return Nothing Just bs -> - liftIO (do (Tagged res) <- decodeIO bs - return (Just res)) `catch` \(err :: PeekException) -> do + liftIO (do decoded <- decodeIO bs + return $ case check decoded of + Right res -> Just res + _ -> Nothing) `catch` \(err :: PeekException) -> do let fpt = T.pack (toFilePath fp) $logDebug ("Error while decoding " <> fpt <> ": " <> T.pack (show err) <> " (this might not be an error, when switching between stack versions)") return Nothing + +storeVersionConfig :: String -> String -> VersionConfig a +storeVersionConfig name hash = (namedVersionConfig name hash) + { vcIgnore = S.fromList + [ "Data.Vector.Unboxed.Base.Vector GHC.Types.Word" + , "Data.ByteString.Internal.ByteString" + ] + , vcRenames = M.fromList + [ ( "Data.Maybe.Maybe", "GHC.Base.Maybe") ] + } diff --git a/src/Stack/Build/Cache.hs b/src/Stack/Build/Cache.hs index 6014e412d2..c68de00e31 100644 --- a/src/Stack/Build/Cache.hs +++ b/src/Stack/Build/Cache.hs @@ -54,14 +54,11 @@ import Data.Maybe (fromMaybe, mapMaybe) import Data.Monoid ((<>)) import Data.Set (Set) import qualified Data.Set as Set -import Data.Store (Store) import qualified Data.Store as Store -import Data.Store.TypeHash (HasTypeHash, mkManyHasTypeHash) import Data.Store.VersionTagged import Data.Text (Text) import qualified Data.Text as T import Data.Traversable (forM) -import GHC.Generics (Generic) import Path import Path.IO import Stack.Constants @@ -103,64 +100,47 @@ markExeNotInstalled loc ident = do ident' <- parseRelFile $ packageIdentifierString ident ignoringAbsence (removeFile $ dir ident') --- | Stored on disk to know whether the flags have changed or any --- files have changed. -data BuildCache = BuildCache - { buildCacheTimes :: !(Map FilePath FileCacheInfo) - -- ^ Modification times of files. - } - deriving (Generic, Eq, Show) -instance Store BuildCache -instance NFData BuildCache - -- | Try to read the dirtiness cache for the given package directory. tryGetBuildCache :: (MonadIO m, MonadReader env m, HasConfig env, MonadThrow m, MonadLogger m, HasEnvConfig env, MonadBaseControl IO m) => Path Abs Dir -> m (Maybe (Map FilePath FileCacheInfo)) -tryGetBuildCache = liftM (fmap buildCacheTimes) . tryGetCache buildCacheFile +tryGetBuildCache dir = liftM (fmap buildCacheTimes) . $(versionedDecodeFile buildCacheVC) =<< buildCacheFile dir -- | Try to read the dirtiness cache for the given package directory. tryGetConfigCache :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env, MonadBaseControl IO m, MonadLogger m) => Path Abs Dir -> m (Maybe ConfigCache) -tryGetConfigCache = tryGetCache configCacheFile +tryGetConfigCache dir = $(versionedDecodeFile configCacheVC) =<< configCacheFile dir -- | Try to read the mod time of the cabal file from the last build tryGetCabalMod :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env, MonadBaseControl IO m, MonadLogger m) => Path Abs Dir -> m (Maybe ModTime) -tryGetCabalMod = tryGetCache configCabalMod - --- | Try to load a cache. -tryGetCache :: (MonadIO m, Store a, HasTypeHash a, MonadBaseControl IO m, MonadLogger m) - => (Path Abs Dir -> m (Path Abs File)) - -> Path Abs Dir - -> m (Maybe a) -tryGetCache get' dir = do - fp <- get' dir - decodeFileMaybe fp +tryGetCabalMod dir = $(versionedDecodeFile modTimeVC) =<< configCabalMod dir -- | Write the dirtiness cache for this package's files. writeBuildCache :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env, MonadLogger m) => Path Abs Dir -> Map FilePath FileCacheInfo -> m () -writeBuildCache dir times = - writeCache - dir - buildCacheFile - BuildCache - { buildCacheTimes = times - } +writeBuildCache dir times = do + fp <- buildCacheFile dir + $(versionedEncodeFile buildCacheVC) fp BuildCache + { buildCacheTimes = times + } -- | Write the dirtiness cache for this package's configuration. writeConfigCache :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env, MonadLogger m) => Path Abs Dir -> ConfigCache -> m () -writeConfigCache dir = writeCache dir configCacheFile +writeConfigCache dir x = do + fp <- configCacheFile dir + $(versionedEncodeFile configCacheVC) fp x -- | See 'tryGetCabalMod' writeCabalMod :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env, MonadLogger m) => Path Abs Dir -> ModTime -> m () -writeCabalMod dir = writeCache dir configCabalMod +writeCabalMod dir x = do + fp <- configCabalMod dir + $(versionedEncodeFile modTimeVC) fp x -- | Delete the caches for the project. deleteCaches :: (MonadIO m, MonadReader env m, MonadCatch m, HasEnvConfig env) @@ -173,16 +153,6 @@ deleteCaches dir = do cfp <- configCacheFile dir ignoringAbsence (removeFile cfp) --- | Write to a cache. -writeCache :: (Store a, NFData a, HasTypeHash a, Eq a, MonadIO m, MonadLogger m) - => Path Abs Dir - -> (Path Abs Dir -> m (Path Abs File)) - -> a - -> m () -writeCache dir get' content = do - fp <- get' dir - taggedEncodeFile fp content - flagCacheFile :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) => Installed -> m (Path Abs File) @@ -200,7 +170,7 @@ tryGetFlagCache :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env -> m (Maybe ConfigCache) tryGetFlagCache gid = do fp <- flagCacheFile gid - decodeFileMaybe fp + $(versionedDecodeFile configCacheVC) fp writeFlagCache :: (MonadIO m, MonadReader env m, HasEnvConfig env, MonadThrow m, MonadLogger m, MonadBaseControl IO m) => Installed @@ -209,27 +179,23 @@ writeFlagCache :: (MonadIO m, MonadReader env m, HasEnvConfig env, MonadThrow m, writeFlagCache gid cache = do file <- flagCacheFile gid ensureDir (parent file) - taggedEncodeFile file cache + $(versionedEncodeFile configCacheVC) file cache -- | Mark a test suite as having succeeded setTestSuccess :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env, MonadLogger m) => Path Abs Dir -> m () -setTestSuccess dir = - writeCache - dir - testSuccessFile - True +setTestSuccess dir = do + fp <- testSuccessFile dir + $(versionedEncodeFile testSuccessVC) fp True -- | Mark a test suite as not having succeeded unsetTestSuccess :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env, MonadLogger m) => Path Abs Dir -> m () -unsetTestSuccess dir = - writeCache - dir - testSuccessFile - False +unsetTestSuccess dir = do + fp <- testSuccessFile dir + $(versionedEncodeFile testSuccessVC) fp False -- | Check if the test suite already passed checkTestSuccess :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env, MonadBaseControl IO m, MonadLogger m) @@ -238,7 +204,7 @@ checkTestSuccess :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig en checkTestSuccess dir = liftM (fromMaybe False) - (tryGetCache testSuccessFile dir) + ($(versionedDecodeFile testSuccessVC) =<< testSuccessFile dir) -------------------------------------- -- Precompiled Cache @@ -320,7 +286,7 @@ writePrecompiledCache baseConfigOpts pkgident copts depIDs mghcPkgId exes = do name <- parseRelFile $ T.unpack exe relPath <- stackRootRelative $ bcoSnapInstallRoot baseConfigOpts bindirSuffix name return $ toFilePath $ relPath - taggedEncodeFile file PrecompiledCache + $(versionedEncodeFile precompiledCacheVC) file PrecompiledCache { pcLibrary = mlibpath , pcExes = exes' } @@ -345,7 +311,7 @@ readPrecompiledCache pkgident copts depIDs = do } (file, getOldFile) <- precompiledCacheFile pkgident copts depIDs - mres <- decodeFileMaybe file + mres <- $(versionedDecodeFile precompiledCacheVC) file case mres of Just res -> return (Just $ toAbsPC res) Nothing -> do @@ -354,7 +320,7 @@ readPrecompiledCache pkgident copts depIDs = do mpc <- fmap (fmap toAbsPC) $ binaryDecodeFileOrFailDeep oldFile -- Write out file in new format. Keep old file around for -- the benefit of older stack versions. - forM_ mpc (taggedEncodeFile file) + forM_ mpc ($(versionedEncodeFile precompiledCacheVC) file) return mpc -- | Ensure that there are no lurking exceptions deep inside the parsed @@ -370,10 +336,3 @@ binaryDecodeFileOrFailDeep fp = liftIO $ fmap (either (\_ -> Nothing) id) $ tryA Right x -> return (Just x) type BinarySchema a = (Binary a, NFData a, HasStructuralInfo a, HasSemanticVersion a) - -$(mkManyHasTypeHash - [ [t| BuildCache |] - -- TODO: put this orphan elsewhere? Not sure if we want tons of - -- instances of HasTypeHash or not. - , [t| Bool |] - ]) diff --git a/src/Stack/BuildPlan.hs b/src/Stack/BuildPlan.hs index 48adfc61f5..ca4628f030 100644 --- a/src/Stack/BuildPlan.hs +++ b/src/Stack/BuildPlan.hs @@ -45,7 +45,7 @@ import Control.Monad.State.Strict (State, execState, get, modify, import Control.Monad.Trans.Control (MonadBaseControl) import qualified Crypto.Hash.SHA256 as SHA256 import Data.Aeson.Extended (WithJSONWarnings(..), logJSONWarnings) -import Data.Store.VersionTagged (taggedDecodeOrLoad, decodeFileMaybe, taggedEncodeFile) +import Data.Store.VersionTagged import qualified Data.ByteString as S import qualified Data.ByteString.Base64.URL as B64URL import qualified Data.ByteString.Char8 as S8 @@ -444,7 +444,7 @@ loadMiniBuildPlan -> m MiniBuildPlan loadMiniBuildPlan name = do path <- configMiniBuildPlanCache name - taggedDecodeOrLoad path $ liftM buildPlanFixes $ do + $(versionedDecodeOrLoad miniBuildPlanVC) path $ liftM buildPlanFixes $ do bp <- loadBuildPlan name toMiniBuildPlan (siCompilerVersion $ bpSystemInfo bp) @@ -971,7 +971,7 @@ parseCustomMiniBuildPlan mconfigPath0 url0 = do -- cases. binaryPath <- getBinaryPath hash alreadyCached <- doesFileExist binaryPath - unless alreadyCached $ taggedEncodeFile binaryPath mbp + unless alreadyCached $ $(versionedEncodeFile miniBuildPlanVC) binaryPath mbp return (mbp, hash) where downloadCustom url req = do @@ -983,7 +983,7 @@ parseCustomMiniBuildPlan mconfigPath0 url0 = do yamlBS <- liftIO $ S.readFile $ toFilePath cacheFP let yamlHash = doHash yamlBS binaryPath <- getBinaryPath yamlHash - liftM (, yamlHash) $ taggedDecodeOrLoad binaryPath $ do + liftM (, yamlHash) $ $(versionedDecodeOrLoad miniBuildPlanVC) binaryPath $ do (cs, mresolver) <- decodeYaml yamlBS parentMbp <- case (csCompilerVersion cs, mresolver) of (Nothing, Nothing) -> throwM (NeitherCompilerOrResolverSpecified url) @@ -1020,7 +1020,7 @@ parseCustomMiniBuildPlan mconfigPath0 url0 = do exists <- doesFileExist binaryPath if exists then do - eres <- decodeFileMaybe binaryPath + eres <- $(versionedDecodeFile miniBuildPlanVC) binaryPath case eres of Just mbp -> return mbp -- Invalid format cache file, remove. diff --git a/src/Stack/PackageDump.hs b/src/Stack/PackageDump.hs index 9da3048945..4d8985a056 100644 --- a/src/Stack/PackageDump.hs +++ b/src/Stack/PackageDump.hs @@ -6,7 +6,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE DataKinds #-} module Stack.PackageDump ( Line , eachSection @@ -15,9 +14,6 @@ module Stack.PackageDump , conduitDumpPackage , ghcPkgDump , ghcPkgDescribe - , InstalledCache - , InstalledCacheInner (..) - , InstalledCacheEntry (..) , newInstalledCache , loadInstalledCache , saveInstalledCache @@ -37,7 +33,6 @@ import Control.Monad.Logger (MonadLogger) import Control.Monad.Trans.Control import Data.Attoparsec.Args import Data.Attoparsec.Text as P -import Data.Store.VersionTagged import Data.Conduit import qualified Data.Conduit.List as CL import qualified Data.Conduit.Text as CT @@ -48,34 +43,18 @@ import qualified Data.Map as Map import Data.Maybe (catMaybes, listToMaybe) import Data.Maybe.Extra (mapMaybeM) import qualified Data.Set as Set -import Data.Store (Store) -import Data.Store.TypeHash (mkManyHasTypeHash) +import Data.Store.VersionTagged import Data.Text (Text) import qualified Data.Text as T import Data.Typeable (Typeable) -import GHC.Generics (Generic) import Path import Path.Extra (toFilePathNoTrailingSep) -import Path.IO (ensureDir) import Prelude -- Fix AMP warning import Stack.GhcPkg import Stack.Types import System.Directory (getDirectoryContents, doesFileExist) import System.Process.Read --- | Cached information on whether package have profiling libraries and haddocks. -newtype InstalledCache = InstalledCache (IORef InstalledCacheInner) -newtype InstalledCacheInner = InstalledCacheInner (Map GhcPkgId InstalledCacheEntry) - deriving (Store, Generic, Eq, Show) - --- | Cached information on whether a package has profiling libraries and haddocks. -data InstalledCacheEntry = InstalledCacheEntry - { installedCacheProfiling :: !Bool - , installedCacheHaddock :: !Bool - , installedCacheIdent :: !PackageIdentifier } - deriving (Eq, Generic, Show) -instance Store InstalledCacheEntry - -- | Call ghc-pkg dump with appropriate flags and stream to the given @Sink@, for a single database ghcPkgDump :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m) @@ -131,14 +110,13 @@ newInstalledCache = liftIO $ InstalledCache <$> newIORef (InstalledCacheInner Ma loadInstalledCache :: (MonadLogger m, MonadIO m, MonadBaseControl IO m) => Path Abs File -> m InstalledCache loadInstalledCache path = do - m <- taggedDecodeOrLoad path (return $ InstalledCacheInner Map.empty) + m <- $(versionedDecodeOrLoad installedCacheVC) path (return $ InstalledCacheInner Map.empty) liftIO $ InstalledCache <$> newIORef m -- | Save a @InstalledCache@ to disk saveInstalledCache :: (MonadLogger m, MonadIO m) => Path Abs File -> InstalledCache -> m () -saveInstalledCache path (InstalledCache ref) = do - ensureDir (parent path) - liftIO (readIORef ref) >>= taggedEncodeFile path +saveInstalledCache path (InstalledCache ref) = + liftIO (readIORef ref) >>= $(versionedEncodeFile installedCacheVC) path -- | Prune a list of possible packages down to those whose dependencies are met. -- @@ -449,5 +427,3 @@ takeWhileC f = go x | f x = yield x >> loop | otherwise = leftover x - -$(mkManyHasTypeHash [ [t| InstalledCacheInner |] ]) diff --git a/src/Stack/PackageIndex.hs b/src/Stack/PackageIndex.hs index 5ffd8d3e25..5dd7f0621f 100644 --- a/src/Stack/PackageIndex.hs +++ b/src/Stack/PackageIndex.hs @@ -76,6 +76,7 @@ import System.Process.Read (EnvOverride, tryProcessStdout) import System.Process.Run (Cmd(..), callProcessInheritStderrStdout) import Data.Streaming.Process (ProcessExitedUnsuccessfully(..)) +import Data.Store.Version -- | Populate the package index caches and return them. populateCache @@ -412,7 +413,11 @@ getPackageCaches = do Nothing -> do result <- liftM mconcat $ forM (configPackageIndices config) $ \index -> do fp <- configPackageIndexCache (indexName index) - PackageCacheMap pis' <- taggedDecodeOrLoad fp $ liftM PackageCacheMap $ populateCache menv index + PackageCacheMap pis' <- + $(versionedDecodeOrLoad (storeVersionConfig "pkg-v1" "aHzcZ6_w3rL6NtEJUqEfh6fcjAc=" + :: VersionConfig PackageCacheMap)) + fp + (liftM PackageCacheMap (populateCache menv index)) return (fmap (index,) pis') liftIO $ writeIORef (configPackageCaches config) (Just result) return result diff --git a/src/Stack/Types.hs b/src/Stack/Types.hs index 744f448367..9644dd7218 100644 --- a/src/Stack/Types.hs +++ b/src/Stack/Types.hs @@ -4,19 +4,20 @@ module Stack.Types (module X) where +import Stack.Types.Build as X import Stack.Types.BuildPlan as X +import Stack.Types.Compiler as X +import Stack.Types.Config as X +import Stack.Types.Docker as X import Stack.Types.FlagName as X import Stack.Types.GhcPkgId as X +import Stack.Types.Image as X +import Stack.Types.Nix as X +import Stack.Types.Package as X +import Stack.Types.PackageDump as X import Stack.Types.PackageIdentifier as X import Stack.Types.PackageIndex as X import Stack.Types.PackageName as X -import Stack.Types.Version as X -import Stack.Types.Config as X -import Stack.Types.Docker as X -import Stack.Types.Nix as X -import Stack.Types.Image as X -import Stack.Types.Build as X -import Stack.Types.Urls as X -import Stack.Types.Package as X -import Stack.Types.Compiler as X import Stack.Types.Sig as X +import Stack.Types.Urls as X +import Stack.Types.Version as X diff --git a/src/Stack/Types/Build.hs b/src/Stack/Types/Build.hs index d818e605ce..c9b315844a 100644 --- a/src/Stack/Types/Build.hs +++ b/src/Stack/Types/Build.hs @@ -31,7 +31,10 @@ module Stack.Types.Build ,defaultBuildOpts ,TaskType(..) ,TaskConfigOpts(..) + ,BuildCache(..) + ,buildCacheVC ,ConfigCache(..) + ,configCacheVC ,ConstructPlanException(..) ,configureOpts ,isStackOpt @@ -39,7 +42,8 @@ module Stack.Types.Build ,wantedLocalPackages ,FileCacheInfo (..) ,ConfigureOpts (..) - ,PrecompiledCache (..)) + ,PrecompiledCache (..) + ,precompiledCacheVC) where import Control.DeepSeq @@ -58,7 +62,8 @@ import Data.Monoid import Data.Set (Set) import qualified Data.Set as Set import Data.Store.Internal (Store) -import Data.Store.TypeHash (mkManyHasTypeHash) +import Data.Store.Version +import Data.Store.VersionTagged import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8With) @@ -453,8 +458,19 @@ newtype PkgDepsOracle = PkgDeps PackageName deriving (Show,Typeable,Eq,Hashable,Store,NFData) --- | Stored on disk to know whether the flags have changed or any --- files have changed. +-- | Stored on disk to know whether the files have changed. +data BuildCache = BuildCache + { buildCacheTimes :: !(Map FilePath FileCacheInfo) + -- ^ Modification times of files. + } + deriving (Generic, Eq, Show, Data, Typeable) +instance NFData BuildCache +instance Store BuildCache + +buildCacheVC :: VersionConfig BuildCache +buildCacheVC = storeVersionConfig "build-v1" "KVUoviSWWAd7tiRRGeWAvd0UIN4=" + +-- | Stored on disk to know whether the flags have changed. data ConfigCache = ConfigCache { configCacheOpts :: !ConfigureOpts -- ^ All options used for this package. @@ -470,10 +486,13 @@ data ConfigCache = ConfigCache , configCacheHaddock :: !Bool -- ^ Are haddocks to be built? } - deriving (Generic,Eq,Show) + deriving (Generic, Eq, Show, Data, Typeable) instance Store ConfigCache instance NFData ConfigCache +configCacheVC :: VersionConfig ConfigCache +configCacheVC = storeVersionConfig "config-v1" "NMEzMXpksE1h7STRzlQ2f6Glkjo=" + -- | A task to perform when building data Task = Task { taskProvides :: !PackageIdentifier @@ -693,7 +712,7 @@ data ConfigureOpts = ConfigureOpts -- if we can use an existing precompiled cache. , coNoDirs :: ![String] } - deriving (Show, Eq, Generic) + deriving (Show, Eq, Generic, Data, Typeable) instance Store ConfigureOpts instance NFData ConfigureOpts @@ -706,14 +725,12 @@ data PrecompiledCache = PrecompiledCache , pcExes :: ![FilePath] -- ^ Full paths to executables } - deriving (Show, Eq, Generic) + deriving (Show, Eq, Generic, Data, Typeable) instance Binary PrecompiledCache instance HasSemanticVersion PrecompiledCache instance HasStructuralInfo PrecompiledCache instance Store PrecompiledCache instance NFData PrecompiledCache -$(mkManyHasTypeHash - [ [t| PrecompiledCache |] - , [t| ConfigCache |] - ]) +precompiledCacheVC :: VersionConfig PrecompiledCache +precompiledCacheVC = storeVersionConfig "precompiled-v1" "eMzSOwaHJMamA5iNKs1A025frlQ=" diff --git a/src/Stack/Types/BuildPlan.hs b/src/Stack/Types/BuildPlan.hs index 48d9effe5c..c61210c7f4 100644 --- a/src/Stack/Types/BuildPlan.hs +++ b/src/Stack/Types/BuildPlan.hs @@ -22,6 +22,7 @@ module Stack.Types.BuildPlan , Component (..) , SnapName (..) , MiniBuildPlan (..) + , miniBuildPlanVC , MiniPackageInfo (..) , CabalFileInfo (..) , GitSHA1 (..) @@ -39,6 +40,7 @@ import Control.Monad.Catch (MonadThrow, throwM) import Data.Aeson (FromJSON (..), ToJSON (..), object, withObject, withText, (.!=), (.:), (.:?), (.=)) import Data.ByteString (ByteString) import qualified Data.ByteString as BS +import Data.Data import qualified Data.HashMap.Strict as HashMap import Data.Hashable (Hashable) import Data.IntMap (IntMap) @@ -49,14 +51,14 @@ import Data.Maybe (fromMaybe) import Data.Monoid import Data.Set (Set) import Data.Store (Store) -import Data.Store.TypeHash (mkManyHasTypeHash) +import Data.Store.Version +import Data.Store.VersionTagged import Data.String (IsString, fromString) import Data.Text (Text, pack, unpack) import qualified Data.Text as T import Data.Text.Read (decimal) import Data.Time (Day) import qualified Data.Traversable as T -import Data.Typeable (TypeRep, Typeable, typeOf) import Data.Vector (Vector) import Distribution.System (Arch, OS (..)) import qualified Distribution.Text as DT @@ -279,7 +281,7 @@ newtype Maintainer = Maintainer { unMaintainer :: Text } -- | Name of an executable. newtype ExeName = ExeName { unExeName :: Text } - deriving (Show, Eq, Ord, Hashable, IsString, Generic, Store, NFData) + deriving (Show, Eq, Ord, Hashable, IsString, Generic, Store, NFData, Data, Typeable) instance ToJSON ExeName where toJSON = toJSON . unExeName instance FromJSON ExeName where @@ -429,10 +431,13 @@ data MiniBuildPlan = MiniBuildPlan { mbpCompilerVersion :: !CompilerVersion , mbpPackages :: !(Map PackageName MiniPackageInfo) } - deriving (Generic, Show, Eq) + deriving (Generic, Show, Eq, Data, Typeable) instance Store MiniBuildPlan instance NFData MiniBuildPlan +miniBuildPlanVC :: VersionConfig MiniBuildPlan +miniBuildPlanVC = storeVersionConfig "mbp-v1" "C8q73RrYq3plf9hDCapjWpnm_yc=" + -- | Information on a single package for the 'MiniBuildPlan'. data MiniPackageInfo = MiniPackageInfo { mpiVersion :: !Version @@ -453,17 +458,15 @@ data MiniPackageInfo = MiniPackageInfo -- the cabal file contents. Useful for grabbing the correct cabal file -- revision directly from a Git repo } - deriving (Generic, Show, Eq) + deriving (Generic, Show, Eq, Data, Typeable) instance Store MiniPackageInfo instance NFData MiniPackageInfo newtype GitSHA1 = GitSHA1 ByteString - deriving (Generic, Show, Eq, NFData, Store) + deriving (Generic, Show, Eq, NFData, Store, Data, Typeable) newtype SnapshotHash = SnapshotHash { unShapshotHash :: ByteString } deriving (Generic, Show, Eq) trimmedSnapshotHash :: SnapshotHash -> ByteString trimmedSnapshotHash = BS.take 12 . unShapshotHash - -$(mkManyHasTypeHash [ [t| MiniBuildPlan |] ]) diff --git a/src/Stack/Types/Compiler.hs b/src/Stack/Types/Compiler.hs index 7d25df194d..e2629d8834 100644 --- a/src/Stack/Types/Compiler.hs +++ b/src/Stack/Types/Compiler.hs @@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} @@ -6,6 +7,7 @@ module Stack.Types.Compiler where import Control.DeepSeq import Data.Aeson +import Data.Data import Data.Map (Map) import qualified Data.Map as Map import Data.Monoid ((<>)) @@ -33,7 +35,7 @@ data CompilerVersion | GhcjsVersion {-# UNPACK #-} !Version -- GHCJS version {-# UNPACK #-} !Version -- GHC version - deriving (Generic, Show, Eq, Ord) + deriving (Generic, Show, Eq, Ord, Data, Typeable) instance Store CompilerVersion instance NFData CompilerVersion instance ToJSON CompilerVersion where diff --git a/src/Stack/Types/Package.hs b/src/Stack/Types/Package.hs index 9d23ed008b..3839fcbfa7 100644 --- a/src/Stack/Types/Package.hs +++ b/src/Stack/Types/Package.hs @@ -26,7 +26,8 @@ import Data.Monoid import Data.Set (Set) import qualified Data.Set as Set import Data.Store (Store) -import Data.Store.TypeHash (mkManyHasTypeHash) +import Data.Store.Version (VersionConfig) +import Data.Store.VersionTagged (storeVersionConfig) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8, decodeUtf8) @@ -350,13 +351,19 @@ data FileCacheInfo = FileCacheInfo , fciSize :: !Word64 , fciHash :: !S.ByteString } - deriving (Generic, Show, Eq) + deriving (Generic, Show, Eq, Data, Typeable) instance Store FileCacheInfo instance NFData FileCacheInfo -- | Used for storage and comparison. newtype ModTime = ModTime (Integer,Rational) - deriving (Ord,Show,Generic,Eq,NFData,Store) + deriving (Ord, Show, Generic, Eq, NFData, Store, Data, Typeable) + +modTimeVC :: VersionConfig ModTime +modTimeVC = storeVersionConfig "mod-time-v1" "UBECpUI0JvM_SBOnRNdaiF9_yOU=" + +testSuccessVC :: VersionConfig Bool +testSuccessVC = storeVersionConfig "test-v1" "jC_GB0SGtbpRQbDlm7oQJP7thu8=" -- | A descriptor from a .cabal file indicating one of the following: -- @@ -427,5 +434,3 @@ installedPackageIdentifier (Executable pid) = pid -- | Get the installed Version. installedVersion :: Installed -> Version installedVersion = packageIdentifierVersion . installedPackageIdentifier - -$(mkManyHasTypeHash [ [t| ModTime |] ]) diff --git a/src/Stack/Types/PackageDump.hs b/src/Stack/Types/PackageDump.hs new file mode 100644 index 0000000000..582bcd5595 --- /dev/null +++ b/src/Stack/Types/PackageDump.hs @@ -0,0 +1,35 @@ +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +module Stack.Types.PackageDump + ( InstalledCache(..) + , InstalledCacheInner(..) + , InstalledCacheEntry(..) + , installedCacheVC + ) where + +import Data.Data +import Data.IORef +import Data.Map (Map) +import Data.Store +import Data.Store.Version +import Data.Store.VersionTagged +import GHC.Generics (Generic) +import Stack.Types.GhcPkgId +import Stack.Types.PackageIdentifier + +-- | Cached information on whether package have profiling libraries and haddocks. +newtype InstalledCache = InstalledCache (IORef InstalledCacheInner) +newtype InstalledCacheInner = InstalledCacheInner (Map GhcPkgId InstalledCacheEntry) + deriving (Store, Generic, Eq, Show, Data, Typeable) + +-- | Cached information on whether a package has profiling libraries and haddocks. +data InstalledCacheEntry = InstalledCacheEntry + { installedCacheProfiling :: !Bool + , installedCacheHaddock :: !Bool + , installedCacheIdent :: !PackageIdentifier } + deriving (Eq, Generic, Show, Data, Typeable) +instance Store InstalledCacheEntry + +installedCacheVC :: VersionConfig InstalledCacheInner +installedCacheVC = storeVersionConfig "installed-v1" "5yL7Ngpy4YKWDDCTUI6zAJ9UySI=" diff --git a/src/Stack/Types/PackageIndex.hs b/src/Stack/Types/PackageIndex.hs index 03703dd195..bc6dbf2dc6 100644 --- a/src/Stack/Types/PackageIndex.hs +++ b/src/Stack/Types/PackageIndex.hs @@ -3,6 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveDataTypeable #-} module Stack.Types.PackageIndex ( PackageDownload (..) @@ -14,11 +15,11 @@ import Control.DeepSeq (NFData) import Control.Monad (mzero) import Data.Aeson.Extended import Data.ByteString (ByteString) +import Data.Data (Data, Typeable) import Data.Int (Int64) import Data.Map (Map) import qualified Data.Map.Strict as Map import Data.Store (Store) -import Data.Store.TypeHash (mkManyHasTypeHash) import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) import Data.Word (Word64) @@ -32,20 +33,20 @@ data PackageCache = PackageCache -- ^ size in bytes of the .cabal file , pcDownload :: !(Maybe PackageDownload) } - deriving (Generic, Eq, Show) + deriving (Generic, Eq, Show, Data, Typeable) instance Store PackageCache instance NFData PackageCache newtype PackageCacheMap = PackageCacheMap (Map PackageIdentifier PackageCache) - deriving (Generic, Store, NFData, Eq, Show) + deriving (Generic, Store, NFData, Eq, Show, Data, Typeable) data PackageDownload = PackageDownload { pdSHA512 :: !ByteString , pdUrl :: !ByteString , pdSize :: !Word64 } - deriving (Show, Generic, Eq) + deriving (Show, Generic, Eq, Data, Typeable) instance Store PackageDownload instance NFData PackageDownload instance FromJSON PackageDownload where @@ -63,5 +64,3 @@ instance FromJSON PackageDownload where , pdUrl = encodeUtf8 url , pdSize = size } - -$(mkManyHasTypeHash [ [t| PackageCacheMap |] ]) diff --git a/stack-7.8.yaml b/stack-7.8.yaml index 2b51344552..fadf2447b9 100644 --- a/stack-7.8.yaml +++ b/stack-7.8.yaml @@ -55,7 +55,7 @@ extra-deps: - http-api-data-0.2.2 - time-locale-compat-0.1.1.1 - persistent-2.5 -- store-0.1.0.1 +- store-0.2.1.0 - th-reify-many-0.1.6 - th-lift-instances-0.1.7 - th-utilities-0.1.1.0 diff --git a/stack-8.0.yaml b/stack-8.0.yaml index e9b8adc95c..d211b2ab90 100644 --- a/stack-8.0.yaml +++ b/stack-8.0.yaml @@ -12,3 +12,4 @@ extra-deps: - http-client-0.5.0 - http-conduit-2.2.0 - http-client-tls-0.3.0 +- store-0.2.1.0 diff --git a/stack.yaml b/stack.yaml index cc5fc53ae9..07378d2a10 100644 --- a/stack.yaml +++ b/stack.yaml @@ -13,8 +13,8 @@ nix: - zlib extra-deps: - th-lift-instances-0.1.7 -- th-utilities-0.1.1.0 -- store-0.1.0.1 +- th-utilities-0.2.0.1 +- store-0.2.1.0 - th-orphans-0.13.1 - http-client-0.5.0 - http-client-tls-0.3.0