Skip to content

Soulomoon/mark dirty keys sync to hls graph3 #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
684a850
passing keys need to be update directly to restartShakeSession
soulomoon Apr 22, 2024
5d09837
send actions to run between restart
soulomoon Apr 24, 2024
13528d7
fix
soulomoon Apr 24, 2024
fdbb7aa
fix
soulomoon Apr 24, 2024
6fc3646
some more fix up
soulomoon Apr 24, 2024
e247ae1
use IO [Key]
soulomoon Apr 24, 2024
7b7ea4d
remove double return
soulomoon Apr 24, 2024
c31a375
Update ghcide/src/Development/IDE/Core/FileExists.hs
soulomoon Apr 26, 2024
bfb06a3
minor fix
soulomoon Apr 26, 2024
8adf5a4
Merge branch 'master' into soulomoon/mark-dirty-keys-sync-to-hls-graph
soulomoon Apr 26, 2024
bbc5c95
capture more dirty keys to between sessions
soulomoon Apr 27, 2024
48d5644
cleanup
soulomoon Apr 27, 2024
e967dde
fix the race between cache value updated but not updated hls-database
soulomoon Apr 28, 2024
69c9396
fix build
soulomoon Apr 28, 2024
02f0d41
fix hls-graph
soulomoon Apr 28, 2024
554102d
Merge branch 'master' into soulomoon/mark-dirty-keys-sync-to-hls-graph
soulomoon Apr 28, 2024
c983727
fix 9.2.8
soulomoon Apr 28, 2024
3748fc2
format
soulomoon Apr 29, 2024
3107879
Merge branch 'master' into soulomoon/mark-dirty-keys-sync-to-hls-graph
soulomoon Apr 30, 2024
a65ac5c
run refreshDeps in a single asyncWithCleanUp
soulomoon May 1, 2024
f7a15cb
Merge branch 'master' into soulomoon/mark-dirty-keys-sync-to-hls-graph
soulomoon May 1, 2024
f4690c5
shut the session before shut the reactor
soulomoon May 1, 2024
c6a33cb
Merge remote-tracking branch 'upstream/soulomoon/mark-dirty-keys-sync…
soulomoon May 1, 2024
0d85ef1
swap shakeShut and stopReactor
soulomoon May 2, 2024
880a93e
Merge branch 'master' into fix-stuck-at-exit
soulomoon May 2, 2024
e6105ff
Merge branch 'master' into soulomoon/mark-dirty-keys-sync-to-hls-graph
soulomoon May 2, 2024
84cf7a6
Merge branch 'master' into fix-stuck-at-exit
soulomoon May 2, 2024
610355c
Revert "shut the session before shut the reactor"
soulomoon May 2, 2024
abf5538
take awasy the session in shutdown to prevent race condition
soulomoon May 2, 2024
53ab0d5
use try takeMVar
soulomoon May 2, 2024
63b1956
remove record dirty key recordDirtyKeys
soulomoon May 2, 2024
ceb7020
time out the shakeShut
soulomoon May 3, 2024
84e6731
fix
soulomoon May 3, 2024
e4fd853
use takeMVar
soulomoon May 3, 2024
036ad1f
use withMVar to prevent stm dead lock
soulomoon May 3, 2024
9b8e966
show error in test
soulomoon May 4, 2024
335274b
stop the progress regardless but do profile if we can get the shake s…
soulomoon May 4, 2024
79a8a5f
Merge branch 'master' into fix-stuck-at-exit
soulomoon May 4, 2024
a3c86b0
do not use progressStop if shake could not be cancel yet
soulomoon May 4, 2024
53e601e
add to for remove value but not dirty
soulomoon May 5, 2024
a9aeef6
Merge branch 'fix-stuck-at-exit' into soulomoon/mark-dirty-keys-sync-…
soulomoon May 5, 2024
c558220
do not log err by default
soulomoon May 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ jobs:
needs:
- pre_job
runs-on: ${{ matrix.os }}
env:
LSP_TEST_LOG_STDERR: 0
strategy:
# We don't want to fail fast.
# We used to fail fast, to avoid caches of failing PRs to overpopulate the CI
Expand Down
29 changes: 12 additions & 17 deletions ghcide/session-loader/Development/IDE/Session.hs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ import qualified Data.HashSet as Set
import Database.SQLite.Simple
import Development.IDE.Core.Tracing (withTrace)
import Development.IDE.Session.Diagnostics (renderCradleError)
import Development.IDE.Types.Shake (WithHieDb)
import Development.IDE.Types.Shake (WithHieDb, toKey)
import HieDb.Create
import HieDb.Types
import HieDb.Utils
Expand Down Expand Up @@ -474,10 +474,9 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
clientConfig <- getClientConfigAction
extras@ShakeExtras{restartShakeSession, ideNc, knownTargetsVar, lspEnv
} <- getShakeExtras
let invalidateShakeCache :: IO ()
invalidateShakeCache = do
let invalidateShakeCache = do
void $ modifyVar' version succ
join $ atomically $ recordDirtyKeys extras GhcSessionIO [emptyFilePath]
return $ toKey GhcSessionIO emptyFilePath

IdeOptions{ optTesting = IdeTesting optTesting
, optCheckProject = getCheckProject
Expand Down Expand Up @@ -516,10 +515,10 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
HM.unionWith (<>) k $ HM.fromList knownTargets
hasUpdate = if known /= known' then Just (unhashed known') else Nothing
writeTVar knownTargetsVar known'
logDirtyKeys <- recordDirtyKeys extras GetKnownTargets [emptyFilePath]
return (logDirtyKeys >> pure hasUpdate)
return (pure hasUpdate)
for_ hasUpdate $ \x ->
logWith recorder Debug $ LogKnownFilesUpdated x
return $ toKey GetKnownTargets emptyFilePath

-- Create a new HscEnv from a hieYaml root and a set of options
let packageSetup :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)
Expand Down Expand Up @@ -612,18 +611,14 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
, "If you are using a .cabal file, please ensure that this module is listed in either the exposed-modules or other-modules section"
]

void $ modifyVar' fileToFlags $
Map.insert hieYaml this_flags_map
void $ modifyVar' filesMap $
flip HM.union (HM.fromList (map ((,hieYaml) . fst) $ concatMap toFlagsMap all_targets))

void $ extendKnownTargets all_targets

-- Invalidate all the existing GhcSession build nodes by restarting the Shake session
invalidateShakeCache

void $ modifyVar' fileToFlags $ Map.insert hieYaml this_flags_map
void $ modifyVar' filesMap $ flip HM.union (HM.fromList (map ((,hieYaml) . fst) $ concatMap toFlagsMap all_targets))
key1 <- extendKnownTargets all_targets
key2 <- invalidateShakeCache
-- The VFS doesn't change on cradle edits, re-use the old one.
restartShakeSession VFSUnmodified "new component" []
restartShakeSession VFSUnmodified "new component" [] $ do
return [key1, key2]
-- Invalidate all the existing GhcSession build nodes by restarting the Shake session

-- Typecheck all files in the project on startup
checkProject <- getCheckProject
Expand Down
1 change: 1 addition & 0 deletions ghcide/src/Development/IDE/Core/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,7 @@ atomicFileWrite se targetPath write = do
let dir = takeDirectory targetPath
createDirectoryIfMissing True dir
(tempFilePath, cleanUp) <- newTempFileWithin dir
-- todo value delete key value here but not mark as dirty.
(write tempFilePath >>= \x -> renameFile tempFilePath targetPath >> atomically (resetInterfaceStore se (toNormalizedFilePath' targetPath)) >> pure x)
`onException` cleanUp

Expand Down
13 changes: 7 additions & 6 deletions ghcide/src/Development/IDE/Core/FileExists.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import qualified Development.IDE.Core.Shake as Shake
import Development.IDE.Graph
import Development.IDE.Types.Location
import Development.IDE.Types.Options
import Development.IDE.Types.Shake (toKey)
import qualified Focus
import Ide.Logger (Pretty (pretty),
Recorder, WithPriority,
Expand Down Expand Up @@ -106,11 +107,11 @@ getFileExistsMapUntracked = do
return v

-- | Modify the global store of file exists.
modifyFileExists :: IdeState -> [(NormalizedFilePath, FileChangeType)] -> IO ()
modifyFileExists :: IdeState -> [(NormalizedFilePath, FileChangeType)] -> IO [Key]
modifyFileExists state changes = do
FileExistsMapVar var <- getIdeGlobalState state
-- Masked to ensure that the previous values are flushed together with the map update
join $ mask_ $ atomicallyNamed "modifyFileExists" $ do
mask_ $ atomicallyNamed "modifyFileExists" $ do
forM_ changes $ \(f,c) ->
case fromChange c of
Just c' -> STM.focus (Focus.insert c') f var
Expand All @@ -119,10 +120,10 @@ modifyFileExists state changes = do
-- flush previous values
let (fileModifChanges, fileExistChanges) =
partition ((== FileChangeType_Changed) . snd) changes
mapM_ (deleteValue (shakeExtras state) GetFileExists . fst) fileExistChanges
io1 <- recordDirtyKeys (shakeExtras state) GetFileExists $ map fst fileExistChanges
io2 <- recordDirtyKeys (shakeExtras state) GetModificationTime $ map fst fileModifChanges
return (io1 <> io2)
keys0 <- concat <$> mapM (deleteValue (shakeExtras state) GetFileExists . fst) fileExistChanges
let keys1 = map (toKey GetFileExists . fst) fileExistChanges
let keys2 = map (toKey GetModificationTime . fst) fileModifChanges
return (keys0 <> keys1 <> keys2)

fromChange :: FileChangeType -> Maybe Bool
fromChange FileChangeType_Created = Just True
Expand Down
38 changes: 19 additions & 19 deletions ghcide/src/Development/IDE/Core/FileStore.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import Development.IDE.Import.DependencyInformation
import Development.IDE.Types.Diagnostics
import Development.IDE.Types.Location
import Development.IDE.Types.Options
import Development.IDE.Types.Shake (toKey)
import HieDb.Create (deleteMissingRealFiles)
import Ide.Logger (Pretty (pretty),
Priority (Info),
Expand Down Expand Up @@ -148,24 +149,24 @@ isInterface :: NormalizedFilePath -> Bool
isInterface f = takeExtension (fromNormalizedFilePath f) `elem` [".hi", ".hi-boot", ".hie", ".hie-boot", ".core"]

-- | Reset the GetModificationTime state of interface files
resetInterfaceStore :: ShakeExtras -> NormalizedFilePath -> STM ()
resetInterfaceStore :: ShakeExtras -> NormalizedFilePath -> STM [Key]
resetInterfaceStore state f = do
deleteValue state GetModificationTime f

-- | Reset the GetModificationTime state of watched files
-- Assumes the list does not include any FOIs
resetFileStore :: IdeState -> [(NormalizedFilePath, LSP.FileChangeType)] -> IO ()
resetFileStore :: IdeState -> [(NormalizedFilePath, LSP.FileChangeType)] -> IO [Key]
resetFileStore ideState changes = mask $ \_ -> do
-- we record FOIs document versions in all the stored values
-- so NEVER reset FOIs to avoid losing their versions
-- FOI filtering is done by the caller (LSP Notification handler)
forM_ changes $ \(nfp, c) -> do
case c of
LSP.FileChangeType_Changed
-- already checked elsewhere | not $ HM.member nfp fois
-> atomically $
deleteValue (shakeExtras ideState) GetModificationTime nfp
_ -> pure ()
fmap concat <$>
forM changes $ \(nfp, c) -> do
case c of
LSP.FileChangeType_Changed
-- already checked elsewhere | not $ HM.member nfp fois
-> atomically $ deleteValue (shakeExtras ideState) GetModificationTime nfp
_ -> pure []


modificationTime :: FileVersion -> Maybe UTCTime
Expand Down Expand Up @@ -215,16 +216,18 @@ setFileModified :: Recorder (WithPriority Log)
-> IdeState
-> Bool -- ^ Was the file saved?
-> NormalizedFilePath
-> IO [Key]
-> IO ()
setFileModified recorder vfs state saved nfp = do
setFileModified recorder vfs state saved nfp actionBefore = do
ideOptions <- getIdeOptionsIO $ shakeExtras state
doCheckParents <- optCheckParents ideOptions
let checkParents = case doCheckParents of
AlwaysCheck -> True
CheckOnSave -> saved
_ -> False
join $ atomically $ recordDirtyKeys (shakeExtras state) GetModificationTime [nfp]
restartShakeSession (shakeExtras state) vfs (fromNormalizedFilePath nfp ++ " (modified)") []
restartShakeSession (shakeExtras state) vfs (fromNormalizedFilePath nfp ++ " (modified)") [] $ do
keys<-actionBefore
return (toKey GetModificationTime nfp:keys)
when checkParents $
typecheckParents recorder state nfp

Expand All @@ -244,14 +247,11 @@ typecheckParentsAction recorder nfp = do
-- | Note that some keys have been modified and restart the session
-- Only valid if the virtual file system was initialised by LSP, as that
-- independently tracks which files are modified.
setSomethingModified :: VFSModified -> IdeState -> [Key] -> String -> IO ()
setSomethingModified vfs state keys reason = do
setSomethingModified :: VFSModified -> IdeState -> String -> IO [Key] -> IO ()
setSomethingModified vfs state reason actionBetweenSession = do
-- Update database to remove any files that might have been renamed/deleted
atomically $ do
writeTQueue (indexQueue $ hiedbWriter $ shakeExtras state) (\withHieDb -> withHieDb deleteMissingRealFiles)
modifyTVar' (dirtyKeys $ shakeExtras state) $ \x ->
foldl' (flip insertKeySet) x keys
void $ restartShakeSession (shakeExtras state) vfs reason []
atomically $ writeTQueue (indexQueue $ hiedbWriter $ shakeExtras state) (\withHieDb -> withHieDb deleteMissingRealFiles)
void $ restartShakeSession (shakeExtras state) vfs reason [] actionBetweenSession

registerFileWatches :: [String] -> LSP.LspT Config IO Bool
registerFileWatches globs = do
Expand Down
13 changes: 8 additions & 5 deletions ghcide/src/Development/IDE/Core/OfInterest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import Development.IDE.Plugin.Completions.Types
import Development.IDE.Types.Exports
import Development.IDE.Types.Location
import Development.IDE.Types.Options (IdeTesting (..))
import Development.IDE.Types.Shake (toKey)
import GHC.TypeLits (KnownSymbol)
import Ide.Logger (Pretty (pretty),
Priority (..),
Expand Down Expand Up @@ -103,24 +104,26 @@ getFilesOfInterestUntracked = do
OfInterestVar var <- getIdeGlobalAction
liftIO $ readVar var

addFileOfInterest :: IdeState -> NormalizedFilePath -> FileOfInterestStatus -> IO ()
addFileOfInterest :: IdeState -> NormalizedFilePath -> FileOfInterestStatus -> IO [Key]
addFileOfInterest state f v = do
OfInterestVar var <- getIdeGlobalState state
(prev, files) <- modifyVar var $ \dict -> do
let (prev, new) = HashMap.alterF (, Just v) f dict
pure (new, (prev, new))
when (prev /= Just v) $ do
join $ atomically $ recordDirtyKeys (shakeExtras state) IsFileOfInterest [f]
if prev /= Just v
then do
logWith (ideLogger state) Debug $
LogSetFilesOfInterest (HashMap.toList files)
return [toKey IsFileOfInterest f]
else return []

deleteFileOfInterest :: IdeState -> NormalizedFilePath -> IO ()
deleteFileOfInterest :: IdeState -> NormalizedFilePath -> IO [Key]
deleteFileOfInterest state f = do
OfInterestVar var <- getIdeGlobalState state
files <- modifyVar' var $ HashMap.delete f
join $ atomically $ recordDirtyKeys (shakeExtras state) IsFileOfInterest [f]
logWith (ideLogger state) Debug $
LogSetFilesOfInterest (HashMap.toList files)
return [toKey IsFileOfInterest f]
scheduleGarbageCollection :: IdeState -> IO ()
scheduleGarbageCollection state = do
GarbageCollectVar var <- getIdeGlobalState state
Expand Down
3 changes: 2 additions & 1 deletion ghcide/src/Development/IDE/Core/Service.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ initialise recorder defaultConfig plugins mainRule lspEnv debouncer options with
mainRule

-- | Shutdown the Compiler Service.
shutdown :: IdeState -> IO ()
-- shutdown :: Recorder (WithPriority Log) -> IdeState -> IO ()
shutdown :: Recorder (WithPriority Shake.Log) -> IdeState -> IO ()
shutdown = shakeShut

-- This will return as soon as the result of the action is
Expand Down
61 changes: 31 additions & 30 deletions ghcide/src/Development/IDE/Core/Shake.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ module Development.IDE.Core.Shake(
FileVersion(..),
updatePositionMapping,
updatePositionMappingHelper,
deleteValue, recordDirtyKeys,
deleteValue,
WithProgressFunc, WithIndefiniteProgressFunc,
ProgressEvent(..),
DelayedAction, mkDelayedAction,
Expand All @@ -75,6 +75,7 @@ module Development.IDE.Core.Shake(
VFSModified(..), getClientConfigAction,
) where

import Control.Concurrent (tryReadMVar, withMVar)
import Control.Concurrent.Async
import Control.Concurrent.STM
import Control.Concurrent.STM.Stats (atomicallyNamed)
Expand Down Expand Up @@ -196,6 +197,7 @@ data Log
| LogShakeGarbageCollection !T.Text !Int !Seconds
-- * OfInterest Log messages
| LogSetFilesOfInterest ![(NormalizedFilePath, FileOfInterestStatus)]
| LogTimeOutShuttingDownWaitForSessionVar !Seconds
deriving Show

instance Pretty Log where
Expand Down Expand Up @@ -239,6 +241,8 @@ instance Pretty Log where
LogSetFilesOfInterest ofInterest ->
"Set files of interst to" <> Pretty.line
<> indent 4 (pretty $ fmap (first fromNormalizedFilePath) ofInterest)
LogTimeOutShuttingDownWaitForSessionVar seconds ->
"Timed out waiting for session var after" <+> pretty seconds <+> "seconds"

-- | We need to serialize writes to the database, so we send any function that
-- needs to write to the database over the channel, where it will be picked up by
Expand Down Expand Up @@ -300,6 +304,7 @@ data ShakeExtras = ShakeExtras
:: VFSModified
-> String
-> [DelayedAction ()]
-> IO [Key]
-> IO ()
#if MIN_VERSION_ghc(9,3,0)
,ideNc :: NameCache
Expand Down Expand Up @@ -562,21 +567,11 @@ deleteValue
=> ShakeExtras
-> k
-> NormalizedFilePath
-> STM ()
-> STM [Key]
deleteValue ShakeExtras{dirtyKeys, state} key file = do
STM.delete (toKey key file) state
modifyTVar' dirtyKeys $ insertKeySet (toKey key file)
return [toKey key file]

recordDirtyKeys
:: Shake.ShakeValue k
=> ShakeExtras
-> k
-> [NormalizedFilePath]
-> STM (IO ())
recordDirtyKeys ShakeExtras{dirtyKeys} key file = do
modifyTVar' dirtyKeys $ \x -> foldl' (flip insertKeySet) x (toKey key <$> file)
return $ withEventTrace "recordDirtyKeys" $ \addEvent -> do
addEvent (fromString $ unlines $ "dirty " <> show key : map fromNormalizedFilePath file)

-- | We return Nothing if the rule has not run and Just Failed if it has failed to produce a value.
getValues ::
Expand Down Expand Up @@ -723,16 +718,21 @@ shakeSessionInit recorder ide@IdeState{..} = do
putMVar shakeSession initSession
logWith recorder Debug LogSessionInitialised

shakeShut :: IdeState -> IO ()
shakeShut IdeState{..} = do
runner <- tryReadMVar shakeSession
-- Shake gets unhappy if you try to close when there is a running
-- request so we first abort that.
for_ runner cancelShakeSession
void $ shakeDatabaseProfile shakeDb
progressStop $ progress shakeExtras
stopMonitoring

shakeShut :: Recorder (WithPriority Log) -> IdeState -> IO ()
shakeShut recorder IdeState{..} = do
res <- timeout 1 $ withMVar shakeSession $ \runner -> do
-- Shake gets unhappy if you try to close when there is a running
-- request so we first abort that.
cancelShakeSession runner
void $ shakeDatabaseProfile shakeDb
-- might hang if there are still running
progressStop $ progress shakeExtras
stopMonitoring
case res of
Nothing -> do
logWith recorder Error $ LogTimeOutShuttingDownWaitForSessionVar 1
stopMonitoring
Just _ -> pure ()

-- | This is a variant of withMVar where the first argument is run unmasked and if it throws
-- an exception, the previous value is restored while the second argument is executed masked.
Expand All @@ -759,12 +759,14 @@ delayedAction a = do
-- | Restart the current 'ShakeSession' with the given system actions.
-- Any actions running in the current session will be aborted,
-- but actions added via 'shakeEnqueue' will be requeued.
shakeRestart :: Recorder (WithPriority Log) -> IdeState -> VFSModified -> String -> [DelayedAction ()] -> IO ()
shakeRestart recorder IdeState{..} vfs reason acts =
shakeRestart :: Recorder (WithPriority Log) -> IdeState -> VFSModified -> String -> [DelayedAction ()] -> IO [Key] -> IO ()
shakeRestart recorder IdeState{..} vfs reason acts ioActionBetweenShakeSession =
withMVar'
shakeSession
(\runner -> do
(stopTime,()) <- duration $ logErrorAfter 10 $ cancelShakeSession runner
keys <- ioActionBetweenShakeSession
atomically $ modifyTVar' (dirtyKeys shakeExtras) $ \x -> foldl' (flip insertKeySet) x keys
res <- shakeDatabaseProfile shakeDb
backlog <- readTVarIO $ dirtyKeys shakeExtras
queue <- atomicallyNamed "actionQueue - peek" $ peekInProgress $ actionQueue shakeExtras
Expand Down Expand Up @@ -1198,7 +1200,7 @@ defineEarlyCutoff' doDiagnostics cmp key file mbOld mode action = do
Just (v@(Succeeded _ x), diags) -> do
ver <- estimateFileVersionUnsafely key (Just x) file
doDiagnostics (vfsVersion =<< ver) $ Vector.toList diags
return $ Just $ RunResult ChangedNothing old $ A v
return $ Just $ RunResult ChangedNothing old (A v) $ return ()
_ -> return Nothing
_ ->
-- assert that a "clean" rule is never a cache miss
Expand All @@ -1222,7 +1224,6 @@ defineEarlyCutoff' doDiagnostics cmp key file mbOld mode action = do
Nothing -> do
pure (toShakeValue ShakeStale mbBs, staleV)
Just v -> pure (maybe ShakeNoCutoff ShakeResult mbBs, Succeeded ver v)
liftIO $ atomicallyNamed "define - write" $ setValues state key file res (Vector.fromList diags)
doDiagnostics (vfsVersion =<< ver) diags
let eq = case (bs, fmap decodeShakeValue mbOld) of
(ShakeResult a, Just (ShakeResult b)) -> cmp a b
Expand All @@ -1232,9 +1233,9 @@ defineEarlyCutoff' doDiagnostics cmp key file mbOld mode action = do
_ -> False
return $ RunResult
(if eq then ChangedRecomputeSame else ChangedRecomputeDiff)
(encodeShakeValue bs) $
A res
liftIO $ atomicallyNamed "define - dirtyKeys" $ modifyTVar' dirtyKeys (deleteKeySet $ toKey key file)
(encodeShakeValue bs)
(A res)
(setValues state key file res (Vector.fromList diags) >> modifyTVar' dirtyKeys (deleteKeySet $ toKey key file))
return res
where
-- Highly unsafe helper to compute the version of a file
Expand Down
Loading