Skip to content

Commit d6a6f52

Browse files
author
Andres Schmois
committed
Remove ModTime check during build (#5125)
1 parent b5d3090 commit d6a6f52

File tree

2 files changed

+38
-52
lines changed

2 files changed

+38
-52
lines changed

src/Stack/Build/Execute.hs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ import qualified Distribution.Text as C
5959
import Distribution.Types.PackageName (mkPackageName)
6060
import Distribution.Types.UnqualComponentName (mkUnqualComponentName)
6161
import Distribution.Version (mkVersion)
62-
import Foreign.C.Types (CTime)
6362
import Path
6463
import Path.CheckInstall
6564
import Path.Extra (toFilePathNoTrailingSep, rejectMissingFile)
@@ -91,7 +90,6 @@ import System.FileLock (withTryFileLock, SharedExclusive (Exclusive),
9190
import qualified System.FilePath as FP
9291
import System.IO.Error (isDoesNotExistError)
9392
import System.PosixCompat.Files (createLink, modificationTime, getFileStatus)
94-
import System.PosixCompat.Time (epochTime)
9593
import RIO.PrettyPrint
9694
import RIO.Process
9795
import Pantry.Internal.Companion
@@ -1601,11 +1599,10 @@ singleBuild ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} installedMap
16011599

16021600
-- FIXME: only output these if they're in the build plan.
16031601

1604-
preBuildTime <- liftIO epochTime
16051602
let postBuildCheck _succeeded = do
16061603
mlocalWarnings <- case taskType of
16071604
TTLocalMutable lp -> do
1608-
warnings <- checkForUnlistedFiles taskType preBuildTime pkgDir
1605+
warnings <- checkForUnlistedFiles taskType pkgDir
16091606
-- TODO: Perhaps only emit these warnings for non extra-dep?
16101607
return (Just (lpCabalFile lp, warnings))
16111608
_ -> return Nothing
@@ -1829,12 +1826,11 @@ checkExeStatus platform distDir name = do
18291826
file = T.unpack name
18301827

18311828
-- | Check if any unlisted files have been found, and add them to the build cache.
1832-
checkForUnlistedFiles :: HasEnvConfig env => TaskType -> CTime -> Path Abs Dir -> RIO env [PackageWarning]
1833-
checkForUnlistedFiles (TTLocalMutable lp) preBuildTime pkgDir = do
1829+
checkForUnlistedFiles :: HasEnvConfig env => TaskType -> Path Abs Dir -> RIO env [PackageWarning]
1830+
checkForUnlistedFiles (TTLocalMutable lp) pkgDir = do
18341831
caches <- runMemoizedWith $ lpNewBuildCaches lp
18351832
(addBuildCache,warnings) <-
18361833
addUnlistedToBuildCache
1837-
preBuildTime
18381834
(lpPackage lp)
18391835
(lpCabalFile lp)
18401836
(lpComponents lp)
@@ -1844,7 +1840,7 @@ checkForUnlistedFiles (TTLocalMutable lp) preBuildTime pkgDir = do
18441840
writeBuildCache pkgDir component $
18451841
Map.unions (cache : newToCache)
18461842
return warnings
1847-
checkForUnlistedFiles TTRemotePackage{} _ _ = return []
1843+
checkForUnlistedFiles TTRemotePackage{} _ = return []
18481844

18491845
-- | Implements running a package's tests. Also handles producing
18501846
-- coverage reports if coverage is enabled.

src/Stack/Build/Source.hs

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import Data.List
2828
import qualified Data.Map as Map
2929
import qualified Data.Map.Strict as M
3030
import qualified Data.Set as Set
31-
import Foreign.C.Types (CTime)
3231
import Stack.Build.Cache
3332
import Stack.Build.Haddock (shouldHaddockDeps)
3433
import Stack.Build.Target
@@ -406,46 +405,41 @@ checkBuildCache :: forall m. (MonadIO m)
406405
-> m (Set FilePath, Map FilePath FileCacheInfo)
407406
checkBuildCache oldCache files = do
408407
fileTimes <- liftM Map.fromList $ forM files $ \fp -> do
409-
mmodTime <- liftIO (getModTimeMaybe (toFilePath fp))
410-
return (toFilePath fp, mmodTime)
408+
mdigest <- liftIO (getFileDigestMaybe (toFilePath fp))
409+
return (toFilePath fp, mdigest)
411410
liftM (mconcat . Map.elems) $ sequence $
412411
Map.mergeWithKey
413-
(\fp mmodTime fci -> Just (go fp mmodTime (Just fci)))
414-
(Map.mapWithKey (\fp mmodTime -> go fp mmodTime Nothing))
412+
(\fp mdigest fci -> Just (go fp mdigest (Just fci)))
413+
(Map.mapWithKey (\fp mdigest -> go fp mdigest Nothing))
415414
(Map.mapWithKey (\fp fci -> go fp Nothing (Just fci)))
416415
fileTimes
417416
oldCache
418417
where
419-
go :: FilePath -> Maybe CTime -> Maybe FileCacheInfo -> m (Set FilePath, Map FilePath FileCacheInfo)
418+
go :: FilePath -> Maybe (FileSize, SHA256) -> Maybe FileCacheInfo -> m (Set FilePath, Map FilePath FileCacheInfo)
420419
-- Filter out the cabal_macros file to avoid spurious recompilations
421420
go fp _ _ | takeFileName fp == "cabal_macros.h" = return (Set.empty, Map.empty)
422421
-- Common case where it's in the cache and on the filesystem.
423-
go fp (Just modTime') (Just fci)
424-
| fciModTime fci == modTime' = return (Set.empty, Map.singleton fp fci)
422+
go fp (Just (size, digest')) (Just fci)
423+
| fciHash fci == digest' = return (Set.empty, Map.singleton fp fci)
425424
| otherwise = do
426-
newFci <- calcFci modTime' fp
427-
let isDirty =
428-
fciSize fci /= fciSize newFci ||
429-
fciHash fci /= fciHash newFci
430-
newDirty = if isDirty then Set.singleton fp else Set.empty
431-
return (newDirty, Map.singleton fp newFci)
425+
newFci <- calcFci (size,digest') fp
426+
return (Set.singleton fp, Map.singleton fp newFci)
432427
-- Missing file. Add it to dirty files, but no FileCacheInfo.
433428
go fp Nothing _ = return (Set.singleton fp, Map.empty)
434429
-- Missing cache. Add it to dirty files and compute FileCacheInfo.
435-
go fp (Just modTime') Nothing = do
436-
newFci <- calcFci modTime' fp
430+
go fp (Just (size, digest')) Nothing = do
431+
newFci <- calcFci (size,digest') fp
437432
return (Set.singleton fp, Map.singleton fp newFci)
438433

439434
-- | Returns entries to add to the build cache for any newly found unlisted modules
440435
addUnlistedToBuildCache
441436
:: HasEnvConfig env
442-
=> CTime
443-
-> Package
437+
=> Package
444438
-> Path Abs File
445439
-> Set NamedComponent
446440
-> Map NamedComponent (Map FilePath a)
447441
-> RIO env (Map NamedComponent [Map FilePath FileCacheInfo], [PackageWarning])
448-
addUnlistedToBuildCache preBuildTime pkg cabalFP nonLibComponents buildCaches = do
442+
addUnlistedToBuildCache pkg cabalFP nonLibComponents buildCaches = do
449443
(componentFiles, warnings) <- getPackageFilesForTargets pkg cabalFP nonLibComponents
450444
results <- forM (M.toList componentFiles) $ \(component, files) -> do
451445
let buildCache = M.findWithDefault M.empty component buildCaches
@@ -457,13 +451,10 @@ addUnlistedToBuildCache preBuildTime pkg cabalFP nonLibComponents buildCaches =
457451
return (M.fromList (map fst results), concatMap snd results)
458452
where
459453
addFileToCache fp = do
460-
mmodTime <- getModTimeMaybe fp
461-
case mmodTime of
454+
mdigest <- getFileDigestMaybe fp
455+
case mdigest of
462456
Nothing -> return Map.empty
463-
Just modTime' ->
464-
if modTime' < preBuildTime
465-
then Map.singleton fp <$> calcFci modTime' fp
466-
else return Map.empty
457+
Just digest' -> Map.singleton fp <$> calcFci digest' fp
467458

468459
-- | Gets list of Paths for files relevant to a set of components in a package.
469460
-- Note that the library component, if any, is always automatically added to the
@@ -484,34 +475,33 @@ getPackageFilesForTargets pkg cabalFP nonLibComponents = do
484475
M.filterWithKey (\component _ -> component `elem` components) compFiles
485476
return (componentsFiles, warnings)
486477

487-
-- | Get file modification time, if it exists.
488-
getModTimeMaybe :: MonadIO m => FilePath -> m (Maybe CTime)
489-
getModTimeMaybe fp =
478+
-- | Get file digest
479+
getFileDigestMaybe :: MonadIO m => FilePath -> m (Maybe (FileSize,SHA256))
480+
getFileDigestMaybe fp =
490481
liftIO
491482
(catch
492483
(liftM
493-
(Just . modificationTime)
494-
(getFileStatus fp))
484+
(\ (size, digest) -> Just (FileSize size, digest))
485+
(withSourceFile fp $ \src -> runConduit $ src .| getZipSink
486+
((,)
487+
<$> ZipSink (CL.fold
488+
(\x y -> x + fromIntegral (S.length y))
489+
0)
490+
<*> ZipSink SHA256.sinkHash)))
495491
(\e ->
496492
if isDoesNotExistError e
497493
then return Nothing
498494
else throwM e))
499495

500496
-- | Create FileCacheInfo for a file.
501-
calcFci :: MonadIO m => CTime -> FilePath -> m FileCacheInfo
502-
calcFci modTime' fp = liftIO $
503-
withSourceFile fp $ \src -> do
504-
(size, digest) <- runConduit $ src .| getZipSink
505-
((,)
506-
<$> ZipSink (CL.fold
507-
(\x y -> x + fromIntegral (S.length y))
508-
0)
509-
<*> ZipSink SHA256.sinkHash)
510-
return FileCacheInfo
511-
{ fciModTime = modTime'
512-
, fciSize = FileSize size
513-
, fciHash = digest
514-
}
497+
calcFci :: MonadIO m => (FileSize,SHA256) -> FilePath -> m FileCacheInfo
498+
calcFci (size, digest) fp = liftIO $ do
499+
modTime' <- fmap modificationTime $ getFileStatus fp
500+
return FileCacheInfo
501+
{ fciModTime = modTime'
502+
, fciSize = size
503+
, fciHash = digest
504+
}
515505

516506
-- | Get 'PackageConfig' for package given its name.
517507
getPackageConfig

0 commit comments

Comments
 (0)