diff --git a/object.h b/object.h index f8b644263f..614a006756 100644 --- a/object.h +++ b/object.h @@ -31,7 +31,7 @@ struct object_array { * revision.h: 0---------10 26 * fetch-pack.c: 0---4 * walker.c: 0-2 - * upload-pack.c: 11----------------19 + * upload-pack.c: 4 11----------------19 * builtin/blame.c: 12-13 * bisect.c: 16 * bundle.c: 16 diff --git a/upload-pack.c b/upload-pack.c index adb8e33757..3227df872c 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -456,7 +456,8 @@ static int is_our_ref(struct object *o) * on successful case, it's up to the caller to close cmd->out */ static int do_reachable_revlist(struct child_process *cmd, - struct object_array *src) + struct object_array *src, + struct object_array *reachable) { static const char *argv[] = { "rev-list", "--stdin", NULL, @@ -487,6 +488,8 @@ static int do_reachable_revlist(struct child_process *cmd, o = get_indexed_object(--i); if (!o) continue; + if (reachable && o->type == OBJ_COMMIT) + o->flags &= ~TMP_MARK; if (!is_our_ref(o)) continue; memcpy(namebuf + 1, oid_to_hex(&o->oid), GIT_SHA1_HEXSZ); @@ -496,8 +499,13 @@ static int do_reachable_revlist(struct child_process *cmd, namebuf[40] = '\n'; for (i = 0; i < src->nr; i++) { o = src->objects[i].item; - if (is_our_ref(o)) + if (is_our_ref(o)) { + if (reachable) + add_object_array(o, NULL, reachable); continue; + } + if (reachable && o->type == OBJ_COMMIT) + o->flags |= TMP_MARK; memcpy(namebuf, oid_to_hex(&o->oid), GIT_SHA1_HEXSZ); if (write_in_full(cmd->in, namebuf, 41) < 0) goto error; @@ -518,13 +526,51 @@ error: return -1; } +static int get_reachable_list(struct object_array *src, + struct object_array *reachable) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + int i; + struct object *o; + char namebuf[42]; /* ^ + SHA-1 + LF */ + + if (do_reachable_revlist(&cmd, src, reachable) < 0) + return -1; + + while ((i = read_in_full(cmd.out, namebuf, 41)) == 41) { + struct object_id sha1; + + if (namebuf[40] != '\n' || get_oid_hex(namebuf, &sha1)) + break; + + o = lookup_object(sha1.hash); + if (o && o->type == OBJ_COMMIT) { + o->flags &= ~TMP_MARK; + } + } + for (i = get_max_object_index(); 0 < i; i--) { + o = get_indexed_object(i - 1); + if (o && o->type == OBJ_COMMIT && + (o->flags & TMP_MARK)) { + add_object_array(o, NULL, reachable); + o->flags &= ~TMP_MARK; + } + } + close(cmd.out); + + if (finish_command(&cmd)) + return -1; + + return 0; +} + static int has_unreachable(struct object_array *src) { struct child_process cmd = CHILD_PROCESS_INIT; char buf[1]; int i; - if (do_reachable_revlist(&cmd, src) < 0) + if (do_reachable_revlist(&cmd, src, NULL) < 0) return 1; /*