@ -19,7 +19,7 @@ static const char bundle_signature[] = "# v2 git bundle\n";
struct ref_list {
struct ref_list {
unsigned int nr, alloc;
unsigned int nr, alloc;
struct {
struct ref_list_entry {
unsigned char sha1[20];
unsigned char sha1[20];
char *name;
char *name;
} *list;
} *list;
@ -167,33 +167,54 @@ static int verify_bundle(struct bundle_header *header)
* to be verbose about the errors
* to be verbose about the errors
*/
*/
struct ref_list *p = &header->prerequisites;
struct ref_list *p = &header->prerequisites;
char **argv;
struct rev_info revs;
int pid, out, i, ret = 0;
const char *argv[] = {NULL, "--all"};
char buffer[1024];
struct object_array refs;
struct commit *commit;
int i, ret = 0, req_nr;
const char *message = "The bundle requires these lacking revs:";
argv = xmalloc((p->nr + 4) * sizeof(const char *));
init_revisions(&revs, NULL);
argv[0] = "rev-list";
for (i = 0; i < p->nr; i++) {
argv[1] = "--not";
struct ref_list_entry *e = p->list + i;
argv[2] = "--all";
struct object *o = parse_object(e->sha1);
for (i = 0; i < p->nr; i++)
if (o) {
argv[i + 3] = xstrdup(sha1_to_hex(p->list[i].sha1));
o->flags |= BOUNDARY_SHOW;
argv[p->nr + 3] = NULL;
add_pending_object(&revs, o, e->name);
out = -1;
continue;
pid = fork_with_pipe((const char **)argv, NULL, &out);
}
if (pid < 0)
if (++ret == 1)
return error("Could not fork rev-list");
error(message);
while (read_string(out, buffer, sizeof(buffer)) > 0)
error("%s %s", sha1_to_hex(e->sha1), e->name);
; /* do nothing */
}
close(out);
if (revs.pending.nr == 0)
for (i = 0; i < p->nr; i++)
return ret;
free(argv[i + 3]);
req_nr = revs.pending.nr;
free(argv);
setup_revisions(2, argv, &revs, NULL);
while (waitpid(pid, &i, 0) < 0)
memset(&refs, 0, sizeof(struct object_array));
if (errno != EINTR)
for (i = 0; i < revs.pending.nr; i++) {
return -1;
struct object_array_entry *e = revs.pending.objects + i;
if (!ret && (!WIFEXITED(i) || WEXITSTATUS(i)))
add_object_array(e->item, e->name, &refs);
return error("At least one prerequisite is lacking.");
}
prepare_revision_walk(&revs);
i = req_nr;
while (i && (commit = get_revision(&revs)))
if (commit->object.flags & BOUNDARY_SHOW)
i--;
for (i = 0; i < req_nr; i++)
if (!(refs.objects[i].item->flags & SHOWN)) {
if (++ret == 1)
error(message);
error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
refs.objects[i].name);
}
for (i = 0; i < refs.nr; i++)
clear_commit_marks((struct commit *)refs.objects[i].item, -1);
return ret;
return ret;
}
}