{"thread":{"id":"26094","subject":"[PATCH] Make rev-list --objects work together with pathspecs","startedAt":"2010-12-17T13:26:47Z","lastAt":"2010-12-17T13:26:47Z","messageCount":1,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"158281","messageId":"1292592407-26645-1-git-send-email-pclouds@gmail.com","threadId":"26094","inReplyTo":null,"subject":"[PATCH] Make rev-list --objects work together with pathspecs","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-12-17T13:26:47Z","receivedAt":"2010-12-17T13:26:47Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"From: Elijah Newren <newren@gmail.com>\n\nWhen traversing commits, the selection of commits would heed the list of\npathspecs passed, but subsequent walking of the trees of those commits\nwould not.  This resulted in 'rev-list --objects HEAD -- <paths>'\ndisplaying objects at unwanted paths.\n\nHave process_tree() call tree_entry_interesting() to determine which paths\nare interesting and should be walked.\n\nNaturally, this change can provide a large speedup when paths are specified\ntogether with --objects, since many tree entries are now correctly ignored.\nInterestingly, though, this change also gives me a small (~1%) but\nrepeatable speedup even when no paths are specified with --objects.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Replacement for 1/2 of en/object-list-with-pathspec, on top of\n nd/struct-pathspec v2 and followup patches.\n\n Note that I dropped path_name() changes.\n\n list-objects.c |   30 ++++++++++++++++++++++++++++--\n 1 files changed, 28 insertions(+), 2 deletions(-)\n\ndiff --git a/list-objects.c b/list-objects.c\nindex 8953548..61f6cc9 100644\n--- a/list-objects.c\n+++ b/list-objects.c\n@@ -61,12 +61,15 @@ static void process_tree(struct rev_info *revs,\n \t\t\t struct tree *tree,\n \t\t\t show_object_fn show,\n \t\t\t struct name_path *path,\n+\t\t\t struct strbuf *base,\n \t\t\t const char *name)\n {\n \tstruct object *obj = &tree->object;\n \tstruct tree_desc desc;\n \tstruct name_entry entry;\n \tstruct name_path me;\n+\tint all_interesting = (revs->diffopt.pathspec.nr == 0);\n+\tint baselen = base->len;\n \n \tif (!revs->tree_objects)\n \t\treturn;\n@@ -82,13 +85,32 @@ static void process_tree(struct rev_info *revs,\n \tme.elem = name;\n \tme.elem_len = strlen(name);\n \n+\tif (!all_interesting) {\n+\t\tstrbuf_addstr(base, name);\n+\t\tif (base->len)\n+\t\t\tstrbuf_addch(base, '/');\n+\t}\n+\n \tinit_tree_desc(&desc, tree->buffer, tree->size);\n \n \twhile (tree_entry(&desc, &entry)) {\n+\t\tif (!all_interesting) {\n+\t\t\tint showit = tree_entry_interesting(&entry,\n+\t\t\t\t\t\t\t    base, 0,\n+\t\t\t\t\t\t\t    &revs->diffopt.pathspec);\n+\n+\t\t\tif (showit < 0)\n+\t\t\t\tbreak;\n+\t\t\telse if (!showit)\n+\t\t\t\tcontinue;\n+\t\t\telse if (showit == 2)\n+\t\t\t\tall_interesting = 1;\n+\t\t}\n+\n \t\tif (S_ISDIR(entry.mode))\n \t\t\tprocess_tree(revs,\n \t\t\t\t     lookup_tree(entry.sha1),\n-\t\t\t\t     show, &me, entry.path);\n+\t\t\t\t     show, &me, base, entry.path);\n \t\telse if (S_ISGITLINK(entry.mode))\n \t\t\tprocess_gitlink(revs, entry.sha1,\n \t\t\t\t\tshow, &me, entry.path);\n@@ -97,6 +119,7 @@ static void process_tree(struct rev_info *revs,\n \t\t\t\t     lookup_blob(entry.sha1),\n \t\t\t\t     show, &me, entry.path);\n \t}\n+\tstrbuf_setlen(base, baselen);\n \tfree(tree->buffer);\n \ttree->buffer = NULL;\n }\n@@ -146,7 +169,9 @@ void traverse_commit_list(struct rev_info *revs,\n {\n \tint i;\n \tstruct commit *commit;\n+\tstruct strbuf base;\n \n+\tstrbuf_init(&base, PATH_MAX);\n \twhile ((commit = get_revision(revs)) != NULL) {\n \t\tadd_pending_tree(revs, commit->tree);\n \t\tshow_commit(commit, data);\n@@ -164,7 +189,7 @@ void traverse_commit_list(struct rev_info *revs,\n \t\t}\n \t\tif (obj->type == OBJ_TREE) {\n \t\t\tprocess_tree(revs, (struct tree *)obj, show_object,\n-\t\t\t\t     NULL, name);\n+\t\t\t\t     NULL, &base, name);\n \t\t\tcontinue;\n \t\t}\n \t\tif (obj->type == OBJ_BLOB) {\n@@ -181,4 +206,5 @@ void traverse_commit_list(struct rev_info *revs,\n \t\trevs->pending.alloc = 0;\n \t\trevs->pending.objects = NULL;\n \t}\n+\tstrbuf_release(&base);\n }\n-- \n1.7.3.3.476.g10a82\n"}]}