From 7b1cda9ca20d2e03f00d34e8c2fb0f8e6569b115 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 3 Feb 2023 16:04:19 +0100 Subject: [PATCH] GitArchiveInputScheme: Restore the lastModified attribute --- src/libfetchers/git-accessor.cc | 11 ++++++++-- src/libfetchers/git-utils.hh | 8 ++++++- src/libfetchers/github.cc | 38 +++++++++++++++++---------------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/libfetchers/git-accessor.cc b/src/libfetchers/git-accessor.cc index 45d387fa9..c50e4355a 100644 --- a/src/libfetchers/git-accessor.cc +++ b/src/libfetchers/git-accessor.cc @@ -243,7 +243,7 @@ static Repository openTarballCache() } } -Hash importTarball(Source & source) +TarballInfo importTarball(Source & source) { auto repo = openTarballCache(); @@ -308,6 +308,8 @@ Hash importTarball(Source & source) size_t componentsToStrip = 1; + time_t lastModified = 0; + for (;;) { // FIXME: merge with extract_archive struct archive_entry * entry; @@ -321,6 +323,8 @@ Hash importTarball(Source & source) else archive.check(r); + lastModified = std::max(lastModified, archive_entry_mtime(entry)); + auto pathComponents = tokenizeString>(path, "/"); std::span pathComponents2{pathComponents}; @@ -388,7 +392,10 @@ Hash importTarball(Source & source) auto [oid, _name] = popBuilder(); - return Hash::parseAny(git_oid_tostr_s(&oid), htSHA1); + return TarballInfo { + .treeHash = Hash::parseAny(git_oid_tostr_s(&oid), htSHA1), + .lastModified = lastModified + }; } ref makeTarballCacheAccessor(const Hash & rev) diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index 775a0d021..227e31942 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -6,7 +6,13 @@ namespace nix { ref makeGitInputAccessor(const CanonPath & path, const Hash & rev); -Hash importTarball(Source & source); +struct TarballInfo +{ + Hash treeHash; + time_t lastModified; +}; + +TarballInfo importTarball(Source & source); ref makeTarballCacheAccessor(const Hash & rev); diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 756dcef8b..5e75a0992 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -168,6 +168,8 @@ struct GitArchiveInputScheme : InputScheme void checkLocks(const Input & specified, const Input & final) const override { + InputScheme::checkLocks(specified, final); + if (auto prevTreeHash = getTreeHash(specified)) { if (getTreeHash(final) != prevTreeHash) throw Error("Git tree hash mismatch in input '%s', expected '%s'", @@ -201,7 +203,7 @@ struct GitArchiveInputScheme : InputScheme virtual DownloadUrl getDownloadUrl(const Input & input) const = 0; - std::pair downloadArchive(ref store, Input input) const + std::pair downloadArchive(ref store, Input input) const { if (!maybeGetStrAttr(input.attrs, "ref")) input.attrs.insert_or_assign("ref", "HEAD"); @@ -214,13 +216,17 @@ struct GitArchiveInputScheme : InputScheme auto cache = getCache(); auto treeHashKey = fmt("git-rev-to-tree-hash-%s", rev->gitRev()); + auto lastModifiedKey = fmt("git-rev-to-last-modified-%s", rev->gitRev()); if (auto treeHashS = cache->queryFact(treeHashKey)) { - auto treeHash = Hash::parseAny(*treeHashS, htSHA1); - if (tarballCacheContains(treeHash)) - return {std::move(input), treeHash}; - else - debug("Git tree with hash '%s' has disappeared from the cache, refetching...", treeHash.gitRev()); + if (auto lastModifiedS = cache->queryFact(lastModifiedKey)) { + auto treeHash = Hash::parseAny(*treeHashS, htSHA1); + auto lastModified = string2Int(*lastModifiedS).value(); + if (tarballCacheContains(treeHash)) + return {std::move(input), TarballInfo { .treeHash = treeHash, .lastModified = lastModified }}; + else + debug("Git tree with hash '%s' has disappeared from the cache, refetching...", treeHash.gitRev()); + } } /* Stream the tarball into the tarball cache. */ @@ -232,26 +238,22 @@ struct GitArchiveInputScheme : InputScheme getFileTransfer()->download(std::move(req), sink); }); - auto treeHash = importTarball(*source); + auto tarballInfo = importTarball(*source); - cache->upsertFact(treeHashKey, treeHash.gitRev()); + cache->upsertFact(treeHashKey, tarballInfo.treeHash.gitRev()); + cache->upsertFact(lastModifiedKey, std::to_string(tarballInfo.lastModified)); - return {std::move(input), treeHash}; + return {std::move(input), tarballInfo}; } std::pair, Input> getAccessor(ref store, const Input & _input) const override { - auto [input, treeHash] = downloadArchive(store, _input); + auto [input, tarballInfo] = downloadArchive(store, _input); - input.attrs.insert_or_assign("treeHash", treeHash.gitRev()); + input.attrs.insert_or_assign("treeHash", tarballInfo.treeHash.gitRev()); + input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified)); - auto accessor = makeTarballCacheAccessor(treeHash); - - #if 0 - auto lastModified = accessor->getLastModified(); - assert(lastModified); - input.attrs.insert_or_assign("lastModified", uint64_t(*lastModified)); - #endif + auto accessor = makeTarballCacheAccessor(tarballInfo.treeHash); accessor->setPathDisplay("«" + input.to_string() + "»");