Hi,
Am Mittwoch, den 06.05.2015, 17:48 +0100 schrieb Neil Mitchell:
> > I tried to use the HEAD-resolving query in the rule for the
> > file-lookup-query:
> >
> > defaultRuleGitLib :: Rules ()
> > defaultRuleGitLib = do
> > rule $ \(GetGitReferenceQ (repoPath, refName)) -> Just $ liftIO $
> > GitSHA <$> getGitReference' repoPath refName
> > rule $ \(GetGitFileRefQ (repoPath, refName, fn)) -> Just $ do
> > GitSHA ref' <- apply1 $ GetGitReferenceQ (repoPath, "HEAD")
> > liftIO $ getGitFileRef' repoPath ref' fn
> >
> > But it would still run "getGitFileRef'" even with an unchanged
> > repository.
>
> So I think that is what you should be doing, and it should (to a first
> approximation) work the way you were hoping for. You roughly have the
> dependency chain:
>
> GetGitReferenceQ <- GetGitFileRefQ <- readGitFile
>
> And since Shake should break the dependency chain whenever a value is
> equal, if HEAD doesn't change, GetGitFileRefQ shouldn't be
> recalculated.
>
> The problem (I suspect) is that the storedValue instance for
> GetGitFileRefQ is being invoked. Can you trace inside the storedValue
> to confirm that's where the reference is being checked?
Yes, indeed. Here a run with no change:
% Compression complete
storedValue GetGitFileRefQ
HEAD lookup!
Tree lookup!
% valid True for (GetGitFileRefQ ("repo","HEAD","a.txt")) (Just "83e1501243b46efbe5407e191840da4ee76b76d4")
storedValue GetGitReferenceQ
HEAD lookup!
% valid True for (GetGitReferenceQ ("repo","HEAD")) (GitSHA "05ddb4a38826098d571f142f11fdd4c23f59ceca")
% Loaded -> Ready, GetGitReferenceQ ("repo","HEAD")
% Loaded -> Ready, GetGitFileRefQ ("repo","HEAD","a.txt")
% valid True for a.out (File {mod=0xA899856F,size=0x2,digest=VAL})
% Loaded -> Ready, a.out
storedValue GetGitFileRefQ
HEAD lookup!
Tree lookup!
% valid True for (GetGitFileRefQ ("repo","HEAD","b.txt")) Nothing
% Loaded -> Ready, GetGitFileRefQ ("repo","HEAD","b.txt")
Build completed in 0:01m
Here a run with a change to HEAD, but not to the actual a.txt:
% Found 6 real entries
storedValue GetGitFileRefQ
HEAD lookup!
Tree lookup!
% valid True for (GetGitFileRefQ ("repo","HEAD","a.txt")) (Just "83e1501243b46efbe5407e191840da4ee76b76d4")
storedValue GetGitReferenceQ
HEAD lookup!
% valid False for (GetGitReferenceQ ("repo","HEAD")) (GitSHA "05ddb4a38826098d571f142f11fdd4c23f59ceca")
% Loaded -> Waiting, GetGitReferenceQ ("repo","HEAD")
% Loaded -> Waiting, GetGitFileRefQ ("repo","HEAD","a.txt")
# GetGitReferenceQ ("repo","HEAD")
HEAD lookup!
% Waiting -> Ready, GetGitReferenceQ ("repo","HEAD")
% Waiting -> Waiting, GetGitFileRefQ ("repo","HEAD","a.txt")
% result (GetGitReferenceQ ("repo","HEAD")) = (GitSHA "d04351227b669d6efde1003cf07951a452e09fd7")
# GetGitFileRefQ ("repo","HEAD","a.txt")
Tree lookup!
% Waiting -> Ready, GetGitFileRefQ ("repo","HEAD","a.txt")
% result (GetGitFileRefQ ("repo","HEAD","a.txt")) = (Just "83e1501243b46efbe5407e191840da4ee76b76d4")
% valid True for a.out (File {mod=0xA899856F,size=0x2,digest=VAL})
% Loaded -> Ready, a.out
storedValue GetGitFileRefQ
HEAD lookup!
Tree lookup!
% valid True for (GetGitFileRefQ ("repo","HEAD","b.txt")) Nothing
% Loaded -> Waiting, GetGitFileRefQ ("repo","HEAD","b.txt")
# GetGitFileRefQ ("repo","HEAD","b.txt")
Tree lookup!
% Waiting -> Ready, GetGitFileRefQ ("repo","HEAD","b.txt")
% result (GetGitFileRefQ ("repo","HEAD","b.txt")) = Nothing
Build completed in 0:01m
and finally a run with a new HEAD with a changed a.txt:
% Found 6 real entries
storedValue GetGitFileRefQ
HEAD lookup!
Tree lookup!
% valid False for (GetGitFileRefQ ("repo","HEAD","a.txt")) (Just "83e1501243b46efbe5407e191840da4ee76b76d4")
% Loaded -> Waiting, GetGitFileRefQ ("repo","HEAD","a.txt")
# GetGitFileRefQ ("repo","HEAD","a.txt")
storedValue GetGitReferenceQ
HEAD lookup!
% valid False for (GetGitReferenceQ ("repo","HEAD")) (GitSHA "d04351227b669d6efde1003cf07951a452e09fd7")
% Loaded -> Waiting, GetGitReferenceQ ("repo","HEAD")
# GetGitReferenceQ ("repo","HEAD")
HEAD lookup!
% Waiting -> Ready, GetGitReferenceQ ("repo","HEAD")
% result (GetGitReferenceQ ("repo","HEAD")) = (GitSHA "60c235b92e3451d9c6e30f0e7805463a71977e56")
Tree lookup!
% Waiting -> Ready, GetGitFileRefQ ("repo","HEAD","a.txt")
% result (GetGitFileRefQ ("repo","HEAD","a.txt")) = (Just "35bfc60cf7524abf9e6a04b6e27098c32407a826")
% valid True for a.out (File {mod=0xA899856F,size=0x2,digest=VAL})
% Loaded -> Waiting, a.out
# a.out
Writing a
% Waiting -> Ready, a.out
% result a.out = (File {mod=0xAAF108F7,size=0x2,digest=VAL})
storedValue GetGitFileRefQ
HEAD lookup!
Tree lookup!
% valid True for (GetGitFileRefQ ("repo","HEAD","b.txt")) Nothing
% Loaded -> Waiting, GetGitFileRefQ ("repo","HEAD","b.txt")
# GetGitFileRefQ ("repo","HEAD","b.txt")
Tree lookup!
% Waiting -> Ready, GetGitFileRefQ ("repo","HEAD","b.txt")
% result (GetGitFileRefQ ("repo","HEAD","b.txt")) = Nothing
Build completed in 0:01m
Not sure what the conclusion is here.
> I think the solution to that is to follow the Rule advice "For rules
> whose values are not stored externally, storedValue should return Just
> with a sentinel value and equalValue should always return EqualCheap
> for that sentinel.". I know the value is stored externally, but its
> stored externally with perfect tracking via the SHA dependency, which
> means it might as well be not stored.
Ah, I might be on an older version (0.13.2, which is in Debian), where
it says
“For rules whose values are not stored externally, storedValue
should return Nothing.”
– hence my earlier question about when to exactly return Nothing.
Indeed, 0.15.1’s docs are more elaborate; sorry for not properly
RTFM’ing here.
What I find confusing: If use use a sentinel value (e.g. "data Answer =
Answer", right?) for when the value is not stored externally, then were
do I store the value at all? Or maybe I’m misunderstanding „external“
here.
I’m slightly confused by the example, which says
“below is a simplified rule for building files, where files are
identified by a FilePath and their state is identified by a hash
of their contents”
but then has ModTime instead of hashes. Intentional or a documentation
glitch?
I’ll experiment a bit more, and push for getting 0.15.1 into Debian.
It’s pending packaging of the js-* libraries, which someone else wanted
to look into this weekend.
Thanks!
Joachim
--