Skip to content

Commit fb9a541

Browse files
dschoJunio C Hamano
authored andcommitted
git-bundle: avoid fork() in verify_bundle()
We can use the revision walker easily for checking if the prerequisites are met, instead of fork()ing off a rev-list, which would list only the first unmet prerequisite. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fa257b0 commit fb9a541

File tree

1 file changed

+48
-27
lines changed

1 file changed

+48
-27
lines changed

builtin-bundle.c

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static const char bundle_signature[] = "# v2 git bundle\n";
1919

2020
struct ref_list {
2121
unsigned int nr, alloc;
22-
struct {
22+
struct ref_list_entry {
2323
unsigned char sha1[20];
2424
char *name;
2525
} *list;
@@ -167,33 +167,54 @@ static int verify_bundle(struct bundle_header *header)
167167
* to be verbose about the errors
168168
*/
169169
struct ref_list *p = &header->prerequisites;
170-
char **argv;
171-
int pid, out, i, ret = 0;
172-
char buffer[1024];
170+
struct rev_info revs;
171+
const char *argv[] = {NULL, "--all"};
172+
struct object_array refs;
173+
struct commit *commit;
174+
int i, ret = 0, req_nr;
175+
const char *message = "The bundle requires these lacking revs:";
173176

174-
argv = xmalloc((p->nr + 4) * sizeof(const char *));
175-
argv[0] = "rev-list";
176-
argv[1] = "--not";
177-
argv[2] = "--all";
178-
for (i = 0; i < p->nr; i++)
179-
argv[i + 3] = xstrdup(sha1_to_hex(p->list[i].sha1));
180-
argv[p->nr + 3] = NULL;
181-
out = -1;
182-
pid = fork_with_pipe((const char **)argv, NULL, &out);
183-
if (pid < 0)
184-
return error("Could not fork rev-list");
185-
while (read_string(out, buffer, sizeof(buffer)) > 0)
186-
; /* do nothing */
187-
close(out);
188-
for (i = 0; i < p->nr; i++)
189-
free(argv[i + 3]);
190-
free(argv);
191-
192-
while (waitpid(pid, &i, 0) < 0)
193-
if (errno != EINTR)
194-
return -1;
195-
if (!ret && (!WIFEXITED(i) || WEXITSTATUS(i)))
196-
return error("At least one prerequisite is lacking.");
177+
init_revisions(&revs, NULL);
178+
for (i = 0; i < p->nr; i++) {
179+
struct ref_list_entry *e = p->list + i;
180+
struct object *o = parse_object(e->sha1);
181+
if (o) {
182+
o->flags |= BOUNDARY_SHOW;
183+
add_pending_object(&revs, o, e->name);
184+
continue;
185+
}
186+
if (++ret == 1)
187+
error(message);
188+
error("%s %s", sha1_to_hex(e->sha1), e->name);
189+
}
190+
if (revs.pending.nr == 0)
191+
return ret;
192+
req_nr = revs.pending.nr;
193+
setup_revisions(2, argv, &revs, NULL);
194+
195+
memset(&refs, 0, sizeof(struct object_array));
196+
for (i = 0; i < revs.pending.nr; i++) {
197+
struct object_array_entry *e = revs.pending.objects + i;
198+
add_object_array(e->item, e->name, &refs);
199+
}
200+
201+
prepare_revision_walk(&revs);
202+
203+
i = req_nr;
204+
while (i && (commit = get_revision(&revs)))
205+
if (commit->object.flags & BOUNDARY_SHOW)
206+
i--;
207+
208+
for (i = 0; i < req_nr; i++)
209+
if (!(refs.objects[i].item->flags & SHOWN)) {
210+
if (++ret == 1)
211+
error(message);
212+
error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
213+
refs.objects[i].name);
214+
}
215+
216+
for (i = 0; i < refs.nr; i++)
217+
clear_commit_marks((struct commit *)refs.objects[i].item, -1);
197218

198219
return ret;
199220
}

0 commit comments

Comments
 (0)