Message ID | 8dc5a8e4e63dc98642176e5b78be739ef721d2d8.1665579160.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | c96060b0cef79c9d76eb97965e700beb9651f35b |
Headers | show |
Series | Bundle URIs III: Parse and download from bundle lists | expand |
"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes: > From: Derrick Stolee <derrickstolee@github.com> > > The verify_bundle() method checks two things for a bundle's > prerequisites: > > 1. Are these objects in the object store? > 2. Are these objects reachable from our references? > > In this second question, multiple uses of verify_bundle() in the same > process can report an invalid bundle even though it is correct. The > reason is due to not clearing all of the commit marks on the commits > previously walked. > ... > Moving this loop to the cleanup step alone would cause a segfault when > running 'git bundle verify' outside of a repository, but this is because > of that error condition using "goto cleanup" when returning is perfectly > safe. Nothing has been initialized at that point, so we can return > immediately without causing any leaks. Nicely analyzed. The implementation clearly follows the design described above. Much better than the previous iteration. Thanks.
diff --git a/bundle.c b/bundle.c index 0208e6d90d3..c277f3b9360 100644 --- a/bundle.c +++ b/bundle.c @@ -202,10 +202,8 @@ int verify_bundle(struct repository *r, int i, ret = 0, req_nr; const char *message = _("Repository lacks these prerequisite commits:"); - if (!r || !r->objects || !r->objects->odb) { - ret = error(_("need a repository to verify a bundle")); - goto cleanup; - } + if (!r || !r->objects || !r->objects->odb) + return error(_("need a repository to verify a bundle")); repo_init_revisions(r, &revs, NULL); for (i = 0; i < p->nr; i++) { @@ -250,15 +248,6 @@ int verify_bundle(struct repository *r, error("%s %s", oid_to_hex(oid), name); } - /* Clean up objects used, as they will be reused. */ - for (i = 0; i < p->nr; i++) { - struct string_list_item *e = p->items + i; - struct object_id *oid = e->util; - commit = lookup_commit_reference_gently(r, oid, 1); - if (commit) - clear_commit_marks(commit, ALL_REV_FLAGS); - } - if (verbose) { struct string_list *r; @@ -287,6 +276,14 @@ int verify_bundle(struct repository *r, list_objects_filter_spec(&header->filter)); } cleanup: + /* Clean up objects used, as they will be reused. */ + for (i = 0; i < p->nr; i++) { + struct string_list_item *e = p->items + i; + struct object_id *oid = e->util; + commit = lookup_commit_reference_gently(r, oid, 1); + if (commit) + clear_commit_marks(commit, ALL_REV_FLAGS | PREREQ_MARK); + } release_revisions(&revs); return ret; }