{"thread":{"id":"3838","subject":"[PATCH] git log [diff-tree options]...","startedAt":"2006-04-09T09:04:02Z","lastAt":"2006-04-11T00:50:26Z","messageCount":22,"participants":["Junio C Hamano","Linus Torvalds","Johannes Schindelin","Timo Hirvonen","Randal L. Schwartz","Petr Baudis"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"18494","messageId":"7v7j5zce7x.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":null,"subject":"[PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-09T09:04:02Z","receivedAt":"2006-04-09T09:04:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"And this makes \"git log\" to take common diff-tree options, so\nthat it can be used as \"git whatchanged\".\n\nThe recent revision walker updates by Linus to make path\nlimiting low-latency helps this quite a bit.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n git.c |   32 +++++++++++++++++++++++++++++++-\n 1 files changed, 31 insertions(+), 1 deletions(-)\n\n52b70d56bd23811003a72866cc23a0a44b9da1b7\ndiff --git a/git.c b/git.c\nindex fa58232..8776088 100644\n--- a/git.c\n+++ b/git.c\n@@ -16,6 +16,8 @@ #include \"common-cmds.h\"\n #include \"cache.h\"\n #include \"commit.h\"\n #include \"revision.h\"\n+#include \"diff.h\"\n+#include \"log-tree.h\"\n \n #ifndef PATH_MAX\n # define PATH_MAX 4096\n@@ -285,7 +287,10 @@ static int cmd_log(int argc, const char \n \tint abbrev = DEFAULT_ABBREV;\n \tint abbrev_commit = 0;\n \tconst char *commit_prefix = \"commit \";\n+\tstruct log_tree_opt opt;\n+\tint do_diff = 0;\n \n+\tinit_log_tree_opt(&opt);\n \targc = setup_revisions(argc, argv, &rev, \"HEAD\");\n \twhile (1 < argc) {\n \t\tconst char *arg = argv[1];\n@@ -310,9 +315,31 @@ static int cmd_log(int argc, const char \n \t\t\telse if (40 < abbrev)\n \t\t\t\tabbrev = 40;\n \t\t}\n-\t\telse\n+\t\telse {\n+\t\t\tint cnt = log_tree_opt_parse(&opt, argv+1, argc-1);\n+\t\t\tif (0 < cnt) {\n+\t\t\t\tdo_diff = 1;\n+\t\t\t\targv += cnt;\n+\t\t\t\targc -= cnt;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tdie(\"unrecognized argument: %s\", arg);\n+\t\t}\n+\n \t\targc--; argv++;\n+\t}\n+\tif (do_diff) {\n+\t\topt.diffopt.abbrev = abbrev;\n+\t\topt.verbose_header = 0;\n+\t\topt.always_show_header = 0;\n+\t\topt.no_commit_id = 1;\n+\t\tif (opt.combine_merges)\n+\t\t\topt.ignore_merges = 0;\n+\t\tif (opt.dense_combined_merges)\n+\t\t\topt.diffopt.output_format = DIFF_FORMAT_PATCH;\n+\t\tif (opt.diffopt.output_format == DIFF_FORMAT_PATCH)\n+\t\t\topt.diffopt.recursive = 1;\n+\t\tdiff_setup_done(&opt.diffopt);\n \t}\n \n \tprepare_revision_walk(&rev);\n@@ -350,6 +377,9 @@ static int cmd_log(int argc, const char \n \t\tpretty_print_commit(commit_format, commit, ~0, buf,\n \t\t\t\t    LOGSIZE, abbrev);\n \t\tprintf(\"%s\\n\", buf);\n+\n+\t\tif (do_diff)\n+\t\t\tlog_tree_commit(&opt, commit);\n \t}\n \tfree(buf);\n \treturn 0;\n-- \n1.2.6.gad0b\n"},{"id":"18495","messageId":"7v1ww7cdme.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"7v7j5zce7x.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-09T09:16:57Z","receivedAt":"2006-04-09T09:16:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> And this makes \"git log\" to take common diff-tree options, so\n> that it can be used as \"git whatchanged\".\n\nBTW, this is *not* \"whatchanged\" in that it does not omit the\nlog when there is no diff output.  It may not matter much --\nwhen we give paths limiter to the command, the commits that are\nshown are already limited by those paths limiter.\n"},{"id":"18501","messageId":"Pine.LNX.4.64.0604090950590.9504@g5.osdl.org","threadId":"3838","inReplyTo":"7v7j5zce7x.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-04-09T16:53:34Z","receivedAt":"2006-04-09T16:53:34Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 9 Apr 2006, Junio C Hamano wrote:\n>\n> And this makes \"git log\" to take common diff-tree options, so\n> that it can be used as \"git whatchanged\".\n\nI wonder... This all looks fine, but there are actually two different \n\"diffs\" that can be shown for \"git log --diff <pathlimiter>\":\n\n - the whole diff for a commit\n\n - the path-limited diff\n\nand I think we'd likely want to have some way to select the output. \nProbably with the path-limited diff being the default (that's what \n\"git-whatchanged\" does), but perhaps with \"--full-diff\" showing the whole \ncommit diff (which is what \"gitk\" does).\n\n\t\tLinus\n"},{"id":"18508","messageId":"7vbqvabn8f.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"Pine.LNX.4.64.0604090950590.9504@g5.osdl.org","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-09T18:46:56Z","receivedAt":"2006-04-09T18:46:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> I wonder... This all looks fine, but there are actually two different \n> \"diffs\" that can be shown for \"git log --diff <pathlimiter>\":\n>\n>  - the whole diff for a commit\n>  - the path-limited diff\n\nYes, exactly the same way sometimes you would want just pickaxe,\nsometimes you would want it with --pickaxe-all.\n\nAlso, I might have to rethink --max-count logic -- I think it is\nreasonable to skip the commit when doing limiting by diff like\n\"whatchanged\" does, but one thing I find suboptimal with the\ncurrent whatchanged is that it does not count commits that are\nactually shown (it counts what the upstream rev-list feeds\ndiff-tree).  With the \"git log --diff\" based whatchanged, it\nbecomes trivial to skip the revs->max_count limiting and have\nthe caller count the commits it actually does something\nuser-visible to, instead of counting the commits it pulled out\nof get_revision().\n\nBTW I think I could remove the log message generation part of\n\"git log\" and have it use the one in log-tree (which I will\nprobably rewrite not to format the message into the static\nthis_header[] buffer when it is not shown).\n\nAnother thing that might be useful is to teach diff-* to do the\ndiffstat part internally.  After that is in place we could\nintroduce --pretty=patch to have \"git log\" produce format-patch\ncompatible output.\n"},{"id":"18511","messageId":"Pine.LNX.4.64.0604091158310.9504@g5.osdl.org","threadId":"3838","inReplyTo":"7vbqvabn8f.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-04-09T19:02:44Z","receivedAt":"2006-04-09T19:02:44Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 9 Apr 2006, Junio C Hamano wrote:\n> \n> Also, I might have to rethink --max-count logic -- I think it is\n> reasonable to skip the commit when doing limiting by diff like\n> \"whatchanged\" does, but one thing I find suboptimal with the\n> current whatchanged is that it does not count commits that are\n> actually shown (it counts what the upstream rev-list feeds\n> diff-tree).  With the \"git log --diff\" based whatchanged, it\n> becomes trivial to skip the revs->max_count limiting and have\n> the caller count the commits it actually does something\n> user-visible to, instead of counting the commits it pulled out\n> of get_revision().\n\nWell, on the other hand, the new \"git log --diff\" should get the revision \ncounting right even if it's _not_ done by the caller.\n\nReally, the only reason \"git-whatchanged\" exists at all is that it used to \nbe originally impossible, and later on too expensive to do the commit- \nlimiting by pathname. With the new incremental path-limiting, the reason \nfor \"git-whatchanged\" simply goes away.\n\nSo I'd suggest:\n - drop git-whatchanged entirely\n - keep it - for historical reasons - as a internal shorthand, and just \n   turn it into \"git log --diff -cc\"\n\nand everybody will be happy (yeah, it will show a few merge commits \nwithout diffs, because the diffs end up being uninteresting, but that's \n_fine_, even if it's not 100% the same thing git-whatchanged used to do)\n\n\t\t\tLinus\n"},{"id":"18513","messageId":"7v3bgmbm8b.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"Pine.LNX.4.64.0604091158310.9504@g5.osdl.org","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-09T19:08:36Z","receivedAt":"2006-04-09T19:08:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Well, on the other hand, the new \"git log --diff\" should get the revision \n> counting right even if it's _not_ done by the caller.\n\nNot if the user uses --diff-filter and/or --pickaxe, and after\nwe start omitting the log message part when no diff is output.\n\n> So I'd suggest:\n>  - drop git-whatchanged entirely\n>  - keep it - for historical reasons - as a internal shorthand, and just \n>    turn it into \"git log --diff -cc\"\n>\n> and everybody will be happy (yeah, it will show a few merge commits \n> without diffs, because the diffs end up being uninteresting, but that's \n> _fine_, even if it's not 100% the same thing git-whatchanged used to do)\n\nI tend to agree.  A merge commit touching a path but not\nactually changing the contents of the path from parents might be\na significant event.\n"},{"id":"18514","messageId":"Pine.LNX.4.64.0604091221540.9504@g5.osdl.org","threadId":"3838","inReplyTo":"7v3bgmbm8b.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-04-09T19:26:18Z","receivedAt":"2006-04-09T19:26:18Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 9 Apr 2006, Junio C Hamano wrote:\n> Linus Torvalds <torvalds@osdl.org> writes:\n> \n> > Well, on the other hand, the new \"git log --diff\" should get the revision \n> > counting right even if it's _not_ done by the caller.\n> \n> Not if the user uses --diff-filter and/or --pickaxe, and after\n> we start omitting the log message part when no diff is output.\n\nFair enough. At that point the counting does have to be done in the \ncaller, I guess.\n\n> A merge commit touching a path but not actually changing the contents of \n> the path from parents might be a significant event.\n\nYes. The fact that git-whatchanged happens to ignore such things right now \nis just a implementation detail, not a \"good thing\". The new git log seems \nto be better in pretty much all respects.\n\nThe bigger conceptual difference is actually that once you do revision \npruning based on the pathname limiter, we prune away parents of merges \nthat seem \"uninteresting\". So before, when you had the same change come \nthrough two different branches, \"git-whatchanged\" would actually show it \ntwice, while the new \"git log\" approach would tend to show it just once \n(because it would pick one of the histories and ignore the other).\n\nI think that's fine (and probably even preferable), but it's another \nexample of something where we might want to have an option to not \nsimplify the merge history. It's likely that nobody will ever care, but \nwho knows..\n\n\t\t\tLinus\n"},{"id":"18515","messageId":"Pine.LNX.4.63.0604092312340.29136@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"3838","inReplyTo":"Pine.LNX.4.64.0604091158310.9504@g5.osdl.org","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-04-09T21:13:47Z","receivedAt":"2006-04-09T21:13:47Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 9 Apr 2006, Linus Torvalds wrote:\n\n>  - keep it - for historical reasons - as a internal shorthand, and just \n>    turn it into \"git log --diff -cc\"\n\nIt is \"git log --cc\", right? And BTW, I was burnt by the difference of \n\"git-log\" and \"git log\" this time. \"git-log\" does not understand \"--cc\". \nCould we kill \"git-log\", please?\n\nCiao,\nDscho\n"},{"id":"18518","messageId":"Pine.LNX.4.63.0604100000430.30000@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"3838","inReplyTo":"Pine.LNX.4.63.0604092312340.29136@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-04-09T22:01:40Z","receivedAt":"2006-04-09T22:01:40Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 9 Apr 2006, Johannes Schindelin wrote:\n\n> On Sun, 9 Apr 2006, Linus Torvalds wrote:\n> \n> >  - keep it - for historical reasons - as a internal shorthand, and just \n> >    turn it into \"git log --diff -cc\"\n> \n> It is \"git log --cc\", right?\n\nLike this?\n\n---\n\n git.c |    8 ++++++++\n 1 files changed, 8 insertions(+), 0 deletions(-)\n\n751e205a9ffd3a55094a0c0f657735023776cf74\ndiff --git a/git.c b/git.c\nindex 8776088..3a94afa 100644\n--- a/git.c\n+++ b/git.c\n@@ -385,6 +385,13 @@ static int cmd_log(int argc, const char \n \treturn 0;\n }\n \n+static int cmd_whatchanged(int argc, const char **argv, char **envp)\n+{\n+\tmemmove(argv + 2, argv + 1, argc - 1);\n+\targv[1] = \"--cc\";\n+\treturn cmd_log(argc + 1, argv, envp);\n+}\n+\n static void handle_internal_command(int argc, const char **argv, char **envp)\n {\n \tconst char *cmd = argv[0];\n@@ -395,6 +402,7 @@ static void handle_internal_command(int \n \t\t{ \"version\", cmd_version },\n \t\t{ \"help\", cmd_help },\n \t\t{ \"log\", cmd_log },\n+\t\t{ \"whatchanged\", cmd_whatchanged },\n \t};\n \tint i;\n \n-- \n1.2.0.g61002-dirty\n"},{"id":"18520","messageId":"20060410012258.589f1581.tihirvon@gmail.com","threadId":"3838","inReplyTo":"Pine.LNX.4.63.0604100000430.30000@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Timo Hirvonen","fromEmail":"tihirvon@gmail.com","sentAt":"2006-04-09T22:22:58Z","receivedAt":"2006-04-09T22:22:58Z","isPatch":true,"sender":{"key":"tihirvon@gmail.com","avatar":null},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n\n> +static int cmd_whatchanged(int argc, const char **argv, char **envp)\n> +{\n> +\tmemmove(argv + 2, argv + 1, argc - 1);\n\nShouldn't the size be sizeof(char *) * argc (NULL terminated array)?\nThere's also overflow...\n\n-- \nhttp://onion.dynserv.net/~timo/\n"},{"id":"18523","messageId":"7vy7ye9uk8.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"Pine.LNX.4.63.0604100000430.30000@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-09T23:51:35Z","receivedAt":"2006-04-09T23:51:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Hi,\n>\n> On Sun, 9 Apr 2006, Johannes Schindelin wrote:\n>\n>> On Sun, 9 Apr 2006, Linus Torvalds wrote:\n>> \n>> >  - keep it - for historical reasons - as a internal shorthand, and just \n>> >    turn it into \"git log --diff -cc\"\n>> \n>> It is \"git log --cc\", right?\n>\n> Like this?\n\nI do not think so.  You should default to --cc only there is no\nexplicit command line stuff from the user.\n"},{"id":"18524","messageId":"Pine.LNX.4.64.0604091702190.9504@g5.osdl.org","threadId":"3838","inReplyTo":"7vy7ye9uk8.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-04-10T00:06:15Z","receivedAt":"2006-04-10T00:06:15Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 9 Apr 2006, Junio C Hamano wrote:\n> \n> I do not think so.  You should default to --cc only there is no\n> explicit command line stuff from the user.\n\nActually, even that would be wrong, when I think more about it. The \ndefault for \"git-whatchanged\" is to do diffing, but default to the \"raw\" \ndiff (just \"-r\" for recursive).\n\nSo the most appropriate default set of flags is likely \"-r -c\", which also \nmeans that any subsequent explicit command line stuff will override it (ie \nadding a \"-p\" should automatically do the right thing).\n\nBut the \"memmove()\" to move the arguments around was definitely broken. \nMuch better to just initialize the diff flags manually, I think.\n\n\t\tLinus\n"},{"id":"18535","messageId":"Pine.LNX.4.63.0604101010001.31612@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"3838","inReplyTo":"20060410012258.589f1581.tihirvon@gmail.com","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-04-10T08:10:41Z","receivedAt":"2006-04-10T08:10:41Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 10 Apr 2006, Timo Hirvonen wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> \n> > +static int cmd_whatchanged(int argc, const char **argv, char **envp)\n> > +{\n> > +\tmemmove(argv + 2, argv + 1, argc - 1);\n> \n> Shouldn't the size be sizeof(char *) * argc (NULL terminated array)?\n> There's also overflow...\n\nYeah, this was some useless late-night coding. But you get the idea.\n\nCiao,\nDscho\n"},{"id":"18537","messageId":"Pine.LNX.4.63.0604101018530.31612@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"3838","inReplyTo":"7vy7ye9uk8.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-04-10T08:22:52Z","receivedAt":"2006-04-10T08:22:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 9 Apr 2006, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > Hi,\n> >\n> > On Sun, 9 Apr 2006, Johannes Schindelin wrote:\n> >\n> >> On Sun, 9 Apr 2006, Linus Torvalds wrote:\n> >> \n> >> >  - keep it - for historical reasons - as a internal shorthand, and just \n> >> >    turn it into \"git log --diff -cc\"\n> >> \n> >> It is \"git log --cc\", right?\n> >\n> > Like this?\n> \n> I do not think so.  You should default to --cc only there is no\n> explicit command line stuff from the user.\n\nWell, my idea was to get rid of the whatchanged script, and deprecate the \ninternal whatchanged. IMHO \"git log\" is much faster typed than \"git \nwhatchanged\", especially if you have no completion installed. I, for one, \nwill never ever again use whatchanged.\n\nBut you and the list gave me bad marks for that patch, and rightfully so.\n\nCiao,\nDscho\n"},{"id":"18546","messageId":"7vodz980az.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"Pine.LNX.4.64.0604090950590.9504@g5.osdl.org","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-10T23:42:44Z","receivedAt":"2006-04-10T23:42:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Sun, 9 Apr 2006, Junio C Hamano wrote:\n>>\n>> And this makes \"git log\" to take common diff-tree options, so\n>> that it can be used as \"git whatchanged\".\n>\n> I wonder... This all looks fine, but there are actually two different \n> \"diffs\" that can be shown for \"git log --diff <pathlimiter>\":\n>\n>  - the whole diff for a commit\n>\n>  - the path-limited diff\n>\n> and I think we'd likely want to have some way to select the output. \n> Probably with the path-limited diff being the default (that's what \n> \"git-whatchanged\" does), but perhaps with \"--full-diff\" showing the whole \n> commit diff (which is what \"gitk\" does).\n\nYes, but it turns out it is a bit tricky, given that the way\ntree-diff.c is written it pretty much assumes the same pathspec\nis used for diff operation during the lifetime of the process.\n\nI think we should move (nr_paths, pathlens and paths) to struct\ndiff_options.  Two patches to follow shortly.\n"},{"id":"18547","messageId":"7virph809g.fsf_-_@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"7vodz980az.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] tree-diff: do not assume we use only one pathspec","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-10T23:43:39Z","receivedAt":"2006-04-10T23:43:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The way tree-diff was set up assumed we would use only one set\nof pathspec during the entire life of the program.  Move the\npathspec related static variables out to diff_options structure\nso that we can filter commits with one set of paths while show\nthe actual diffs using different set of paths.\n\nI suspect this breaks blame.c, and makes \"git log paths...\" to\ndefault to the --full-diff, the latter of which is dealt with\nthe next commit.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n diff-tree.c |    2 +-\n diff.h      |    6 +++++-\n revision.c  |    2 +-\n tree-diff.c |   46 +++++++++++++++++++++++++---------------------\n 4 files changed, 32 insertions(+), 24 deletions(-)\n\nbe7b412689f723a1008b40712d9f0b96773ad81a\ndiff --git a/diff-tree.c b/diff-tree.c\nindex 2a088d1..2b79dd0 100644\n--- a/diff-tree.c\n+++ b/diff-tree.c\n@@ -120,7 +120,7 @@ int main(int argc, const char **argv)\n \tif (opt->diffopt.output_format == DIFF_FORMAT_PATCH)\n \t\topt->diffopt.recursive = 1;\n \n-\tdiff_tree_setup_paths(get_pathspec(prefix, argv));\n+\tdiff_tree_setup_paths(get_pathspec(prefix, argv), opt);\n \tdiff_setup_done(&opt->diffopt);\n \n \tswitch (nr_sha1) {\ndiff --git a/diff.h b/diff.h\nindex a02ef28..cc7cc62 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -38,11 +38,15 @@ struct diff_options {\n \tint setup;\n \tint abbrev;\n \n+\tint nr_paths;\n+\tconst char **paths;\n+\tint *pathlens;\n \tchange_fn_t change;\n \tadd_remove_fn_t add_remove;\n };\n \n-extern void diff_tree_setup_paths(const char **paths);\n+extern void diff_tree_setup_paths(const char **paths, struct diff_options *);\n+extern void diff_tree_release_paths(struct diff_options *);\n extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,\n \t\t     const char *base, struct diff_options *opt);\n extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,\ndiff --git a/revision.c b/revision.c\nindex fe26562..634f9a5 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -707,7 +707,7 @@ int setup_revisions(int argc, const char\n \t\trevs->limited = 1;\n \n \tif (revs->prune_data) {\n-\t\tdiff_tree_setup_paths(revs->prune_data);\n+\t\tdiff_tree_setup_paths(revs->prune_data, &diff_opt);\n \t\trevs->prune_fn = try_to_simplify_commit;\n \t}\n \ndiff --git a/tree-diff.c b/tree-diff.c\nindex 701fbba..1cdf8aa 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -5,11 +5,6 @@ #include \"cache.h\"\n #include \"diff.h\"\n #include \"tree.h\"\n \n-// What paths are we interested in?\n-static int nr_paths = 0;\n-static const char **paths = NULL;\n-static int *pathlens = NULL;\n-\n static char *malloc_base(const char *base, const char *path, int pathlen)\n {\n \tint baselen = strlen(base);\n@@ -72,14 +67,14 @@ static int compare_tree_entry(struct tre\n \treturn 0;\n }\n \n-static int interesting(struct tree_desc *desc, const char *base)\n+static int interesting(struct tree_desc *desc, const char *base, struct diff_options *opt)\n {\n \tconst char *path;\n \tunsigned mode;\n \tint i;\n \tint baselen, pathlen;\n \n-\tif (!nr_paths)\n+\tif (!opt->nr_paths)\n \t\treturn 1;\n \n \t(void)tree_entry_extract(desc, &path, &mode);\n@@ -87,9 +82,9 @@ static int interesting(struct tree_desc \n \tpathlen = strlen(path);\n \tbaselen = strlen(base);\n \n-\tfor (i=0; i < nr_paths; i++) {\n-\t\tconst char *match = paths[i];\n-\t\tint matchlen = pathlens[i];\n+\tfor (i=0; i < opt->nr_paths; i++) {\n+\t\tconst char *match = opt->paths[i];\n+\t\tint matchlen = opt->pathlens[i];\n \n \t\tif (baselen >= matchlen) {\n \t\t\t/* If it doesn't match, move along... */\n@@ -129,7 +124,7 @@ static int interesting(struct tree_desc \n static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base)\n {\n \twhile (desc->size) {\n-\t\tif (interesting(desc, base))\n+\t\tif (interesting(desc, base, opt))\n \t\t\tshow_entry(opt, prefix, desc, base);\n \t\tupdate_tree_entry(desc);\n \t}\n@@ -167,11 +162,11 @@ static int show_entry(struct diff_option\n int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)\n {\n \twhile (t1->size | t2->size) {\n-\t\tif (nr_paths && t1->size && !interesting(t1, base)) {\n+\t\tif (opt->nr_paths && t1->size && !interesting(t1, base, opt)) {\n \t\t\tupdate_tree_entry(t1);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (nr_paths && t2->size && !interesting(t2, base)) {\n+\t\tif (opt->nr_paths && t2->size && !interesting(t2, base, opt)) {\n \t\t\tupdate_tree_entry(t2);\n \t\t\tcontinue;\n \t\t}\n@@ -229,19 +224,28 @@ static int count_paths(const char **path\n \treturn i;\n }\n \n-void diff_tree_setup_paths(const char **p)\n+void diff_tree_release_paths(struct diff_options *opt)\n {\n+\tfree(opt->pathlens);\n+}\n+\n+void diff_tree_setup_paths(const char **p, struct diff_options *opt)\n+{\n+\topt->nr_paths = 0;\n+\topt->pathlens = NULL;\n+\topt->paths = NULL;\n+\n \tif (p) {\n \t\tint i;\n \n-\t\tpaths = p;\n-\t\tnr_paths = count_paths(paths);\n-\t\tif (nr_paths == 0) {\n-\t\t\tpathlens = NULL;\n+\t\topt->paths = p;\n+\t\topt->nr_paths = count_paths(p);\n+\t\tif (opt->nr_paths == 0) {\n+\t\t\topt->pathlens = NULL;\n \t\t\treturn;\n \t\t}\n-\t\tpathlens = xmalloc(nr_paths * sizeof(int));\n-\t\tfor (i=0; i<nr_paths; i++)\n-\t\t\tpathlens[i] = strlen(paths[i]);\n+\t\topt->pathlens = xmalloc(opt->nr_paths * sizeof(int));\n+\t\tfor (i=0; i < opt->nr_paths; i++)\n+\t\t\topt->pathlens[i] = strlen(p[i]);\n \t}\n }\n-- \n1.3.0.rc3.g910a\n"},{"id":"18548","messageId":"7vek05808p.fsf_-_@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"7vodz980az.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] git log --full-diff","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-10T23:44:06Z","receivedAt":"2006-04-10T23:44:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Without this flag, \"git log -p paths...\" shows commits that\ntouch the specified paths, and diffs about the same specified\npaths.  With this, the full diff is shown for commits that touch\nthe specified paths.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n git.c |   13 ++++++++++++-\n 1 files changed, 12 insertions(+), 1 deletions(-)\n\nfd3ed3d9667e034b90aad02b4f9e5efcc61f1ce3\ndiff --git a/git.c b/git.c\nindex 8776088..ad896da 100644\n--- a/git.c\n+++ b/git.c\n@@ -288,7 +288,9 @@ static int cmd_log(int argc, const char \n \tint abbrev_commit = 0;\n \tconst char *commit_prefix = \"commit \";\n \tstruct log_tree_opt opt;\n+\tint shown = 0;\n \tint do_diff = 0;\n+\tint full_diff = 0;\n \n \tinit_log_tree_opt(&opt);\n \targc = setup_revisions(argc, argv, &rev, \"HEAD\");\n@@ -315,6 +317,10 @@ static int cmd_log(int argc, const char \n \t\t\telse if (40 < abbrev)\n \t\t\t\tabbrev = 40;\n \t\t}\n+\t\telse if (!strcmp(arg, \"--full-diff\")) {\n+\t\t\tdo_diff = 1;\n+\t\t\tfull_diff = 1;\n+\t\t}\n \t\telse {\n \t\t\tint cnt = log_tree_opt_parse(&opt, argv+1, argc-1);\n \t\t\tif (0 < cnt) {\n@@ -328,6 +334,7 @@ static int cmd_log(int argc, const char \n \n \t\targc--; argv++;\n \t}\n+\n \tif (do_diff) {\n \t\topt.diffopt.abbrev = abbrev;\n \t\topt.verbose_header = 0;\n@@ -339,12 +346,16 @@ static int cmd_log(int argc, const char \n \t\t\topt.diffopt.output_format = DIFF_FORMAT_PATCH;\n \t\tif (opt.diffopt.output_format == DIFF_FORMAT_PATCH)\n \t\t\topt.diffopt.recursive = 1;\n+\t\tif (!full_diff && rev.prune_data)\n+\t\t\tdiff_tree_setup_paths(rev.prune_data, &opt.diffopt);\n \t\tdiff_setup_done(&opt.diffopt);\n \t}\n \n \tprepare_revision_walk(&rev);\n \tsetup_pager();\n \twhile ((commit = get_revision(&rev)) != NULL) {\n+\t\tif (commit_format != CMIT_FMT_ONELINE && shown)\n+\t\t\tputchar('\\n');\n \t\tfputs(commit_prefix, stdout);\n \t\tif (abbrev_commit && abbrev)\n \t\t\tfputs(find_unique_abbrev(commit->object.sha1, abbrev),\n@@ -377,9 +388,9 @@ static int cmd_log(int argc, const char \n \t\tpretty_print_commit(commit_format, commit, ~0, buf,\n \t\t\t\t    LOGSIZE, abbrev);\n \t\tprintf(\"%s\\n\", buf);\n-\n \t\tif (do_diff)\n \t\t\tlog_tree_commit(&opt, commit);\n+\t\tshown = 1;\n \t}\n \tfree(buf);\n \treturn 0;\n-- \n1.3.0.rc3.g910a\n"},{"id":"18549","messageId":"Pine.LNX.4.64.0604101652220.2998@g5.osdl.org","threadId":"3838","inReplyTo":"7vodz980az.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-04-10T23:54:19Z","receivedAt":"2006-04-10T23:54:19Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 10 Apr 2006, Junio C Hamano wrote:\n> >\n> > and I think we'd likely want to have some way to select the output. \n> > Probably with the path-limited diff being the default (that's what \n> > \"git-whatchanged\" does), but perhaps with \"--full-diff\" showing the whole \n> > commit diff (which is what \"gitk\" does).\n> \n> Yes, but it turns out it is a bit tricky, given that the way\n> tree-diff.c is written it pretty much assumes the same pathspec\n> is used for diff operation during the lifetime of the process.\n\nHmm.. The hacky approach would seem to be to just call \n\"diff_tree_setup_paths()\" just before doing the diff (and re-set it \nafterwards). That should work, I don't think we keep any real state \naround.\n\n> I think we should move (nr_paths, pathlens and paths) to struct\n> diff_options.  Two patches to follow shortly.\n\nThat certainly seems to be the cleanest option. Not just because it should \nsolve this problem, but because it's also what looks most natural anyway \n(and matches the \"struct revs\" approach).\n\n\t\tLinus\n"},{"id":"18552","messageId":"86k69xasg0.fsf@blue.stonehenge.com","threadId":"3838","inReplyTo":"Pine.LNX.4.63.0604092312340.29136@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2006-04-11T00:04:15Z","receivedAt":"2006-04-11T00:04:15Z","isPatch":true,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Johannes\" == Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\nJohannes> Hi,\nJohannes> On Sun, 9 Apr 2006, Linus Torvalds wrote:\n\n>> - keep it - for historical reasons - as a internal shorthand, and just \n>> turn it into \"git log --diff -cc\"\n\nJohannes> It is \"git log --cc\", right? And BTW, I was burnt by the difference of \nJohannes> \"git-log\" and \"git log\" this time. \"git-log\" does not understand \"--cc\". \nJohannes> Could we kill \"git-log\", please?\n\nWait.  Why is there a git log and a git-log?  Shouldn't those\nbe *absolutely* identical?  Or have we now finally diverged, violating\nrules that were established earlier?\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"18554","messageId":"7vveth6kdg.fsf@assigned-by-dhcp.cox.net","threadId":"3838","inReplyTo":"86k69xasg0.fsf@blue.stonehenge.com","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-11T00:12:11Z","receivedAt":"2006-04-11T00:12:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"merlyn@stonehenge.com (Randal L. Schwartz) writes:\n\n> Wait.  Why is there a git log and a git-log?  Shouldn't those\n> be *absolutely* identical?  Or have we now finally diverged, violating\n> rules that were established earlier?\n\nWhat rule ;-)?\n\nI kept \"git-log.sh\" for two reasons.  (1) to see how long it\ntakes people to notice, and (2) to have a handy way to verify\npotential regressions.\n\nThere is no reason for them to be *absolutely* identical -- if\nthe git.c embedded one turns out to be usable, useful and even\nsuperiour, git-log.sh based one should be retired, and will be\nmade again as synonyms, perhaps like this:\n\n--\ndiff --git a/Makefile b/Makefile\nindex a979205..5239526 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -116,7 +116,7 @@ SCRIPT_SH = \\\n \tgit-add.sh git-bisect.sh git-branch.sh git-checkout.sh \\\n \tgit-cherry.sh git-clean.sh git-clone.sh git-commit.sh \\\n \tgit-count-objects.sh git-diff.sh git-fetch.sh \\\n-\tgit-format-patch.sh git-log.sh git-ls-remote.sh \\\n+\tgit-format-patch.sh git-ls-remote.sh \\\n \tgit-merge-one-file.sh git-parse-remote.sh \\\n \tgit-prune.sh git-pull.sh git-push.sh git-rebase.sh \\\n \tgit-repack.sh git-request-pull.sh git-reset.sh \\\n@@ -167,6 +167,8 @@ PROGRAMS = \\\n \tgit-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \\\n \tgit-describe$X git-merge-tree$X git-blame$X git-imap-send$X\n \n+BUILT_INS = git-log$X\n+\n # what 'all' will build and 'install' will install, in gitexecdir\n ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)\n \n@@ -448,7 +450,7 @@ LIB_OBJS += $(COMPAT_OBJS)\n export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir\n ### Build rules\n \n-all: $(ALL_PROGRAMS) git$X gitk\n+all: $(ALL_PROGRAMS) git$X $(BUILT_INS) gitk\n \n all:\n \t$(MAKE) -C templates\n@@ -460,6 +462,9 @@ git$X: git.c common-cmds.h $(GITLIBS)\n \t$(CC) -DGIT_VERSION='\"$(GIT_VERSION)\"' \\\n \t\t$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \\\n \t\t$(ALL_LDFLAGS) $(LIBS)\n+\n+$(BUILT_INS): git$X\n+\trm -f $@ && ln git$X $@\n \n common-cmds.h: Documentation/git-*.txt\n \t./generate-cmdlist.sh > $@\n@@ -642,7 +647,7 @@ ### Cleaning rules\n \n clean:\n \trm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \\\n-\t\t$(LIB_FILE) $(XDIFF_LIB)\n+\t\t$(LIB_FILE) $(XDIFF_LIB) $(BUILT_INS)\n \trm -f $(ALL_PROGRAMS) git$X\n \trm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags\n \trm -rf $(GIT_TARNAME)\n"},{"id":"18556","messageId":"20060411003126.GX27689@pasky.or.cz","threadId":"3838","inReplyTo":"7vveth6kdg.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-04-11T00:31:26Z","receivedAt":"2006-04-11T00:31:26Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Tue, Apr 11, 2006 at 02:12:11AM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> said that...\n> There is no reason for them to be *absolutely* identical\n\nOne is that people expect them to be. It's been implied that \"git xyzzy\"\nis functionally fully equivalent to \"git-xyzzy\" for too long to silently\nbreak this now.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nRight now I am having amnesia and deja-vu at the same time.  I think\nI have forgotten this before.\n"},{"id":"18558","messageId":"861ww5aqb1.fsf@blue.stonehenge.com","threadId":"3838","inReplyTo":"20060411003126.GX27689@pasky.or.cz","subject":"Re: [PATCH] git log [diff-tree options]...","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2006-04-11T00:50:26Z","receivedAt":"2006-04-11T00:50:26Z","isPatch":true,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Petr\" == Petr Baudis <pasky@suse.cz> writes:\n\nPetr> Dear diary, on Tue, Apr 11, 2006 at 02:12:11AM CEST, I got a letter\nPetr> where Junio C Hamano <junkio@cox.net> said that...\n>> There is no reason for them to be *absolutely* identical\n\nPetr> One is that people expect them to be. It's been implied that \"git xyzzy\"\nPetr> is functionally fully equivalent to \"git-xyzzy\" for too long to silently\nPetr> break this now.\n\nYes, this is what I was referencing.  I would *never* have considered\nthat git-log and \"git log\" be different things now that it's been firmly\nengrained that they are the same.  Please don't violate the model.\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"}]}