diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index b723554cc36..2d8ed1b5d64 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -57,7 +57,7 @@ bool operator == (const git_oid & oid1, const git_oid & oid2) namespace nix { -struct GitInputAccessor; +struct GitInputAccessorImpl; // Some wrapper types that ensure that the git_*_free functions get called. template @@ -334,9 +334,11 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this } /** - * A 'GitInputAccessor' with no regard for export-ignore or any other transformations. + * A 'GitInputAccessorImpl' with no regard for export-ignore or any other transformations. */ - ref getRawAccessor(const Hash & rev); + ref getRawAccessor(const Hash & rev); + + ref getPlainAccessor(const Hash & rev) override; ref getAccessor(const Hash & rev, bool exportIgnore) override; @@ -477,17 +479,24 @@ ref GitRepo::openRepo(const std::filesystem::path & path, bool create, /** * Raw git tree input accessor. */ -struct GitInputAccessor : InputAccessor +struct GitInputAccessorImpl : GitInputAccessor { ref repo; Tree root; - GitInputAccessor(ref repo_, const Hash & rev) + GitInputAccessorImpl(ref repo_, const Hash & rev) : repo(repo_) , root(peelObject(*repo, lookupObject(*repo, hashToOID(rev)).get(), GIT_OBJECT_TREE)) { } + Hash getTreeHash() override + { + auto * oid = git_tree_id(root.get()); + assert(oid); + return toHash(*oid); + } + std::string readBlob(const CanonPath & path, bool symlink) { auto blob = getBlob(path, symlink); @@ -922,17 +931,22 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink } }; -ref GitRepoImpl::getRawAccessor(const Hash & rev) +ref GitRepoImpl::getRawAccessor(const Hash & rev) { auto self = ref(shared_from_this()); - return make_ref(self, rev); + return make_ref(self, rev); +} + +ref GitRepoImpl::getPlainAccessor(const Hash & rev) +{ + return getRawAccessor(rev); } ref GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore) { - auto self = ref(shared_from_this()); - ref rawGitAccessor = getRawAccessor(rev); + ref rawGitAccessor = getRawAccessor(rev); if (exportIgnore) { + auto self = ref(shared_from_this()); return make_ref(self, rawGitAccessor, rev); } else { diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index fbb2d947b45..bd15e405e2b 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -16,6 +16,16 @@ struct GitFileSystemObjectSink : FileSystemObjectSink virtual Hash sync() = 0; }; +/** + * Git Input Accessor + * + * Created from `GitRepo`. Support some additional operations. + */ +struct GitInputAccessor : InputAccessor +{ + virtual Hash getTreeHash() = 0; +}; + struct GitRepo { virtual ~GitRepo() @@ -75,6 +85,8 @@ struct GitRepo virtual bool hasObject(const Hash & oid) = 0; + virtual ref getPlainAccessor(const Hash & rev) = 0; + virtual ref getAccessor(const Hash & rev, bool exportIgnore) = 0; virtual ref getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0; diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 34cfd3f5bea..1ddcf5c51d0 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -206,6 +206,7 @@ struct GitInputScheme : InputScheme "shallow", "submodules", "exportIgnore", + "treeHash", "lastModified", "revCount", "narHash", @@ -601,6 +602,8 @@ struct GitInputScheme : InputScheme auto rev = *input.getRev(); + auto gotTreeHash = repo->getPlainAccessor(rev)->getTreeHash(); + Attrs infoAttrs({ {"rev", rev.gitRev()}, {"lastModified", getLastModified(repoInfo, repoDir, rev)}, @@ -646,6 +649,11 @@ struct GitInputScheme : InputScheme mounts.insert_or_assign(CanonPath::root, accessor); accessor = makeMountedInputAccessor(std::move(mounts)); } + } else { + /* If we don't have submodules and aren't doing export + ignore, then the tree hash is useful info to provide. */ + if (experimentalFeatureSettings.isEnabled(Xp::GitHashing) && !exportIgnore) + input.attrs.insert_or_assign("treeHash", gotTreeHash.gitRev()); } assert(!origRev || origRev == rev); diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 8100afe4d74..89198d9e94d 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -276,9 +276,8 @@ struct GitArchiveInputScheme : InputScheme { auto [input, tarballInfo] = downloadArchive(store, _input); - #if 0 - input.attrs.insert_or_assign("treeHash", tarballInfo.treeHash.gitRev()); - #endif + if (experimentalFeatureSettings.isEnabled(Xp::GitHashing)) + input.attrs.insert_or_assign("treeHash", tarballInfo.treeHash.gitRev()); input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified)); auto accessor = getTarballCache()->getAccessor(tarballInfo.treeHash, false);