8000 Fix shallow root maintenance during fetch by kcsaul · Pull Request #6846 · libgit2/libgit2 · GitHub
[go: up one dir, main page]

Skip to content

Fix shallow root maintenance during fetch #6846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libgit2/transports/smart_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ static int setup_shallow_roots(

memcpy(out->ptr, wants->shallow_roots,
sizeof(git_oid) * wants->shallow_roots_len);
out->size = wants->shallow_roots_len;
}

return 0;
Expand Down
148 changes: 145 additions & 3 deletions tests/libgit2/online/shallow.c
10000
Original file line numberDiff line number Diff line change
Expand Up @@ -242,10 +242,15 @@ void test_online_shallow__shorten_four(void)
cl_assert_equal_b(true, git_repository_is_shallow(repo));

cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(3, roots_len);
cl_assert_equal_s("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864", git_oid_tostr_s(&roots[0]));
cl_assert_equal_s("59706a11bde2b9899a278838ef20a97e8f8795d2", git_oid_tostr_s(&roots[1]));
cl_assert_equal_i(6, roots_len);
/* roots added during initial clone, not removed as not encountered during fetch */
cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots[0]));
cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots[1]));
cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots[3]));
/* roots added during fetch */
cl_assert_equal_s("bab66b48f836ed950c99134ef666436fb07a09a0", git_oid_tostr_s(&roots[2]));
cl_assert_equal_s("59706a11bde2b9899a278838ef20a97e8f8795d2", git_oid_tostr_s(&roots[4]));
cl_assert_equal_s("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864", git_oid_tostr_s(&roots[5]));

git_revwalk_new(&walk, repo);
git_revwalk_push_head(walk);
Expand All @@ -263,3 +268,140 @@ void test_online_shallow__shorten_four(void)
git_revwalk_free(walk);
git_repository_free(repo);
}

void test_online_shallow__preserve_unrelated_roots(void)
{
git_str path = GIT_STR_INIT;
git_repository *repo;
git_revwalk *walk;
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
git_remote *origin = NULL;
git_strarray refspecs;
git_oid oid;
git_oid *roots;
size_t roots_len;
size_t num_commits = 0;
int error = 0;
git_oid first_oid;
git_oid second_oid;
git_oid third_oid;
char *first_commit = "c070ad8c08840c8116da865b2d65593a6bb9cd2a";
char *second_commit = "6e1475206e57110fcef4b92320436c1e9872a322";
char *third_commit = "7f822839a2fe9760f386cbbbcb3f92c5fe81def7";

#ifdef GIT_EXPERIMENTAL_SHA256
cl_git_pass(git_oid_fromstr(&first_oid, first_commit, GIT_OID_SHA1));
cl_git_pass(git_oid_fromstr(&second_oid, second_commit, GIT_OID_SHA1));
cl_git_pass(git_oid_fromstr(&third_oid, third_commit, GIT_OID_SHA1));
#else
cl_git_pass(git_oid_fromstr(&first_oid, first_commit));
cl_git_pass(git_oid_fromstr(&second_oid, second_commit));
cl_git_pass(git_oid_fromstr(&third_oid, third_commit));
#endif

/* setup empty repository without cloning */
git_str_joinpath(&path, clar_sandbox_path(), "preserve_unrelated_roots");
cl_git_pass(git_repository_init(&repo, git_str_cstr(&path), true));
cl_git_pass(git_remote_create(&origin, repo, "origin", "https://github.com/libgit2/TestGitRepository"));
cl_assert_equal_b(false, git_repository_is_shallow(repo));

/* shallow fetch for first commit */
fetch_opts.depth = 1;
refspecs.strings = &first_commit;
refspecs.count = 1;
cl_git_pass(git_remote_fetch(origin, &refspecs, &fetch_opts, NULL));
cl_assert_equal_b(true, git_repository_is_shallow(repo));

cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(1, roots_len);
cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots[0]));

cl_git_pass(git_revwalk_new(&walk, repo));
cl_git_pass(git_revwalk_push(walk, &first_oid));
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(num_commits, 1);
cl_assert_equal_i(error, GIT_ITEROVER);

/* shallow fetch for second commit */
fetch_opts.depth = 1;
refspecs.strings = &second_commit;
refspecs.count = 1;
cl_git_pass(git_remote_fetch(origin, &refspecs, &fetch_opts, NULL));
cl_assert_equal_b(true, git_repository_is_shallow(repo));

git__free(roots);
cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(2, roots_len);
cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots[0]));
cl_assert_equal_s("6e1475206e57110fcef4b92320436c1e9872a322", git_oid_tostr_s(&roots[1]));

git_revwalk_free(walk);
cl_git_pass(git_revwalk_new(&walk, repo));
cl_git_pass(git_revwalk_push(walk, &second_oid));
num_commits = 0;
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(error, GIT_ITEROVER);
cl_assert_equal_i(num_commits, 1);

/* fetch full history for third commit, includes first commit which should be removed from shallow roots */
fetch_opts.depth = 100;
refspecs.strings = &third_commit;
refspecs.count = 1;
cl_git_pass(git_remote_fetch(origin, &refspecs, &fetch_opts, NULL));
cl_assert_equal_b(true, git_repository_is_shallow(repo));

git__free(roots);
cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(1, roots_len);
cl_assert_equal_s("6e1475206e57110fcef4b92320436c1e9872a322", git_oid_tostr_s(&roots[0]));

git_revwalk_free(walk);
cl_git_pass(git_revwalk_new(&walk, repo));
cl_git_pass(git_revwalk_push(walk, &third_oid));
num_commits = 0;
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(error, GIT_ITEROVER);
cl_assert_equal_i(num_commits, 12);

cl_git_pass(git_revwalk_reset(walk));
cl_git_pass(git_revwalk_push(walk, &second_oid));
num_commits = 0;
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(error, GIT_ITEROVER);
cl_assert_equal_i(num_commits, 1);

/* unshallow repository without specifying any refspec */
fetch_opts.depth = GIT_FETCH_DEPTH_UNSHALLOW;
cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL));
cl_assert_equal_b(false, git_repository_is_shallow(repo));

git__free(roots);
cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(0, roots_len);

git_revwalk_free(walk);
cl_git_pass(git_revwalk_new(&walk, repo));
cl_git_pass(git_revwalk_push(walk, &first_oid));
cl_git_pass(git_revwalk_push(walk, &second_oid));
cl_git_pass(git_revwalk_push(walk, &third_oid));
num_commits = 0;
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(error, GIT_ITEROVER);
cl_assert_equal_i(num_commits, 18);

git__free(roots);
git_remote_free(origin);
git_str_dispose(&path);
git_revwalk_free(walk);
git_repository_free(repo);
}
Loading
0