{"thread":{"id":"20869","subject":"[PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","startedAt":"2009-09-07T14:11:48Z","lastAt":"2009-10-27T21:11:21Z","messageCount":8,"participants":["Nick Edelen","Shawn O. Pearce","Chris Johnsen","Thomas Rast"],"isPatch":true,"patchVersion":4,"patchTotal":6},"messages":[{"id":"122627","messageId":"op.uzv4dyuotdk399@sirnot.private","threadId":"20869","inReplyTo":null,"subject":"[PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Nick Edelen","fromEmail":"sirnot@gmail.com","sentAt":"2009-09-07T14:11:48Z","receivedAt":"2009-09-07T14:11:48Z","isPatch":true,"sender":{"key":"sirnot@gmail.com","avatar":null},"body":"Adds support for graft commits in rev-cache (w/ test), and slightly alters\ngraft mechanism.  Before, parse_commit() checked the graft list on every\ncommit.  Now register_commit_graft() preemptively loads graft commits into\nmemory, and sets a new 'graft' flag in the object.  This allows awareness of\nthe commits' medical history without searching a (normally private) array upon\neach commit.\n\nSigned-off-by: Nick Edelen <sirnot@gmail.com>\n\n---\nTHE PATCH THAT NEVER WAS!  (sorry about the wack numbering; the change isn't\nvery big and it seemed silly to escalate the version)\n\n builtin-rev-cache.c       |   14 ++++++++++++--\n commit.c                  |   25 +++++++++++++++++++++++--\n object.h                  |    3 ++-\n rev-cache.c               |   32 ++++++++++++++++++++++++++++++++\n t/t6017-rev-cache-list.sh |    6 ++++++\n 5 files changed, 75 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-rev-cache.c b/builtin-rev-cache.c\nindex 4c1766d..b36bc39 100644\n--- a/builtin-rev-cache.c\n+++ b/builtin-rev-cache.c\n@@ -102,8 +102,18 @@ static int test_rev_list(int argc, const char *argv[])\n \t\t\tflags ^= UNINTERESTING;\n \t\telse if (!strcmp(argv[i], \"--objects\"))\n \t\t\trevs.tree_objects = revs.blob_objects = 1;\n-\t\telse\n-\t\t\thandle_revision_arg(argv[i], &revs, flags, 1);\n+\t\telse {\n+\t\t\tstruct commit_graft graft;\n+\n+\t\t\tif (argv[i][0] == ':') {\n+\t\t\t\thandle_revision_arg(argv[i] + 1, &revs, flags, 1);\n+\n+\t\t\t\thashcpy(graft.sha1, revs.pending.objects[revs.pending.nr - 1].item->sha1);\n+\t\t\t\tgraft.nr_parent = -1;\n+\t\t\t\tregister_commit_graft(&graft, 0);\n+\t\t\t} else\n+\t\t\t\thandle_revision_arg(argv[i], &revs, flags, 1);\n+\t\t}\n \t}\n \n \tsetup_revisions(0, 0, &revs, 0);\ndiff --git a/commit.c b/commit.c\nindex b7485c4..8429f69 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -99,6 +99,7 @@ static int commit_graft_pos(const unsigned char *sha1)\n \n int register_commit_graft(struct commit_graft *graft, int ignore_dups)\n {\n+\tstruct commit *commit;\n \tint pos = commit_graft_pos(graft->sha1);\n \n \tif (0 <= pos) {\n@@ -123,6 +124,12 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups)\n \t\t\t(commit_graft_nr - pos - 1) *\n \t\t\tsizeof(*commit_graft));\n \tcommit_graft[pos] = graft;\n+\n+\tcommit = lookup_commit(graft->sha1);\n+\tcommit->object.graft = 1;\n+\tcommit->object.parsed = 0;\n+\tparse_commit(commit); /* in case commit was already parsed */\n+\n \treturn 0;\n }\n \n@@ -221,6 +228,7 @@ int write_shallow_commits(int fd, int use_pack_protocol)\n \n int unregister_shallow(const unsigned char *sha1)\n {\n+\tstruct commit *commit;\n \tint pos = commit_graft_pos(sha1);\n \tif (pos < 0)\n \t\treturn -1;\n@@ -229,6 +237,12 @@ int unregister_shallow(const unsigned char *sha1)\n \t\t\t\tsizeof(struct commit_graft *)\n \t\t\t\t* (commit_graft_nr - pos - 1));\n \tcommit_graft_nr--;\n+\n+\tcommit = lookup_commit(sha1);\n+\tcommit->object.graft = 0;\n+\tcommit->object.parsed = 0;\n+\tparse_commit(commit);\n+\n \treturn 0;\n }\n \n@@ -255,7 +269,11 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n \twhile (pop_commit(pptr))\n \t\t; /* clear anything from cache */\n \n-\tgraft = lookup_commit_graft(item->object.sha1);\n+\tif (item->object.graft)\n+\t\tgraft = lookup_commit_graft(item->object.sha1);\n+\telse\n+\t\tgraft = 0;\n+\n \twhile (bufptr + 48 < tail && !memcmp(bufptr, \"parent \", 7)) {\n \t\tstruct commit *new_parent;\n \n@@ -283,7 +301,10 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n \t\t\t\tcontinue;\n \t\t\tpptr = &commit_list_insert(new_parent, pptr)->next;\n \t\t}\n-\t}\n+\t\titem->object.graft = 1;\n+\t} else\n+\t\titem->object.graft = 0;\n+\n \titem->date = parse_commit_date(bufptr, tail);\n \n \treturn 0;\ndiff --git a/object.h b/object.h\nindex 89dd0c4..f848e0f 100644\n--- a/object.h\n+++ b/object.h\n@@ -22,7 +22,7 @@ struct object_array {\n };\n \n #define TYPE_BITS   3\n-#define FLAG_BITS  27\n+#define FLAG_BITS  26\n \n /*\n  * The object type is stored in 3 bits.\n@@ -30,6 +30,7 @@ struct object_array {\n struct object {\n \tunsigned parsed : 1;\n \tunsigned used : 1;\n+\tunsigned graft : 1;\n \tunsigned type : TYPE_BITS;\n \tunsigned flags : FLAG_BITS;\n \tunsigned char sha1[20];\ndiff --git a/rev-cache.c b/rev-cache.c\nindex 3595f66..84305e9 100644\n--- a/rev-cache.c\n+++ b/rev-cache.c\n@@ -663,9 +663,41 @@ static int traverse_cache_slice_1(struct rc_slice_header *head, unsigned char *m\n \t\t\t}\n \t\t} else if (!ipath_nr && co->date <= date)\n \t\t\tslop--;\n+\t\telse if (!ipath_nr && !upath_nr)\n+\t\t\tbreak;\n \t\telse\n \t\t\tslop = SLOP;\n \n+\t\t/* before opening further topo-relations, check if the parenting has had medical attention */\n+\t\tif (obj->graft) {\n+\t\t\tstruct commit_list *list;\n+\n+\t\t\tparse_commit(co);\n+\t\t\tobj->flags &= ~FACE_VALUE;\n+\t\t\tlast_objects[path] = 0;\n+\n+\t\t\t/* we're only interested in its indirect influence */\n+\t\t\tfor (list = co->parents; list; list = list->next) {\n+\t\t\t\tstruct rc_index_entry *iep;\n+\t\t\t\tstruct object *po = &list->item->object;\n+\n+\t\t\t\tiep = search_index(po->sha1);\n+\t\t\t\tif (!iep || hashcmp(idx_caches + 20 * iep->cache_index, head->sha1)) {\n+\t\t\t\t\tif (!(obj->flags & UNINTERESTING) && !(po->flags & UNINTERESTING))\n+\t\t\t\t\t\tioutside = 1;\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\t/* an abrupt end */\n+\t\t\tmyworkp = &commit_list_insert(co, myworkp)->next;\n+\t\t\tif (entry->uninteresting)\n+\t\t\t\tupath_nr--;\n+\t\t\telse\n+\t\t\t\tipath_nr--;\n+\t\t\tpaths[path] = 0;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\t/* open parents */\n \t\tif (entry->merge_nr) {\n \t\t\tint j, off = index + sizeof(struct rc_object_entry_ondisk);\ndiff --git a/t/t6017-rev-cache-list.sh b/t/t6017-rev-cache-list.sh\nindex 3286560..6ada7ac 100755\n--- a/t/t6017-rev-cache-list.sh\n+++ b/t/t6017-rev-cache-list.sh\n@@ -92,6 +92,7 @@ git-rev-list --topo-order HEAD --not HEAD~2 >proper_commit_list_limited2\n git-rev-list --topo-order HEAD >proper_commit_list\n git-rev-list --objects HEAD >proper_object_list\n git-rev-list HEAD --max-age=$min_date --min-age=$max_date >proper_list_date_limited\n+git-rev-cache test HEAD :HEAD~2 >proper_shallow_list\n \n cache_sha1=`git-rev-cache add HEAD 2>output.err`\n \n@@ -252,4 +253,9 @@ test_expect_success 'test --ignore-size function in fuse' '\n \ttest -e .git/rev-cache/$cache_sha1\n '\n \n+test_expect_success 'check graft handling' '\n+\tgit-rev-cache test HEAD :HEAD~2 >list\n+\ttest_cmp list proper_shallow_list\n+'\n+\n test_done\n-- \ntg: (3a6aad2..) t/revcache/graft (depends on: t/revcache/names)\n"},{"id":"123909","messageId":"op.u0xtfzjrtdk399@sirnot.ed.ac.uk","threadId":"20869","inReplyTo":"op.uzv4dyuotdk399@sirnot.private","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Nick Edelen","fromEmail":"sirnot@gmail.com","sentAt":"2009-09-27T22:44:13Z","receivedAt":"2009-09-27T22:44:13Z","isPatch":true,"sender":{"key":"sirnot@gmail.com","avatar":null},"body":"Adds support for graft commits in rev-cache (w/ test), and slightly alters\ngraft mechanism.  Before, parse_commit() checked the graft list on every\ncommit.  Now register_commit_graft() preemptively loads graft commits into\nmemory, and sets a new 'graft' flag in the object.  This allows awareness of\nthe commits' medical history without searching a (normally private) array upon\neach commit.\n\nSigned-off-by: Nick Edelen <sirnot@gmail.com>\n\n---\nIn my infinite wisdom, I had forgotten to actually load the graft file in the\nmechanism change.  This rectifies the error, fixing test t6001-rev-list-graft.\n(this was the only test that I found rev-cache to break; if you find others\nplease tell me!)\n\n  builtin-rev-cache.c       |   14 ++++++++++++--\n  commit.c                  |   27 +++++++++++++++++++++++++--\n  object.h                  |    3 ++-\n  rev-cache.c               |   32 ++++++++++++++++++++++++++++++++\n  t/t6017-rev-cache-list.sh |    6 ++++++\n  5 files changed, 77 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-rev-cache.c b/builtin-rev-cache.c\nindex 4c1766d..b36bc39 100644\n--- a/builtin-rev-cache.c\n+++ b/builtin-rev-cache.c\n@@ -102,8 +102,18 @@ static int test_rev_list(int argc, const char *argv[])\n  \t\t\tflags ^= UNINTERESTING;\n  \t\telse if (!strcmp(argv[i], \"--objects\"))\n  \t\t\trevs.tree_objects = revs.blob_objects = 1;\n-\t\telse\n-\t\t\thandle_revision_arg(argv[i], &revs, flags, 1);\n+\t\telse {\n+\t\t\tstruct commit_graft graft;\n+\n+\t\t\tif (argv[i][0] == ':') {\n+\t\t\t\thandle_revision_arg(argv[i] + 1, &revs, flags, 1);\n+\n+\t\t\t\thashcpy(graft.sha1, revs.pending.objects[revs.pending.nr - 1].item->sha1);\n+\t\t\t\tgraft.nr_parent = -1;\n+\t\t\t\tregister_commit_graft(&graft, 0);\n+\t\t\t} else\n+\t\t\t\thandle_revision_arg(argv[i], &revs, flags, 1);\n+\t\t}\n  \t}\n\n  \tsetup_revisions(0, 0, &revs, 0);\ndiff --git a/commit.c b/commit.c\nindex b7485c4..dd0e3ca 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -99,6 +99,7 @@ static int commit_graft_pos(const unsigned char *sha1)\n\n  int register_commit_graft(struct commit_graft *graft, int ignore_dups)\n  {\n+\tstruct commit *commit;\n  \tint pos = commit_graft_pos(graft->sha1);\n\n  \tif (0 <= pos) {\n@@ -123,6 +124,12 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups)\n  \t\t\t(commit_graft_nr - pos - 1) *\n  \t\t\tsizeof(*commit_graft));\n  \tcommit_graft[pos] = graft;\n+\n+\tcommit = lookup_commit(graft->sha1);\n+\tcommit->object.graft = 1;\n+\tcommit->object.parsed = 0;\n+\tparse_commit(commit); /* in case commit was already parsed */\n+\n  \treturn 0;\n  }\n\n@@ -221,6 +228,7 @@ int write_shallow_commits(int fd, int use_pack_protocol)\n\n  int unregister_shallow(const unsigned char *sha1)\n  {\n+\tstruct commit *commit;\n  \tint pos = commit_graft_pos(sha1);\n  \tif (pos < 0)\n  \t\treturn -1;\n@@ -229,6 +237,12 @@ int unregister_shallow(const unsigned char *sha1)\n  \t\t\t\tsizeof(struct commit_graft *)\n  \t\t\t\t* (commit_graft_nr - pos - 1));\n  \tcommit_graft_nr--;\n+\n+\tcommit = lookup_commit(sha1);\n+\tcommit->object.graft = 0;\n+\tcommit->object.parsed = 0;\n+\tparse_commit(commit);\n+\n  \treturn 0;\n  }\n\n@@ -255,7 +269,13 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n  \twhile (pop_commit(pptr))\n  \t\t; /* clear anything from cache */\n\n-\tgraft = lookup_commit_graft(item->object.sha1);\n+\t/* make sure .graft flag is initialized */\n+\tprepare_commit_graft();\n+\tif (item->object.graft)\n+\t\tgraft = lookup_commit_graft(item->object.sha1);\n+\telse\n+\t\tgraft = 0;\n+\n  \twhile (bufptr + 48 < tail && !memcmp(bufptr, \"parent \", 7)) {\n  \t\tstruct commit *new_parent;\n\n@@ -283,7 +303,10 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n  \t\t\t\tcontinue;\n  \t\t\tpptr = &commit_list_insert(new_parent, pptr)->next;\n  \t\t}\n-\t}\n+\t\titem->object.graft = 1;\n+\t} else\n+\t\titem->object.graft = 0;\n+\n  \titem->date = parse_commit_date(bufptr, tail);\n\n  \treturn 0;\ndiff --git a/object.h b/object.h\nindex 89dd0c4..f848e0f 100644\n--- a/object.h\n+++ b/object.h\n@@ -22,7 +22,7 @@ struct object_array {\n  };\n\n  #define TYPE_BITS   3\n-#define FLAG_BITS  27\n+#define FLAG_BITS  26\n\n  /*\n   * The object type is stored in 3 bits.\n@@ -30,6 +30,7 @@ struct object_array {\n  struct object {\n  \tunsigned parsed : 1;\n  \tunsigned used : 1;\n+\tunsigned graft : 1;\n  \tunsigned type : TYPE_BITS;\n  \tunsigned flags : FLAG_BITS;\n  \tunsigned char sha1[20];\ndiff --git a/rev-cache.c b/rev-cache.c\nindex 6c96297..f7b1cd2 100644\n--- a/rev-cache.c\n+++ b/rev-cache.c\n@@ -664,9 +664,41 @@ static int traverse_cache_slice_1(struct rc_slice_header *head, unsigned char *m\n  \t\t\t}\n  \t\t} else if (!ipath_nr && co->date <= date)\n  \t\t\tslop--;\n+\t\telse if (!ipath_nr && !upath_nr)\n+\t\t\tbreak;\n  \t\telse\n  \t\t\tslop = SLOP;\n\n+\t\t/* before opening further topo-relations, check if the parenting has had medical attention */\n+\t\tif (obj->graft) {\n+\t\t\tstruct commit_list *list;\n+\n+\t\t\tparse_commit(co);\n+\t\t\tobj->flags &= ~FACE_VALUE;\n+\t\t\tlast_objects[path] = 0;\n+\n+\t\t\t/* we're only interested in its indirect influence */\n+\t\t\tfor (list = co->parents; list; list = list->next) {\n+\t\t\t\tstruct rc_index_entry *iep;\n+\t\t\t\tstruct object *po = &list->item->object;\n+\n+\t\t\t\tiep = search_index(po->sha1);\n+\t\t\t\tif (!iep || hashcmp(idx_caches + 20 * iep->cache_index, head->sha1)) {\n+\t\t\t\t\tif (!(obj->flags & UNINTERESTING) && !(po->flags & UNINTERESTING))\n+\t\t\t\t\t\tioutside = 1;\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\t/* an abrupt end */\n+\t\t\tmyworkp = &commit_list_insert(co, myworkp)->next;\n+\t\t\tif (entry->uninteresting)\n+\t\t\t\tupath_nr--;\n+\t\t\telse\n+\t\t\t\tipath_nr--;\n+\t\t\tpaths[path] = 0;\n+\t\t\tcontinue;\n+\t\t}\n+\n  \t\t/* open parents */\n  \t\tif (entry->merge_nr) {\n  \t\t\tint j, off = index + sizeof(struct rc_object_entry_ondisk);\ndiff --git a/t/t6017-rev-cache-list.sh b/t/t6017-rev-cache-list.sh\nindex 3286560..6ada7ac 100755\n--- a/t/t6017-rev-cache-list.sh\n+++ b/t/t6017-rev-cache-list.sh\n@@ -92,6 +92,7 @@ git-rev-list --topo-order HEAD --not HEAD~2 >proper_commit_list_limited2\n  git-rev-list --topo-order HEAD >proper_commit_list\n  git-rev-list --objects HEAD >proper_object_list\n  git-rev-list HEAD --max-age=$min_date --min-age=$max_date >proper_list_date_limited\n+git-rev-cache test HEAD :HEAD~2 >proper_shallow_list\n\n  cache_sha1=`git-rev-cache add HEAD 2>output.err`\n\n@@ -252,4 +253,9 @@ test_expect_success 'test --ignore-size function in fuse' '\n  \ttest -e .git/rev-cache/$cache_sha1\n  '\n\n+test_expect_success 'check graft handling' '\n+\tgit-rev-cache test HEAD :HEAD~2 >list\n+\ttest_cmp list proper_shallow_list\n+'\n+\n  test_done\n-- \ntg: (ceb0b39..) t/revcache/graft (depends on: t/revcache/names)\n"},{"id":"124001","messageId":"20090929163414.GA25756@spearce.org","threadId":"20869","inReplyTo":"op.u0xtfzjrtdk399@sirnot.ed.ac.uk","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-09-29T16:34:14Z","receivedAt":"2009-09-29T16:34:14Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Nick Edelen <sirnot@gmail.com> wrote:\n> Adds support for graft commits in rev-cache (w/ test), and slightly alters\n> graft mechanism.  Before, parse_commit() checked the graft list on every\n> commit.  Now register_commit_graft() preemptively loads graft commits into\n> memory, and sets a new 'graft' flag in the object.  This allows awareness of\n> the commits' medical history without searching a (normally private) array upon\n> each commit.\n...\n> diff --git a/builtin-rev-cache.c b/builtin-rev-cache.c\n> index 4c1766d..b36bc39 100644\n\nThis doesn't apply against ne/rev-cache^, and I don't have the\nblobs in my repostiory.  So I'm dropping this patch and will wait\nfor a resend of the series or something...\n\n-- \nShawn.\n"},{"id":"124022","messageId":"A32FCFC6-13E2-4A9D-88FB-01ED47FE88AA@pobox.com","threadId":"20869","inReplyTo":"20090929163414.GA25756@spearce.org","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Chris Johnsen","fromEmail":"chris_johnsen@pobox.com","sentAt":"2009-09-30T08:00:19Z","receivedAt":"2009-09-30T08:00:19Z","isPatch":true,"sender":{"key":"chris_johnsen@pobox.com","avatar":"https://avatars.githubusercontent.com/u/107071?v=4"},"body":"On 2009 Sep 29, at 11:34, Shawn O. Pearce wrote:\n> Nick Edelen <sirnot@gmail.com> wrote:\n>> diff --git a/builtin-rev-cache.c b/builtin-rev-cache.c\n>> index 4c1766d..b36bc39 100644\n>\n> This doesn't apply against ne/rev-cache^, and I don't have the\n> blobs in my repostiory.  So I'm dropping this patch and will wait\n> for a resend of the series or something...\n\nIt appears that the patch suffers from \"format=flowed\" whitespace\nmangling. This caused the context lines to have an extra leading\nspace character.\n\nAfter running a ham-fisted \"sed -e 's/^  / /'\" over the patch,\n'git am' was able to apply it to ne/rev-cache^ (d05c9be9fa) even\nthough one of the referenced blobs (6c96297; rev-cache.c) was missing.\n\n-- \nChris\n"},{"id":"125422","messageId":"4ADCCCA9.4000802@gmail.com","threadId":"20869","inReplyTo":"op.uzv4dyuotdk399@sirnot.private","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Nick Edelen","fromEmail":"sirnot@gmail.com","sentAt":"2009-10-19T20:31:37Z","receivedAt":"2009-10-19T20:31:37Z","isPatch":true,"sender":{"key":"sirnot@gmail.com","avatar":null},"body":"Adds support for graft commits in rev-cache (w/ test), and slightly alters\ngraft mechanism.  Before, parse_commit() checked the graft list on every\ncommit.  Now register_commit_graft() preemptively loads graft commits into\nmemory, and sets a new 'graft' flag in the object.  This allows awareness of\nthe commits' medical history without searching a (normally private) array upon\neach commit.\n\nSigned-off-by: Nick Edelen <sirnot@gmail.com>\n\n---\nfixed bug in mechanism alteration, which was causing test t6001 to fail.\n\n builtin-rev-cache.c       |   14 ++++++++++++--\n commit.c                  |   27 +++++++++++++++++++++++++--\n object.h                  |    3 ++-\n rev-cache.c               |   32 ++++++++++++++++++++++++++++++++\n t/t6017-rev-cache-list.sh |    6 ++++++\n 5 files changed, 77 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-rev-cache.c b/builtin-rev-cache.c\nindex 4c1766d..b36bc39 100644\n--- a/builtin-rev-cache.c\n+++ b/builtin-rev-cache.c\n@@ -102,8 +102,18 @@ static int test_rev_list(int argc, const char *argv[])\n \t\t\tflags ^= UNINTERESTING;\n \t\telse if (!strcmp(argv[i], \"--objects\"))\n \t\t\trevs.tree_objects = revs.blob_objects = 1;\n-\t\telse\n-\t\t\thandle_revision_arg(argv[i], &revs, flags, 1);\n+\t\telse {\n+\t\t\tstruct commit_graft graft;\n+\n+\t\t\tif (argv[i][0] == ':') {\n+\t\t\t\thandle_revision_arg(argv[i] + 1, &revs, flags, 1);\n+\n+\t\t\t\thashcpy(graft.sha1, revs.pending.objects[revs.pending.nr - 1].item->sha1);\n+\t\t\t\tgraft.nr_parent = -1;\n+\t\t\t\tregister_commit_graft(&graft, 0);\n+\t\t\t} else\n+\t\t\t\thandle_revision_arg(argv[i], &revs, flags, 1);\n+\t\t}\n \t}\n \n \tsetup_revisions(0, 0, &revs, 0);\ndiff --git a/commit.c b/commit.c\nindex 61d83c6..c227748 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -99,6 +99,7 @@ static int commit_graft_pos(const unsigned char *sha1)\n \n int register_commit_graft(struct commit_graft *graft, int ignore_dups)\n {\n+\tstruct commit *commit;\n \tint pos = commit_graft_pos(graft->sha1);\n \n \tif (0 <= pos) {\n@@ -123,6 +124,12 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups)\n \t\t\t(commit_graft_nr - pos - 1) *\n \t\t\tsizeof(*commit_graft));\n \tcommit_graft[pos] = graft;\n+\n+\tcommit = lookup_commit(graft->sha1);\n+\tcommit->object.graft = 1;\n+\tcommit->object.parsed = 0;\n+\tparse_commit(commit); /* in case commit was already parsed */\n+\n \treturn 0;\n }\n \n@@ -221,6 +228,7 @@ int write_shallow_commits(int fd, int use_pack_protocol)\n \n int unregister_shallow(const unsigned char *sha1)\n {\n+\tstruct commit *commit;\n \tint pos = commit_graft_pos(sha1);\n \tif (pos < 0)\n \t\treturn -1;\n@@ -229,6 +237,12 @@ int unregister_shallow(const unsigned char *sha1)\n \t\t\t\tsizeof(struct commit_graft *)\n \t\t\t\t* (commit_graft_nr - pos - 1));\n \tcommit_graft_nr--;\n+\n+\tcommit = lookup_commit(sha1);\n+\tcommit->object.graft = 0;\n+\tcommit->object.parsed = 0;\n+\tparse_commit(commit);\n+\n \treturn 0;\n }\n \n@@ -255,7 +269,13 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n \twhile (pop_commit(pptr))\n \t\t; /* clear anything from cache */\n \n-\tgraft = lookup_commit_graft(item->object.sha1);\n+\t/* make sure .graft flag is initialized */\n+\tprepare_commit_graft();\n+\tif (item->object.graft)\n+\t\tgraft = lookup_commit_graft(item->object.sha1);\n+\telse\n+\t\tgraft = 0;\n+\n \twhile (bufptr + 48 < tail && !memcmp(bufptr, \"parent \", 7)) {\n \t\tstruct commit *new_parent;\n \n@@ -283,7 +303,10 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n \t\t\t\tcontinue;\n \t\t\tpptr = &commit_list_insert(new_parent, pptr)->next;\n \t\t}\n-\t}\n+\t\titem->object.graft = 1;\n+\t} else\n+\t\titem->object.graft = 0;\n+\n \titem->date = parse_commit_date(bufptr, tail);\n \n \treturn 0;\ndiff --git a/object.h b/object.h\nindex 89dd0c4..f848e0f 100644\n--- a/object.h\n+++ b/object.h\n@@ -22,7 +22,7 @@ struct object_array {\n };\n \n #define TYPE_BITS   3\n-#define FLAG_BITS  27\n+#define FLAG_BITS  26\n \n /*\n  * The object type is stored in 3 bits.\n@@ -30,6 +30,7 @@ struct object_array {\n struct object {\n \tunsigned parsed : 1;\n \tunsigned used : 1;\n+\tunsigned graft : 1;\n \tunsigned type : TYPE_BITS;\n \tunsigned flags : FLAG_BITS;\n \tunsigned char sha1[20];\ndiff --git a/rev-cache.c b/rev-cache.c\nindex 6c96297..f7b1cd2 100644\n--- a/rev-cache.c\n+++ b/rev-cache.c\n@@ -664,9 +664,41 @@ static int traverse_cache_slice_1(struct rc_slice_header *head, unsigned char *m\n \t\t\t}\n \t\t} else if (!ipath_nr && co->date <= date)\n \t\t\tslop--;\n+\t\telse if (!ipath_nr && !upath_nr)\n+\t\t\tbreak;\n \t\telse\n \t\t\tslop = SLOP;\n \n+\t\t/* before opening further topo-relations, check if the parenting has had medical attention */\n+\t\tif (obj->graft) {\n+\t\t\tstruct commit_list *list;\n+\n+\t\t\tparse_commit(co);\n+\t\t\tobj->flags &= ~FACE_VALUE;\n+\t\t\tlast_objects[path] = 0;\n+\n+\t\t\t/* we're only interested in its indirect influence */\n+\t\t\tfor (list = co->parents; list; list = list->next) {\n+\t\t\t\tstruct rc_index_entry *iep;\n+\t\t\t\tstruct object *po = &list->item->object;\n+\n+\t\t\t\tiep = search_index(po->sha1);\n+\t\t\t\tif (!iep || hashcmp(idx_caches + 20 * iep->cache_index, head->sha1)) {\n+\t\t\t\t\tif (!(obj->flags & UNINTERESTING) && !(po->flags & UNINTERESTING))\n+\t\t\t\t\t\tioutside = 1;\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\t/* an abrupt end */\n+\t\t\tmyworkp = &commit_list_insert(co, myworkp)->next;\n+\t\t\tif (entry->uninteresting)\n+\t\t\t\tupath_nr--;\n+\t\t\telse\n+\t\t\t\tipath_nr--;\n+\t\t\tpaths[path] = 0;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\t/* open parents */\n \t\tif (entry->merge_nr) {\n \t\t\tint j, off = index + sizeof(struct rc_object_entry_ondisk);\ndiff --git a/t/t6017-rev-cache-list.sh b/t/t6017-rev-cache-list.sh\nindex f0f3bcf..3e16949 100755\n--- a/t/t6017-rev-cache-list.sh\n+++ b/t/t6017-rev-cache-list.sh\n@@ -92,6 +92,7 @@ git-rev-list --topo-order HEAD --not HEAD~2 >proper_commit_list_limited2\n git-rev-list --topo-order HEAD >proper_commit_list\n git-rev-list --objects HEAD >proper_object_list\n git-rev-list HEAD --max-age=$min_date --min-age=$max_date >proper_list_date_limited\n+git-rev-cache test HEAD :HEAD~2 >proper_shallow_list 2>/dev/null\n \n cache_sha1=`git-rev-cache add HEAD 2>output.err`\n \n@@ -252,4 +253,9 @@ test_expect_success 'test --ignore-size function in fuse' '\n \ttest -e .git/rev-cache/$cache_sha1\n '\n \n+test_expect_success 'check graft handling' '\n+\tgit-rev-cache test HEAD :HEAD~2 >list\n+\ttest_cmp list proper_shallow_list\n+'\n+\n test_done\n-- \ntg: (52c9694..) t/revcache/graft (depends on: t/revcache/names)\n"},{"id":"125582","messageId":"200910211115.25017.trast@student.ethz.ch","threadId":"20869","inReplyTo":"4ADCCCA9.4000802@gmail.com","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2009-10-21T09:15:17Z","receivedAt":"2009-10-21T09:15:17Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Nick Edelen wrote:\n> Adds support for graft commits in rev-cache (w/ test), and slightly alters\n> graft mechanism.  Before, parse_commit() checked the graft list on every\n> commit.  Now register_commit_graft() preemptively loads graft commits into\n> memory, and sets a new 'graft' flag in the object.  This allows awareness of\n> the commits' medical history without searching a (normally private) array upon\n> each commit.\n\nI felt adventurous and merged the topic into my local build, but I get\n\"error: duplicate graft data ...\" in repositories with only a single\nline in .git/info/grafts, which bisects to this commit (1c0a666 in\ntoday's pu).\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"125597","messageId":"200910211544.08776.trast@student.ethz.ch","threadId":"20869","inReplyTo":"200910211115.25017.trast@student.ethz.ch","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2009-10-21T13:44:07Z","receivedAt":"2009-10-21T13:44:07Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Thomas Rast wrote:\n> Nick Edelen wrote:\n> > Adds support for graft commits in rev-cache (w/ test), and slightly alters\n> > graft mechanism.  Before, parse_commit() checked the graft list on every\n> > commit.  Now register_commit_graft() preemptively loads graft commits into\n> > memory, and sets a new 'graft' flag in the object.  This allows awareness of\n> > the commits' medical history without searching a (normally private) array upon\n> > each commit.\n> \n> I felt adventurous and merged the topic into my local build, but I get\n> \"error: duplicate graft data ...\" in repositories with only a single\n> line in .git/info/grafts, which bisects to this commit (1c0a666 in\n> today's pu).\n\nHere's the complaint in squashable form if you want to keep it as a\ntestcase:\n\ndiff --git i/t/t6001-rev-list-graft.sh w/t/t6001-rev-list-graft.sh\nindex b2131cd..49ba37b 100755\n--- i/t/t6001-rev-list-graft.sh\n+++ w/t/t6001-rev-list-graft.sh\n@@ -110,4 +110,18 @@ do\n \t\"\n \n done\n+\n+duplicate_error=\"error: duplicate graft\"\n+\n+test_expect_success 'duplicates: no false positives' '\n+\techo $B0 $A2 > .git/info/grafts &&\n+\t! git rev-list -1 HEAD 2>&1 | grep -q \"$duplicate_error\"\n+'\n+\n+test_expect_success 'duplicates: no false negatives' '\n+\techo $B0 $A2 > .git/info/grafts &&\n+\techo $B0 $A1 >> .git/info/grafts &&\n+\tgit rev-list -1 HEAD 2>&1 | grep \"$duplicate_error\"\n+'\n+\n test_done\n\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"126060","messageId":"c77435a80910271411y5cb0e8d6u59be909b2a44c54a@mail.gmail.com","threadId":"20869","inReplyTo":"200910211115.25017.trast@student.ethz.ch","subject":"Re: [PATCH 7/6 (v4)] support for commit grafts, slight change to general mechanism","fromName":"Nick Edelen","fromEmail":"sirnot@gmail.com","sentAt":"2009-10-27T21:11:21Z","receivedAt":"2009-10-27T21:11:21Z","isPatch":true,"sender":{"key":"sirnot@gmail.com","avatar":null},"body":"> I felt adventurous and merged the topic into my local build, but I get\n> \"error: duplicate graft data ...\" in repositories with only a single\n> line in .git/info/grafts, which bisects to this commit (1c0a666 in\n> today's pu).\n\nOops, it looks like there's a bug in my bugfix...  I had\nparse_commit() accidentally calling itself through\nregister_commit_graft(); fixed now though.  Thanks for giving it a try\nthough!\n"}]}