git fetcher: use resolveRef for getting revision of reference

* Add regression test
* Fix 'no repo' test so it doesn't succeed if the data is still in cache
* Use git_revparse_single inside git-utils instead of reimplementing the same logic.
This commit is contained in:
Bouke van der Bijl 2024-03-14 14:04:51 +01:00
parent c152c2767a
commit 60c2d15f5a
3 changed files with 14 additions and 21 deletions

View File

@ -21,6 +21,7 @@
#include <git2/refs.h> #include <git2/refs.h>
#include <git2/remote.h> #include <git2/remote.h>
#include <git2/repository.h> #include <git2/repository.h>
#include <git2/revparse.h>
#include <git2/status.h> #include <git2/status.h>
#include <git2/submodule.h> #include <git2/submodule.h>
#include <git2/tree.h> #include <git2/tree.h>
@ -199,27 +200,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
Hash resolveRef(std::string ref) override Hash resolveRef(std::string ref) override
{ {
// Handle revisions used as refs. Object object;
{ if (git_revparse_single(Setter(object), *this, ref.c_str()))
git_oid oid;
if (git_oid_fromstr(&oid, ref.c_str()) == 0)
return toHash(oid);
}
// Resolve short names like 'master'.
Reference ref2;
if (!git_reference_dwim(Setter(ref2), *this, ref.c_str()))
ref = git_reference_name(ref2.get());
// Resolve full references like 'refs/heads/master'.
Reference ref3;
if (git_reference_lookup(Setter(ref3), *this, ref.c_str()))
throw Error("resolving Git reference '%s': %s", ref, git_error_last()->message); throw Error("resolving Git reference '%s': %s", ref, git_error_last()->message);
auto oid = git_object_id(object.get());
auto oid = git_reference_target(ref3.get());
if (!oid)
throw Error("cannot get OID for Git reference '%s'", git_reference_name(ref3.get()));
return toHash(*oid); return toHash(*oid);
} }

View File

@ -585,7 +585,7 @@ struct GitInputScheme : InputScheme
repoInfo.url repoInfo.url
); );
} else } else
input.attrs.insert_or_assign("rev", Hash::parseAny(chomp(readFile(localRefFile)), HashAlgorithm::SHA1).gitRev()); input.attrs.insert_or_assign("rev", repo->resolveRef(ref).gitRev());
// cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder
} }

View File

@ -43,10 +43,18 @@ path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree git+file://$TEST_RO
export _NIX_FORCE_HTTP=1 export _NIX_FORCE_HTTP=1
[[ $(tail -n 1 $path0/hello) = "hello" ]] [[ $(tail -n 1 $path0/hello) = "hello" ]]
# Nuke the cache
rm -rf $TEST_HOME/.cache/nix
# Fetch the default branch. # Fetch the default branch.
path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath")
[[ $(cat $path/hello) = world ]] [[ $(cat $path/hello) = world ]]
# Fetch when the cache has packed-refs
# Regression test of #8822
git -C $TEST_HOME/.cache/nix/gitv3/*/ pack-refs --all
path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath")
# Fetch a rev from another branch # Fetch a rev from another branch
git -C $repo checkout -b devtest git -C $repo checkout -b devtest
echo "different file" >> $TEST_ROOT/git/differentbranch echo "different file" >> $TEST_ROOT/git/differentbranch
@ -251,6 +259,7 @@ path12=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = file://$repo
# should fail if there is no repo # should fail if there is no repo
rm -rf $repo/.git rm -rf $repo/.git
rm -rf $TEST_HOME/.cache/nix
(! nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath") (! nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath")
# should succeed for a repo without commits # should succeed for a repo without commits