{"thread":{"id":"3116","subject":"[PATCH/RFC] rev-list: understand bound commits.","startedAt":"2006-01-21T08:23:14Z","lastAt":"2006-01-21T08:23:14Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"14976","messageId":"7vslrirnv1.fsf@assigned-by-dhcp.cox.net","threadId":"3116","inReplyTo":null,"subject":"[PATCH/RFC] rev-list: understand bound commits.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-01-21T08:23:14Z","receivedAt":"2006-01-21T08:23:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This adds support for \"bind\" lines in commit objects, so that\n\"rev-list --objects piped to pack-objects\" pattern can be used\nfor git native transports.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n * Linus, I would really appreciate if you can proofread and\n   comment on this patch.  I am reasonably sure that I did not\n   break things when no commit with \"bind\" lines are involved,\n   but I am not sure if this makes --objects do the right thing\n   to produce correct packs.  The goal is still to have:\n\n   $ git rev-list --objects A..B\n\n   to produce list of objects that are needed to complete B for\n   somebody who has A, taking into account the objects contained\n   in the subproject commits, while:\n\n   $ git rev-list A..B\n\n   should not worry anything about subproject commits.\n\n rev-list.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----\n 1 files changed, 61 insertions(+), 4 deletions(-)\n\ne0571c156e9abd75473c6c85e224965dae842a65\ndiff --git a/rev-list.c b/rev-list.c\nindex f2534fd..339926a 100644\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -201,6 +201,37 @@ static struct object_list **process_tree\n \treturn p;\n }\n \n+static struct object_list **process_commit_part(struct commit *, struct object_list **, const char *);\n+\n+static struct object_list **process_bound_commit(struct commit *bound, struct object_list **p, const char *name)\n+{\n+\tstruct object *obj = &bound->object;\n+\n+\tif (!list_objects)\n+\t\treturn p;\n+\tif (obj->flags & (UNINTERESTING|SEEN))\n+\t\treturn p;\n+\tif (parse_commit(bound) < 0)\n+\t\tdie(\"bad commit object %s\", sha1_to_hex(obj->sha1));\n+\tobj->flags |= SEEN;\n+\tp = add_object(obj, p, name);\n+\treturn process_commit_part(bound, p, name);\n+}\n+\n+static struct object_list **process_commit_part(struct commit *commit, struct object_list **p, const char *name)\n+{\n+\tp = process_tree(commit->tree, p, name);\n+\tif (commit->binds) {\n+\t\tstruct commit_list *bp = commit->binds;\n+\t\twhile (bp) {\n+\t\t\tstruct commit *bound = bp->item;\n+\t\t\tbp = bp->next;\n+\t\t\tp = process_bound_commit(bound, p, name);\n+\t\t}\n+\t}\n+\treturn p;\n+}\n+\n static struct object_list *pending_objects = NULL;\n \n static void show_commit_list(struct commit_list *list)\n@@ -209,7 +240,7 @@ static void show_commit_list(struct comm\n \twhile (list) {\n \t\tstruct commit *commit = pop_most_recent_commit(&list, SEEN);\n \n-\t\tp = process_tree(commit->tree, p, \"\");\n+\t\tp = process_commit_part(commit, p, \"\");\n \t\tif (process_commit(commit) == STOP)\n \t\t\tbreak;\n \t}\n@@ -231,6 +262,10 @@ static void show_commit_list(struct comm\n \t\t\tp = process_blob((struct blob *)obj, p, name);\n \t\t\tcontinue;\n \t\t}\n+\t\tif (obj->type == commit_type) {\n+\t\t\tp = process_bound_commit((struct commit *)obj, p, name);\n+\t\t\tcontinue;\n+\t\t}\n \t\tdie(\"unknown pending object %s (%s)\", sha1_to_hex(obj->sha1), name);\n \t}\n \twhile (objects) {\n@@ -285,6 +320,16 @@ static void mark_tree_uninteresting(stru\n \t}\n }\n \n+static void mark_bound_commits(struct commit *commit, int flags)\n+{\n+\tstruct commit_list *clist = commit->binds;\n+\twhile (clist) {\n+\t\tstruct commit *bound = clist->item;\n+\t\tbound->object.flags |= flags;\n+\t\tclist = clist->next;\n+\t}\n+}\n+\n static void mark_parents_uninteresting(struct commit *commit)\n {\n \tstruct commit_list *parents = commit->parents;\n@@ -305,6 +350,13 @@ static void mark_parents_uninteresting(s\n \t\t\tmark_parents_uninteresting(commit);\n \n \t\t/*\n+\t\t * Subproject commits bound to an uninteresting\n+\t\t * parent is not interesting.\n+\t\t */\n+\t\tif (commit->binds)\n+\t\t\tmark_bound_commits(commit, UNINTERESTING);\n+\n+\t\t/*\n \t\t * A missing commit is ok iff its parent is marked \n \t\t * uninteresting.\n \t\t *\n@@ -520,6 +572,7 @@ static void add_parents_to_list(struct c\n \t\t\tp->object.flags |= UNINTERESTING;\n \t\t\tif (p->parents)\n \t\t\t\tmark_parents_uninteresting(p);\n+\t\t\tmark_bound_commits(p, UNINTERESTING);\n \t\t\tif (p->object.flags & SEEN)\n \t\t\t\tcontinue;\n \t\t\tp->object.flags |= SEEN;\n@@ -599,9 +652,12 @@ static struct commit_list *limit_list(st\n \t\t\tobj->flags |= UNINTERESTING;\n \t\tif (unpacked && has_sha1_pack(obj->sha1))\n \t\t\tobj->flags |= UNINTERESTING;\n-\t\tadd_parents_to_list(commit, &list);\n+\t\tif (commit->parents)\n+\t\t\tadd_parents_to_list(commit, &list);\n \t\tif (obj->flags & UNINTERESTING) {\n-\t\t\tmark_parents_uninteresting(commit);\n+\t\t\tif (commit->parents)\n+\t\t\t\tmark_parents_uninteresting(commit);\n+\t\t\tmark_bound_commits(commit, UNINTERESTING);\n \t\t\tif (everybody_uninteresting(list))\n \t\t\t\tbreak;\n \t\t\tcontinue;\n@@ -654,8 +710,9 @@ static struct commit *get_commit_referen\n \t\tobject->flags |= flags;\n \t\tif (parse_commit(commit) < 0)\n \t\t\tdie(\"unable to parse commit %s\", name);\n-\t\tif (flags & UNINTERESTING)\n+\t\tif ((flags & UNINTERESTING) && commit->parents)\n \t\t\tmark_parents_uninteresting(commit);\n+\t\tmark_bound_commits(commit, flags);\n \t\treturn commit;\n \t}\n \n-- \n1.1.4.g5a4c\n"}]}