alternates: allow relative paths in all repositories

Git does not limit relative paths in alternates to the first
repository, so libgit2 shouldn't either.
This commit is contained in:
Mike Frysinger
2025-01-15 21:00:06 -05:00
committed by Edward Thomson
parent 4fb6de4cd7
commit f4c3b351df
2 changed files with 38 additions and 6 deletions

View File

@@ -790,12 +790,8 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
if (*alternate == '\0' || *alternate == '#')
continue;
/*
* Relative path: build based on the current `objects`
* folder. However, relative paths are only allowed in
* the current repository.
*/
if (*alternate == '.' && !alternate_depth) {
/* Relative path: build based on the current `objects` folder. */
if (*alternate == '.') {
if ((result = git_str_joinpath(&alternates_path, objects_dir, alternate)) < 0)
break;
alternate = git_str_cstr(&alternates_path);

View File

@@ -78,3 +78,39 @@ void test_odb_alternates__long_chain(void)
cl_git_fail(git_commit_lookup(&commit, repo, &oid));
git_repository_free(repo);
}
void test_odb_alternates__relative(void)
{
git_commit *commit;
git_oid oid;
/* Set the alternate A -> testrepo.git */
init_linked_repo(paths[0], cl_fixture("testrepo.git"));
/* Set the alternate B -> A */
init_linked_repo(paths[1], paths[0]);
/* Set the alternate C -> B */
init_linked_repo(paths[2], paths[1]);
/* Use a relative alternates path for B -> A */
cl_git_pass(git_fs_path_prettify(&filepath, paths[1], NULL));
cl_git_pass(git_str_joinpath(&filepath, filepath.ptr, "objects/info/alternates"));
cl_git_pass(git_filebuf_open(&file, git_str_cstr(&filepath), 0, 0666));
git_filebuf_printf(&file, "../../%s/objects\n", paths[0]);
cl_git_pass(git_filebuf_commit(&file));
/* Now load B and see if we can find an object from testrepo.git */
cl_git_pass(git_repository_open(&repo, paths[1]));
git_oid__fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OID_SHA1);
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
git_commit_free(commit);
git_repository_free(repo);
/* Now load C and see if we can find an object from testrepo.git */
cl_git_pass(git_repository_open(&repo, paths[2]));
git_oid__fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OID_SHA1);
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
git_commit_free(commit);
git_repository_free(repo);
}