{"thread":{"id":"613","subject":"speeding up cg-log -u","startedAt":"2005-05-14T06:19:14Z","lastAt":"2005-05-16T15:38:58Z","messageCount":14,"participants":["Zack Brown","Junio C Hamano","Petr Baudis","Daniel Barkalow"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"3284","messageId":"20050514061914.GB14353@tumblerings.org","threadId":"613","inReplyTo":null,"subject":"speeding up cg-log -u","fromName":"Zack Brown","fromEmail":"zbrown@tumblerings.org","sentAt":"2005-05-14T06:19:14Z","receivedAt":"2005-05-14T06:19:14Z","isPatch":false,"sender":{"key":"zbrown@tumblerings.org","avatar":null},"body":"Hi folks,\n\nI notice that cg-log takes a -u parameter, that lets you restrict the log\nentries that are displayed, to match the argument you give it. So\n\ncg-log -uKH\n\nshows all the logs where Greg KH played a part.\n\nCurrently cg-log handles this by grabbing all the log data from git, and\nthen grepping through it.\n\nWould it be faster to handle this on the git side, telling git to only\nretrieve the logs that match the specified query? If feasible, this might\nspeed up various web interfaces into git repositories.\n\nBe well,\nZack\n\n-- \nZack Brown\n"},{"id":"3289","messageId":"7vhdh6444j.fsf@assigned-by-dhcp.cox.net","threadId":"613","inReplyTo":"20050514061914.GB14353@tumblerings.org","subject":"Re: speeding up cg-log -u","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-14T08:13:16Z","receivedAt":"2005-05-14T08:13:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"ZB\" == Zack Brown <zbrown@tumblerings.org> writes:\n\nZB> Would it be faster to handle this on the git side, telling git to only\nZB> retrieve the logs that match the specified query? If feasible, this might\nZB> speed up various web interfaces into git repositories.\n\nHere are two places you can add a simple hook.  Implementation\nof author_match() function is left as an exercise for you ;-).\nLet us know if you get speed improvements, please.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n$ jit-diff\n# - 9: (Anonymous snapshot)\n# + (working tree)\n--- a/cache.h\n+++ b/cache.h\n@@ -178,6 +178,7 @@ extern void *read_object_with_reference(\n const char *show_date(unsigned long time, int timezone);\n void parse_date(char *date, char *buf, int bufsize);\n void datestamp(char *buf, int bufsize);\n+int author_match(struct commit *, const char *);\n \n static inline void *xmalloc(int size)\n {\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -11,6 +11,7 @@ int main(int argc, char **argv)\n \tunsigned long max_age = -1;\n \tunsigned long min_age = -1;\n \tint max_count = -1;\n+\tconst char *author = NULL;\n \n \tfor (i = 1 ; i < argc; i++) {\n \t\tchar *arg = argv[i];\n@@ -21,6 +22,8 @@ int main(int argc, char **argv)\n \t\t\tmax_age = atoi(arg + 10);\n \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n \t\t\tmin_age = atoi(arg + 10);\n+\t\t} else if (!strncmp(arg, \"--author=\", 9)) {\n+\t\t\tauthor = arg + 9;\n \t\t} else {\n \t\t\tcommit_arg = arg;\n \t\t}\n@@ -28,6 +31,7 @@ int main(int argc, char **argv)\n \n \tif (!commit_arg || get_sha1(commit_arg, sha1))\n \t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n+\t\t      \"  --author=author\\n\"\n \t\t      \"  --max-count=nr\\n\"\n \t\t      \"  --max-age=epoch\\n\"\n \t\t      \"  --min-age=epoch\\n\");\n@@ -44,6 +48,8 @@ int main(int argc, char **argv)\n \t\t\tcontinue;\n \t\tif (max_age != -1 && (commit->date < max_age))\n \t\t\tbreak;\n+\t\tif (!author_match(commit, author))\n+\t\t\tcontinue;\n \t\tif (max_count != -1 && !max_count--)\n \t\t\tbreak;\n \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n--- a/rev-tree.c\n+++ b/rev-tree.c\n@@ -64,7 +64,7 @@ void process_commit(unsigned char *sha1)\n }\n \n /*\n- * Usage: rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id2>]\n+ * Usage: rev-tree [--edges] [--author <author>] [--cache <cache-file>] <commit-id> [<commit-id2>]\n  *\n  * The cache-file can be quite important for big trees. This is an\n  * expensive operation if you have to walk the whole chain of\n@@ -75,6 +75,7 @@ int main(int argc, char **argv)\n \tint i;\n \tint nr = 0;\n \tunsigned char sha1[MAX_COMMITS][20];\n+\tconst char *author = NULL; \n \n \t/*\n \t * First - pick up all the revisions we can (both from\n@@ -83,6 +84,11 @@ int main(int argc, char **argv)\n \tfor (i = 1; i < argc ; i++) {\n \t\tchar *arg = argv[i];\n \n+\t\tif (!strcmp(arg, \"--author\")) {\n+\t\t\tauthor = argv[++i];\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (!strcmp(arg, \"--cache\")) {\n \t\t\tread_cache_file(argv[++i]);\n \t\t\tcontinue;\n@@ -98,7 +104,7 @@ int main(int argc, char **argv)\n \t\t\tbasemask |= 1<<nr;\n \t\t}\n \t\tif (nr >= MAX_COMMITS || get_sha1(arg, sha1[nr]))\n-\t\t\tusage(\"rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]\");\n+\t\t\tusage(\"rev-tree [--edges] [--author <author>] [--cache <cache-file>] <commit-id> [<commit-id>]\");\n \t\tprocess_commit(sha1[nr]);\n \t\tnr++;\n \t}\n@@ -125,6 +131,9 @@ int main(int argc, char **argv)\n \t\tif (!interesting(commit))\n \t\t\tcontinue;\n \n+\t\tif (!author_match(commit, author))\n+\t\t\tcontinue;\n+\n \t\tprintf(\"%lu %s:%d\", commit->date, sha1_to_hex(obj->sha1), \n \t\t       obj->flags);\n \t\tp = commit->parents;\n\n\n\n"},{"id":"3295","messageId":"7vu0l62l27.fsf@assigned-by-dhcp.cox.net","threadId":"613","inReplyTo":"20050514061914.GB14353@tumblerings.org","subject":"[PATCH] Add --author match to git-rev-list and git-rev-tree.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-14T09:50:24Z","receivedAt":"2005-05-14T09:50:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zack Brown wondered if handling author match at core GIT level\nwould make cg-log -u go faster (JIT also can use this in jit-log\n--author).  Here is a patch to implement it.\n\nI considered adding author and committer strings to commit\nobjects for general use as commit objects are parsed, but I was\nunsure about the lifetime rules of the commit objects (nobody\nseems to free them in the current code), so refrained from doing\nso for the time being.  The code instead re-reads the commit\nobject when it needs to filter them by the author.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\ncommit.c   |   42 ++++++++++++++++++++++++++++++++++++++++++\ncommit.h   |    2 ++\nrev-list.c |    6 ++++++\nrev-tree.c |   13 +++++++++++--\n4 files changed, 61 insertions(+), 2 deletions(-)\n\n--- a/commit.c\n+++ b/commit.c\n@@ -152,3 +152,45 @@\n \t}\n \treturn ret;\n }\n+\n+int author_match(const struct commit *item, const char *author)\n+{\n+\tchar type[20];\n+\tvoid *buffer;\n+\tchar *author_line, *ep;\n+\tunsigned long size;\n+\tint ret;\n+\n+\tbuffer = read_sha1_file(item->object.sha1, type, &size);\n+\tif (!buffer)\n+\t\treturn error(\"Could not read %s\",\n+\t\t\t     sha1_to_hex(item->object.sha1));\n+\tif (strcmp(type, commit_type)) {\n+\t\tfree(buffer);\n+\t\terror(\"Object %s not a commit\",\n+\t\t      sha1_to_hex(item->object.sha1));\n+\t\treturn 0;\n+\t}\n+\t/* we do not care what is in the message; we do not\n+\t * want to overrun with strstr and strchr.\n+\t */\n+\tep = buffer + (size -1);\n+\t*ep = 0;\n+\tif ((author_line = strstr(buffer, \"\\nauthor \")) == 0) {\n+\t\tfree(buffer);\n+\t\terror(\"Commit %s does not have author.\",\n+\t\t      sha1_to_hex(item->object.sha1));\n+\t\treturn 0;\n+\t}\n+\tauthor_line = strchr(author_line, ' ') + 1;\n+\tif ((ep = strchr(author_line, '>')) == 0) {\n+\t\tfree(buffer);\n+\t\terror(\"Commit %s has a malformed author line.\",\n+\t\t      sha1_to_hex(item->object.sha1));\n+\t\treturn 0;\n+\t}\n+\t*++ep = 0;\n+\tret = (strstr(author_line, author) != 0);\n+\tfree(buffer);\n+\treturn ret;\n+}\n--- a/commit.h\n+++ b/commit.h\n@@ -36,4 +36,6 @@\n struct commit *pop_most_recent_commit(struct commit_list **list, \n \t\t\t\t      unsigned int mark);\n \n+int author_match(const struct commit *, const char *);\n+\n #endif /* COMMIT_H */\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -11,6 +11,7 @@\n \tunsigned long max_age = -1;\n \tunsigned long min_age = -1;\n \tint max_count = -1;\n+\tconst char *author = NULL;\n \n \tfor (i = 1 ; i < argc; i++) {\n \t\tchar *arg = argv[i];\n@@ -21,6 +22,8 @@\n \t\t\tmax_age = atoi(arg + 10);\n \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n \t\t\tmin_age = atoi(arg + 10);\n+\t\t} else if (!strncmp(arg, \"--author=\", 9)) {\n+\t\t\tauthor = arg + 9;\n \t\t} else {\n \t\t\tcommit_arg = arg;\n \t\t}\n@@ -28,6 +31,7 @@\n \n \tif (!commit_arg || get_sha1(commit_arg, sha1))\n \t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n+\t\t      \"  --author=author\\n\"\n \t\t      \"  --max-count=nr\\n\"\n \t\t      \"  --max-age=epoch\\n\"\n \t\t      \"  --min-age=epoch\\n\");\n@@ -44,6 +48,8 @@\n \t\t\tcontinue;\n \t\tif (max_age != -1 && (commit->date < max_age))\n \t\t\tbreak;\n+\t\tif (author && !author_match(commit, author))\n+\t\t\tcontinue;\n \t\tif (max_count != -1 && !max_count--)\n \t\t\tbreak;\n \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n--- a/rev-tree.c\n+++ b/rev-tree.c\n@@ -64,7 +64,7 @@\n }\n \n /*\n- * Usage: rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id2>]\n+ * Usage: rev-tree [--edges] [--author <author>] [--cache <cache-file>] <commit-id> [<commit-id2>]\n  *\n  * The cache-file can be quite important for big trees. This is an\n  * expensive operation if you have to walk the whole chain of\n@@ -75,6 +75,7 @@\n \tint i;\n \tint nr = 0;\n \tunsigned char sha1[MAX_COMMITS][20];\n+\tconst char *author = NULL; \n \n \t/*\n \t * First - pick up all the revisions we can (both from\n@@ -83,6 +84,11 @@\n \tfor (i = 1; i < argc ; i++) {\n \t\tchar *arg = argv[i];\n \n+\t\tif (!strcmp(arg, \"--author\")) {\n+\t\t\tauthor = argv[++i];\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (!strcmp(arg, \"--cache\")) {\n \t\t\tread_cache_file(argv[++i]);\n \t\t\tcontinue;\n@@ -98,7 +104,7 @@\n \t\t\tbasemask |= 1<<nr;\n \t\t}\n \t\tif (nr >= MAX_COMMITS || get_sha1(arg, sha1[nr]))\n-\t\t\tusage(\"rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]\");\n+\t\t\tusage(\"rev-tree [--edges] [--author <author>] [--cache <cache-file>] <commit-id> [<commit-id>]\");\n \t\tprocess_commit(sha1[nr]);\n \t\tnr++;\n \t}\n@@ -125,6 +131,9 @@\n \t\tif (!interesting(commit))\n \t\t\tcontinue;\n \n+\t\tif (author && !author_match(commit, author))\n+\t\t\tcontinue;\n+\n \t\tprintf(\"%lu %s:%d\", commit->date, sha1_to_hex(obj->sha1), \n \t\t       obj->flags);\n \t\tp = commit->parents;\n------------------------------------------------\n\n"},{"id":"3297","messageId":"20050514103937.GA3905@pasky.ji.cz","threadId":"613","inReplyTo":"7vu0l62l27.fsf@assigned-by-dhcp.cox.net","subject":"Re: speeding up cg-log -u","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-14T10:39:37Z","receivedAt":"2005-05-14T10:39:37Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sat, May 14, 2005 at 08:19:14AM CEST, I got a letter\nwhere Zack Brown <zbrown@tumblerings.org> told me that...\n> Currently cg-log handles this by grabbing all the log data from git, and\n> then grepping through it.\n\nWhich is clearly suboptimal since cg-log now does git-cat-file up to\n_three_ times per commit. It should instead process the commit only\nonce.\n\nDear diary, on Sat, May 14, 2005 at 11:50:24AM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> +\tbuffer = read_sha1_file(item->object.sha1, type, &size);\n\nIf it do that, I wonder how much speedup would be using this instead.\nBut probably still significant one.\n\nWhat I don't like is that it searches only the author field. I find the\nbehaviour that it searches in the committer field as well very useful,\nsince I can easily check whose patches on a file I checked it - that's\nuseful when porting own stuff to another branch, or frequently it's the\nonly thing I actually remember. :-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3302","messageId":"20050514111427.GC3905@pasky.ji.cz","threadId":"613","inReplyTo":"20050514103937.GA3905@pasky.ji.cz","subject":"Re: speeding up cg-log -u","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-14T11:14:27Z","receivedAt":"2005-05-14T11:14:27Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Where was my English? Sorry.\n\n> If it do that, I wonder how much speedup would be using this instead.\n(does)\n> But probably still significant one.\n> \n> What I don't like is that it searches only the author field. I find the\n> behaviour that it searches in the committer field as well very useful,\n> since I can easily check whose patches on a file I checked it\n(which patches of a file I checked in)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3303","messageId":"7vk6m212g7.fsf@assigned-by-dhcp.cox.net","threadId":"613","inReplyTo":"20050514103937.GA3905@pasky.ji.cz","subject":"Re: speeding up cg-log -u","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-14T11:17:44Z","receivedAt":"2005-05-14T11:17:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\nPB> Dear diary, on Sat, May 14, 2005 at 11:50:24AM CEST, I got a letter\nPB> where Junio C Hamano <junkio@cox.net> told me that...\n>> +\tbuffer = read_sha1_file(item->object.sha1, type, &size);\n\nPB> If it do that, I wonder how much speedup would be using this instead.\nPB> But probably still significant one.\n\nI would imagine so (only benchmark would tell), because you\nwould not spawn git-cat-file for each individual commit object.\n\nWhenever I work with those \"struct object\" derivatives, I get\nvery frustrated by the fact that they are designed to cater only\nto the need of very narrow immediate users.  The first round of\ntree objects did not even have names for each entry because the\nonly thing it cared about was connectivity checking, and for\nthat purpose callers would not care about what each blob or\nsubtree was referred as.  Now when I want to use commit objects\nI find that it only records the commit date (other than\nconnectivity information).  It really appears that connectivity\nis the primary thing and everything else is bolted on top.\n\nNot wanting to keep the whole object because of their size is\nunderstandable since the users of \"struct object\" derivatives\nrarely if ever seem to free them once they get hold of them.\nAnd not wanting to think ahead about what is worth keeping (like\nnames for tree entries back then, or commit author names) is\nalso understandable, but it still is frustrating.  Not that I\nwould want to solve this myself ...\n\n"},{"id":"3307","messageId":"20050514142325.GC14353@tumblerings.org","threadId":"613","inReplyTo":"7vk6m212g7.fsf@assigned-by-dhcp.cox.net","subject":"Re: speeding up cg-log -u","fromName":"Zack Brown","fromEmail":"zbrown@tumblerings.org","sentAt":"2005-05-14T14:23:25Z","receivedAt":"2005-05-14T14:23:25Z","isPatch":false,"sender":{"key":"zbrown@tumblerings.org","avatar":null},"body":"On Sat, May 14, 2005 at 04:17:44AM -0700, Junio C Hamano wrote:\n> Not wanting to keep the whole object because of their size is\n> understandable since the users of \"struct object\" derivatives\n> rarely if ever seem to free them once they get hold of them.\n> And not wanting to think ahead about what is worth keeping (like\n> names for tree entries back then, or commit author names) is\n> also understandable, but it still is frustrating.\n\nSo if this design is changed to suit -u, would a further redesign be needed\nto support an option to filter on keywords in the body of the changelog\nentry? Perhaps this will result in a net slowdown for the usual case of just\ngrabbing all log entries.\n\nBe well,\nZack\n\n>  Not that I\n> would want to solve this myself ...\n> \n> -\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n\n-- \nZack Brown\n"},{"id":"3309","messageId":"20050514144057.GH3905@pasky.ji.cz","threadId":"613","inReplyTo":"20050514142325.GC14353@tumblerings.org","subject":"Re: speeding up cg-log -u","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-14T14:40:57Z","receivedAt":"2005-05-14T14:40:57Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sat, May 14, 2005 at 04:23:25PM CEST, I got a letter\nwhere Zack Brown <zbrown@tumblerings.org> told me that...\n> On Sat, May 14, 2005 at 04:17:44AM -0700, Junio C Hamano wrote:\n> > Not wanting to keep the whole object because of their size is\n> > understandable since the users of \"struct object\" derivatives\n> > rarely if ever seem to free them once they get hold of them.\n> > And not wanting to think ahead about what is worth keeping (like\n> > names for tree entries back then, or commit author names) is\n> > also understandable, but it still is frustrating.\n> \n> So if this design is changed to suit -u, would a further redesign be needed\n> to support an option to filter on keywords in the body of the changelog\n> entry? Perhaps this will result in a net slowdown for the usual case of just\n> grabbing all log entries.\n\nI admit not looking at this code for a rather long time, but what about\njust telling the commit parser what stuff are you interested in and it\nwould leave the rest of the structure fields NULL? That would mean only\nslight memory usage increase and basically no time increase.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3313","messageId":"20050514150607.GA14184@tumblerings.org","threadId":"613","inReplyTo":"7vu0l62l27.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Add --author match to git-rev-list and git-rev-tree.","fromName":"Zack Brown","fromEmail":"zbrown@tumblerings.org","sentAt":"2005-05-14T15:06:07Z","receivedAt":"2005-05-14T15:06:07Z","isPatch":true,"sender":{"key":"zbrown@tumblerings.org","avatar":null},"body":"On Sat, May 14, 2005 at 02:50:24AM -0700, Junio C Hamano wrote:\n> Zack Brown wondered if handling author match at core GIT level\n> would make cg-log -u go faster (JIT also can use this in jit-log\n> --author).  Here is a patch to implement it.\n> \n> I considered adding author and committer strings to commit\n> objects for general use as commit objects are parsed, but I was\n> unsure about the lifetime rules of the commit objects (nobody\n> seems to free them in the current code), so refrained from doing\n> so for the time being.  The code instead re-reads the commit\n> object when it needs to filter them by the author.\n\nI applied this, but can't figure out the change to make to cg-log in order to\nactually test it.\n\n- git-cat-file commit $commit | grep -e '^author ' -e '^committer ' | grep -qi \"$user\" || continue\n+ git-cat-file --author $user commit $commit || continue\n\nsure didn't work.\n\nZ\n\n> \n> Signed-off-by: Junio C Hamano <junkio@cox.net>\n> ---\n> \n> commit.c   |   42 ++++++++++++++++++++++++++++++++++++++++++\n> commit.h   |    2 ++\n> rev-list.c |    6 ++++++\n> rev-tree.c |   13 +++++++++++--\n> 4 files changed, 61 insertions(+), 2 deletions(-)\n> \n> --- a/commit.c\n> +++ b/commit.c\n> @@ -152,3 +152,45 @@\n>  \t}\n>  \treturn ret;\n>  }\n> +\n> +int author_match(const struct commit *item, const char *author)\n> +{\n> +\tchar type[20];\n> +\tvoid *buffer;\n> +\tchar *author_line, *ep;\n> +\tunsigned long size;\n> +\tint ret;\n> +\n> +\tbuffer = read_sha1_file(item->object.sha1, type, &size);\n> +\tif (!buffer)\n> +\t\treturn error(\"Could not read %s\",\n> +\t\t\t     sha1_to_hex(item->object.sha1));\n> +\tif (strcmp(type, commit_type)) {\n> +\t\tfree(buffer);\n> +\t\terror(\"Object %s not a commit\",\n> +\t\t      sha1_to_hex(item->object.sha1));\n> +\t\treturn 0;\n> +\t}\n> +\t/* we do not care what is in the message; we do not\n> +\t * want to overrun with strstr and strchr.\n> +\t */\n> +\tep = buffer + (size -1);\n> +\t*ep = 0;\n> +\tif ((author_line = strstr(buffer, \"\\nauthor \")) == 0) {\n> +\t\tfree(buffer);\n> +\t\terror(\"Commit %s does not have author.\",\n> +\t\t      sha1_to_hex(item->object.sha1));\n> +\t\treturn 0;\n> +\t}\n> +\tauthor_line = strchr(author_line, ' ') + 1;\n> +\tif ((ep = strchr(author_line, '>')) == 0) {\n> +\t\tfree(buffer);\n> +\t\terror(\"Commit %s has a malformed author line.\",\n> +\t\t      sha1_to_hex(item->object.sha1));\n> +\t\treturn 0;\n> +\t}\n> +\t*++ep = 0;\n> +\tret = (strstr(author_line, author) != 0);\n> +\tfree(buffer);\n> +\treturn ret;\n> +}\n> --- a/commit.h\n> +++ b/commit.h\n> @@ -36,4 +36,6 @@\n>  struct commit *pop_most_recent_commit(struct commit_list **list, \n>  \t\t\t\t      unsigned int mark);\n>  \n> +int author_match(const struct commit *, const char *);\n> +\n>  #endif /* COMMIT_H */\n> --- a/rev-list.c\n> +++ b/rev-list.c\n> @@ -11,6 +11,7 @@\n>  \tunsigned long max_age = -1;\n>  \tunsigned long min_age = -1;\n>  \tint max_count = -1;\n> +\tconst char *author = NULL;\n>  \n>  \tfor (i = 1 ; i < argc; i++) {\n>  \t\tchar *arg = argv[i];\n> @@ -21,6 +22,8 @@\n>  \t\t\tmax_age = atoi(arg + 10);\n>  \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n>  \t\t\tmin_age = atoi(arg + 10);\n> +\t\t} else if (!strncmp(arg, \"--author=\", 9)) {\n> +\t\t\tauthor = arg + 9;\n>  \t\t} else {\n>  \t\t\tcommit_arg = arg;\n>  \t\t}\n> @@ -28,6 +31,7 @@\n>  \n>  \tif (!commit_arg || get_sha1(commit_arg, sha1))\n>  \t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n> +\t\t      \"  --author=author\\n\"\n>  \t\t      \"  --max-count=nr\\n\"\n>  \t\t      \"  --max-age=epoch\\n\"\n>  \t\t      \"  --min-age=epoch\\n\");\n> @@ -44,6 +48,8 @@\n>  \t\t\tcontinue;\n>  \t\tif (max_age != -1 && (commit->date < max_age))\n>  \t\t\tbreak;\n> +\t\tif (author && !author_match(commit, author))\n> +\t\t\tcontinue;\n>  \t\tif (max_count != -1 && !max_count--)\n>  \t\t\tbreak;\n>  \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n> --- a/rev-tree.c\n> +++ b/rev-tree.c\n> @@ -64,7 +64,7 @@\n>  }\n>  \n>  /*\n> - * Usage: rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id2>]\n> + * Usage: rev-tree [--edges] [--author <author>] [--cache <cache-file>] <commit-id> [<commit-id2>]\n>   *\n>   * The cache-file can be quite important for big trees. This is an\n>   * expensive operation if you have to walk the whole chain of\n> @@ -75,6 +75,7 @@\n>  \tint i;\n>  \tint nr = 0;\n>  \tunsigned char sha1[MAX_COMMITS][20];\n> +\tconst char *author = NULL; \n>  \n>  \t/*\n>  \t * First - pick up all the revisions we can (both from\n> @@ -83,6 +84,11 @@\n>  \tfor (i = 1; i < argc ; i++) {\n>  \t\tchar *arg = argv[i];\n>  \n> +\t\tif (!strcmp(arg, \"--author\")) {\n> +\t\t\tauthor = argv[++i];\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n>  \t\tif (!strcmp(arg, \"--cache\")) {\n>  \t\t\tread_cache_file(argv[++i]);\n>  \t\t\tcontinue;\n> @@ -98,7 +104,7 @@\n>  \t\t\tbasemask |= 1<<nr;\n>  \t\t}\n>  \t\tif (nr >= MAX_COMMITS || get_sha1(arg, sha1[nr]))\n> -\t\t\tusage(\"rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]\");\n> +\t\t\tusage(\"rev-tree [--edges] [--author <author>] [--cache <cache-file>] <commit-id> [<commit-id>]\");\n>  \t\tprocess_commit(sha1[nr]);\n>  \t\tnr++;\n>  \t}\n> @@ -125,6 +131,9 @@\n>  \t\tif (!interesting(commit))\n>  \t\t\tcontinue;\n>  \n> +\t\tif (author && !author_match(commit, author))\n> +\t\t\tcontinue;\n> +\n>  \t\tprintf(\"%lu %s:%d\", commit->date, sha1_to_hex(obj->sha1), \n>  \t\t       obj->flags);\n>  \t\tp = commit->parents;\n> ------------------------------------------------\n> \n> -\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n\n-- \nZack Brown\n"},{"id":"3323","messageId":"20050514155257.GR3905@pasky.ji.cz","threadId":"613","inReplyTo":"20050514150607.GA14184@tumblerings.org","subject":"Re: [PATCH] Add --author match to git-rev-list and git-rev-tree.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-14T15:52:57Z","receivedAt":"2005-05-14T15:52:57Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sat, May 14, 2005 at 05:06:07PM CEST, I got a letter\nwhere Zack Brown <zbrown@tumblerings.org> told me that...\n> On Sat, May 14, 2005 at 02:50:24AM -0700, Junio C Hamano wrote:\n> > Zack Brown wondered if handling author match at core GIT level\n> > would make cg-log -u go faster (JIT also can use this in jit-log\n> > --author).  Here is a patch to implement it.\n> > \n> > I considered adding author and committer strings to commit\n> > objects for general use as commit objects are parsed, but I was\n> > unsure about the lifetime rules of the commit objects (nobody\n> > seems to free them in the current code), so refrained from doing\n> > so for the time being.  The code instead re-reads the commit\n> > object when it needs to filter them by the author.\n> \n> I applied this, but can't figure out the change to make to cg-log in order to\n> actually test it.\n> \n> - git-cat-file commit $commit | grep -e '^author ' -e '^committer ' | grep -qi \"$user\" || continue\n> + git-cat-file --author $user commit $commit || continue\n> \n> sure didn't work.\n\nYou throw that whole thing away and pass the --author parameter directly\nto git-rev-(list|tree).\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3326","messageId":"20050514160213.GF14184@tumblerings.org","threadId":"613","inReplyTo":"20050514155257.GR3905@pasky.ji.cz","subject":"Re: [PATCH] Add --author match to git-rev-list and git-rev-tree.","fromName":"Zack Brown","fromEmail":"zbrown@tumblerings.org","sentAt":"2005-05-14T16:02:13Z","receivedAt":"2005-05-14T16:02:13Z","isPatch":true,"sender":{"key":"zbrown@tumblerings.org","avatar":null},"body":"On Sat, May 14, 2005 at 05:52:57PM +0200, Petr Baudis wrote:\n> Dear diary, on Sat, May 14, 2005 at 05:06:07PM CEST, I got a letter\n> where Zack Brown <zbrown@tumblerings.org> told me that...\n> > On Sat, May 14, 2005 at 02:50:24AM -0700, Junio C Hamano wrote:\n> > > Zack Brown wondered if handling author match at core GIT level\n> > > would make cg-log -u go faster (JIT also can use this in jit-log\n> > > --author).  Here is a patch to implement it.\n> > > \n> > > I considered adding author and committer strings to commit\n> > > objects for general use as commit objects are parsed, but I was\n> > > unsure about the lifetime rules of the commit objects (nobody\n> > > seems to free them in the current code), so refrained from doing\n> > > so for the time being.  The code instead re-reads the commit\n> > > object when it needs to filter them by the author.\n> > \n> > I applied this, but can't figure out the change to make to cg-log in order to\n> > actually test it.\n> > \n> > - git-cat-file commit $commit | grep -e '^author ' -e '^committer ' | grep -qi \"$user\" || continue\n> > + git-cat-file --author $user commit $commit || continue\n> > \n> > sure didn't work.\n> \n> You throw that whole thing away and pass the --author parameter directly\n> to git-rev-(list|tree).\n\nYou mean like this?\n\nBe well,\nZack\n\n\nUse git-rev-(list|tree) --author to cg-log\n\nSigned-off-by: Zack Brown <zbrown@tumblerings.org>\n\n--- de641904363cd3759f132ee7c0dfaf8a2ee58388/cg-log  (mode:100755)\n+++ uncommitted/cg-log  (mode:100755)\n@@ -112,12 +112,20 @@\n if [ \"$log_end\" ]; then\n        id1=\"$(commit-id $log_start)\" || exit 1\n        id2=\"$(commit-id $log_end)\" || exit 1\n-       revls=\"git-rev-tree $id2 ^$id1\"\n+       if [ \"$user\" ]; then\n+               revls=\"git-rev-tree --author $user $id2 ^$id1\"\n+       else\n+               revls=\"git-rev-tree $id2 ^$id1\"\n+       fi\n        revsort=\"sort -rn\"\n        revfmt=\"git-rev-tree\"\n else\n        id1=\"$(commit-id $log_start)\" || exit 1\n-       revls=\"git-rev-list $id1\"\n+       if [ \"$user\" ]; then\n+               revls=\"git-rev-list --author $user $id1\"\n+       else\n+               revls=\"git-rev-list $id1\"\n+       fi\n        revsort=\"cat\"\n        revfmt=\"git-rev-list\"\n fi\n@@ -131,9 +139,6 @@\n                parent=$(git-cat-file commit $commit | sed -n '2s/parent //p;2Q')\n                [ \"$parent\" ] && [ \"$(git-diff-tree -r $commit $parent \"$@\")\" ] || continue\n        fi\n-       if [ \"$user\" ]; then\n-               git-cat-file commit $commit | grep -e '^author ' -e '^committer ' | grep -qi \"$user\" || continue\n-       fi\n        echo $colheader\"\"commit ${commit%:*} $coldefault;\n        git-cat-file commit $commit | \\\n                while read key rest; do\n\n> \n> -- \n> \t\t\t\tPetr \"Pasky\" Baudis\n> Stuff: http://pasky.or.cz/\n> C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n> -\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n\n-- \nZack Brown\n"},{"id":"3366","messageId":"Pine.LNX.4.21.0505151158300.30848-100000@iabervon.org","threadId":"613","inReplyTo":"7vk6m212g7.fsf@assigned-by-dhcp.cox.net","subject":"Re: speeding up cg-log -u","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-05-15T16:09:55Z","receivedAt":"2005-05-15T16:09:55Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 14 May 2005, Junio C Hamano wrote:\n\n> Whenever I work with those \"struct object\" derivatives, I get\n> very frustrated by the fact that they are designed to cater only\n> to the need of very narrow immediate users. \n\nThey aren't designed for the immediate users; they're implemented for the\nimmediate users. Feel free to add more fields as you need them. The\ncurrent selection is based on only adding things when there's a user for\nthem.\n\n> The first round of tree objects did not even have names for each entry\n> because the only thing it cared about was connectivity checking, and for\n> that purpose callers would not care about what each blob or\n> subtree was referred as.  Now when I want to use commit objects\n> I find that it only records the commit date (other than\n> connectivity information).  It really appears that connectivity\n> is the primary thing and everything else is bolted on top.\n\nExistance is the primary thing, and everything else was added as\nneeded. (Pure connectivity is a bit special, because it's a property of\ngeneric objects so that fsck-cache doesn't need to know about particular\ntypes of objects unless there are particular things to check about them)\n\nIf you need more fields, let me know, and I'll figure out how to include\nthem.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"3409","messageId":"7voebboafy.fsf@assigned-by-dhcp.cox.net","threadId":"613","inReplyTo":"Pine.LNX.4.21.0505151158300.30848-100000@iabervon.org","subject":"Re: speeding up cg-log -u","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-16T08:13:21Z","receivedAt":"2005-05-16T08:13:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"DB\" == Daniel Barkalow <barkalow@iabervon.org> writes:\n\nDB> Existance is the primary thing, and everything else was added as\nDB> needed. (Pure connectivity is a bit special, because it's a property of\nDB> generic objects so that fsck-cache doesn't need to know about particular\nDB> types of objects unless there are particular things to check about them)\n\nDB> If you need more fields, let me know, and I'll figure out how to include\nDB> them.\n\nCould you take a look at the latest round of the patch and see\nwhat I did there makes sense?\n\n    From: Junio C Hamano <junkio@cox.net>\n    Date: Sun, 15 May 2005 14:18:36 -0700\n    Message-ID: <7vy8agqjbn.fsf@assigned-by-dhcp.cox.net>\n    Subject: [PATCH 1/4] Add --author and --committer match\n             to git-rev-list and git-rev-tree.\n\nAnother thing I wanted to ask you about was lifetime rules.\nWhen we \"lookup\" these objects (and then \"parse\" them, which\ncauses more memory to be used), who is responsible for freeing\nthem?  When my program thinks it is done with a commit, is it\nallowed to free it?  Or does the lookup machinery own all of the\nobjects that have ever been looked up, and the program should\nnot worry about freeing them to begin with?\n\n"},{"id":"3414","messageId":"Pine.LNX.4.21.0505161115010.30848-100000@iabervon.org","threadId":"613","inReplyTo":"7voebboafy.fsf@assigned-by-dhcp.cox.net","subject":"Re: speeding up cg-log -u","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-05-16T15:38:58Z","receivedAt":"2005-05-16T15:38:58Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 16 May 2005, Junio C Hamano wrote:\n\n> >>>>> \"DB\" == Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> DB> Existance is the primary thing, and everything else was added as\n> DB> needed. (Pure connectivity is a bit special, because it's a property of\n> DB> generic objects so that fsck-cache doesn't need to know about particular\n> DB> types of objects unless there are particular things to check about them)\n> \n> DB> If you need more fields, let me know, and I'll figure out how to include\n> DB> them.\n> \n> Could you take a look at the latest round of the patch and see\n> what I did there makes sense?\n> \n>     From: Junio C Hamano <junkio@cox.net>\n>     Date: Sun, 15 May 2005 14:18:36 -0700\n>     Message-ID: <7vy8agqjbn.fsf@assigned-by-dhcp.cox.net>\n>     Subject: [PATCH 1/4] Add --author and --committer match\n>              to git-rev-list and git-rev-tree.\n\nIt seems generally good to me.\n\nI think it would fit stylistically a bit better if the \"mark\" field on the\nperson names were left for programs to use however they wanted, and the\n\"interesting\" determination were done in the programs (or, since there are\ntwo with the same characteristics, a new file they both link against).\n\nAlternatively, put the used bit definitions in the header file and have a\nmask for unused flags.\n\n> Another thing I wanted to ask you about was lifetime rules.\n> When we \"lookup\" these objects (and then \"parse\" them, which\n> causes more memory to be used), who is responsible for freeing\n> them?  When my program thinks it is done with a commit, is it\n> allowed to free it?  Or does the lookup machinery own all of the\n> objects that have ever been looked up, and the program should\n> not worry about freeing them to begin with?\n\nThe lookup machinery owns all of the objects that have been looked up. The\nthing is that the program can never effectively tell if it's really done\nwith a commit, because some other branch it's following could have\nincorrect dates and suddenly turn out to be descended from a commit that\nit freed, and things would likely misbehave if the object were looked up\nagain, since the flags would be reset.\n\nWe could have something that causes them to be reset to unparsed, if the\nprogram thinks that, even if it references the same object again, it won't\nneed the contents.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"}]}