{"thread":{"id":"47735","subject":"[PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","startedAt":"2018-02-01T13:02:37Z","lastAt":"2018-02-27T23:24:51Z","messageCount":19,"participants":["Nguyễn Thái Ngọc Duy","Junio C Hamano","Duy Nguyen","Eric Sunshine"],"isPatch":true,"patchVersion":3,"patchTotal":2},"messages":[{"id":"338026","messageId":"20180201130221.15563-1-pclouds@gmail.com","threadId":"47735","inReplyTo":null,"subject":"[PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-01T13:02:19Z","receivedAt":"2018-02-01T13:02:37Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Changes since v2 [1]:\n\n- goes back to my original version (yay!) where the extra info\n  is appended after the path name. More is described in 2/2\n- --compact-summary is now renamed --stat-with-summary and implies\n  --stat\n- 1/2 is just a cleanup patch to make it easier to add 2/2\n\n[1] https://public-inbox.org/git/20180118100546.32251-1-pclouds@gmail.com/\n\nNguyễn Thái Ngọc Duy (2):\n  diff.c: refactor pprint_rename() to use strbuf\n  diff: add --stat-with-summary\n\n Documentation/diff-options.txt                     |   8 ++\n diff.c                                             | 101 ++++++++++++++-------\n diff.h                                             |   1 +\n t/t4013-diff-various.sh                            |   5 +\n ...pretty_--root_--stat-with-summary_initial (new) |  12 +++\n ...tty_-R_--root_--stat-with-summary_initial (new) |  12 +++\n ...iff-tree_--stat-with-summary_initial_mode (new) |   4 +\n ...-tree_-R_--stat-with-summary_initial_mode (new) |   4 +\n 8 files changed, 113 insertions(+), 34 deletions(-)\n\n-- \n2.16.1.75.ga05e3333b4\n\n"},{"id":"338027","messageId":"20180201130221.15563-2-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180201130221.15563-1-pclouds@gmail.com","subject":"[PATCH v3 1/2] diff.c: refactor pprint_rename() to use strbuf","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-01T13:02:20Z","receivedAt":"2018-02-01T13:02:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Instead of passing char* around, let function handle strbuf\ndirectly. All callers already use strbuf internally.\n\nThis helps kill the \"not free\" exception in free_diffstat_info(). I\ndon't think this code is so critical that we need to avoid some free()\ncalls.\n\nThe other benefit comes in the next patch, where we append something\nin pname before returning from fill_print_name(). With strbuf, it's\nvery simple. With \"char *\" we may have to resort to explicit\nreallocation and stuff.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n diff.c | 59 ++++++++++++++++++++++++++--------------------------------\n 1 file changed, 26 insertions(+), 33 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 0a9a0cdf18..9d874a670f 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2045,11 +2045,10 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)\n \t}\n }\n \n-static char *pprint_rename(const char *a, const char *b)\n+static void pprint_rename(struct strbuf *name, const char *a, const char *b)\n {\n \tconst char *old = a;\n \tconst char *new = b;\n-\tstruct strbuf name = STRBUF_INIT;\n \tint pfx_length, sfx_length;\n \tint pfx_adjust_for_slash;\n \tint len_a = strlen(a);\n@@ -2059,10 +2058,10 @@ static char *pprint_rename(const char *a, const char *b)\n \tint qlen_b = quote_c_style(b, NULL, NULL, 0);\n \n \tif (qlen_a || qlen_b) {\n-\t\tquote_c_style(a, &name, NULL, 0);\n-\t\tstrbuf_addstr(&name, \" => \");\n-\t\tquote_c_style(b, &name, NULL, 0);\n-\t\treturn strbuf_detach(&name, NULL);\n+\t\tquote_c_style(a, name, NULL, 0);\n+\t\tstrbuf_addstr(name, \" => \");\n+\t\tquote_c_style(b, name, NULL, 0);\n+\t\treturn;\n \t}\n \n \t/* Find common prefix */\n@@ -2109,19 +2108,18 @@ static char *pprint_rename(const char *a, const char *b)\n \tif (b_midlen < 0)\n \t\tb_midlen = 0;\n \n-\tstrbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);\n+\tstrbuf_grow(name, pfx_length + a_midlen + b_midlen + sfx_length + 7);\n \tif (pfx_length + sfx_length) {\n-\t\tstrbuf_add(&name, a, pfx_length);\n-\t\tstrbuf_addch(&name, '{');\n+\t\tstrbuf_add(name, a, pfx_length);\n+\t\tstrbuf_addch(name, '{');\n \t}\n-\tstrbuf_add(&name, a + pfx_length, a_midlen);\n-\tstrbuf_addstr(&name, \" => \");\n-\tstrbuf_add(&name, b + pfx_length, b_midlen);\n+\tstrbuf_add(name, a + pfx_length, a_midlen);\n+\tstrbuf_addstr(name, \" => \");\n+\tstrbuf_add(name, b + pfx_length, b_midlen);\n \tif (pfx_length + sfx_length) {\n-\t\tstrbuf_addch(&name, '}');\n-\t\tstrbuf_add(&name, a + len_a - sfx_length, sfx_length);\n+\t\tstrbuf_addch(name, '}');\n+\t\tstrbuf_add(name, a + len_a - sfx_length, sfx_length);\n \t}\n-\treturn strbuf_detach(&name, NULL);\n }\n \n struct diffstat_t {\n@@ -2197,23 +2195,17 @@ static void show_graph(struct strbuf *out, char ch, int cnt,\n \n static void fill_print_name(struct diffstat_file *file)\n {\n-\tchar *pname;\n+\tstruct strbuf pname = STRBUF_INIT;\n \n \tif (file->print_name)\n \t\treturn;\n \n-\tif (!file->is_renamed) {\n-\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tif (quote_c_style(file->name, &buf, NULL, 0)) {\n-\t\t\tpname = strbuf_detach(&buf, NULL);\n-\t\t} else {\n-\t\t\tpname = file->name;\n-\t\t\tstrbuf_release(&buf);\n-\t\t}\n-\t} else {\n-\t\tpname = pprint_rename(file->from_name, file->name);\n-\t}\n-\tfile->print_name = pname;\n+\tif (file->is_renamed)\n+\t\tpprint_rename(&pname, file->from_name, file->name);\n+\telse\n+\t\tquote_c_style(file->name, &pname, NULL, 0);\n+\n+\tfile->print_name = strbuf_detach(&pname, NULL);\n }\n \n static void print_stat_summary_inserts_deletes(struct diff_options *options,\n@@ -2797,8 +2789,7 @@ static void free_diffstat_info(struct diffstat_t *diffstat)\n \tint i;\n \tfor (i = 0; i < diffstat->nr; i++) {\n \t\tstruct diffstat_file *f = diffstat->files[i];\n-\t\tif (f->name != f->print_name)\n-\t\t\tfree(f->print_name);\n+\t\tfree(f->print_name);\n \t\tfree(f->name);\n \t\tfree(f->from_name);\n \t\tfree(f);\n@@ -5241,10 +5232,12 @@ static void show_rename_copy(struct diff_options *opt, const char *renamecopy,\n \t\tstruct diff_filepair *p)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-\tchar *names = pprint_rename(p->one->path, p->two->path);\n+\tstruct strbuf names = STRBUF_INIT;\n+\n+\tpprint_rename(&names, p->one->path, p->two->path);\n \tstrbuf_addf(&sb, \" %s %s (%d%%)\\n\",\n-\t\t\trenamecopy, names, similarity_index(p));\n-\tfree(names);\n+\t\t    renamecopy, names.buf, similarity_index(p));\n+\tstrbuf_release(&names);\n \temit_diff_symbol(opt, DIFF_SYMBOL_SUMMARY,\n \t\t\t\t sb.buf, sb.len, 0);\n \tshow_mode_change(opt, p, 0);\n-- \n2.16.1.75.ga05e3333b4\n\n"},{"id":"338028","messageId":"20180201130221.15563-3-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180201130221.15563-1-pclouds@gmail.com","subject":"[PATCH v3 2/2] diff: add --stat-with-summary","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-01T13:02:21Z","receivedAt":"2018-02-01T13:02:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Certain information is currently shown with --summary, but when used\nin combination with --stat it's a bit hard to read since info of the\nsame file is in two places (--stat and --summary).\n\nOn top of that, commits that add or remove files double the number of\ndisplay lines, which could be a lot if you add or remove a lot of\nfiles.\n\n--stat-with-summary embeds most of --summary back in --stat in the\nlittle space between the file name part and the graph line, e.g. with\ncommit 0433d533f1:\n\n   Documentation/merge-config.txt         |  4 +\n   builtin/merge.c                        |  2 +\n   ...-pull-verify-signatures.sh (new +x) | 81 ++++++++++++++\n   t/t7612-merge-verify-signatures.sh     | 45 ++++++++\n   4 files changed, 132 insertions(+)\n\nIt helps both condensing information and saving some text\nspace. What's new in diffstat is:\n\n- A new 0644 file is shown as (new)\n- A new 0755 file is shown as (new +x)\n- A new symlink is shown as (new +l)\n- A deleted file is shown as (gone)\n- A mode change adding executable bit is shown as (mode +x)\n- A mode change removing it is shown as (mode -x)\n\nNote that --stat-with-summary does not contain all the information\n--summary provides. Rewrite percentage is not shown but it could be\nadded later, like R50% or C20%.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/diff-options.txt                |  8 ++++\n diff.c                                        | 42 ++++++++++++++++++-\n diff.h                                        |  1 +\n t/t4013-diff-various.sh                       |  5 +++\n ...-pretty_--root_--stat-with-summary_initial | 12 ++++++\n ...etty_-R_--root_--stat-with-summary_initial | 12 ++++++\n ...diff-tree_--stat-with-summary_initial_mode |  4 ++\n ...f-tree_-R_--stat-with-summary_initial_mode |  4 ++\n 8 files changed, 87 insertions(+), 1 deletion(-)\n create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--stat-with-summary_initial_mode\n create mode 100644 t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex c330c01ff0..595e4cd548 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -128,6 +128,14 @@ have to use `--diff-algorithm=default` option.\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\n \n+--stat-with-summary::\n+\tOutput a condensed summary of extended header information such\n+\tas file creations or deletions (\"new\" or \"gone\", optionally \"+l\"\n+\tif it's a symlink) and mode changes (\"+x\" or \"-x\" for adding\n+\tor removing executable bit respectively) in diffstat. The\n+\tinformation is put betwen the filename part and the graph\n+\tpart. Implies `--stat`.\n+\n --numstat::\n \tSimilar to `--stat`, but shows number of added and\n \tdeleted lines in decimal notation and pathname without\ndiff --git a/diff.c b/diff.c\nindex 9d874a670f..6bf9867388 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2129,6 +2129,7 @@ struct diffstat_t {\n \t\tchar *from_name;\n \t\tchar *name;\n \t\tchar *print_name;\n+\t\tconst char *comments;\n \t\tunsigned is_unmerged:1;\n \t\tunsigned is_binary:1;\n \t\tunsigned is_renamed:1;\n@@ -2205,6 +2206,9 @@ static void fill_print_name(struct diffstat_file *file)\n \telse\n \t\tquote_c_style(file->name, &pname, NULL, 0);\n \n+\tif (file->comments)\n+\t\tstrbuf_addf(&pname, \" (%s)\", file->comments);\n+\n \tfile->print_name = strbuf_detach(&pname, NULL);\n }\n \n@@ -3239,6 +3243,32 @@ static void builtin_diff(const char *name_a,\n \treturn;\n }\n \n+static char *get_compact_summary(const struct diff_filepair *p, int is_renamed)\n+{\n+\tif (!is_renamed) {\n+\t\tif (p->status == DIFF_STATUS_ADDED) {\n+\t\t\tif (S_ISLNK(p->two->mode))\n+\t\t\t\treturn \"new +l\";\n+\t\t\telse if ((p->two->mode & 0777) == 0755)\n+\t\t\t\treturn \"new +x\";\n+\t\t\telse\n+\t\t\t\treturn \"new\";\n+\t\t} else if (p->status == DIFF_STATUS_DELETED)\n+\t\t\treturn \"gone\";\n+\t}\n+\tif (S_ISLNK(p->one->mode) && !S_ISLNK(p->two->mode))\n+\t\treturn \"mode -l\";\n+\telse if (!S_ISLNK(p->one->mode) && S_ISLNK(p->two->mode))\n+\t\treturn \"mode +l\";\n+\telse if ((p->one->mode & 0777) == 0644 &&\n+\t\t (p->two->mode & 0777) == 0755)\n+\t\treturn \"mode +x\";\n+\telse if ((p->one->mode & 0777) == 0755 &&\n+\t\t (p->two->mode & 0777) == 0644)\n+\t\treturn \"mode -x\";\n+\treturn NULL;\n+}\n+\n static void builtin_diffstat(const char *name_a, const char *name_b,\n \t\t\t     struct diff_filespec *one,\n \t\t\t     struct diff_filespec *two,\n@@ -3258,6 +3288,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,\n \n \tdata = diffstat_add(diffstat, name_a, name_b);\n \tdata->is_interesting = p->status != DIFF_STATUS_UNKNOWN;\n+\tif (o->flags.stat_with_summary)\n+\t\tdata->comments = get_compact_summary(p, data->is_renamed);\n \n \tif (!one || !two) {\n \t\tdata->is_unmerged = 1;\n@@ -4300,6 +4332,7 @@ static int stat_opt(struct diff_options *options, const char **av)\n \tint graph_width = options->stat_graph_width;\n \tint count = options->stat_count;\n \tint argcount = 1;\n+\tunsigned with_summary = options->flags.stat_with_summary;\n \n \tif (!skip_prefix(arg, \"--stat\", &arg))\n \t\tdie(\"BUG: stat option does not begin with --stat: %s\", arg);\n@@ -4343,6 +4376,9 @@ static int stat_opt(struct diff_options *options, const char **av)\n \t\t\t\tcount = strtoul(av[1], &end, 10);\n \t\t\t\targcount = 2;\n \t\t\t}\n+\t\t} else if (skip_prefix(arg, \"-with-summary\", &arg)) {\n+\t\t\twith_summary = 1;\n+\t\t\tend = (char*)arg;\n \t\t}\n \t\tbreak;\n \tcase '=':\n@@ -4361,6 +4397,7 @@ static int stat_opt(struct diff_options *options, const char **av)\n \toptions->stat_graph_width = graph_width;\n \toptions->stat_width = width;\n \toptions->stat_count = count;\n+\toptions->flags.stat_with_summary = with_summary;\n \treturn argcount;\n }\n \n@@ -4542,7 +4579,10 @@ int diff_opt_parse(struct diff_options *options,\n \telse if (!strcmp(arg, \"-s\") || !strcmp(arg, \"--no-patch\"))\n \t\toptions->output_format |= DIFF_FORMAT_NO_OUTPUT;\n \telse if (starts_with(arg, \"--stat\"))\n-\t\t/* --stat, --stat-width, --stat-name-width, or --stat-count */\n+\t\t/*\n+\t\t * --stat, --stat-width, --stat-name-width,\n+\t\t * --stat-count or --stat-with-summary.\n+\t\t */\n \t\treturn stat_opt(options, av);\n \n \t/* renames options */\ndiff --git a/diff.h b/diff.h\nindex 6bd278aac1..d29560f822 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -93,6 +93,7 @@ struct diff_flags {\n \tunsigned dirstat_by_line:1;\n \tunsigned funccontext:1;\n \tunsigned default_follow_renames:1;\n+\tunsigned stat_with_summary:1;\n };\n \n static inline void diff_flags_or(struct diff_flags *a,\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex f10798b2df..aa6f5da21c 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -361,6 +361,11 @@ diff --no-index --raw dir2 dir\n diff --no-index --raw --abbrev=4 dir2 dir\n :noellipses diff --no-index --raw --abbrev=4 dir2 dir\n diff --no-index --raw --no-abbrev dir2 dir\n+\n+diff-tree --pretty --root --stat-with-summary initial\n+diff-tree --pretty -R --root --stat-with-summary initial\n+diff-tree --stat-with-summary initial mode\n+diff-tree -R --stat-with-summary initial mode\n EOF\n \n test_expect_success 'log -S requires an argument' '\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial\nnew file mode 100644\nindex 0000000000..105f29a92d\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial\n@@ -0,0 +1,12 @@\n+$ git diff-tree --pretty --root --stat-with-summary initial\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+\n+ dir/sub (new) | 2 ++\n+ file0 (new)   | 3 +++\n+ file2 (new)   | 3 +++\n+ 3 files changed, 8 insertions(+)\n+$\ndiff --git a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial\nnew file mode 100644\nindex 0000000000..45008d09fc\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial\n@@ -0,0 +1,12 @@\n+$ git diff-tree --pretty -R --root --stat-with-summary initial\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+\n+ dir/sub (gone) | 2 --\n+ file0 (gone)   | 3 ---\n+ file2 (gone)   | 3 ---\n+ 3 files changed, 8 deletions(-)\n+$\ndiff --git a/t/t4013/diff.diff-tree_--stat-with-summary_initial_mode b/t/t4013/diff.diff-tree_--stat-with-summary_initial_mode\nnew file mode 100644\nindex 0000000000..f99fcdc101\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--stat-with-summary_initial_mode\n@@ -0,0 +1,4 @@\n+$ git diff-tree --stat-with-summary initial mode\n+ file0 (mode +x) | 0\n+ 1 file changed, 0 insertions(+), 0 deletions(-)\n+$\ndiff --git a/t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode b/t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode\nnew file mode 100644\nindex 0000000000..8dc8f3fe95\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode\n@@ -0,0 +1,4 @@\n+$ git diff-tree -R --stat-with-summary initial mode\n+ file0 (mode -x) | 0\n+ 1 file changed, 0 insertions(+), 0 deletions(-)\n+$\n-- \n2.16.1.75.ga05e3333b4\n\n"},{"id":"338116","messageId":"xmqqefm3cgd7.fsf@gitster-ct.c.googlers.com","threadId":"47735","inReplyTo":"20180201130221.15563-1-pclouds@gmail.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-02T19:59:32Z","receivedAt":"2018-02-02T19:59:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> Changes since v2 [1]:\n>\n> - goes back to my original version (yay!) where the extra info\n>   is appended after the path name. More is described in 2/2\n> - --compact-summary is now renamed --stat-with-summary and implies\n>   --stat\n> - 1/2 is just a cleanup patch to make it easier to add 2/2\n\nIt may be just me and other old timers, but --X-with-Y naming means\nquite different thing around these commands, and --stat-with-summary\nwould hint, at least to us, that it would behave as if the two\noptions \"--stat --summary\" are given at the same time.\n\nAnd from that point of view, the new name is a bit confusing one.\n\nThe patches themselves look excellent.  Thanks.\n"},{"id":"338212","messageId":"CACsJy8B5DYpSQnJiLK8r4naaBh0YWLGwn9FuvM6EhP74E4E_CA@mail.gmail.com","threadId":"47735","inReplyTo":"xmqqefm3cgd7.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-05T11:28:47Z","receivedAt":"2018-02-05T11:29:23Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sat, Feb 3, 2018 at 2:59 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> Changes since v2 [1]:\n>>\n>> - goes back to my original version (yay!) where the extra info\n>>   is appended after the path name. More is described in 2/2\n>> - --compact-summary is now renamed --stat-with-summary and implies\n>>   --stat\n>> - 1/2 is just a cleanup patch to make it easier to add 2/2\n>\n> It may be just me and other old timers, but --X-with-Y naming means\n> quite different thing around these commands, and --stat-with-summary\n> would hint, at least to us, that it would behave as if the two\n> options \"--stat --summary\" are given at the same time.\n>\n> And from that point of view, the new name is a bit confusing one.\n\nI don't have any good alternative name to be honest. It's kinda hard\nto come up with another word that says \"extended header information\nsuch as creations, renames and mode changes\", except maybe the vague\nname --stat-extended?\n-- \nDuy\n"},{"id":"338230","messageId":"xmqq8tc7b6yt.fsf@gitster-ct.c.googlers.com","threadId":"47735","inReplyTo":"CACsJy8B5DYpSQnJiLK8r4naaBh0YWLGwn9FuvM6EhP74E4E_CA@mail.gmail.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-05T18:56:58Z","receivedAt":"2018-02-05T18:57:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> On Sat, Feb 3, 2018 at 2:59 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>>\n>>> Changes since v2 [1]:\n>>>\n>>> - goes back to my original version (yay!) where the extra info\n>>>   is appended after the path name. More is described in 2/2\n>>> - --compact-summary is now renamed --stat-with-summary and implies\n>>>   --stat\n>>> - 1/2 is just a cleanup patch to make it easier to add 2/2\n>>\n>> It may be just me and other old timers, but --X-with-Y naming means\n>> quite different thing around these commands, and --stat-with-summary\n>> would hint, at least to us, that it would behave as if the two\n>> options \"--stat --summary\" are given at the same time.\n>>\n>> And from that point of view, the new name is a bit confusing one.\n>\n> I don't have any good alternative name to be honest. It's kinda hard\n> to come up with another word that says \"extended header information\n> such as creations, renames and mode changes\", except maybe the vague\n> name --stat-extended?\n\nI actually think compact-summary was a good way to phrase it.\n\nPersonally, I think it was a UI mistake that --summary can be given\nindependently with or without --stat (instead, there shouldn't have\nbeen the --summary option, and instead when it was added, --stat\njust should have gained an extra kind of output).  A single option\nthat can give both kinds of info may be a good way forward, so\nanother possibility may be --summary-in-stat (meaning: the info\ngiven by summary is included in stat output).  I dunno.\n\n"},{"id":"338497","messageId":"CACsJy8CQLnzX6vijE+WHE3_nwqVfFiNWFb_rcA-Lw_fvGf=aFw@mail.gmail.com","threadId":"47735","inReplyTo":"xmqq8tc7b6yt.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-06T10:20:11Z","receivedAt":"2018-02-06T10:20:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Feb 6, 2018 at 1:56 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> On Sat, Feb 3, 2018 at 2:59 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>>>\n>>>> Changes since v2 [1]:\n>>>>\n>>>> - goes back to my original version (yay!) where the extra info\n>>>>   is appended after the path name. More is described in 2/2\n>>>> - --compact-summary is now renamed --stat-with-summary and implies\n>>>>   --stat\n>>>> - 1/2 is just a cleanup patch to make it easier to add 2/2\n>>>\n>>> It may be just me and other old timers, but --X-with-Y naming means\n>>> quite different thing around these commands, and --stat-with-summary\n>>> would hint, at least to us, that it would behave as if the two\n>>> options \"--stat --summary\" are given at the same time.\n>>>\n>>> And from that point of view, the new name is a bit confusing one.\n>>\n>> I don't have any good alternative name to be honest. It's kinda hard\n>> to come up with another word that says \"extended header information\n>> such as creations, renames and mode changes\", except maybe the vague\n>> name --stat-extended?\n>\n> I actually think compact-summary was a good way to phrase it.\n>\n> Personally, I think it was a UI mistake that --summary can be given\n> independently with or without --stat (instead, there shouldn't have\n> been the --summary option, and instead when it was added, --stat\n> just should have gained an extra kind of output).  A single option\n> that can give both kinds of info may be a good way forward, so\n> another possibility may be --summary-in-stat (meaning: the info\n> given by summary is included in stat output).  I dunno.\n>\n\n+Eric maybe he has some idea (sorry I forgot to include people from\nthe last round).\n-- \nDuy\n"},{"id":"338599","messageId":"CAPig+cR9RycfLz0C6tXA4iPXdqoyczfij8CBaU4MmRGRmuRhSQ@mail.gmail.com","threadId":"47735","inReplyTo":"CACsJy8CQLnzX6vijE+WHE3_nwqVfFiNWFb_rcA-Lw_fvGf=aFw@mail.gmail.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-02-07T09:52:03Z","receivedAt":"2018-02-07T09:52:10Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Feb 6, 2018 at 5:20 AM, Duy Nguyen <pclouds@gmail.com> wrote:\n> On Tue, Feb 6, 2018 at 1:56 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Duy Nguyen <pclouds@gmail.com> writes:\n>> I actually think compact-summary was a good way to phrase it.\n>>\n>> Personally, I think it was a UI mistake that --summary can be given\n>> independently with or without --stat (instead, there shouldn't have\n>> been the --summary option, and instead when it was added, --stat\n>> just should have gained an extra kind of output).  A single option\n>> that can give both kinds of info may be a good way forward, so\n>> another possibility may be --summary-in-stat (meaning: the info\n>> given by summary is included in stat output).  I dunno.\n>\n> +Eric maybe he has some idea (sorry I forgot to include people from\n> the last round).\n\nWhat about the earlier suggestion[1] (and minor follow-ups[2,3]) of\nmaking this another option to --stat= (for instance, --stat=compact)?\nDid that idea get shot down or am I misunderstanding the question\nhere.\n\n[1]: https://public-inbox.org/git/CAPig+cQLgs59JYxcmK30qY307ArwqJx6pNOo95Z39_jJ9+D6+g@mail.gmail.com/\n[2]: https://public-inbox.org/git/CACsJy8B5qrN8T1aai3y3nfEc5baqn2Xkk6vZozMp5Lh-mPZ0VQ@mail.gmail.com/\n[3]: https://public-inbox.org/git/CACsJy8CPHk+aXHr-mkHZi27s=c3+ny8D9CSuzOSO8PweviBcqQ@mail.gmail.com/\n"},{"id":"338602","messageId":"CACsJy8AiBq__c0UET5ywMbTTz_MJNo-bZ-qAaoGZXdMNnECcaQ@mail.gmail.com","threadId":"47735","inReplyTo":"CAPig+cR9RycfLz0C6tXA4iPXdqoyczfij8CBaU4MmRGRmuRhSQ@mail.gmail.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-07T10:36:26Z","receivedAt":"2018-02-07T10:37:07Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Feb 7, 2018 at 4:52 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Tue, Feb 6, 2018 at 5:20 AM, Duy Nguyen <pclouds@gmail.com> wrote:\n>> On Tue, Feb 6, 2018 at 1:56 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Duy Nguyen <pclouds@gmail.com> writes:\n>>> I actually think compact-summary was a good way to phrase it.\n>>>\n>>> Personally, I think it was a UI mistake that --summary can be given\n>>> independently with or without --stat (instead, there shouldn't have\n>>> been the --summary option, and instead when it was added, --stat\n>>> just should have gained an extra kind of output).  A single option\n>>> that can give both kinds of info may be a good way forward, so\n>>> another possibility may be --summary-in-stat (meaning: the info\n>>> given by summary is included in stat output).  I dunno.\n>>\n>> +Eric maybe he has some idea (sorry I forgot to include people from\n>> the last round).\n>\n> What about the earlier suggestion[1] (and minor follow-ups[2,3]) of\n> making this another option to --stat= (for instance, --stat=compact)?\n> Did that idea get shot down or am I misunderstanding the question\n> here.\n\nI thought that was something like\n--stat[=<width>[,<name-width>[,<count>,[compact]]]] and turning on\n\"compact\" alone would get awkward because you need to specify all\nthose widths and counts too. --stat=compact as a separate form, with\nno combination with any other stat params, does not feel justified. We\ncould just do --stat-compact then. Perhaps we can allow compact to\nappear anywhere in --stat=, and not just the end? The --stat= syntax\nwould be\n\n--stat=[<option>[,<option>[,<option>...]]]\n\nwhere option could be keyword ones like compact or anything else in\nfuture, or <keyword>=<value> form. <option> could also be a number,\nbut in that case the three consecutive number options will present\nwidth, name-width and count in this order.\n\nOr we could simply add new --stat= syntax _without_ \"<option> as\nnumbers\". widths and counts must be specified keywords as well, e.g.\n--stat=width=40,name-width=20,count=10,compact and leave the old\nsyntax \"--stat=<width>,<name-width>,<count>\" alone.\n\nThen we still need to decide the new keyword for this feature, I feel\ncompact is a bit too vague (I read --stat=compact as \"it's compact\nstat\", not \"stat with compact summary\"), so perhaps\n--stat=compact-summary, or just --stat=summary?\n\n> [1]: https://public-inbox.org/git/CAPig+cQLgs59JYxcmK30qY307ArwqJx6pNOo95Z39_jJ9+D6+g@mail.gmail.com/\n> [2]: https://public-inbox.org/git/CACsJy8B5qrN8T1aai3y3nfEc5baqn2Xkk6vZozMp5Lh-mPZ0VQ@mail.gmail.com/\n> [3]: https://public-inbox.org/git/CACsJy8CPHk+aXHr-mkHZi27s=c3+ny8D9CSuzOSO8PweviBcqQ@mail.gmail.com/\n-- \nDuy\n"},{"id":"338648","messageId":"xmqqy3k47jdg.fsf@gitster-ct.c.googlers.com","threadId":"47735","inReplyTo":"CACsJy8AiBq__c0UET5ywMbTTz_MJNo-bZ-qAaoGZXdMNnECcaQ@mail.gmail.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-07T18:19:23Z","receivedAt":"2018-02-07T18:19:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> ...\n> Then we still need to decide the new keyword for this feature, I feel\n> compact is a bit too vague (I read --stat=compact as \"it's compact\n> stat\", not \"stat with compact summary\"), so perhaps\n> --stat=compact-summary, or just --stat=summary?\n\nYup, this is about giving summary in a compact way, not about giving\na compact stat information.  I agree with all the above reasoning,\nand that is why I said that your \"compact-summary\" was a good way to\nrefer to the feature.\n"},{"id":"338979","messageId":"CACsJy8ByZzR4GqVus=__RUg7W390e2ABoCb1ANewb5KRmBuV4Q@mail.gmail.com","threadId":"47735","inReplyTo":"xmqqy3k47jdg.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-10T10:24:31Z","receivedAt":"2018-02-10T10:25:07Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 8, 2018 at 1:19 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> ...\n>> Then we still need to decide the new keyword for this feature, I feel\n>> compact is a bit too vague (I read --stat=compact as \"it's compact\n>> stat\", not \"stat with compact summary\"), so perhaps\n>> --stat=compact-summary, or just --stat=summary?\n>\n> Yup, this is about giving summary in a compact way, not about giving\n> a compact stat information.  I agree with all the above reasoning,\n> and that is why I said that your \"compact-summary\" was a good way to\n> refer to the feature.\n\nOK I'll wait for a few days. If there's no comment, I'll go with\n--stat=compact-summary.\n-- \nDuy\n"},{"id":"338993","messageId":"xmqqr2pstxok.fsf@gitster-ct.c.googlers.com","threadId":"47735","inReplyTo":"CACsJy8ByZzR4GqVus=__RUg7W390e2ABoCb1ANewb5KRmBuV4Q@mail.gmail.com","subject":"Re: [PATCH v3 0/2] diff: add --stat-with-summary (was --compact-summary)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-10T20:08:27Z","receivedAt":"2018-02-10T20:08:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n>> Yup, this is about giving summary in a compact way, not about giving\n>> a compact stat information.  I agree with all the above reasoning,\n>> and that is why I said that your \"compact-summary\" was a good way to\n>> refer to the feature.\n>\n> OK I'll wait for a few days. If there's no comment, I'll go with\n> --stat=compact-summary.\n\nSorry, but that is not what I agreed with you on ;-) I meant to say\nthat your earlier --compact-summary made sense.  I do not think\n\"compact summary\" as a value of \"--stat\" makes any sense.  It's not\nlike this new one is one of the ways we offer to present \"stat\"\ndifferently and compared to other existing ways this is to give the\nstat in a compactly summarized fashion.  If this were a value to\n\"--summary\", then \"--summary=in-stat\" might make sense, in that this\nis not about how we show the \"stat\" information but about how/where\n\"summary\" information is shown.\n\n"},{"id":"340165","messageId":"20180224140509.25061-1-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180201130221.15563-1-pclouds@gmail.com","subject":"[PATCH v4 0/2] diff: add --compact-summary (aka nd/diff-stat-with-summary)","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-24T14:05:07Z","receivedAt":"2018-02-24T14:05:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"v4 renames the option back to --compact-summary. I can't think of any\nbetter name.\n\nInterdiff\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex 595e4cd548..e3a44f03cd 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -128,7 +128,7 @@ have to use `--diff-algorithm=default` option.\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\n \n---stat-with-summary::\n+--compact-summary::\n \tOutput a condensed summary of extended header information such\n \tas file creations or deletions (\"new\" or \"gone\", optionally \"+l\"\n \tif it's a symlink) and mode changes (\"+x\" or \"-x\" for adding\ndiff --git a/diff.c b/diff.c\nindex e7ff7dceb7..62e413a80f 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4332,7 +4332,6 @@ static int stat_opt(struct diff_options *options, const char **av)\n \tint graph_width = options->stat_graph_width;\n \tint count = options->stat_count;\n \tint argcount = 1;\n-\tunsigned with_summary = options->flags.stat_with_summary;\n \n \tif (!skip_prefix(arg, \"--stat\", &arg))\n \t\tdie(\"BUG: stat option does not begin with --stat: %s\", arg);\n@@ -4376,9 +4375,6 @@ static int stat_opt(struct diff_options *options, const char **av)\n \t\t\t\tcount = strtoul(av[1], &end, 10);\n \t\t\t\targcount = 2;\n \t\t\t}\n-\t\t} else if (skip_prefix(arg, \"-with-summary\", &arg)) {\n-\t\t\twith_summary = 1;\n-\t\t\tend = (char*)arg;\n \t\t}\n \t\tbreak;\n \tcase '=':\n@@ -4397,7 +4393,6 @@ static int stat_opt(struct diff_options *options, const char **av)\n \toptions->stat_graph_width = graph_width;\n \toptions->stat_width = width;\n \toptions->stat_count = count;\n-\toptions->flags.stat_with_summary = with_summary;\n \treturn argcount;\n }\n \n@@ -4579,11 +4574,13 @@ int diff_opt_parse(struct diff_options *options,\n \telse if (!strcmp(arg, \"-s\") || !strcmp(arg, \"--no-patch\"))\n \t\toptions->output_format |= DIFF_FORMAT_NO_OUTPUT;\n \telse if (starts_with(arg, \"--stat\"))\n-\t\t/*\n-\t\t * --stat, --stat-width, --stat-name-width,\n-\t\t * --stat-count or --stat-with-summary.\n-\t\t */\n+\t\t/* --stat, --stat-width, --stat-name-width, or --stat-count */\n \t\treturn stat_opt(options, av);\n+\telse if (!strcmp(arg, \"--compact-summary\")) {\n+\t\t options->flags.stat_with_summary = 1;\n+\t\t options->output_format |= DIFF_FORMAT_DIFFSTAT;\n+\t} else if (!strcmp(arg, \"--no-compact-summary\"))\n+\t\t options->flags.stat_with_summary = 0;\n \n \t/* renames options */\n \telse if (starts_with(arg, \"-B\") ||\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex aa6f5da21c..3f9a24fd56 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -362,10 +362,10 @@ diff --no-index --raw --abbrev=4 dir2 dir\n :noellipses diff --no-index --raw --abbrev=4 dir2 dir\n diff --no-index --raw --no-abbrev dir2 dir\n \n-diff-tree --pretty --root --stat-with-summary initial\n-diff-tree --pretty -R --root --stat-with-summary initial\n-diff-tree --stat-with-summary initial mode\n-diff-tree -R --stat-with-summary initial mode\n+diff-tree --pretty --root --stat --compact-summary initial\n+diff-tree --pretty -R --root --stat --compact-summary initial\n+diff-tree --stat --compact-summary initial mode\n+diff-tree -R --stat --compact-summary initial mode\n EOF\n \n test_expect_success 'log -S requires an argument' '\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\nsimilarity index 78%\nrename from t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial\nrename to t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\nindex 105f29a92d..d6451ff7cc 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--stat-with-summary_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n@@ -1,4 +1,4 @@\n-$ git diff-tree --pretty --root --stat-with-summary initial\n+$ git diff-tree --pretty --root --stat --compact-summary initial\n commit 444ac553ac7612cc88969031b02b3767fb8a353a\n Author: A U Thor <author@example.com>\n Date:   Mon Jun 26 00:00:00 2006 +0000\ndiff --git a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\nsimilarity index 78%\nrename from t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial\nrename to t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\nindex 45008d09fc..1989e55cd0 100644\n--- a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat-with-summary_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n@@ -1,4 +1,4 @@\n-$ git diff-tree --pretty -R --root --stat-with-summary initial\n+$ git diff-tree --pretty -R --root --stat --compact-summary initial\n commit 444ac553ac7612cc88969031b02b3767fb8a353a\n Author: A U Thor <author@example.com>\n Date:   Mon Jun 26 00:00:00 2006 +0000\ndiff --git a/t/t4013/diff.diff-tree_--stat-with-summary_initial_mode b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\nsimilarity index 57%\nrename from t/t4013/diff.diff-tree_--stat-with-summary_initial_mode\nrename to t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\nindex f99fcdc101..9c7c8f63af 100644\n--- a/t/t4013/diff.diff-tree_--stat-with-summary_initial_mode\n+++ b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n@@ -1,4 +1,4 @@\n-$ git diff-tree --stat-with-summary initial mode\n+$ git diff-tree --stat --compact-summary initial mode\n  file0 (mode +x) | 0\n  1 file changed, 0 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\nsimilarity index 55%\nrename from t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode\nrename to t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\nindex 8dc8f3fe95..e38f3d3bfb 100644\n--- a/t/t4013/diff.diff-tree_-R_--stat-with-summary_initial_mode\n+++ b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n@@ -1,4 +1,4 @@\n-$ git diff-tree -R --stat-with-summary initial mode\n+$ git diff-tree -R --stat --compact-summary initial mode\n  file0 (mode -x) | 0\n  1 file changed, 0 insertions(+), 0 deletions(-)\n $\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340166","messageId":"20180224140509.25061-2-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180224140509.25061-1-pclouds@gmail.com","subject":"[PATCH v4 1/2] diff.c: refactor pprint_rename() to use strbuf","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-24T14:05:08Z","receivedAt":"2018-02-24T14:05:38Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Instead of passing char* around, let function handle strbuf\ndirectly. All callers already use strbuf internally.\n\nThis helps kill the \"not free\" exception in free_diffstat_info(). I\ndon't think this code is so critical that we need to avoid some free()\ncalls.\n\nThe other benefit comes in the next patch, where we append something\nin pname before returning from fill_print_name(). With strbuf, it's\nvery simple. With \"char *\" we may have to resort to explicit\nreallocation and stuff.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n diff.c | 59 ++++++++++++++++++++++++++--------------------------------\n 1 file changed, 26 insertions(+), 33 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 21c3838b25..e3f72de27d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2045,11 +2045,10 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)\n \t}\n }\n \n-static char *pprint_rename(const char *a, const char *b)\n+static void pprint_rename(struct strbuf *name, const char *a, const char *b)\n {\n \tconst char *old = a;\n \tconst char *new = b;\n-\tstruct strbuf name = STRBUF_INIT;\n \tint pfx_length, sfx_length;\n \tint pfx_adjust_for_slash;\n \tint len_a = strlen(a);\n@@ -2059,10 +2058,10 @@ static char *pprint_rename(const char *a, const char *b)\n \tint qlen_b = quote_c_style(b, NULL, NULL, 0);\n \n \tif (qlen_a || qlen_b) {\n-\t\tquote_c_style(a, &name, NULL, 0);\n-\t\tstrbuf_addstr(&name, \" => \");\n-\t\tquote_c_style(b, &name, NULL, 0);\n-\t\treturn strbuf_detach(&name, NULL);\n+\t\tquote_c_style(a, name, NULL, 0);\n+\t\tstrbuf_addstr(name, \" => \");\n+\t\tquote_c_style(b, name, NULL, 0);\n+\t\treturn;\n \t}\n \n \t/* Find common prefix */\n@@ -2109,19 +2108,18 @@ static char *pprint_rename(const char *a, const char *b)\n \tif (b_midlen < 0)\n \t\tb_midlen = 0;\n \n-\tstrbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);\n+\tstrbuf_grow(name, pfx_length + a_midlen + b_midlen + sfx_length + 7);\n \tif (pfx_length + sfx_length) {\n-\t\tstrbuf_add(&name, a, pfx_length);\n-\t\tstrbuf_addch(&name, '{');\n+\t\tstrbuf_add(name, a, pfx_length);\n+\t\tstrbuf_addch(name, '{');\n \t}\n-\tstrbuf_add(&name, a + pfx_length, a_midlen);\n-\tstrbuf_addstr(&name, \" => \");\n-\tstrbuf_add(&name, b + pfx_length, b_midlen);\n+\tstrbuf_add(name, a + pfx_length, a_midlen);\n+\tstrbuf_addstr(name, \" => \");\n+\tstrbuf_add(name, b + pfx_length, b_midlen);\n \tif (pfx_length + sfx_length) {\n-\t\tstrbuf_addch(&name, '}');\n-\t\tstrbuf_add(&name, a + len_a - sfx_length, sfx_length);\n+\t\tstrbuf_addch(name, '}');\n+\t\tstrbuf_add(name, a + len_a - sfx_length, sfx_length);\n \t}\n-\treturn strbuf_detach(&name, NULL);\n }\n \n struct diffstat_t {\n@@ -2197,23 +2195,17 @@ static void show_graph(struct strbuf *out, char ch, int cnt,\n \n static void fill_print_name(struct diffstat_file *file)\n {\n-\tchar *pname;\n+\tstruct strbuf pname = STRBUF_INIT;\n \n \tif (file->print_name)\n \t\treturn;\n \n-\tif (!file->is_renamed) {\n-\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tif (quote_c_style(file->name, &buf, NULL, 0)) {\n-\t\t\tpname = strbuf_detach(&buf, NULL);\n-\t\t} else {\n-\t\t\tpname = file->name;\n-\t\t\tstrbuf_release(&buf);\n-\t\t}\n-\t} else {\n-\t\tpname = pprint_rename(file->from_name, file->name);\n-\t}\n-\tfile->print_name = pname;\n+\tif (file->is_renamed)\n+\t\tpprint_rename(&pname, file->from_name, file->name);\n+\telse\n+\t\tquote_c_style(file->name, &pname, NULL, 0);\n+\n+\tfile->print_name = strbuf_detach(&pname, NULL);\n }\n \n static void print_stat_summary_inserts_deletes(struct diff_options *options,\n@@ -2797,8 +2789,7 @@ static void free_diffstat_info(struct diffstat_t *diffstat)\n \tint i;\n \tfor (i = 0; i < diffstat->nr; i++) {\n \t\tstruct diffstat_file *f = diffstat->files[i];\n-\t\tif (f->name != f->print_name)\n-\t\t\tfree(f->print_name);\n+\t\tfree(f->print_name);\n \t\tfree(f->name);\n \t\tfree(f->from_name);\n \t\tfree(f);\n@@ -5241,10 +5232,12 @@ static void show_rename_copy(struct diff_options *opt, const char *renamecopy,\n \t\tstruct diff_filepair *p)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-\tchar *names = pprint_rename(p->one->path, p->two->path);\n+\tstruct strbuf names = STRBUF_INIT;\n+\n+\tpprint_rename(&names, p->one->path, p->two->path);\n \tstrbuf_addf(&sb, \" %s %s (%d%%)\\n\",\n-\t\t\trenamecopy, names, similarity_index(p));\n-\tfree(names);\n+\t\t    renamecopy, names.buf, similarity_index(p));\n+\tstrbuf_release(&names);\n \temit_diff_symbol(opt, DIFF_SYMBOL_SUMMARY,\n \t\t\t\t sb.buf, sb.len, 0);\n \tshow_mode_change(opt, p, 0);\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340167","messageId":"20180224140509.25061-3-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180224140509.25061-1-pclouds@gmail.com","subject":"[PATCH v4 2/2] diff: add --stat-with-summary","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-24T14:05:09Z","receivedAt":"2018-02-24T14:05:52Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Certain information is currently shown with --summary, but when used\nin combination with --stat it's a bit hard to read since info of the\nsame file is in two places (--stat and --summary).\n\nOn top of that, commits that add or remove files double the number of\ndisplay lines, which could be a lot if you add or remove a lot of\nfiles.\n\n--stat-with-summary embeds most of --summary back in --stat in the\nlittle space between the file name part and the graph line, e.g. with\ncommit 0433d533f1:\n\n   Documentation/merge-config.txt         |  4 +\n   builtin/merge.c                        |  2 +\n   ...-pull-verify-signatures.sh (new +x) | 81 ++++++++++++++\n   t/t7612-merge-verify-signatures.sh     | 45 ++++++++\n   4 files changed, 132 insertions(+)\n\nIt helps both condensing information and saving some text\nspace. What's new in diffstat is:\n\n- A new 0644 file is shown as (new)\n- A new 0755 file is shown as (new +x)\n- A new symlink is shown as (new +l)\n- A deleted file is shown as (gone)\n- A mode change adding executable bit is shown as (mode +x)\n- A mode change removing it is shown as (mode -x)\n\nNote that --stat-with-summary does not contain all the information\n--summary provides. Rewrite percentage is not shown but it could be\nadded later, like R50% or C20%.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/diff-options.txt                |  8 ++++\n diff.c                                        | 37 +++++++++++++++++++\n diff.h                                        |  1 +\n t/t4013-diff-various.sh                       |  5 +++\n ...ty_--root_--stat_--compact-summary_initial | 12 ++++++\n ...-R_--root_--stat_--compact-summary_initial | 12 ++++++\n ...tree_--stat_--compact-summary_initial_mode |  4 ++\n ...e_-R_--stat_--compact-summary_initial_mode |  4 ++\n 8 files changed, 83 insertions(+)\n create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n create mode 100644 t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex c330c01ff0..e3a44f03cd 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -128,6 +128,14 @@ have to use `--diff-algorithm=default` option.\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\n \n+--compact-summary::\n+\tOutput a condensed summary of extended header information such\n+\tas file creations or deletions (\"new\" or \"gone\", optionally \"+l\"\n+\tif it's a symlink) and mode changes (\"+x\" or \"-x\" for adding\n+\tor removing executable bit respectively) in diffstat. The\n+\tinformation is put betwen the filename part and the graph\n+\tpart. Implies `--stat`.\n+\n --numstat::\n \tSimilar to `--stat`, but shows number of added and\n \tdeleted lines in decimal notation and pathname without\ndiff --git a/diff.c b/diff.c\nindex e3f72de27d..62e413a80f 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2129,6 +2129,7 @@ struct diffstat_t {\n \t\tchar *from_name;\n \t\tchar *name;\n \t\tchar *print_name;\n+\t\tconst char *comments;\n \t\tunsigned is_unmerged:1;\n \t\tunsigned is_binary:1;\n \t\tunsigned is_renamed:1;\n@@ -2205,6 +2206,9 @@ static void fill_print_name(struct diffstat_file *file)\n \telse\n \t\tquote_c_style(file->name, &pname, NULL, 0);\n \n+\tif (file->comments)\n+\t\tstrbuf_addf(&pname, \" (%s)\", file->comments);\n+\n \tfile->print_name = strbuf_detach(&pname, NULL);\n }\n \n@@ -3239,6 +3243,32 @@ static void builtin_diff(const char *name_a,\n \treturn;\n }\n \n+static char *get_compact_summary(const struct diff_filepair *p, int is_renamed)\n+{\n+\tif (!is_renamed) {\n+\t\tif (p->status == DIFF_STATUS_ADDED) {\n+\t\t\tif (S_ISLNK(p->two->mode))\n+\t\t\t\treturn \"new +l\";\n+\t\t\telse if ((p->two->mode & 0777) == 0755)\n+\t\t\t\treturn \"new +x\";\n+\t\t\telse\n+\t\t\t\treturn \"new\";\n+\t\t} else if (p->status == DIFF_STATUS_DELETED)\n+\t\t\treturn \"gone\";\n+\t}\n+\tif (S_ISLNK(p->one->mode) && !S_ISLNK(p->two->mode))\n+\t\treturn \"mode -l\";\n+\telse if (!S_ISLNK(p->one->mode) && S_ISLNK(p->two->mode))\n+\t\treturn \"mode +l\";\n+\telse if ((p->one->mode & 0777) == 0644 &&\n+\t\t (p->two->mode & 0777) == 0755)\n+\t\treturn \"mode +x\";\n+\telse if ((p->one->mode & 0777) == 0755 &&\n+\t\t (p->two->mode & 0777) == 0644)\n+\t\treturn \"mode -x\";\n+\treturn NULL;\n+}\n+\n static void builtin_diffstat(const char *name_a, const char *name_b,\n \t\t\t     struct diff_filespec *one,\n \t\t\t     struct diff_filespec *two,\n@@ -3258,6 +3288,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,\n \n \tdata = diffstat_add(diffstat, name_a, name_b);\n \tdata->is_interesting = p->status != DIFF_STATUS_UNKNOWN;\n+\tif (o->flags.stat_with_summary)\n+\t\tdata->comments = get_compact_summary(p, data->is_renamed);\n \n \tif (!one || !two) {\n \t\tdata->is_unmerged = 1;\n@@ -4544,6 +4576,11 @@ int diff_opt_parse(struct diff_options *options,\n \telse if (starts_with(arg, \"--stat\"))\n \t\t/* --stat, --stat-width, --stat-name-width, or --stat-count */\n \t\treturn stat_opt(options, av);\n+\telse if (!strcmp(arg, \"--compact-summary\")) {\n+\t\t options->flags.stat_with_summary = 1;\n+\t\t options->output_format |= DIFF_FORMAT_DIFFSTAT;\n+\t} else if (!strcmp(arg, \"--no-compact-summary\"))\n+\t\t options->flags.stat_with_summary = 0;\n \n \t/* renames options */\n \telse if (starts_with(arg, \"-B\") ||\ndiff --git a/diff.h b/diff.h\nindex 6bd278aac1..d29560f822 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -93,6 +93,7 @@ struct diff_flags {\n \tunsigned dirstat_by_line:1;\n \tunsigned funccontext:1;\n \tunsigned default_follow_renames:1;\n+\tunsigned stat_with_summary:1;\n };\n \n static inline void diff_flags_or(struct diff_flags *a,\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex f10798b2df..3f9a24fd56 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -361,6 +361,11 @@ diff --no-index --raw dir2 dir\n diff --no-index --raw --abbrev=4 dir2 dir\n :noellipses diff --no-index --raw --abbrev=4 dir2 dir\n diff --no-index --raw --no-abbrev dir2 dir\n+\n+diff-tree --pretty --root --stat --compact-summary initial\n+diff-tree --pretty -R --root --stat --compact-summary initial\n+diff-tree --stat --compact-summary initial mode\n+diff-tree -R --stat --compact-summary initial mode\n EOF\n \n test_expect_success 'log -S requires an argument' '\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\nnew file mode 100644\nindex 0000000000..d6451ff7cc\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n@@ -0,0 +1,12 @@\n+$ git diff-tree --pretty --root --stat --compact-summary initial\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+\n+ dir/sub (new) | 2 ++\n+ file0 (new)   | 3 +++\n+ file2 (new)   | 3 +++\n+ 3 files changed, 8 insertions(+)\n+$\ndiff --git a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\nnew file mode 100644\nindex 0000000000..1989e55cd0\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n@@ -0,0 +1,12 @@\n+$ git diff-tree --pretty -R --root --stat --compact-summary initial\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+\n+ dir/sub (gone) | 2 --\n+ file0 (gone)   | 3 ---\n+ file2 (gone)   | 3 ---\n+ 3 files changed, 8 deletions(-)\n+$\ndiff --git a/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\nnew file mode 100644\nindex 0000000000..9c7c8f63af\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n@@ -0,0 +1,4 @@\n+$ git diff-tree --stat --compact-summary initial mode\n+ file0 (mode +x) | 0\n+ 1 file changed, 0 insertions(+), 0 deletions(-)\n+$\ndiff --git a/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\nnew file mode 100644\nindex 0000000000..e38f3d3bfb\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n@@ -0,0 +1,4 @@\n+$ git diff-tree -R --stat --compact-summary initial mode\n+ file0 (mode -x) | 0\n+ 1 file changed, 0 insertions(+), 0 deletions(-)\n+$\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340168","messageId":"20180224140959.25402-1-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180224140509.25061-1-pclouds@gmail.com","subject":"[PATCH v5 0/2] diff: add --compact-summary (aka nd/diff-stat-with-summary)","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-24T14:09:57Z","receivedAt":"2018-02-24T14:10:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"... and v5 fixes the commit message of 2/2 where in v4 it still\nmentions --stat-with-summary instead of --compact-summary. Sorry.\n\nNguyễn Thái Ngọc Duy (2):\n  diff.c: refactor pprint_rename() to use strbuf\n  diff: add --compact-summary\n\n Documentation/diff-options.txt                |  8 ++\n diff.c                                        | 96 ++++++++++++-------\n diff.h                                        |  1 +\n t/t4013-diff-various.sh                       |  5 +\n ...ty_--root_--stat_--compact-summary_initial | 12 +++\n ...-R_--root_--stat_--compact-summary_initial | 12 +++\n ...tree_--stat_--compact-summary_initial_mode |  4 +\n ...e_-R_--stat_--compact-summary_initial_mode |  4 +\n 8 files changed, 109 insertions(+), 33 deletions(-)\n create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n create mode 100644 t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340169","messageId":"20180224140959.25402-2-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180224140959.25402-1-pclouds@gmail.com","subject":"[PATCH v5 1/2] diff.c: refactor pprint_rename() to use strbuf","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-24T14:09:58Z","receivedAt":"2018-02-24T14:10:16Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Instead of passing char* around, let function handle strbuf\ndirectly. All callers already use strbuf internally.\n\nThis helps kill the \"not free\" exception in free_diffstat_info(). I\ndon't think this code is so critical that we need to avoid some free()\ncalls.\n\nThe other benefit comes in the next patch, where we append something\nin pname before returning from fill_print_name(). With strbuf, it's\nvery simple. With \"char *\" we may have to resort to explicit\nreallocation and stuff.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n diff.c | 59 ++++++++++++++++++++++++++--------------------------------\n 1 file changed, 26 insertions(+), 33 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 21c3838b25..e3f72de27d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2045,11 +2045,10 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)\n \t}\n }\n \n-static char *pprint_rename(const char *a, const char *b)\n+static void pprint_rename(struct strbuf *name, const char *a, const char *b)\n {\n \tconst char *old = a;\n \tconst char *new = b;\n-\tstruct strbuf name = STRBUF_INIT;\n \tint pfx_length, sfx_length;\n \tint pfx_adjust_for_slash;\n \tint len_a = strlen(a);\n@@ -2059,10 +2058,10 @@ static char *pprint_rename(const char *a, const char *b)\n \tint qlen_b = quote_c_style(b, NULL, NULL, 0);\n \n \tif (qlen_a || qlen_b) {\n-\t\tquote_c_style(a, &name, NULL, 0);\n-\t\tstrbuf_addstr(&name, \" => \");\n-\t\tquote_c_style(b, &name, NULL, 0);\n-\t\treturn strbuf_detach(&name, NULL);\n+\t\tquote_c_style(a, name, NULL, 0);\n+\t\tstrbuf_addstr(name, \" => \");\n+\t\tquote_c_style(b, name, NULL, 0);\n+\t\treturn;\n \t}\n \n \t/* Find common prefix */\n@@ -2109,19 +2108,18 @@ static char *pprint_rename(const char *a, const char *b)\n \tif (b_midlen < 0)\n \t\tb_midlen = 0;\n \n-\tstrbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);\n+\tstrbuf_grow(name, pfx_length + a_midlen + b_midlen + sfx_length + 7);\n \tif (pfx_length + sfx_length) {\n-\t\tstrbuf_add(&name, a, pfx_length);\n-\t\tstrbuf_addch(&name, '{');\n+\t\tstrbuf_add(name, a, pfx_length);\n+\t\tstrbuf_addch(name, '{');\n \t}\n-\tstrbuf_add(&name, a + pfx_length, a_midlen);\n-\tstrbuf_addstr(&name, \" => \");\n-\tstrbuf_add(&name, b + pfx_length, b_midlen);\n+\tstrbuf_add(name, a + pfx_length, a_midlen);\n+\tstrbuf_addstr(name, \" => \");\n+\tstrbuf_add(name, b + pfx_length, b_midlen);\n \tif (pfx_length + sfx_length) {\n-\t\tstrbuf_addch(&name, '}');\n-\t\tstrbuf_add(&name, a + len_a - sfx_length, sfx_length);\n+\t\tstrbuf_addch(name, '}');\n+\t\tstrbuf_add(name, a + len_a - sfx_length, sfx_length);\n \t}\n-\treturn strbuf_detach(&name, NULL);\n }\n \n struct diffstat_t {\n@@ -2197,23 +2195,17 @@ static void show_graph(struct strbuf *out, char ch, int cnt,\n \n static void fill_print_name(struct diffstat_file *file)\n {\n-\tchar *pname;\n+\tstruct strbuf pname = STRBUF_INIT;\n \n \tif (file->print_name)\n \t\treturn;\n \n-\tif (!file->is_renamed) {\n-\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tif (quote_c_style(file->name, &buf, NULL, 0)) {\n-\t\t\tpname = strbuf_detach(&buf, NULL);\n-\t\t} else {\n-\t\t\tpname = file->name;\n-\t\t\tstrbuf_release(&buf);\n-\t\t}\n-\t} else {\n-\t\tpname = pprint_rename(file->from_name, file->name);\n-\t}\n-\tfile->print_name = pname;\n+\tif (file->is_renamed)\n+\t\tpprint_rename(&pname, file->from_name, file->name);\n+\telse\n+\t\tquote_c_style(file->name, &pname, NULL, 0);\n+\n+\tfile->print_name = strbuf_detach(&pname, NULL);\n }\n \n static void print_stat_summary_inserts_deletes(struct diff_options *options,\n@@ -2797,8 +2789,7 @@ static void free_diffstat_info(struct diffstat_t *diffstat)\n \tint i;\n \tfor (i = 0; i < diffstat->nr; i++) {\n \t\tstruct diffstat_file *f = diffstat->files[i];\n-\t\tif (f->name != f->print_name)\n-\t\t\tfree(f->print_name);\n+\t\tfree(f->print_name);\n \t\tfree(f->name);\n \t\tfree(f->from_name);\n \t\tfree(f);\n@@ -5241,10 +5232,12 @@ static void show_rename_copy(struct diff_options *opt, const char *renamecopy,\n \t\tstruct diff_filepair *p)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-\tchar *names = pprint_rename(p->one->path, p->two->path);\n+\tstruct strbuf names = STRBUF_INIT;\n+\n+\tpprint_rename(&names, p->one->path, p->two->path);\n \tstrbuf_addf(&sb, \" %s %s (%d%%)\\n\",\n-\t\t\trenamecopy, names, similarity_index(p));\n-\tfree(names);\n+\t\t    renamecopy, names.buf, similarity_index(p));\n+\tstrbuf_release(&names);\n \temit_diff_symbol(opt, DIFF_SYMBOL_SUMMARY,\n \t\t\t\t sb.buf, sb.len, 0);\n \tshow_mode_change(opt, p, 0);\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340170","messageId":"20180224140959.25402-3-pclouds@gmail.com","threadId":"47735","inReplyTo":"20180224140959.25402-1-pclouds@gmail.com","subject":"[PATCH v5 2/2] diff: add --compact-summary","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-02-24T14:09:59Z","receivedAt":"2018-02-24T14:10:21Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Certain information is currently shown with --summary, but when used\nin combination with --stat it's a bit hard to read since info of the\nsame file is in two places (--stat and --summary).\n\nOn top of that, commits that add or remove files double the number of\ndisplay lines, which could be a lot if you add or remove a lot of\nfiles.\n\n--compact-summary embeds most of --summary back in --stat in the\nlittle space between the file name part and the graph line, e.g. with\ncommit 0433d533f1:\n\n   Documentation/merge-config.txt         |  4 +\n   builtin/merge.c                        |  2 +\n   ...-pull-verify-signatures.sh (new +x) | 81 ++++++++++++++\n   t/t7612-merge-verify-signatures.sh     | 45 ++++++++\n   4 files changed, 132 insertions(+)\n\nIt helps both condensing information and saving some text\nspace. What's new in diffstat is:\n\n- A new 0644 file is shown as (new)\n- A new 0755 file is shown as (new +x)\n- A new symlink is shown as (new +l)\n- A deleted file is shown as (gone)\n- A mode change adding executable bit is shown as (mode +x)\n- A mode change removing it is shown as (mode -x)\n\nNote that --compact-summary does not contain all the information\n--summary provides. Rewrite percentage is not shown but it could be\nadded later, like R50% or C20%.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/diff-options.txt                |  8 ++++\n diff.c                                        | 37 +++++++++++++++++++\n diff.h                                        |  1 +\n t/t4013-diff-various.sh                       |  5 +++\n ...ty_--root_--stat_--compact-summary_initial | 12 ++++++\n ...-R_--root_--stat_--compact-summary_initial | 12 ++++++\n ...tree_--stat_--compact-summary_initial_mode |  4 ++\n ...e_-R_--stat_--compact-summary_initial_mode |  4 ++\n 8 files changed, 83 insertions(+)\n create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n create mode 100644 t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n create mode 100644 t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex c330c01ff0..e3a44f03cd 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -128,6 +128,14 @@ have to use `--diff-algorithm=default` option.\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\n \n+--compact-summary::\n+\tOutput a condensed summary of extended header information such\n+\tas file creations or deletions (\"new\" or \"gone\", optionally \"+l\"\n+\tif it's a symlink) and mode changes (\"+x\" or \"-x\" for adding\n+\tor removing executable bit respectively) in diffstat. The\n+\tinformation is put betwen the filename part and the graph\n+\tpart. Implies `--stat`.\n+\n --numstat::\n \tSimilar to `--stat`, but shows number of added and\n \tdeleted lines in decimal notation and pathname without\ndiff --git a/diff.c b/diff.c\nindex e3f72de27d..62e413a80f 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2129,6 +2129,7 @@ struct diffstat_t {\n \t\tchar *from_name;\n \t\tchar *name;\n \t\tchar *print_name;\n+\t\tconst char *comments;\n \t\tunsigned is_unmerged:1;\n \t\tunsigned is_binary:1;\n \t\tunsigned is_renamed:1;\n@@ -2205,6 +2206,9 @@ static void fill_print_name(struct diffstat_file *file)\n \telse\n \t\tquote_c_style(file->name, &pname, NULL, 0);\n \n+\tif (file->comments)\n+\t\tstrbuf_addf(&pname, \" (%s)\", file->comments);\n+\n \tfile->print_name = strbuf_detach(&pname, NULL);\n }\n \n@@ -3239,6 +3243,32 @@ static void builtin_diff(const char *name_a,\n \treturn;\n }\n \n+static char *get_compact_summary(const struct diff_filepair *p, int is_renamed)\n+{\n+\tif (!is_renamed) {\n+\t\tif (p->status == DIFF_STATUS_ADDED) {\n+\t\t\tif (S_ISLNK(p->two->mode))\n+\t\t\t\treturn \"new +l\";\n+\t\t\telse if ((p->two->mode & 0777) == 0755)\n+\t\t\t\treturn \"new +x\";\n+\t\t\telse\n+\t\t\t\treturn \"new\";\n+\t\t} else if (p->status == DIFF_STATUS_DELETED)\n+\t\t\treturn \"gone\";\n+\t}\n+\tif (S_ISLNK(p->one->mode) && !S_ISLNK(p->two->mode))\n+\t\treturn \"mode -l\";\n+\telse if (!S_ISLNK(p->one->mode) && S_ISLNK(p->two->mode))\n+\t\treturn \"mode +l\";\n+\telse if ((p->one->mode & 0777) == 0644 &&\n+\t\t (p->two->mode & 0777) == 0755)\n+\t\treturn \"mode +x\";\n+\telse if ((p->one->mode & 0777) == 0755 &&\n+\t\t (p->two->mode & 0777) == 0644)\n+\t\treturn \"mode -x\";\n+\treturn NULL;\n+}\n+\n static void builtin_diffstat(const char *name_a, const char *name_b,\n \t\t\t     struct diff_filespec *one,\n \t\t\t     struct diff_filespec *two,\n@@ -3258,6 +3288,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,\n \n \tdata = diffstat_add(diffstat, name_a, name_b);\n \tdata->is_interesting = p->status != DIFF_STATUS_UNKNOWN;\n+\tif (o->flags.stat_with_summary)\n+\t\tdata->comments = get_compact_summary(p, data->is_renamed);\n \n \tif (!one || !two) {\n \t\tdata->is_unmerged = 1;\n@@ -4544,6 +4576,11 @@ int diff_opt_parse(struct diff_options *options,\n \telse if (starts_with(arg, \"--stat\"))\n \t\t/* --stat, --stat-width, --stat-name-width, or --stat-count */\n \t\treturn stat_opt(options, av);\n+\telse if (!strcmp(arg, \"--compact-summary\")) {\n+\t\t options->flags.stat_with_summary = 1;\n+\t\t options->output_format |= DIFF_FORMAT_DIFFSTAT;\n+\t} else if (!strcmp(arg, \"--no-compact-summary\"))\n+\t\t options->flags.stat_with_summary = 0;\n \n \t/* renames options */\n \telse if (starts_with(arg, \"-B\") ||\ndiff --git a/diff.h b/diff.h\nindex 6bd278aac1..d29560f822 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -93,6 +93,7 @@ struct diff_flags {\n \tunsigned dirstat_by_line:1;\n \tunsigned funccontext:1;\n \tunsigned default_follow_renames:1;\n+\tunsigned stat_with_summary:1;\n };\n \n static inline void diff_flags_or(struct diff_flags *a,\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex f10798b2df..3f9a24fd56 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -361,6 +361,11 @@ diff --no-index --raw dir2 dir\n diff --no-index --raw --abbrev=4 dir2 dir\n :noellipses diff --no-index --raw --abbrev=4 dir2 dir\n diff --no-index --raw --no-abbrev dir2 dir\n+\n+diff-tree --pretty --root --stat --compact-summary initial\n+diff-tree --pretty -R --root --stat --compact-summary initial\n+diff-tree --stat --compact-summary initial mode\n+diff-tree -R --stat --compact-summary initial mode\n EOF\n \n test_expect_success 'log -S requires an argument' '\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\nnew file mode 100644\nindex 0000000000..d6451ff7cc\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n@@ -0,0 +1,12 @@\n+$ git diff-tree --pretty --root --stat --compact-summary initial\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+\n+ dir/sub (new) | 2 ++\n+ file0 (new)   | 3 +++\n+ file2 (new)   | 3 +++\n+ 3 files changed, 8 insertions(+)\n+$\ndiff --git a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\nnew file mode 100644\nindex 0000000000..1989e55cd0\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n@@ -0,0 +1,12 @@\n+$ git diff-tree --pretty -R --root --stat --compact-summary initial\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+\n+ dir/sub (gone) | 2 --\n+ file0 (gone)   | 3 ---\n+ file2 (gone)   | 3 ---\n+ 3 files changed, 8 deletions(-)\n+$\ndiff --git a/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\nnew file mode 100644\nindex 0000000000..9c7c8f63af\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n@@ -0,0 +1,4 @@\n+$ git diff-tree --stat --compact-summary initial mode\n+ file0 (mode +x) | 0\n+ 1 file changed, 0 insertions(+), 0 deletions(-)\n+$\ndiff --git a/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\nnew file mode 100644\nindex 0000000000..e38f3d3bfb\n--- /dev/null\n+++ b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n@@ -0,0 +1,4 @@\n+$ git diff-tree -R --stat --compact-summary initial mode\n+ file0 (mode -x) | 0\n+ 1 file changed, 0 insertions(+), 0 deletions(-)\n+$\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340485","messageId":"xmqqa7vunhhf.fsf@gitster-ct.c.googlers.com","threadId":"47735","inReplyTo":"20180224140959.25402-1-pclouds@gmail.com","subject":"Re: [PATCH v5 0/2] diff: add --compact-summary (aka nd/diff-stat-with-summary)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-02-27T23:24:44Z","receivedAt":"2018-02-27T23:24:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> ... and v5 fixes the commit message of 2/2 where in v4 it still\n> mentions --stat-with-summary instead of --compact-summary. Sorry.\n>\n> Nguyễn Thái Ngọc Duy (2):\n>   diff.c: refactor pprint_rename() to use strbuf\n>   diff: add --compact-summary\n\nThanks, will queue.  I guess we all run out of paints of different\ncolours, and it's a good time to go incremental by merging the topic\nto 'next'.\n\n>\n>  Documentation/diff-options.txt                |  8 ++\n>  diff.c                                        | 96 ++++++++++++-------\n>  diff.h                                        |  1 +\n>  t/t4013-diff-various.sh                       |  5 +\n>  ...ty_--root_--stat_--compact-summary_initial | 12 +++\n>  ...-R_--root_--stat_--compact-summary_initial | 12 +++\n>  ...tree_--stat_--compact-summary_initial_mode |  4 +\n>  ...e_-R_--stat_--compact-summary_initial_mode |  4 +\n>  8 files changed, 109 insertions(+), 33 deletions(-)\n>  create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial\n>  create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial\n>  create mode 100644 t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode\n>  create mode 100644 t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode\n"}]}