[PATCH/RFC] rev-list: understand bound commits.
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:17
Subsystem:
the rest · Maintainer:
Linus Torvalds
This adds support for "bind" lines in commit objects, so that "rev-list --objects piped to pack-objects" pattern can be used for git native transports. Signed-off-by: Junio C Hamano <redacted> --- * Linus, I would really appreciate if you can proofread and comment on this patch. I am reasonably sure that I did not break things when no commit with "bind" lines are involved, but I am not sure if this makes --objects do the right thing to produce correct packs. The goal is still to have: $ git rev-list --objects A..B to produce list of objects that are needed to complete B for somebody who has A, taking into account the objects contained in the subproject commits, while: $ git rev-list A..B should not worry anything about subproject commits. rev-list.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 61 insertions(+), 4 deletions(-) e0571c156e9abd75473c6c85e224965dae842a65
diff --git a/rev-list.c b/rev-list.c
index f2534fd..339926a 100644
--- a/rev-list.c
+++ b/rev-list.c@@ -201,6 +201,37 @@ static struct object_list **process_tree return p; } +static struct object_list **process_commit_part(struct commit *, struct object_list **, const char *); + +static struct object_list **process_bound_commit(struct commit *bound, struct object_list **p, const char *name) +{ + struct object *obj = &bound->object; + + if (!list_objects) + return p; + if (obj->flags & (UNINTERESTING|SEEN)) + return p; + if (parse_commit(bound) < 0) + die("bad commit object %s", sha1_to_hex(obj->sha1)); + obj->flags |= SEEN; + p = add_object(obj, p, name); + return process_commit_part(bound, p, name); +} + +static struct object_list **process_commit_part(struct commit *commit, struct object_list **p, const char *name) +{ + p = process_tree(commit->tree, p, name); + if (commit->binds) { + struct commit_list *bp = commit->binds; + while (bp) { + struct commit *bound = bp->item; + bp = bp->next; + p = process_bound_commit(bound, p, name); + } + } + return p; +} + static struct object_list *pending_objects = NULL; static void show_commit_list(struct commit_list *list)
@@ -209,7 +240,7 @@ static void show_commit_list(struct comm while (list) { struct commit *commit = pop_most_recent_commit(&list, SEEN); - p = process_tree(commit->tree, p, ""); + p = process_commit_part(commit, p, ""); if (process_commit(commit) == STOP) break; }
@@ -231,6 +262,10 @@ static void show_commit_list(struct comm p = process_blob((struct blob *)obj, p, name); continue; } + if (obj->type == commit_type) { + p = process_bound_commit((struct commit *)obj, p, name); + continue; + } die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name); } while (objects) {
@@ -285,6 +320,16 @@ static void mark_tree_uninteresting(stru } } +static void mark_bound_commits(struct commit *commit, int flags) +{ + struct commit_list *clist = commit->binds; + while (clist) { + struct commit *bound = clist->item; + bound->object.flags |= flags; + clist = clist->next; + } +} + static void mark_parents_uninteresting(struct commit *commit) { struct commit_list *parents = commit->parents;
@@ -305,6 +350,13 @@ static void mark_parents_uninteresting(s mark_parents_uninteresting(commit); /* + * Subproject commits bound to an uninteresting + * parent is not interesting. + */ + if (commit->binds) + mark_bound_commits(commit, UNINTERESTING); + + /* * A missing commit is ok iff its parent is marked * uninteresting. *
@@ -520,6 +572,7 @@ static void add_parents_to_list(struct c p->object.flags |= UNINTERESTING; if (p->parents) mark_parents_uninteresting(p); + mark_bound_commits(p, UNINTERESTING); if (p->object.flags & SEEN) continue; p->object.flags |= SEEN;
@@ -599,9 +652,12 @@ static struct commit_list *limit_list(st obj->flags |= UNINTERESTING; if (unpacked && has_sha1_pack(obj->sha1)) obj->flags |= UNINTERESTING; - add_parents_to_list(commit, &list); + if (commit->parents) + add_parents_to_list(commit, &list); if (obj->flags & UNINTERESTING) { - mark_parents_uninteresting(commit); + if (commit->parents) + mark_parents_uninteresting(commit); + mark_bound_commits(commit, UNINTERESTING); if (everybody_uninteresting(list)) break; continue;
@@ -654,8 +710,9 @@ static struct commit *get_commit_referen object->flags |= flags; if (parse_commit(commit) < 0) die("unable to parse commit %s", name); - if (flags & UNINTERESTING) + if ((flags & UNINTERESTING) && commit->parents) mark_parents_uninteresting(commit); + mark_bound_commits(commit, flags); return commit; }
--
1.1.4.g5a4c