{"thread":{"id":"29589","subject":"[PATCH 2/4] help.c: make term_columns() cached and export it","startedAt":"2012-02-09T23:58:37Z","lastAt":"2012-02-16T20:01:38Z","messageCount":46,"participants":["Zbigniew Jędrzejewski-Szmek","Junio C Hamano","Nguyen Thai Ngoc Duy","Johannes Sixt"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"184297","messageId":"1328831921-27272-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":null,"subject":"(unknown)","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-09T23:58:37Z","receivedAt":"2012-02-09T23:58:37Z","isPatch":false,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Hi,\n\nthis is a patch series to make 'git diff --stat' use full terminal\nwidth instead of hard-coded 80 columns.\n\nThis is quite useful when working on projects with nested directory\nstructure, e.g. Java:\n .../{ => workspace/tasks}/GetTaskResultAction.java |   10 +-\n .../tasks}/RemoveAllAbortedTasksAction.java        |    7 +-\n .../tasks}/RemoveAllFailedTasksAction.java         |    7 +-\nis changed to display full paths if the terminal window is wide\nenough.\n\nGit usually uses the full terminal width automatically, so it should\ndo so with --stat too.\n\nThe \"big\" functional change in the patch series is s/80/term_columns()/\nin show_stats(). The fourth patch also changes the partitioning of\navailable columns to dedicate more space to file names.\n"},{"id":"184296","messageId":"1328831921-27272-2-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328831921-27272-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 1/4] Move git_version_string to help.c in preparation for diff changes","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-09T23:58:38Z","receivedAt":"2012-02-09T23:58:38Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"git_version_string is declared in builtins.h, but lived in git.c.\n\nWhen diff.c starts to use functions from help.c, linking against\nlibgit.a will fail, unless git.o containing git_version_string is\nlinked too. This variable is only used in a couple of places, help.c\nbeing one of them. git.o is biggish, so it let's move\ngit_version_string to help.c.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n Makefile |    5 +++--\n git.c    |    2 --\n help.c   |    2 ++\n 3 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex a782409..264fe4f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1851,7 +1851,7 @@ strip: $(PROGRAMS) git$X\n \t$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X\n \n git.o: common-cmds.h\n-git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='\"$(GIT_VERSION)\"' \\\n+git.sp git.s git.o: EXTRA_CPPFLAGS = \\\n \t'-DGIT_HTML_PATH=\"$(htmldir_SQ)\"' \\\n \t'-DGIT_MAN_PATH=\"$(mandir_SQ)\"' \\\n \t'-DGIT_INFO_PATH=\"$(infodir_SQ)\"'\n@@ -1860,7 +1860,8 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \\\n \t\t$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)\n \n-help.sp help.o: common-cmds.h\n+help.o: common-cmds.h\n+help.sp help.o: EXTRA_CPPFLAGS = -DGIT_VERSION='\"$(GIT_VERSION)\"'\n \n builtin/help.sp builtin/help.o: common-cmds.h\n builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \\\ndiff --git a/git.c b/git.c\nindex 3805616..a24a0fd 100644\n--- a/git.c\n+++ b/git.c\n@@ -256,8 +256,6 @@ static int handle_alias(int *argcp, const char ***argv)\n \treturn ret;\n }\n \n-const char git_version_string[] = GIT_VERSION;\n-\n #define RUN_SETUP\t\t(1<<0)\n #define RUN_SETUP_GENTLY\t(1<<1)\n #define USE_PAGER\t\t(1<<2)\ndiff --git a/help.c b/help.c\nindex cbbe966..bc15066 100644\n--- a/help.c\n+++ b/help.c\n@@ -409,6 +409,8 @@ const char *help_unknown_cmd(const char *cmd)\n \texit(1);\n }\n \n+const char git_version_string[] = GIT_VERSION;\n+\n int cmd_version(int argc, const char **argv, const char *prefix)\n {\n \tprintf(\"git version %s\\n\", git_version_string);\n-- \n1.7.9.rc2.127.gcb239\n"},{"id":"184293","messageId":"1328831921-27272-3-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328831921-27272-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 2/4] help.c: make term_columns() cached and export it","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-09T23:58:39Z","receivedAt":"2012-02-09T23:58:39Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Since term_columns() will usually fail, when a pager is installed,\nthe cache is primed before the pager is installed. If a pager is not\ninstalled, then the cache will be set on first use.\n\nConforms to The Single UNIX Specification, Version 2\n(http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n help.c  |   31 +++++++++++++++++++++++--------\n help.h  |    2 ++\n pager.c |    5 +++++\n 3 files changed, 30 insertions(+), 8 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex bc15066..75b8d4b 100644\n--- a/help.c\n+++ b/help.c\n@@ -5,26 +5,41 @@\n #include \"help.h\"\n #include \"common-cmds.h\"\n \n-/* most GUI terminals set COLUMNS (although some don't export it) */\n-static int term_columns(void)\n+/* cache for term_columns() value. Set on first use or when\n+ * installing a pager and replacing stdout.\n+ */\n+static int term_columns_cache;\n+\n+/* Return cached value (iff set) or $COLUMNS (iff set and positive) or\n+ * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n+ *\n+ * $COLUMNS even if set, is usually not exported, so\n+ * the variable can be used to override autodection.\n+ */\n+int term_columns(void)\n {\n-\tchar *col_string = getenv(\"COLUMNS\");\n-\tint n_cols;\n+\tif (term_columns_cache)\n+\t\treturn term_columns_cache;\n \n-\tif (col_string && (n_cols = atoi(col_string)) > 0)\n-\t\treturn n_cols;\n+\t{\n+\t\tchar *col_string = getenv(\"COLUMNS\");\n+\t\tint n_cols;\n+\n+\t\tif (col_string && (n_cols = atoi(col_string)) > 0)\n+\t\t\treturn (term_columns_cache = n_cols);\n+\t}\n \n #ifdef TIOCGWINSZ\n \t{\n \t\tstruct winsize ws;\n \t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n \t\t\tif (ws.ws_col)\n-\t\t\t\treturn ws.ws_col;\n+\t\t\t\treturn (term_columns_cache = ws.ws_col);\n \t\t}\n \t}\n #endif\n \n-\treturn 80;\n+\treturn (term_columns_cache = 80);\n }\n \n void add_cmdname(struct cmdnames *cmds, const char *name, int len)\ndiff --git a/help.h b/help.h\nindex b6b12d5..880a4b4 100644\n--- a/help.h\n+++ b/help.h\n@@ -29,4 +29,6 @@ extern void list_commands(const char *title,\n \t\t\t  struct cmdnames *main_cmds,\n \t\t\t  struct cmdnames *other_cmds);\n \n+extern int term_columns(void);\n+\n #endif /* HELP_H */\ndiff --git a/pager.c b/pager.c\nindex 975955b..e7032de 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"run-command.h\"\n #include \"sigchain.h\"\n+#include \"help.h\"\n \n #ifndef DEFAULT_PAGER\n #define DEFAULT_PAGER \"less\"\n@@ -76,6 +77,10 @@ void setup_pager(void)\n \tif (!pager)\n \t\treturn;\n \n+\t/* prime the term_columns() cache before it is too\n+\t * late and stdout is replaced */\n+\t(void) term_columns();\n+\n \tsetenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n \n \t/* spawn the pager */\n-- \n1.7.9.rc2.127.gcb239\n"},{"id":"184295","messageId":"1328831921-27272-4-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328831921-27272-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 3/4] diff --stat: use the real terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-09T23:58:40Z","receivedAt":"2012-02-09T23:58:40Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Some projects (especially in Java), have long filename paths, with\nnested directories or long individual filenames. When files are\nrenamed, the stat output can be almost useless. If the middle part\nbetween { and } is long (because the file was moved to a completely\ndifferent directory), then most of the path would be truncated.\n\nIt makes sense to use the full terminal width.\n\nThe output is still not optimal, because too many columns are devoted\nto +- output, and not enough to filenames, but this is a policy\nquestion, changed in next commit.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n diff.c |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 7e15426..8406a0d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -7,6 +7,7 @@\n #include \"diffcore.h\"\n #include \"delta.h\"\n #include \"xdiff-interface.h\"\n+#include \"help.h\"\n #include \"color.h\"\n #include \"attr.h\"\n #include \"run-command.h\"\n@@ -1341,7 +1342,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tline_prefix = msg->buf;\n \t}\n \n-\twidth = options->stat_width ? options->stat_width : 80;\n+\twidth = options->stat_width ? options->stat_width : term_columns();\n \tname_width = options->stat_name_width ? options->stat_name_width : 50;\n \tcount = options->stat_count ? options->stat_count : data->nr;\n \n-- \n1.7.9.rc2.127.gcb239\n"},{"id":"184294","messageId":"1328831921-27272-5-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328831921-27272-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 4/4] diff --stat: use most of the space for file names","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-09T23:58:41Z","receivedAt":"2012-02-09T23:58:41Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n diff.c |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 8406a0d..6220190 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1343,7 +1343,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t}\n \n \twidth = options->stat_width ? options->stat_width : term_columns();\n-\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n+\tname_width = options->stat_name_width ? options->stat_name_width\n+\t\t: term_columns() - 20; /* the graph defaults to 20 columns */\n \tcount = options->stat_count ? options->stat_count : data->nr;\n \n \t/* Sanity: give at least 5 columns to the graph,\n-- \n1.7.9.rc2.127.gcb239\n"},{"id":"184299","messageId":"7vipjftt06.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1328831921-27272-2-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/4] Move git_version_string to help.c in preparation for diff changes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-10T00:46:33Z","receivedAt":"2012-02-10T00:46:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> git_version_string is declared in builtins.h, but lived in git.c.\n>\n> When diff.c starts to use functions from help.c, linking against\n> libgit.a will fail,  unless git.o containing git_version_string is\n> linked too.\n\nSorry, it is unclear what you mean by the above, nor why you need this\nchange in the first place. The resulting diff.o will certainly linked to\ngit.o as it does not have its own \"main()\" at all.  And builtins.h is a\nperfect place to declare things that are for the use of built-in commands\nlike implementations of diff family of commands, as they all are linked\ninto git.o (namely the commands[] array in handle_internal_command()) to\nbe usable.\n\nWhat am I missing from between the lines of your log message?\n"},{"id":"184300","messageId":"7vehu3tssz.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1328831921-27272-3-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 2/4] help.c: make term_columns() cached and export it","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-10T00:50:52Z","receivedAt":"2012-02-10T00:50:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> diff --git a/help.c b/help.c\n> index bc15066..75b8d4b 100644\n> --- a/help.c\n> +++ b/help.c\n> @@ -5,26 +5,41 @@\n>  #include \"help.h\"\n>  #include \"common-cmds.h\"\n>  \n> -/* most GUI terminals set COLUMNS (although some don't export it) */\n> -static int term_columns(void)\n> +/* cache for term_columns() value. Set on first use or when\n> + * installing a pager and replacing stdout.\n> + */\n\nJust a style.\n\n\t/*\n         * We format multi-line\n         * comment block like\n         * this.\n         */\n\n> +static int term_columns_cache;\n> +\n> +/* Return cached value (iff set) or $COLUMNS (iff set and positive) or\n> + * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n> + *\n> + * $COLUMNS even if set, is usually not exported, so\n> + * the variable can be used to override autodection.\n> + */\n> +int term_columns(void)\n>  {\n> -\tchar *col_string = getenv(\"COLUMNS\");\n> -\tint n_cols;\n> +\tif (term_columns_cache)\n> +\t\treturn term_columns_cache;\n>  \n> -\tif (col_string && (n_cols = atoi(col_string)) > 0)\n> -\t\treturn n_cols;\n> +\t{\n> +\t\tchar *col_string = getenv(\"COLUMNS\");\n> +\t\tint n_cols;\n> +\n> +\t\tif (col_string && (n_cols = atoi(col_string)) > 0)\n> +\t\t\treturn (term_columns_cache = n_cols);\n> +\t}\n\nI can see the justification for the existing one inside the #ifdef below,\nbut why do you need the extra scope above?\n\nWe tend to avoid assignment as a part of another expression.  The old code\nalready violates that convention, but please do not make it worse by\nintroducing three new ones.\n"},{"id":"184302","messageId":"7vaa4rtsm9.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1328831921-27272-4-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 3/4] diff --stat: use the real terminal width","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-10T00:54:54Z","receivedAt":"2012-02-10T00:54:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Some projects (especially in Java), have long filename paths, with\n> nested directories or long individual filenames. When files are\n> renamed, the stat output can be almost useless. If the middle part\n> between { and } is long (because the file was moved to a completely\n> different directory), then most of the path would be truncated.\n>\n> It makes sense to use the full terminal width.\n>\n> The output is still not optimal, because too many columns are devoted\n> to +- output, and not enough to filenames, but this is a policy\n> question, changed in next commit.\n>\n> Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n> ---\n>  diff.c |    3 ++-\n>  1 files changed, 2 insertions(+), 1 deletions(-)\n>\n> diff --git a/diff.c b/diff.c\n> index 7e15426..8406a0d 100644\n> --- a/diff.c\n> +++ b/diff.c\n> @@ -7,6 +7,7 @@\n>  #include \"diffcore.h\"\n>  #include \"delta.h\"\n>  #include \"xdiff-interface.h\"\n> +#include \"help.h\"\n>  #include \"color.h\"\n>  #include \"attr.h\"\n>  #include \"run-command.h\"\n> @@ -1341,7 +1342,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>  \t\tline_prefix = msg->buf;\n>  \t}\n>  \n> -\twidth = options->stat_width ? options->stat_width : 80;\n> +\twidth = options->stat_width ? options->stat_width : term_columns();\n\nThe output from \"git format-patch\" shouldn't be affected at all by the\nwidth of the terminal the patch sender happened to have used when the\ncommand was run when the user did not explicitly ask a custom width by\ngiving a --stat-width command line option.\n\nHow do you prevent regression to the command in this series?\n"},{"id":"184303","messageId":"7v62fftsl5.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1328831921-27272-5-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 4/4] diff --stat: use most of the space for file names","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-10T00:55:34Z","receivedAt":"2012-02-10T00:55:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n> ---\n>  diff.c |    3 ++-\n>  1 files changed, 2 insertions(+), 1 deletions(-)\n>\n> diff --git a/diff.c b/diff.c\n> index 8406a0d..6220190 100644\n> --- a/diff.c\n> +++ b/diff.c\n> @@ -1343,7 +1343,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>  \t}\n>  \n>  \twidth = options->stat_width ? options->stat_width : term_columns();\n> -\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n> +\tname_width = options->stat_name_width ? options->stat_name_width\n> +\t\t: term_columns() - 20; /* the graph defaults to 20 columns */\n\nWhy?  Isn't 80-50 = 30?\n"},{"id":"184327","messageId":"CACsJy8APGeTNv_E3qD=xFCiLC25M_nm3aJbq6YU73J=X0Wxh2w@mail.gmail.com","threadId":"29589","inReplyTo":"1328831921-27272-4-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 3/4] diff --stat: use the real terminal width","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-02-10T06:15:35Z","receivedAt":"2012-02-10T06:15:35Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2012/2/10 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>:\n> @@ -1341,7 +1342,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>                line_prefix = msg->buf;\n>        }\n>\n> -       width = options->stat_width ? options->stat_width : 80;\n> +       width = options->stat_width ? options->stat_width : term_columns();\n>        name_width = options->stat_name_width ? options->stat_name_width : 50;\n>        count = options->stat_count ? options->stat_count : data->nr;\n\nI tried this in the past and \"git log -p\" looked ugly on git.git\nmainly because commit messages are still ~70 char long lines on my 279\nchar wide terminal. If this is project dependent, perhaps a config\nkey? Also the \"50\" below the changed line, maybe you want to change it\nto 0.6 * width.\n-- \nDuy\n"},{"id":"184344","messageId":"4F34FE9A.7020600@in.waw.pl","threadId":"29589","inReplyTo":"CACsJy8APGeTNv_E3qD=xFCiLC25M_nm3aJbq6YU73J=X0Wxh2w@mail.gmail.com","subject":"Re: [PATCH 3/4] diff --stat: use the real terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-10T11:25:14Z","receivedAt":"2012-02-10T11:25:14Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"On 02/10/2012 07:15 AM, Nguyen Thai Ngoc Duy wrote:\n> 2012/2/10 Zbigniew Jędrzejewski-Szmek<zbyszek@in.waw.pl>:\n>> @@ -1341,7 +1342,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>>                 line_prefix = msg->buf;\n>>         }\n>>\n>> -       width = options->stat_width ? options->stat_width : 80;\n>> +       width = options->stat_width ? options->stat_width : term_columns();\n>>         name_width = options->stat_name_width ? options->stat_name_width : 50;\n>>         count = options->stat_count ? options->stat_count : data->nr;\n>\n> I tried this in the past and \"git log -p\" looked ugly on git.git\n> mainly because commit messages are still ~70 char long lines on my 279\n> char wide terminal. If this is project dependent, perhaps a config\n> key? Also the \"50\" below the changed line, maybe you want to change it\n> to 0.6 * width.\n\nThanks for all the comments. I'll post a newer version, but I have two \nquestions:\n\nI agree that making the output very wide with lots of +- is not very \nelegant. (E.g. 8f24a6323ece9be1bf1a04b4b5856112438337f2 has\n    builtin/grep.c |  142 +++--------------------------------....--\nwhich doesn't look right.). So I think it would make sense to limit\nthe graph part to something like 50 columns, even if there's more space.\nI believe that git.git would look fine with this change. There are some \nfairly long lines \n(t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master \nis 86 chars) but with 50 columns of graph the output would take 140 \ncolumns -- with the graph part slightly sticking out from the 80 column \ndescriptions, but still not too ugly.\n\nShould I add a new option --stat-graph-width in analogy to \n--stat-name-width, or should this be hard-coded?\n\nJC:\n > The output from \"git format-patch\" shouldn't be affected at all by the\n > width of the terminal the patch sender happened to have used when the\n > command was run when the user did not explicitly ask a custom width by\n > giving a --stat-width command line option.\n >\n > How do you prevent regression to the command in this series?\ngit format-patch is not affected by default. But with --stdout\nthe width is changed, iff stdout is a tty. When --stdout output\nis connected to a pipe, the width is not changed. I think that\nthis behaviour is OK.\n\nShould a test be added to check that 'git format-patch --stat' output \ndoesn't change? Should I test for something else?\n\n--\nZbyszek\n"},{"id":"184348","messageId":"CACsJy8AQdz=uwDm+FOgcUB5JOi5U7w-W4w7yUPL6wd2FO-bArg@mail.gmail.com","threadId":"29589","inReplyTo":"4F34FE9A.7020600@in.waw.pl","subject":"Re: [PATCH 3/4] diff --stat: use the real terminal width","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-02-10T13:00:27Z","receivedAt":"2012-02-10T13:00:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2012/2/10 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>:\n>> I tried this in the past and \"git log -p\" looked ugly on git.git\n>> mainly because commit messages are still ~70 char long lines on my 279\n>> char wide terminal. If this is project dependent, perhaps a config\n>> key? Also the \"50\" below the changed line, maybe you want to change it\n>> to 0.6 * width.\n>\n>\n> Thanks for all the comments. I'll post a newer version, but I have two\n> questions:\n>\n> I agree that making the output very wide with lots of +- is not very\n> elegant. (E.g. 8f24a6323ece9be1bf1a04b4b5856112438337f2 has\n>   builtin/grep.c |  142 +++--------------------------------....--\n> which doesn't look right.). So I think it would make sense to limit\n> the graph part to something like 50 columns, even if there's more space.\n> I believe that git.git would look fine with this change. There are some\n> fairly long lines\n> (t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n> is 86 chars) but with 50 columns of graph the output would take 140 columns\n> -- with the graph part slightly sticking out from the 80 column\n> descriptions, but still not too ugly.\n\nYou also need to pay attention, not to exceed term_columns() because\nof this dynamic name part. But the idea sounds good to me.\n\nIt would be even better if we had some heuristics to shorten\nexceptionally long names with ellipsis, to keep the name part from\nbeing overly stretched.\n\n> Should I add a new option --stat-graph-width in analogy to\n> --stat-name-width, or should this be hard-coded?\n\nI don't know about other people, but I have no urge to change graph width.\n-- \nDuy\n"},{"id":"184360","messageId":"1328891972-23695-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"CACsJy8AQdz=uwDm+FOgcUB5JOi5U7w-W4w7yUPL6wd2FO-bArg@mail.gmail.com","subject":"[PATCH 0/3 v2] diff --stat: use the real terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-10T16:39:29Z","receivedAt":"2012-02-10T16:39:29Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Hi,\nthis is version 2.\nChanges:\n\n- style fixes\n- some tests for git-format-patch added\n- patches 3 and 4 squashed together, since they touch the same lines\n- graph width is limited to 40 columns, even if there's more space\n- patch descriptions extended and cleared up\n\nDescription (modified):\n\nthis is a patch series to make 'git diff --stat' use full terminal\nwidth instead of hard-coded 80 columns.\n\nThis is quite useful when working on projects with nested directory\nstructure, e.g. Java:\n .../{ => workspace/tasks}/GetTaskResultAction.java |   10 +-\n .../tasks}/RemoveAllAbortedTasksAction.java        |    7 +-\n .../tasks}/RemoveAllFailedTasksAction.java         |    7 +-\nis changed to display full paths if the terminal window is wide\nenough.\n\nGit usually uses the full terminal width automatically, so it should\ndo so with --stat too.\n\nThe \"big\" functional change in the patch series is\ns/80/term_columns()/ in show_stats(). The partitioning of available\ncolumns is changed to dedicate more space to file names and the number\nof columns used for +- graph is limited.\n"},{"id":"184361","messageId":"1328891972-23695-2-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328891972-23695-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 1/3] Move git_version_string to help.c before diff changes","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-10T16:39:30Z","receivedAt":"2012-02-10T16:39:30Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"git_version_string lives in git.c. When diff.c starts to use functions\nfrom help.c, which in turn use git_version_string, linking against\nlibgit.a will fail. This is because git_version_string is physically\nlocated in git.o, and this object file is not part of libgit.a. One\noption would be to add git.o to libgit.a, but git.o is biggish. The\nsecond, better option is to move git_version_string to somewhere where\nit'll become part of libgit.a. This variable is only used in a couple\nof places, help.c being one of them, so it let's move\ngit_version_string from git.c to help.c. The git binary is linked with\nhelp.o, so it is not affected by this move.\n\nWithout this change the next commit would fail with:\n$ gcc  -g -O0 -I. -DUSE_LIBPCRE  -DHAVE_PATHS_H -DHAVE_DEV_TTY -DSHA1_HEADER='<openssl/sha.h>'  -DNO_STRLCPY -DNO_MKSTEMPS -o git-daemon   daemon.o libgit.a xdiff/lib.a  -lpcre -lz  -lcrypto -lpthread\nlibgit.a(help.o): In function `cmd_version':\n/home/zbyszek/git/git/help.c:435: undefined reference to `git_version_string'\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n Makefile |    5 +++--\n git.c    |    2 --\n help.c   |    2 ++\n 3 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 4817157..ccafb95 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1890,7 +1890,7 @@ strip: $(PROGRAMS) git$X\n \t$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X\n \n git.o: common-cmds.h\n-git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='\"$(GIT_VERSION)\"' \\\n+git.sp git.s git.o: EXTRA_CPPFLAGS = \\\n \t'-DGIT_HTML_PATH=\"$(htmldir_SQ)\"' \\\n \t'-DGIT_MAN_PATH=\"$(mandir_SQ)\"' \\\n \t'-DGIT_INFO_PATH=\"$(infodir_SQ)\"'\n@@ -1899,7 +1899,8 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \\\n \t\t$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)\n \n-help.sp help.o: common-cmds.h\n+help.o: common-cmds.h\n+help.sp help.o: EXTRA_CPPFLAGS = -DGIT_VERSION='\"$(GIT_VERSION)\"'\n \n builtin/help.sp builtin/help.o: common-cmds.h\n builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \\\ndiff --git a/git.c b/git.c\nindex 3805616..a24a0fd 100644\n--- a/git.c\n+++ b/git.c\n@@ -256,8 +256,6 @@ static int handle_alias(int *argcp, const char ***argv)\n \treturn ret;\n }\n \n-const char git_version_string[] = GIT_VERSION;\n-\n #define RUN_SETUP\t\t(1<<0)\n #define RUN_SETUP_GENTLY\t(1<<1)\n #define USE_PAGER\t\t(1<<2)\ndiff --git a/help.c b/help.c\nindex cbbe966..bc15066 100644\n--- a/help.c\n+++ b/help.c\n@@ -409,6 +409,8 @@ const char *help_unknown_cmd(const char *cmd)\n \texit(1);\n }\n \n+const char git_version_string[] = GIT_VERSION;\n+\n int cmd_version(int argc, const char **argv, const char *prefix)\n {\n \tprintf(\"git version %s\\n\", git_version_string);\n-- \n1.7.9.263.g4be11.dirty\n"},{"id":"184363","messageId":"1328891972-23695-3-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328891972-23695-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 2/3] help.c: make term_columns() cached and export it","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-10T16:39:31Z","receivedAt":"2012-02-10T16:39:31Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Since term_columns() will usually fail, when a pager is installed,\nthe cache is primed before the pager is installed. If a pager is not\ninstalled, then the cache will be set on first use.\n\nConforms to The Single UNIX Specification, Version 2\n(http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n help.c  |   37 +++++++++++++++++++++++++++++--------\n help.h  |    2 ++\n pager.c |    5 +++++\n 3 files changed, 36 insertions(+), 8 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex bc15066..5d1cb1d 100644\n--- a/help.c\n+++ b/help.c\n@@ -5,26 +5,47 @@\n #include \"help.h\"\n #include \"common-cmds.h\"\n \n-/* most GUI terminals set COLUMNS (although some don't export it) */\n-static int term_columns(void)\n+/* \n+ * Cache for term_columns() value. Set on first use or when\n+ * installing a pager and replacing stdout.\n+ */\n+static int term_columns_cache;\n+\n+/* \n+ * Return cached value (if set) or $COLUMNS (if set and positive) or\n+ * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n+ *\n+ * $COLUMNS even if set, is usually not exported, so\n+ * the variable can be used to override autodection.\n+ */\n+int term_columns(void)\n {\n-\tchar *col_string = getenv(\"COLUMNS\");\n+\tchar *col_string;\n \tint n_cols;\n \n-\tif (col_string && (n_cols = atoi(col_string)) > 0)\n-\t\treturn n_cols;\n+\tif (term_columns_cache)\n+\t\treturn term_columns_cache;\n+\n+\tcol_string = getenv(\"COLUMNS\");\n+\tif (col_string && (n_cols = atoi(col_string)) > 0) {\n+\t\tterm_columns_cache = n_cols;\n+\t\treturn term_columns_cache;\n+\t}\n \n #ifdef TIOCGWINSZ\n \t{\n \t\tstruct winsize ws;\n \t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n-\t\t\tif (ws.ws_col)\n-\t\t\t\treturn ws.ws_col;\n+\t\t\tif (ws.ws_col) {\n+\t\t\t\tterm_columns_cache = ws.ws_col;\n+\t\t\t\treturn term_columns_cache;\n+\t\t\t}\n \t\t}\n \t}\n #endif\n \n-\treturn 80;\n+\tterm_columns_cache = 80;\n+\treturn term_columns_cache;\n }\n \n void add_cmdname(struct cmdnames *cmds, const char *name, int len)\ndiff --git a/help.h b/help.h\nindex b6b12d5..880a4b4 100644\n--- a/help.h\n+++ b/help.h\n@@ -29,4 +29,6 @@ extern void list_commands(const char *title,\n \t\t\t  struct cmdnames *main_cmds,\n \t\t\t  struct cmdnames *other_cmds);\n \n+extern int term_columns(void);\n+\n #endif /* HELP_H */\ndiff --git a/pager.c b/pager.c\nindex 975955b..e7032de 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"run-command.h\"\n #include \"sigchain.h\"\n+#include \"help.h\"\n \n #ifndef DEFAULT_PAGER\n #define DEFAULT_PAGER \"less\"\n@@ -76,6 +77,10 @@ void setup_pager(void)\n \tif (!pager)\n \t\treturn;\n \n+\t/* prime the term_columns() cache before it is too\n+\t * late and stdout is replaced */\n+\t(void) term_columns();\n+\n \tsetenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n \n \t/* spawn the pager */\n-- \n1.7.9.263.g4be11.dirty\n"},{"id":"184362","messageId":"1328891972-23695-4-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1328891972-23695-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 3/3] diff --stat: use the real terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-10T16:39:32Z","receivedAt":"2012-02-10T16:39:32Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Some projects (especially in Java), have long filename paths, with\nnested directories or long individual filenames. When files are\nrenamed, the stat output can be almost useless. If the middle part\nbetween { and } is long (because the file was moved to a completely\ndifferent directory), then most of the path would be truncated.\n\nIt makes sense to use the full terminal width.\n\nIf commits changing a lot of lines are displayed in a wide terminal\nwindow (200 or more columns), and the +- graph uses the full width,\nthe output looks bad. Messages wrapped to about 80 columns are\ninterspersed with very long +- lines. It makes sense to limit the\nwidth of the graph to a fixed value, even if more columns are\navailable. This fixed value is subjectively hard-coded to be 40\ncolumns, but seems to work well for git.git and linux-2.6.git and\nother repositories.\n\nThree tests are added: the first one check that --stat output for a\nlong file name is the same as previously (the test should pass\nindependently of this patch). The last two check that --stat output\nwith a massive change uses only 40 columns for +- in graph output.\nThose two tests are dependent on this patch.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n diff.c                  |   26 ++++++++++++++------------\n t/t4014-format-patch.sh |   40 ++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 54 insertions(+), 12 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 84780fd..8176d74 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -7,6 +7,7 @@\n #include \"diffcore.h\"\n #include \"delta.h\"\n #include \"xdiff-interface.h\"\n+#include \"help.h\"\n #include \"color.h\"\n #include \"attr.h\"\n #include \"run-command.h\"\n@@ -1376,7 +1377,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \tint i, len, add, del, adds = 0, dels = 0;\n \tuintmax_t max_change = 0, max_len = 0;\n \tint total_files = data->nr;\n-\tint width, name_width, count;\n+\tint width, name_width, graph_width, count;\n \tconst char *reset, *add_c, *del_c;\n \tconst char *line_prefix = \"\";\n \tint extra_shown = 0;\n@@ -1390,8 +1391,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tline_prefix = msg->buf;\n \t}\n \n-\twidth = options->stat_width ? options->stat_width : 80;\n-\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n+\twidth = options->stat_width ? options->stat_width : term_columns();\n+\tname_width = options->stat_name_width ? options->stat_name_width\n+\t\t: width * 5/8; /* this gives 50 if not on tty */\n \tcount = options->stat_count ? options->stat_count : data->nr;\n \n \t/* Sanity: give at least 5 columns to the graph,\n@@ -1433,14 +1435,14 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t * 10 is for one blank at the beginning of the line plus\n \t * \" | count \" between the name and the graph.\n \t *\n-\t * From here on, name_width is the width of the name area,\n-\t * and width is the width of the graph area.\n+\t * From here name_width is the width of the name area,\n+\t * and graph_width is the width of the graph area.\n+\t * max_change is used to scale graph properly.\n \t */\n \tname_width = (name_width < max_len) ? name_width : max_len;\n-\tif (width < (name_width + 10) + max_change)\n-\t\twidth = width - (name_width + 10);\n-\telse\n-\t\twidth = max_change;\n+\tgraph_width = max_change < 40 ? max_change : 40;\n+\tif (width < (name_width + 10) + graph_width)\n+\t\tgraph_width = width - (name_width + 10);\n \n \tfor (i = 0; i < count; i++) {\n \t\tconst char *prefix = \"\";\n@@ -1497,9 +1499,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tadds += add;\n \t\tdels += del;\n \n-\t\tif (width <= max_change) {\n-\t\t\tadd = scale_linear(add, width, max_change);\n-\t\t\tdel = scale_linear(del, width, max_change);\n+\t\tif (graph_width <= max_change) {\n+\t\t\tadd = scale_linear(add, graph_width, max_change);\n+\t\t\tdel = scale_linear(del, graph_width, max_change);\n \t\t}\n \t\tfprintf(options->file, \"%s\", line_prefix);\n \t\tshow_name(options->file, prefix, name, len);\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7dfe716..bd3002b 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -894,4 +894,44 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\t 1 +\n+EOF\n+name=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n+test_expect_success 'format patch filename width is limited' \"\n+\t> ${name} &&\n+\tgit add ${name} &&\n+\tgit commit -m message &&\n+\techo a > ${name} &&\n+\tgit commit -m message ${name} &&\n+\tgit format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 aaaaa > actual &&\n+\ttest_cmp expect actual\n+\"\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch graph width is 40 columns' '\n+\t> abcd &&\n+\tgit add abcd &&\n+\tgit commit -m message &&\n+\tseq 1000 > abcd &&\n+\tgit commit -m message abcd &&\n+\tgit format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch ignores COLUMNS' '\n+\t> abcd &&\n+\tgit add abcd &&\n+\tgit commit -m message &&\n+\tseq 1000 > abcd &&\n+\tgit commit -m message abcd &&\n+\tCOLUMNS=200 git format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.7.9.263.g4be11.dirty\n"},{"id":"184370","messageId":"7vty2yr2of.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1328891972-23695-2-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/3] Move git_version_string to help.c before diff changes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-10T17:58:08Z","receivedAt":"2012-02-10T17:58:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> git_version_string lives in git.c. When diff.c starts to use functions\n> from help.c, which in turn use git_version_string, linking against\n> libgit.a will fail. This is because git_version_string is physically\n> located in git.o, and this object file is not part of libgit.a.\n\nBut what is wrong about that?\n\nIf you are making the termio related code reusable and sharable by turning\nthe static \"term_columns()\" in help.o into an external symbol, there is no\nreason that termio related function, which is now useful outside the\ncontext of giving help, must stay in help.c where its life happened to\nhave started.  In fact, \"tell me how wide the terminal is\" does not belong\nto something called \"help subsystem\", no?\n\nWouldn't a new file, term.c or something, be a lot more suitable home for\nthe function you will be reusing from diff and other parts of the system?\n"},{"id":"184375","messageId":"7vmx8qr1gb.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1328891972-23695-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 0/3 v2] diff --stat: use the real terminal width","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-10T18:24:36Z","receivedAt":"2012-02-10T18:24:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> - style fixes\n\nI think I still saw at least one malformatted multi-line comments in this\nround, though (I stopped looking after I saw one, so there may be others).\n\n> - some tests for git-format-patch added\n> - patches 3 and 4 squashed together, since they touch the same lines\n> - graph width is limited to 40 columns, even if there's more space\n\nHmm.\n\nThis is what we have in the documentation.\n\n        --stat[=<width>[,<name-width>[,<count>]]]::\n                Generate a diffstat.  You can override the default\n                output width for 80-column terminal by `--stat=<width>`.\n                The width of the filename part can be controlled by\n                giving another width to it separated by a comma.\n\nNaïvely, one would expect that a \"use the real terminal width\" series\nwould be only to learn the width of the terminal and tweak its hardcoded\ndefault \"80\" to that width, and change nothing else, leaving the default\nfor name-width to \"50\", which still can be overridable if needed.\n\nBut the reason somebody wants to have a wider width is more often not\nbecause they want to see longer bars, but because they want to see long\nnames without truncation, so in retrospect, the order the \"--stat=\" option\ntakes its values is inconvenient.  Users would more often want to tinker\nwith name-width than width because the latter can be auto-detected.\n\nWhich is a bit unfortunate.\n\nIn any case, the above needs to be updated to describe what the updated\nlogic does.  Do you have documentation updates in the series?\n\nJudging from what you wrote in the above, the updated logic is, instead of\nthe \"naïve\" version:\n\n - auto-detect, if possible, to set the default \"width\" to COLUMNS instead\n   of hardcoded 80; and\n\n - instead of using hardcoded 50, use width-40 as the default as the\n   default \"name-width\".\n\nBut if that is what is going on, shouldn't your \"40\" be \"30\" to retain\nbackward compatibility for people who work on 80-column terminals?\n\nOr is there something more complex going on that you are not describing\nhere?\n"},{"id":"184424","messageId":"CACsJy8AjqqEpJr64DJUqVumw1sB2g3pvuz-g4DxhmS-ZbGhY3w@mail.gmail.com","threadId":"29589","inReplyTo":"1328891972-23695-3-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 2/3] help.c: make term_columns() cached and export it","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-02-11T04:36:23Z","receivedAt":"2012-02-11T04:36:23Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2012/2/10 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>:\n> Since term_columns() will usually fail, when a pager is installed,\n> the cache is primed before the pager is installed. If a pager is not\n> installed, then the cache will be set on first use.\n\nConflict alert. term_columns() is also moved out of help.c in\nnd/columns series on pu, commit cb0850f (Save terminal width before\nsetting up pager - 2012-02-04)\n\n>\n> Conforms to The Single UNIX Specification, Version 2\n> (http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).\n>\n> Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n> ---\n>  help.c  |   37 +++++++++++++++++++++++++++++--------\n>  help.h  |    2 ++\n>  pager.c |    5 +++++\n>  3 files changed, 36 insertions(+), 8 deletions(-)\n>\n> diff --git a/help.c b/help.c\n> index bc15066..5d1cb1d 100644\n> --- a/help.c\n> +++ b/help.c\n> @@ -5,26 +5,47 @@\n>  #include \"help.h\"\n>  #include \"common-cmds.h\"\n>\n> -/* most GUI terminals set COLUMNS (although some don't export it) */\n> -static int term_columns(void)\n> +/*\n> + * Cache for term_columns() value. Set on first use or when\n> + * installing a pager and replacing stdout.\n> + */\n> +static int term_columns_cache;\n> +\n> +/*\n> + * Return cached value (if set) or $COLUMNS (if set and positive) or\n> + * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n> + *\n> + * $COLUMNS even if set, is usually not exported, so\n> + * the variable can be used to override autodection.\n> + */\n> +int term_columns(void)\n>  {\n> -       char *col_string = getenv(\"COLUMNS\");\n> +       char *col_string;\n>        int n_cols;\n>\n> -       if (col_string && (n_cols = atoi(col_string)) > 0)\n> -               return n_cols;\n> +       if (term_columns_cache)\n> +               return term_columns_cache;\n> +\n> +       col_string = getenv(\"COLUMNS\");\n> +       if (col_string && (n_cols = atoi(col_string)) > 0) {\n> +               term_columns_cache = n_cols;\n> +               return term_columns_cache;\n> +       }\n>\n>  #ifdef TIOCGWINSZ\n>        {\n>                struct winsize ws;\n>                if (!ioctl(1, TIOCGWINSZ, &ws)) {\n> -                       if (ws.ws_col)\n> -                               return ws.ws_col;\n> +                       if (ws.ws_col) {\n> +                               term_columns_cache = ws.ws_col;\n> +                               return term_columns_cache;\n> +                       }\n>                }\n>        }\n>  #endif\n>\n> -       return 80;\n> +       term_columns_cache = 80;\n> +       return term_columns_cache;\n>  }\n>\n>  void add_cmdname(struct cmdnames *cmds, const char *name, int len)\n> diff --git a/help.h b/help.h\n> index b6b12d5..880a4b4 100644\n> --- a/help.h\n> +++ b/help.h\n> @@ -29,4 +29,6 @@ extern void list_commands(const char *title,\n>                          struct cmdnames *main_cmds,\n>                          struct cmdnames *other_cmds);\n>\n> +extern int term_columns(void);\n> +\n>  #endif /* HELP_H */\n> diff --git a/pager.c b/pager.c\n> index 975955b..e7032de 100644\n> --- a/pager.c\n> +++ b/pager.c\n> @@ -1,6 +1,7 @@\n>  #include \"cache.h\"\n>  #include \"run-command.h\"\n>  #include \"sigchain.h\"\n> +#include \"help.h\"\n>\n>  #ifndef DEFAULT_PAGER\n>  #define DEFAULT_PAGER \"less\"\n> @@ -76,6 +77,10 @@ void setup_pager(void)\n>        if (!pager)\n>                return;\n>\n> +       /* prime the term_columns() cache before it is too\n> +        * late and stdout is replaced */\n> +       (void) term_columns();\n> +\n>        setenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n>\n>        /* spawn the pager */\n> --\n> 1.7.9.263.g4be11.dirty\n>\n\n\n\n-- \nDuy\n"},{"id":"184450","messageId":"4F3647B4.8090803@in.waw.pl","threadId":"29589","inReplyTo":"CACsJy8AjqqEpJr64DJUqVumw1sB2g3pvuz-g4DxhmS-ZbGhY3w@mail.gmail.com","subject":"Re: [PATCH 2/3] help.c: make term_columns() cached and export it","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-11T10:49:24Z","receivedAt":"2012-02-11T10:49:24Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"On 02/11/2012 05:36 AM, Nguyen Thai Ngoc Duy wrote:\n> 2012/2/10 Zbigniew Jędrzejewski-Szmek<zbyszek@in.waw.pl>:\n>> Since term_columns() will usually fail, when a pager is installed,\n>> the cache is primed before the pager is installed. If a pager is not\n>> installed, then the cache will be set on first use.\n>\n> Conflict alert. term_columns() is also moved out of help.c in\n> nd/columns series on pu, commit cb0850f (Save terminal width before\n> setting up pager - 2012-02-04)\n\nThanks for the heads-up. I think that the two patches should be\nmerged, especially because there's an error in cb0850f (a variable is\nread-only, never written).\n\nTweaks to cb0850f (Save terminal width before setting up pager - \n2012-02-04):\n\n[This actually was done on top of today's pu, so it will not apply\n  cleanly to cb0850f].\n\n- term_columns() lives in pager.c so it should be declared in\n   cache.h like other public functions in pager.c. It has nothing to do\n   with columns.h.\n- simplify logic to use a static variable instead of two global\n   variables (cb0850f actually doesn't work at all because\n   spawned_pager wasn't ever set).\n- check the cache first, then do getenv(COLUMNS) + atoi, then do\n   ioctl(). The behaviour is equivalent to checking COLUMNS first, but\n   is slightly more efficient.\n- document the function\n- remove #include \"column.h\" added in 88c9754c4097 column: Fix some\n   compiler and sparse warnings (Wed Feb 8 2012).\n\nJunio suggested that \"a new file, term.c or something, be a lot more\nsuitable home for the function you will be reusing from diff and other\nparts of the system\". Nevertheless, I think that adding two files (.c\nand .h) to hold one function isn't worth it. It can live in pager.c.\nTerminal size is logically connected to paging after all.\n---\n  cache.h  |    1 +\n  column.h |    1 -\n  pager.c  |   64 +++++++++++++++++++++++-----------------\n  3 files changed, 38 insertions(+), 28 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 6c70dbc..b4422d4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1196,6 +1196,7 @@ extern void setup_pager(void);\n  extern const char *pager_program;\n  extern int pager_in_use(void);\n  extern int pager_use_color;\n+extern int term_columns(void);\n\n  extern const char *editor_program;\n  extern const char *askpass_program;\ndiff --git a/column.h b/column.h\nindex b9dec64..142299e 100644\n--- a/column.h\n+++ b/column.h\n@@ -17,7 +17,6 @@ struct column_options {\n  \tconst char *nl;\n  };\n\n-extern int term_columns(void);\n  extern void print_columns(const struct string_list *list,\n  \t\t\t  unsigned int mode,\n  \t\t\t  struct column_options *opts);\ndiff --git a/pager.c b/pager.c\nindex fe203a7..d105761 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -7,21 +7,6 @@\n  #define DEFAULT_PAGER \"less\"\n  #endif\n\n-static int spawned_pager;\n-static int max_columns;\n-\n-static int retrieve_terminal_width(void)\n-{\n-#ifdef TIOCGWINSZ\n-\tstruct winsize ws;\n-\tif (ioctl(1, TIOCGWINSZ, &ws))  /* e.g., ENOSYS */\n-\t\treturn 0;\n-\treturn ws.ws_col;\n-#else\n-\treturn 0;\n-#endif\n-}\n-\n  /*\n   * This is split up from the rest of git so that we can do\n   * something different on Windows.\n@@ -88,16 +73,15 @@ const char *git_pager(int stdout_is_tty)\n  void setup_pager(void)\n  {\n  \tconst char *pager = git_pager(isatty(1));\n-\tint width;\n\n  \tif (!pager || pager_in_use())\n  \t\treturn;\n\n-\tsetenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n+\t/* prime the term_columns() cache before it is too\n+\t * late and stdout is replaced */\n+\t(void) term_columns();\n\n-\twidth = retrieve_terminal_width();\n-\tif (width)\n-\t\tmax_columns = width;\n+\tsetenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n\n  \t/* spawn the pager */\n  \tpager_argv[0] = pager;\n@@ -132,17 +116,43 @@ int pager_in_use(void)\n  \treturn env ? git_config_bool(\"GIT_PAGER_IN_USE\", env) : 0;\n  }\n\n+/*\n+ * Return cached value (if set) or $COLUMNS (if set and positive) or\n+ * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n+ *\n+ * $COLUMNS even if set, is usually not exported, so\n+ * the variable can be used to override autodection.\n+ * This behaviour conforms to The Single UNIX Specification, Version 2\n+ * \n(http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).\n+ */\n  int term_columns(void)\n  {\n-\tchar *col_string = getenv(\"COLUMNS\");\n+\tstatic int term_columns_cache;\n+\n+\tchar *col_string;\n  \tint n_cols;\n\n-\tif (col_string && (n_cols = atoi(col_string)) > 0)\n-\t\treturn n_cols;\n+\tif (term_columns_cache)\n+\t\treturn term_columns_cache;\n+\n+\tcol_string = getenv(\"COLUMNS\");\n+\tif (col_string && (n_cols = atoi(col_string)) > 0) {\n+\t\tterm_columns_cache = n_cols;\n+\t\treturn term_columns_cache;\n+\t}\n\n-\tif (spawned_pager && max_columns)\n-\t\treturn max_columns;\n+#ifdef TIOCGWINSZ\n+\t{\n+\t\tstruct winsize ws;\n+\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n+\t\t\tif (ws.ws_col) {\n+\t\t\t\tterm_columns_cache = ws.ws_col;\n+\t\t\t\treturn term_columns_cache;\n+\t\t\t}\n+\t\t}\n+\t}\n+#endif\n\n-\tn_cols = retrieve_terminal_width();\n-\treturn n_cols ? n_cols : 80;\n+\tterm_columns_cache = 80;\n+\treturn term_columns_cache;\n  }\n-- \n1.7.9.310.g883d84c.dirty\n"},{"id":"184503","messageId":"7vsjigl79j.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"4F3647B4.8090803@in.waw.pl","subject":"Re: [PATCH 2/3] help.c: make term_columns() cached and export it","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-12T09:40:08Z","receivedAt":"2012-02-12T09:40:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Junio suggested that \"a new file, term.c or something, be a lot more\n> suitable home for the function you will be reusing from diff and other\n> parts of the system\". Nevertheless, I think that adding two files (.c\n> and .h) to hold one function isn't worth it. It can live in pager.c.\n> Terminal size is logically connected to paging after all.\n\nI do not have any objection to the above reasoning.\n\nGiven that Nguyen's columns topic hasn't been merged to 'next' and I\nexpect it will be re-rolled anyway, I would prefer a patch that does the\nmove from help.c to pager.c that is based directly on v1.7.9, on top of\nwhich your work and the columns topic can both be built independently.\n\nThanks.\n"},{"id":"184509","messageId":"1329055953-29632-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"7vsjigl79j.fsf@alter.siamese.dyndns.org","subject":"[PATCH 1/2] Save terminal width before setting up pager and export term_columns()","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-12T14:12:32Z","receivedAt":"2012-02-12T14:12:32Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"term_columns() checks for terminal width via ioctl(2). After\nredirecting, stdin is no longer terminal to get terminal width.\n\nCheck terminal width and save it before redirecting stdin in\nsetup_pager() by calling term_columns().\n\nMove term_columns() to pager.c and export it in cache.h.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n cache.h |  1 +\n help.c  | 22 -------------------\n pager.c | 45 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 46 insertions(+), 22 deletions(-)\n\nThis replaces cb0850f (Save terminal width before setting up pager -\n2012-02-04) from Nguyễn Thái Ngọc Duy and my previous patch to export\nterm_columns().\n\nThis is directly on top of v1.7.9 as requested.\n\nI removed Signed-off-by from Nguyễn and Junio because the patch is\nsubstantially changed.\n\ndiff --git a/cache.h b/cache.h\nindex 10afd71..2f30b3a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1175,6 +1175,7 @@ extern void setup_pager(void);\n extern const char *pager_program;\n extern int pager_in_use(void);\n extern int pager_use_color;\n+extern int term_columns(void);\n \n extern const char *editor_program;\n extern const char *askpass_program;\ndiff --git a/help.c b/help.c\nindex cbbe966..14eefc9 100644\n--- a/help.c\n+++ b/help.c\n@@ -5,28 +5,6 @@\n #include \"help.h\"\n #include \"common-cmds.h\"\n \n-/* most GUI terminals set COLUMNS (although some don't export it) */\n-static int term_columns(void)\n-{\n-\tchar *col_string = getenv(\"COLUMNS\");\n-\tint n_cols;\n-\n-\tif (col_string && (n_cols = atoi(col_string)) > 0)\n-\t\treturn n_cols;\n-\n-#ifdef TIOCGWINSZ\n-\t{\n-\t\tstruct winsize ws;\n-\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n-\t\t\tif (ws.ws_col)\n-\t\t\t\treturn ws.ws_col;\n-\t\t}\n-\t}\n-#endif\n-\n-\treturn 80;\n-}\n-\n void add_cmdname(struct cmdnames *cmds, const char *name, int len)\n {\n \tstruct cmdname *ent = xmalloc(sizeof(*ent) + len + 1);\ndiff --git a/pager.c b/pager.c\nindex 975955b..b8049a4 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -76,6 +76,10 @@ void setup_pager(void)\n \tif (!pager)\n \t\treturn;\n \n+\t/* prime the term_columns() cache before it is too\n+\t * late and stdout is replaced */\n+\t(void) term_columns();\n+\n \tsetenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n \n \t/* spawn the pager */\n@@ -110,3 +114,44 @@ int pager_in_use(void)\n \tenv = getenv(\"GIT_PAGER_IN_USE\");\n \treturn env ? git_config_bool(\"GIT_PAGER_IN_USE\", env) : 0;\n }\n+\n+/*\n+ * Return cached value (if set) or $COLUMNS (if set and positive) or\n+ * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n+ *\n+ * $COLUMNS even if set, is usually not exported, so\n+ * the variable can be used to override autodection.\n+ * This behaviour conforms to The Single UNIX Specification, Version 2\n+ * (http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).\n+ */\n+int term_columns(void)\n+{\n+\tstatic int term_columns_cache;\n+\n+\tchar *col_string;\n+\tint n_cols;\n+\n+\tif (term_columns_cache)\n+\t\treturn term_columns_cache;\n+\n+\tcol_string = getenv(\"COLUMNS\");\n+\tif (col_string && (n_cols = atoi(col_string)) > 0) {\n+\t\tterm_columns_cache = n_cols;\n+\t\treturn term_columns_cache;\n+\t}\n+\n+#ifdef TIOCGWINSZ\n+\t{\n+\t\tstruct winsize ws;\n+\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n+\t\t\tif (ws.ws_col) {\n+\t\t\t\tterm_columns_cache = ws.ws_col;\n+\t\t\t\treturn term_columns_cache;\n+\t\t\t}\n+\t\t}\n+\t}\n+#endif\n+\n+\tterm_columns_cache = 80;\n+\treturn term_columns_cache;\n+}\n-- \n1.7.9.3.g2429d.dirty\n"},{"id":"184510","messageId":"1329056180-29796-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"7vsjigl79j.fsf@alter.siamese.dyndns.org","subject":"[PATCH 2/2] Rename lineno_width to decimal_width and export it","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-12T14:16:20Z","receivedAt":"2012-02-12T14:16:20Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"This function will be used in calculating diff --stat graph width.\nThe name is changed because the function works for any number.\nThe function is moved from builtins/blame.c to pager.c because it\nwill be used not only in builtins/blame.c.\n---\n builtin/blame.c | 18 +++---------------\n cache.h         |  1 +\n pager.c         | 12 ++++++++++++\n 3 files changed, 16 insertions(+), 15 deletions(-)\n\nThis is another function to be exported. I hope it can be exported\ntogether with term_columns(). I'll use it the next version of the diff\n--stat patch.\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 5a67c20..f028e8a 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -1829,18 +1829,6 @@ static int read_ancestry(const char *graft_file)\n }\n \n /*\n- * How many columns do we need to show line numbers in decimal?\n- */\n-static int lineno_width(int lines)\n-{\n-\tint i, width;\n-\n-\tfor (width = 1, i = 10; i <= lines; width++)\n-\t\ti *= 10;\n-\treturn width;\n-}\n-\n-/*\n  * How many columns do we need to show line numbers, authors,\n  * and filenames?\n  */\n@@ -1880,9 +1868,9 @@ static void find_alignment(struct scoreboard *sb, int *option)\n \t\tif (largest_score < ent_score(sb, e))\n \t\t\tlargest_score = ent_score(sb, e);\n \t}\n-\tmax_orig_digits = lineno_width(longest_src_lines);\n-\tmax_digits = lineno_width(longest_dst_lines);\n-\tmax_score_digits = lineno_width(largest_score);\n+\tmax_orig_digits = decimal_width(longest_src_lines);\n+\tmax_digits = decimal_width(longest_dst_lines);\n+\tmax_score_digits = decimal_width(largest_score);\n }\n \n /*\ndiff --git a/cache.h b/cache.h\nindex 2f30b3a..3857dfd 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1176,6 +1176,7 @@ extern const char *pager_program;\n extern int pager_in_use(void);\n extern int pager_use_color;\n extern int term_columns(void);\n+extern int decimal_width(int number);\n \n extern const char *editor_program;\n extern const char *askpass_program;\ndiff --git a/pager.c b/pager.c\nindex b8049a4..b6d44ef 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -155,3 +155,15 @@ int term_columns(void)\n \tterm_columns_cache = 80;\n \treturn term_columns_cache;\n }\n+\n+/*\n+ * How many columns do we need to show numbers in decimal?\n+ */\n+int decimal_width(int number)\n+{\n+\tint i, width;\n+\n+\tfor (width = 1, i = 10; i <= number; width++)\n+\t\ti *= 10;\n+\treturn width;\n+}\n-- \n1.7.9.3.g2429d.dirty\n"},{"id":"184512","messageId":"1329057019-29983-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"7vmx8qr1gb.fsf@alter.siamese.dyndns.org","subject":"[PATCH v3] diff --stat: use the full terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-12T14:30:19Z","receivedAt":"2012-02-12T14:30:19Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Use as many columns as necessary for filenames, as few columns as\nnecessary for change counts, and up to 40 columns for the histogram.\n\nSome projects (especially in Java), have long filename paths, with\nnested directories or long individual filenames. When files are\nrenamed, the stat output can be almost useless. If the middle part\nbetween { and } is long (because the file was moved to a completely\ndifferent directory), then most of the path would be truncated.\n\nIt makes sense to detect and use the full terminal width and display\nfull filenames if possible.\n\nIf commits changing a lot of lines are displayed in a wide terminal\nwindow (200 or more columns), and the +- graph would use the full\nwidth, the output would look bad. Messages wrapped to about 80\ncolumns would be interspersed with very long +- lines. It makes\nsense to limit the width of the histogram to a fixed value, even if more\ncolumns are available. This fixed value is subjectively hard-coded to\nbe 40 columns, which seems to work well for git.git and linux-2.6.git and\nsome other repositories.\n\nIf there isn't enough columns to print both the filename and the histogram,\nat least 5/8 of available space is devoted to filenames. On a standard 80 column\nterminal, or if not connected to a terminal and using the default of 80 columns,\nthis gives the same partition as before.\n\nNumber of columns required for change counts is computed based on\nthe maximum number of changed lines. This means that usually a few more\ncolumns will be available for the filenames and the histogram.\n\nTests are added for various combinations of long filename and big change\ncount and ways to specify widths.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\nHi,\nthis is v3 (reduced to one patch) on top of:\n- Save terminal width before setting up pager and export term_columns(),\n- Rename lineno_width to decimal_width and export it.\n\nThe logic is described in a comment in show_stats() in diff.c. In case\nof a column 80 terminal window, the output will not be identical,\nbecause of using decimal_width, but it'll be very close to what was\nthere previously.\n\nv3:\n- use decimal_width(max_change) to calculate number of columns\n  required for change counts\n- rework the logic to divide columns\n- document the logic in comments, update docs\n- add more tests\n\nv2:\n- style fixes\n- some tests for git-format-patch added\n- patches 3 and 4 squashed together, since they touch the same lines\n- graph width is limited to 40 columns, even if there's more space\n- patch descriptions extended and cleared up\n\n Documentation/diff-options.txt | 14 +++---\n diff.c                         | 93 +++++++++++++++++++++++++------------\n t/t4014-format-patch.sh        | 98 +++++++++++++++++++++++++++++++++++++++-\n 3 files changed, 168 insertions(+), 37 deletions(-)\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex 9f7cba2..35dfdfb 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -53,13 +53,15 @@ endif::git-format-patch[]\n \tGenerate a diff using the \"patience diff\" algorithm.\n \n --stat[=<width>[,<name-width>[,<count>]]]::\n-\tGenerate a diffstat.  You can override the default\n-\toutput width for 80-column terminal by `--stat=<width>`.\n-\tThe width of the filename part can be controlled by\n-\tgiving another width to it separated by a comma.\n+\tGenerate a diffstat. By default, as much space as necessary\n+\twill be used for the filename part, and up to 40 columns for\n+\tthe graph histogram. Maximum width defaults to terminal width,\n+\tor 80 columns if not connected to a terminal, and can be\n+\toverriden by `<width>`. The width of the filename part can be\n+\tlimited by giving another width `<name-width>` after a comma.\n \tBy giving a third parameter `<count>`, you can limit the\n-\toutput to the first `<count>` lines, followed by\n-\t`...` if there are more.\n+\toutput to the first `<count>` lines, followed by `...` if\n+\tthere are more.\n +\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\ndiff --git a/diff.c b/diff.c\nindex 7e15426..7abcbe9 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1327,7 +1327,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \tint i, len, add, del, adds = 0, dels = 0;\n \tuintmax_t max_change = 0, max_len = 0;\n \tint total_files = data->nr;\n-\tint width, name_width, count;\n+\tint width, name_width, graph_width, number_width, count;\n \tconst char *reset, *add_c, *del_c;\n \tconst char *line_prefix = \"\";\n \tint extra_shown = 0;\n@@ -1341,25 +1341,13 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tline_prefix = msg->buf;\n \t}\n \n-\twidth = options->stat_width ? options->stat_width : 80;\n-\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n-\tcount = options->stat_count ? options->stat_count : data->nr;\n-\n-\t/* Sanity: give at least 5 columns to the graph,\n-\t * but leave at least 10 columns for the name.\n-\t */\n-\tif (width < 25)\n-\t\twidth = 25;\n-\tif (name_width < 10)\n-\t\tname_width = 10;\n-\telse if (width < name_width + 15)\n-\t\tname_width = width - 15;\n-\n \t/* Find the longest filename and max number of changes */\n \treset = diff_get_color_opt(options, DIFF_RESET);\n \tadd_c = diff_get_color_opt(options, DIFF_FILE_NEW);\n \tdel_c = diff_get_color_opt(options, DIFF_FILE_OLD);\n \n+\tcount = options->stat_count ? options->stat_count : data->nr;\n+\n \tfor (i = 0; (i < count) && (i < data->nr); i++) {\n \t\tstruct diffstat_file *file = data->files[i];\n \t\tuintmax_t change = file->added + file->deleted;\n@@ -1380,19 +1368,63 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t}\n \tcount = i; /* min(count, data->nr) */\n \n-\t/* Compute the width of the graph part;\n-\t * 10 is for one blank at the beginning of the line plus\n-\t * \" | count \" between the name and the graph.\n+\t/* We have width = stat_width or term_columns() columns total.\n+\t * We want a maximum of min(max_len, stat_name_width) for the name part.\n+\t * We want a maximum of min(max_change, 40) for the +- part.\n+\t * We also need 1 for \" \" and 4 + decimal_width(max_change)\n+\t * for \" | NNNN \" and one for \" \" at the end, altogether\n+\t * 6 + decimal_width(max_change).\n+\t *\n+\t * If there's not enough space, we will use stat_name_width\n+\t * or 5/8*width for filename, and the rest for constant\n+\t * elements + histogram, but no more than 40 for the histogram.\n+\t * (5/8 gives 50 for filename and 30 for constant parts and\n+\t * histogram for the standard terminal size).\n \t *\n-\t * From here on, name_width is the width of the name area,\n-\t * and width is the width of the graph area.\n+\t * In other words: stat_width limits the maximum width, and\n+\t * stat_name_width fixes the maximum width of the filename,\n+\t * and is also used to divide available columns if there\n+\t * aren't enough.\n \t */\n-\tname_width = (name_width < max_len) ? name_width : max_len;\n-\tif (width < (name_width + 10) + max_change)\n-\t\twidth = width - (name_width + 10);\n-\telse\n-\t\twidth = max_change;\n+\twidth = options->stat_width ? options->stat_width : term_columns();\n+\tnumber_width = decimal_width(max_change);\n+\t/* first sizes that are wanted */\n+\tgraph_width = max_change < 40 ? max_change : 40;\n+\tname_width = (options->stat_name_width > 0 &&\n+\t\t      options->stat_name_width < max_len) ?\n+\t\toptions->stat_name_width : max_len;\n+\n+\t/* sanity: guarantee a minimum and maximum width */\n+\tif (width < 25)\n+\t\twidth = 25;\n+\n+\tif (name_width + number_width + 6 + graph_width > width) {\n+\t\tif (graph_width > width * 3/8 - number_width - 6)\n+\t\t\tgraph_width = width * 3/8 - number_width - 6;\n+\t\tif (graph_width > 40)\n+\t\t\tgraph_width =  40;\n+\t\tif (name_width > width - number_width - 6 - graph_width)\n+\t\t\tname_width = width - number_width - 6 - graph_width;\n+\t\telse\n+\t\t\tgraph_width = width - number_width - 6 - name_width;\n+\t}\n \n+\t/* More sanity: give at least 5 columns to the graph,\n+\t * but leave at least 10 columns for the name.\n+\t *\n+\t * This should already be satisfied, unless max_change is\n+\t * really huge. If the window is extemely narrow, this might\n+\t * overflow available columns.\n+\t */\n+\tif (name_width < 10 && max_len >= 10)\n+\t\tname_width = 10;\n+\tif (graph_width < 5 && max_change >= 5)\n+\t\tgraph_width = 5;\n+\n+\t/* From here name_width is the width of the name area,\n+\t * and graph_width is the width of the graph area.\n+\t * max_change is used to scale graph properly.\n+\t */\n \tfor (i = 0; i < count; i++) {\n \t\tconst char *prefix = \"\";\n \t\tchar *name = data->files[i]->print_name;\n@@ -1448,14 +1480,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tadds += add;\n \t\tdels += del;\n \n-\t\tif (width <= max_change) {\n-\t\t\tadd = scale_linear(add, width, max_change);\n-\t\t\tdel = scale_linear(del, width, max_change);\n+\t\tif (graph_width <= max_change) {\n+\t\t\tadd = scale_linear(add, graph_width, max_change);\n+\t\t\tdel = scale_linear(del, graph_width, max_change);\n \t\t}\n \t\tfprintf(options->file, \"%s\", line_prefix);\n \t\tshow_name(options->file, prefix, name, len);\n-\t\tfprintf(options->file, \"%5\"PRIuMAX\"%s\", added + deleted,\n-\t\t\t\tadded + deleted ? \" \" : \"\");\n+\t\tfprintf(options->file, \" %*\"PRIuMAX\"%s\",\n+\t\t\tnumber_width, added + deleted,\n+\t\t\tadded + deleted ? \" \" : \"\");\n \t\tshow_graph(options->file, '+', add, add_c, reset);\n \t\tshow_graph(options->file, '-', del, del_c, reset);\n \t\tfprintf(options->file, \"\\n\");\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 6797512..91be989 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -519,7 +519,7 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \n cat > expect << EOF\n ---\n- file |   16 ++++++++++++++++\n+ file | 16 ++++++++++++++++\n  1 files changed, 16 insertions(+), 0 deletions(-)\n \n diff --git a/file b/file\n@@ -894,4 +894,100 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+name=aaaaaaaaaa\n+name=$name$name$name$name$name$name$name$name$name$name$name$name\n+test_expect_success 'preparation' \"\n+\t> ${name} &&\n+\tgit add ${name} &&\n+\tgit commit -m message &&\n+\techo a > ${name} &&\n+\tgit commit -m message ${name}\n+\"\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n+EOF\n+test_expect_success 'format patch graph width is 80 columns' '\n+\tgit format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 aaaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n+EOF\n+test_expect_success 'format patch --stat=width with long name' '\n+\tgit format-patch --stat=40 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-width=width works long name' '\n+\tgit format-patch --stat-width=40 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat=...,name-width with long name' '\n+\tgit format-patch --stat=60,32 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-name-width with long name' '\n+\tgit format-patch --stat-name-width=32 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'preparation' '\n+\t> abcd &&\n+\tgit add abcd &&\n+\tgit commit -m message &&\n+\tseq 1000 > abcd &&\n+\tgit commit -m message abcd\n+'\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch graph width is 40 columns' '\n+\tgit format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch ignores COLUMNS' '\n+\tCOLUMNS=200 git format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch --stat=width with big change' '\n+\tgit format-patch --stat=40 --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-width=width with big change' '\n+\tgit format-patch --stat-width=40 --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++\n+EOF\n+test_expect_success 'format patch --stat=width with big change and long name' '\n+\tcp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n+\tgit add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n+\tgit commit -m message &&\n+\tgit format-patch --stat-width=60 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.7.9.3.g2429d.dirty\n"},{"id":"184622","messageId":"7vlio6baoo.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329055953-29632-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/2] Save terminal width before setting up pager and export term_columns()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-13T23:00:55Z","receivedAt":"2012-02-13T23:00:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> term_columns() checks for terminal width via ioctl(2). After\n> redirecting, stdin is no longer terminal to get terminal width.\n\ns/stdin/stdout/\n\n> Check terminal width and save it before redirecting stdin in\n> setup_pager() by calling term_columns().\n>\n> Move term_columns() to pager.c and export it in cache.h.\n>\n> Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n> ---\n\nThanks.\n\nIt probably is worth mentioning what the end-user visible effect of this\nchange is somewhere in the log message.\n\nI somehow find \"term_columns_cache\" a funny name for this variable and\ndoes not describe what it does.  Unlike a real cache, we cannot discard it\nand re-read it even if we later wanted to.\n\nI am tempted to rewrite the patch like this to update other minor style\nissues.\n\n-- >8 --\nFrom: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\nDate: Sun, 12 Feb 2012 15:12:32 +0100\nSubject: [PATCH] pager: find out the terminal width before spawning the pager\n\nterm_columns() checks for terminal width via ioctl(2) on the standard\noutput, but we spawn the pager too early for this check to be useful.\n\nThe effect of this buglet can be observed by opening a wide terminal and\nrunning \"git -p help --all\", which still shows 80-column output, while\n\"git help --all\" uses the full terminal width. Run the check before we\nspawn the pager to fix this.\n\nWhile at it, move term_columns() to pager.c and export it from cache.h so\nthat callers other than the help subsystem can use it.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n cache.h |    1 +\n help.c  |   22 ----------------------\n pager.c |   43 +++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 44 insertions(+), 22 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 79c612f..c7e3b4d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1172,6 +1172,7 @@ extern void setup_pager(void);\n extern const char *pager_program;\n extern int pager_in_use(void);\n extern int pager_use_color;\n+extern int term_columns(void);\n \n extern const char *editor_program;\n extern const char *askpass_program;\ndiff --git a/help.c b/help.c\nindex cbbe966..14eefc9 100644\n--- a/help.c\n+++ b/help.c\n@@ -5,28 +5,6 @@\n #include \"help.h\"\n #include \"common-cmds.h\"\n \n-/* most GUI terminals set COLUMNS (although some don't export it) */\n-static int term_columns(void)\n-{\n-\tchar *col_string = getenv(\"COLUMNS\");\n-\tint n_cols;\n-\n-\tif (col_string && (n_cols = atoi(col_string)) > 0)\n-\t\treturn n_cols;\n-\n-#ifdef TIOCGWINSZ\n-\t{\n-\t\tstruct winsize ws;\n-\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n-\t\t\tif (ws.ws_col)\n-\t\t\t\treturn ws.ws_col;\n-\t\t}\n-\t}\n-#endif\n-\n-\treturn 80;\n-}\n-\n void add_cmdname(struct cmdnames *cmds, const char *name, int len)\n {\n \tstruct cmdname *ent = xmalloc(sizeof(*ent) + len + 1);\ndiff --git a/pager.c b/pager.c\nindex 975955b..e06cfa0 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -76,6 +76,12 @@ void setup_pager(void)\n \tif (!pager)\n \t\treturn;\n \n+\t/*\n+\t * force computing the width of the terminal before we redirect\n+\t * the standard output to the pager.\n+\t */\n+\t(void) term_columns();\n+\n \tsetenv(\"GIT_PAGER_IN_USE\", \"true\", 1);\n \n \t/* spawn the pager */\n@@ -110,3 +116,40 @@ int pager_in_use(void)\n \tenv = getenv(\"GIT_PAGER_IN_USE\");\n \treturn env ? git_config_bool(\"GIT_PAGER_IN_USE\", env) : 0;\n }\n+\n+/*\n+ * Return cached value (if set) or $COLUMNS (if set and positive) or\n+ * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.\n+ *\n+ * $COLUMNS even if set, is usually not exported, so\n+ * the variable can be used to override autodection.\n+ * This behaviour conforms to The Single UNIX Specification, Version 2\n+ * (http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).\n+ */\n+int term_columns(void)\n+{\n+\tstatic int term_columns_at_startup;\n+\n+\tchar *col_string;\n+\tint n_cols;\n+\n+\tif (term_columns_at_startup)\n+\t\treturn term_columns_at_startup;\n+\n+\tterm_columns_at_startup = 80;\n+\n+\tcol_string = getenv(\"COLUMNS\");\n+\tif (col_string && (n_cols = atoi(col_string)) > 0)\n+\t\tterm_columns_at_startup = n_cols;\n+#ifdef TIOCGWINSZ\n+\telse {\n+\t\tstruct winsize ws;\n+\t\tif (!ioctl(1, TIOCGWINSZ, &ws)) {\n+\t\t\tif (ws.ws_col) {\n+\t\t\t\tterm_columns_at_startup = ws.ws_col;\n+\t\t\t}\n+\t\t}\n+\t}\n+#endif\n+\treturn term_columns_at_startup;\n+}\n-- \n1.7.9.300.gd47e4\n"},{"id":"184623","messageId":"7vhayub9d3.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329056180-29796-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 2/2] Rename lineno_width to decimal_width and export it","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-13T23:29:28Z","receivedAt":"2012-02-13T23:29:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> This function will be used in calculating diff --stat graph width.\n> The name is changed because the function works for any number.\n> The function is moved from builtins/blame.c to pager.c because it\n> will be used not only in builtins/blame.c.\n\nI'd prefer to see description of preliminary changes phrased without\ndepending too heavily on things that hasn't happened when possible.\nMaking a generic helper function to count digits necessary to print a\ncardinal number available to future callers is a good thing by itself,\neven if the \"dynamic --stat width computation\" turned out to be a bad\nidea for whatever reason (I am not saying it is a bad idea here).\n\nPerhaps like this.\n\n\tSubject: make lineno_width() from blame reusable for others\n\n\tbuiltin/blame.c has a helper function to compute how many columns\n\twe need to show a line-number, whose implementation is reusable as\n\ta more generic helper function to count the number of columns\n\tnecessary to show any cardinal number.\n\n\tRename it to decimal_width(), move it to pager.c and export it for\n        use by future callers.\n\nAnd you can say something like \"I'll be using this in 'diff --stat' in\nlater patches\" after the three-dash line.\n\n> ---\n\nSign-off before the three-dash line?\n\n> +/*\n> + * How many columns do we need to show numbers in decimal?\n\ns/numbers/this number/;\n\n> + */\n> +int decimal_width(int number)\n\nDon't we want to make the argument \"unsigned number\" instead?\n\n> +{\n> +\tint i, width;\n> +\n> +\tfor (width = 1, i = 10; i <= number; width++)\n> +\t\ti *= 10;\n> +\treturn width;\n> +}\n"},{"id":"184629","messageId":"7vsjie9q77.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329057019-29983-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH v3] diff --stat: use the full terminal width","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-14T01:08:44Z","receivedAt":"2012-02-14T01:08:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Use as many columns as necessary for filenames, as few columns as\n> necessary for change counts, and up to 40 columns for the histogram.\n>\n> Some projects (especially in Java), have long filename paths, with\n> nested directories or long individual filenames. When files are\n> renamed, the stat output can be almost useless. If the middle part\n\ns/the stat output/the name part in &/;\n\n> between { and } is long (because the file was moved to a completely\n> different directory), then most of the path would be truncated.\n>\n> It makes sense to detect and use the full terminal width and display\n> full filenames if possible.\n>\n> If commits changing a lot of lines are displayed in a wide terminal\n> window (200 or more columns), and the +- graph would use the full\n> width, the output would look bad. Messages wrapped to about 80\n> columns would be interspersed with very long +- lines. It makes\n> sense to limit the width of the histogram to a fixed value, even if more\n\nI do not think the graph ++++++--- part is \"histogram\", which is a name\nfor a specific type of graph that depicts a distribution of data.\n\nWe show the number of lines changed in a graph.  Unless people come up\nwith a better name, I would suggest calling it just \"the graph part\", or\nsimply \"the graph\", throughout the patch.\n\n> columns are available. This fixed value is subjectively hard-coded to\n> be 40 columns, which seems to work well for git.git and linux-2.6.git and\n> some other repositories.\n>\n> If there isn't enough columns to print both the filename and the histogram,\n> at least 5/8 of available space is devoted to filenames. On a standard 80 column\n> terminal, or if not connected to a terminal and using the default of 80 columns,\n> this gives the same partition as before.\n>\n> Number of columns required for change counts is computed based on\n> the maximum number of changed lines. This means that usually a few more\n> columns will be available for the filenames and the histogram.\n>\n> Tests are added for various combinations of long filename and big change\n> count and ways to specify widths.\n>\n> Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n> ---\n> ...\n> diff --git a/diff.c b/diff.c\n> index 7e15426..7abcbe9 100644\n> --- a/diff.c\n> +++ b/diff.c\n> @@ -1327,7 +1327,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>  \tint i, len, add, del, adds = 0, dels = 0;\n>  \tuintmax_t max_change = 0, max_len = 0;\n>  \tint total_files = data->nr;\n> -\tint width, name_width, count;\n> +\tint width, name_width, graph_width, number_width, count;\n>  \tconst char *reset, *add_c, *del_c;\n>  \tconst char *line_prefix = \"\";\n>  \tint extra_shown = 0;\n> @@ -1341,25 +1341,13 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>  \t\tline_prefix = msg->buf;\n>  \t}\n>  \n> -\twidth = options->stat_width ? options->stat_width : 80;\n> -\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n> -\tcount = options->stat_count ? options->stat_count : data->nr;\n\nIt was somewhat distracting that you moved this \"count =\" below, which I\ndo not think was necessary.\n\n> -\t/* Sanity: give at least 5 columns to the graph,\n> -\t * but leave at least 10 columns for the name.\n> -\t */\n> -\tif (width < 25)\n> -\t\twidth = 25;\n> -\tif (name_width < 10)\n> -\t\tname_width = 10;\n> -\telse if (width < name_width + 15)\n> -\t\tname_width = width - 15;\n\nRemoval of this sanity check is fine as long as sanity is kept by the new\ncode in the later part. This was primarily so that people won't specify\nimpossible values (e.g. what happens when name_width that is wider than\nthe total width is given).\n\n> ...\n> +\tcount = options->stat_count ? options->stat_count : data->nr;\n> +\n> @@ -1380,19 +1368,63 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n>  \t}\n>  \tcount = i; /* min(count, data->nr) */\n>  \n> -\t/* Compute the width of the graph part;\n> -\t * 10 is for one blank at the beginning of the line plus\n> -\t * \" | count \" between the name and the graph.\n\n\n> +\t/* We have width = stat_width or term_columns() columns total.\n\nJust a style, but in the more recent part of the codebase,\n\n\t/*\n         * We have width = ....\n\nis preferred.\n\n> +\t * We want a maximum of min(max_len, stat_name_width) for the name part.\n> +\t * We want a maximum of min(max_change, 40) for the +- part.\n> +\t * We also need 1 for \" \" and 4 + decimal_width(max_change)\n> +\t * for \" | NNNN \" and one for \" \" at the end, altogether\n> +\t * 6 + decimal_width(max_change).\n\nThe math looks correct but 'one for \" \" at the end' sounds as if you are\nprinting a SP, but I think we simply avoid printing anything, so perhaps\nrewrite it to \"we leave one column at the end\" or something.\n\n> +\t * If there's not enough space, we will use stat_name_width\n> +\t * or 5/8*width for filename, and the rest for constant\n\n\"A or B for filename\"---unclear how it picks between A or B.\n\n\"A or B, whichever is shorter, for filename\", perhaps?\n\n> +\t * elements + histogram, but no more than 40 for the histogram.\n> +\t * (5/8 gives 50 for filename and 30 for constant parts and\n> +\t * histogram for the standard terminal size).\n>  \t *\n> -\t * From here on, name_width is the width of the name area,\n> -\t * and width is the width of the graph area.\n> +\t * In other words: stat_width limits the maximum width, and\n> +\t * stat_name_width fixes the maximum width of the filename,\n> +\t * and is also used to divide available columns if there\n> +\t * aren't enough.\n>  \t */\n> -\tname_width = (name_width < max_len) ? name_width : max_len;\n> -\tif (width < (name_width + 10) + max_change)\n> -\t\twidth = width - (name_width + 10);\n> -\telse\n> -\t\twidth = max_change;\n> +\twidth = options->stat_width ? options->stat_width : term_columns();\n> +\tnumber_width = decimal_width(max_change);\n> +\t/* first sizes that are wanted */\n\nMissing verb; \"first, compute sizes that are ...\"?\n\n> +\tgraph_width = max_change < 40 ? max_change : 40;\n> +\tname_width = (options->stat_name_width > 0 &&\n> +\t\t      options->stat_name_width < max_len) ?\n> +\t\toptions->stat_name_width : max_len;\n\nmental note: name_width can be limited to max_len, and graph_width may be\nquite small when max_change is small.  The total graph may be much smaller\nthan the terminal width in such a case (and it is not a wasted space on\nthe right hand side of the terminal).\n\n> +\t/* sanity: guarantee a minimum and maximum width */\n> +\tif (width < 25)\n> +\t\twidth = 25;\n> +\n> +\tif (name_width + number_width + 6 + graph_width > width) {\n> +\t\tif (graph_width > width * 3/8 - number_width - 6)\n> +\t\t\tgraph_width = width * 3/8 - number_width - 6;\n> +\t\tif (graph_width > 40)\n> +\t\t\tgraph_width =  40;\n> +\t\tif (name_width > width - number_width - 6 - graph_width)\n> +\t\t\tname_width = width - number_width - 6 - graph_width;\n> +\t\telse\n> +\t\t\tgraph_width = width - number_width - 6 - name_width;\n> +\t}\n>  \n> +\t/* More sanity: give at least 5 columns to the graph,\n\nHrm, having to have a separate \"More sanity\" is ugly, and you seem to\nalready know it \"This should already be satisfied...\".\n\nCan the logic above be tightened to make this \"mopping up\" unnecessary?\n\n> +\t * but leave at least 10 columns for the name.\n> +\t *\n> +\t * This should already be satisfied, unless max_change is\n> +\t * really huge. If the window is extemely narrow, this might\n> +\t * overflow available columns.\n> +\t */\n> +\tif (name_width < 10 && max_len >= 10)\n> +\t\tname_width = 10;\n\nThe logic up to this point uses the same \"25 <= width, 10 <= name_width\"\nas the original to ensure that graph and the fixed part can use at least\n15 columns.  And then you do this:\n\n> +\tif (graph_width < 5 && max_change >= 5)\n> +\t\tgraph_width = 5;\n\nwhich means you are allocating 10 columns for fixed part.  In the\noriginal, it was OK to give fixed number of columns for fixed part like\nthis, as it always gave fixed 5 columns to show the number.  Don't you\nneed to adjust that 10 depending on the decimal_width(max_change), now\nyour number_width flexes?\n\nThis patch also breaks many existing tests that need to be adjusted for\nthe change to use decimal_width(max_change), which I do not care to fix up\nfor you.  Perhaps that part of the change needs to be split out into a\nseparate patch.\n\nAmong the tests it breaks is t1200-tutorial.sh, which means that the\ntutorial document that has illustration of the sample output also needs to\nbe updated before the final round.\n\nThanks.\n"},{"id":"184650","messageId":"CACsJy8Da=JMF7B9hW+WXzRXQFiGJxh0S7HYFg9+uweZ=pMOmTQ@mail.gmail.com","threadId":"29589","inReplyTo":"1329055953-29632-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/2] Save terminal width before setting up pager and export term_columns()","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-02-14T11:44:46Z","receivedAt":"2012-02-14T11:44:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2012/2/12 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>:\n> This replaces cb0850f (Save terminal width before setting up pager -\n> 2012-02-04) from Nguyễn Thái Ngọc Duy and my previous patch to export\n> term_columns().\n>\n> This is directly on top of v1.7.9 as requested.\n>\n> I removed Signed-off-by from Nguyễn and Junio because the patch is\n> substantially changed.\n\nNo problems. I will rebase my series on top of this patch (its final\nversion, that is).\n-- \nDuy\n"},{"id":"184651","messageId":"4F3A4B56.50909@in.waw.pl","threadId":"29589","inReplyTo":"CACsJy8Da=JMF7B9hW+WXzRXQFiGJxh0S7HYFg9+uweZ=pMOmTQ@mail.gmail.com","subject":"Re: [PATCH 1/2] Save terminal width before setting up pager and export term_columns()","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-14T11:53:58Z","receivedAt":"2012-02-14T11:53:58Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"On 02/14/2012 12:44 PM, Nguyen Thai Ngoc Duy wrote:\n> 2012/2/12 Zbigniew Jędrzejewski-Szmek<zbyszek@in.waw.pl>:\n>> This replaces cb0850f (Save terminal width before setting up pager -\n>> 2012-02-04) from Nguyễn Thái Ngọc Duy and my previous patch to export\n>> term_columns().\n>>\n>> This is directly on top of v1.7.9 as requested.\n>>\n>> I removed Signed-off-by from Nguyễn and Junio because the patch is\n>> substantially changed.\n>\n> No problems. I will rebase my series on top of this patch (its final\n> version, that is).\nHi, I think that Junio's will be the final version. I have no objections \nto it.\n\nZbyszek\n"},{"id":"184654","messageId":"1329222251-28188-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"7vhayub9d3.fsf@alter.siamese.dyndns.org","subject":"[PATCH v2] make lineno_width() from blame reusable for others","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-14T12:24:11Z","receivedAt":"2012-02-14T12:24:11Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"builtin/blame.c has a helper function to compute how many columns we\nneed to show a line-number, whose implementation is reusable as a more\ngeneric helper function to count the number of columns necessary to\nshow any cardinal number.\n\nRename it to decimal_width(), move it to pager.c and export it for use\nby future callers. The argument type is changed to unsigned to underline\nthe fact that the function supports only non-negative numbers.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\nI'll be using this in the 'diff --stat: use the full terminal width'\npatch.\n\nv2: - change arg type to unsigned\n    - corrected commit message\n\n builtin/blame.c | 18 +++---------------\n cache.h         |  1 +\n pager.c         | 12 ++++++++++++\n 3 files changed, 16 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 5a67c20..f028e8a 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -1829,18 +1829,6 @@ static int read_ancestry(const char *graft_file)\n }\n \n /*\n- * How many columns do we need to show line numbers in decimal?\n- */\n-static int lineno_width(int lines)\n-{\n-\tint i, width;\n-\n-\tfor (width = 1, i = 10; i <= lines; width++)\n-\t\ti *= 10;\n-\treturn width;\n-}\n-\n-/*\n  * How many columns do we need to show line numbers, authors,\n  * and filenames?\n  */\n@@ -1880,9 +1868,9 @@ static void find_alignment(struct scoreboard *sb, int *option)\n \t\tif (largest_score < ent_score(sb, e))\n \t\t\tlargest_score = ent_score(sb, e);\n \t}\n-\tmax_orig_digits = lineno_width(longest_src_lines);\n-\tmax_digits = lineno_width(longest_dst_lines);\n-\tmax_score_digits = lineno_width(largest_score);\n+\tmax_orig_digits = decimal_width(longest_src_lines);\n+\tmax_digits = decimal_width(longest_dst_lines);\n+\tmax_score_digits = decimal_width(largest_score);\n }\n \n /*\ndiff --git a/cache.h b/cache.h\nindex 2f30b3a..3504bcc 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1176,6 +1176,7 @@ extern const char *pager_program;\n extern int pager_in_use(void);\n extern int pager_use_color;\n extern int term_columns(void);\n+extern int decimal_width(unsigned number);\n \n extern const char *editor_program;\n extern const char *askpass_program;\ndiff --git a/pager.c b/pager.c\nindex e06cfa0..2e16a9c 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -153,3 +153,15 @@ int term_columns(void)\n #endif\n \treturn term_columns_at_startup;\n }\n+\n+/*\n+ * How many columns do we need to show this number in decimal?\n+ */\n+int decimal_width(unsigned number)\n+{\n+\tint i, width;\n+\n+\tfor (width = 1, i = 10; i <= number; width++)\n+\t\ti *= 10;\n+\treturn width;\n+}\n-- \n1.7.9.3.g2429d.dirty\n"},{"id":"184735","messageId":"1329263146-19215-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"7vsjie9q77.fsf@alter.siamese.dyndns.org","subject":"[PATCH 1/3 v4] diff --stat: use the full terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-14T23:45:44Z","receivedAt":"2012-02-14T23:45:44Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Use as many columns as necessary for filenames, as few columns as\nnecessary for change counts, and up to 40 columns for the graph.\n\nSome projects (especially in Java), have long filename paths, with\nnested directories or long individual filenames. When files are\nrenamed, the filename part in stat output can be almost useless. If\nthe middle part between { and } is long (because the file was moved to\na completely different directory), then most of the path would be\ntruncated.\n\nIt makes sense to detect and use the full terminal width and display\nfull filenames if possible.\n\nIf commits changing a lot of lines are displayed in a wide terminal\nwindow (200 or more columns), and the +- graph would use the full\nwidth, the output would look bad. Messages wrapped to about 80 columns\nwould be interspersed with very long +- lines. It makes sense to limit\nthe width of the graph part to a fixed value, even if more columns are\navailable. This fixed value is subjectively hard-coded to be 40\ncolumns, which seems to work well for git.git and linux-2.6.git and\nsome other repositories.\n\nIf there isn't enough columns to print both the filename and the\ngraph, at least 5/8 of available space is devoted to filenames. On a\nstandard 80 column terminal, or if not connected to a terminal and\nusing the default of 80 columns, this gives the same partition as\nbefore.\n\nNumber of columns required for change counts is computed based on the\nmaximum number of changed lines. This means that usually a few more\ncolumns will be available for the filenames and the graph.\n\nEleven tests are added for various combinations of long filename and\nbig change count and ways to specify widths.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\nHi,\n\nthank you for the review and comments. I think that they are all taken\ninto account.\n\nWhile working on the tests, I noticed that it would be nice to align\nthe output for binary files (\"Bin XXX -> YYY bytes\") -- that change\nis the subject of patch 2/3.\n\nTutorial is updated along with tests in 3/3.\n\nI've added 'v4' to the other two patches in this series like to this\none, despite them beeing new. I hope that this is proper form.\n\nv4:\n- comments are updated and the word \"histogram\" is banished\n- \"mopping up\" is removed (but the minimum width are guaranteed)\n\nv3:\n- use decimal_width(max_change) to calculate number of columns\n  required for change counts\n- rework the logic to divide columns\n- document the logic in comments, update docs\n- add more tests\n\nv2:\n- style fixes\n- some tests for git-format-patch added\n- patches 3 and 4 squashed together, since they touch the same lines\n- graph width is limited to 40 columns, even if there's more space\n- patch descriptions extended and cleared up\n\n\n Documentation/diff-options.txt | 14 +++---\n diff.c                         | 94 +++++++++++++++++++++++++++------------\n t/t4014-format-patch.sh        | 96 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 169 insertions(+), 35 deletions(-)\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex 9f7cba2..36e4ee3 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -53,13 +53,15 @@ endif::git-format-patch[]\n \tGenerate a diff using the \"patience diff\" algorithm.\n \n --stat[=<width>[,<name-width>[,<count>]]]::\n-\tGenerate a diffstat.  You can override the default\n-\toutput width for 80-column terminal by `--stat=<width>`.\n-\tThe width of the filename part can be controlled by\n-\tgiving another width to it separated by a comma.\n+\tGenerate a diffstat. By default, as much space as necessary\n+\twill be used for the filename part, and up to 40 columns for\n+\tthe graph part. Maximum width defaults to terminal width,\n+\tor 80 columns if not connected to a terminal, and can be\n+\toverriden by `<width>`. The width of the filename part can be\n+\tlimited by giving another width `<name-width>` after a comma.\n \tBy giving a third parameter `<count>`, you can limit the\n-\toutput to the first `<count>` lines, followed by\n-\t`...` if there are more.\n+\toutput to the first `<count>` lines, followed by `...` if\n+\tthere are more.\n +\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\ndiff --git a/diff.c b/diff.c\nindex 7e15426..4dc2b5c 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1327,7 +1327,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \tint i, len, add, del, adds = 0, dels = 0;\n \tuintmax_t max_change = 0, max_len = 0;\n \tint total_files = data->nr;\n-\tint width, name_width, count;\n+\tint width, name_width, graph_width, number_width, count;\n \tconst char *reset, *add_c, *del_c;\n \tconst char *line_prefix = \"\";\n \tint extra_shown = 0;\n@@ -1341,25 +1341,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tline_prefix = msg->buf;\n \t}\n \n-\twidth = options->stat_width ? options->stat_width : 80;\n-\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n \tcount = options->stat_count ? options->stat_count : data->nr;\n \n-\t/* Sanity: give at least 5 columns to the graph,\n-\t * but leave at least 10 columns for the name.\n-\t */\n-\tif (width < 25)\n-\t\twidth = 25;\n-\tif (name_width < 10)\n-\t\tname_width = 10;\n-\telse if (width < name_width + 15)\n-\t\tname_width = width - 15;\n-\n-\t/* Find the longest filename and max number of changes */\n \treset = diff_get_color_opt(options, DIFF_RESET);\n \tadd_c = diff_get_color_opt(options, DIFF_FILE_NEW);\n \tdel_c = diff_get_color_opt(options, DIFF_FILE_OLD);\n \n+\t/*\n+\t * Find the longest filename and max number of changes\n+\t */\n \tfor (i = 0; (i < count) && (i < data->nr); i++) {\n \t\tstruct diffstat_file *file = data->files[i];\n \t\tuintmax_t change = file->added + file->deleted;\n@@ -1380,19 +1370,64 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t}\n \tcount = i; /* min(count, data->nr) */\n \n-\t/* Compute the width of the graph part;\n-\t * 10 is for one blank at the beginning of the line plus\n-\t * \" | count \" between the name and the graph.\n+\t/*\n+\t * We have width = stat_width or term_columns() columns total.\n+\t * We want a maximum of min(max_len, stat_name_width) for the name part.\n+\t * We want a maximum of min(max_change, 40) for the +- part.\n+\t * We also need 1 for \" \" and 4 + decimal_width(max_change)\n+\t * for \" | NNNN \" and one the empty column at the end, altogether\n+\t * 6 + decimal_width(max_change).\n+\t *\n+\t * If there's not enough space, we will use the smaller of\n+\t * stat_name_width (if set) and 5/8*width for the filename,\n+\t * and the rest for constant elements + histogram, but no more\n+\t * than 40 for the histogram.\n+\t * (5/8 gives 50 for filename and 30 for constant parts +\n+\t * histogram for the standard terminal size).\n \t *\n-\t * From here on, name_width is the width of the name area,\n-\t * and width is the width of the graph area.\n+\t * In other words: stat_width limits the maximum width, and\n+\t * stat_name_width fixes the maximum width of the filename,\n+\t * and is also used to divide available columns if there\n+\t * aren't enough.\n \t */\n-\tname_width = (name_width < max_len) ? name_width : max_len;\n-\tif (width < (name_width + 10) + max_change)\n-\t\twidth = width - (name_width + 10);\n-\telse\n-\t\twidth = max_change;\n \n+\twidth = options->stat_width ? options->stat_width : term_columns();\n+\tnumber_width = decimal_width(max_change);\n+\n+\t/*\n+\t * Guarantee 3/8*16==6 for the graph part\n+\t * and 5/8*16==10 for the filename part\n+\t */\n+\tif (width < 16 + 6 + number_width)\n+\t\twidth = 16 + 6 + number_width;\n+\n+\t/*\n+\t * First assign sizes that are wanted, ignoring available width.\n+\t */\n+\tgraph_width = max_change < 40 ? max_change : 40;\n+\tname_width = (options->stat_name_width > 0 &&\n+\t\t      options->stat_name_width < max_len) ?\n+\t\toptions->stat_name_width : max_len;\n+\n+\t/*\n+\t * Adjust adjustable widths not to exceed maximum width\n+\t */\n+\tif (name_width + number_width + 6 + graph_width > width) {\n+\t\tif (graph_width > width * 3/8 - number_width - 6)\n+\t\t\tgraph_width = width * 3/8 - number_width - 6;\n+\t\tif (graph_width > 40)\n+\t\t\tgraph_width =  40;\n+\t\tif (name_width > width - number_width - 6 - graph_width)\n+\t\t\tname_width = width - number_width - 6 - graph_width;\n+\t\telse\n+\t\t\tgraph_width = width - number_width - 6 - name_width;\n+\t}\n+\n+\t/*\n+\t * From here name_width is the width of the name area,\n+\t * and graph_width is the width of the graph area.\n+\t * max_change is used to scale graph properly.\n+\t */\n \tfor (i = 0; i < count; i++) {\n \t\tconst char *prefix = \"\";\n \t\tchar *name = data->files[i]->print_name;\n@@ -1448,14 +1483,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tadds += add;\n \t\tdels += del;\n \n-\t\tif (width <= max_change) {\n-\t\t\tadd = scale_linear(add, width, max_change);\n-\t\t\tdel = scale_linear(del, width, max_change);\n+\t\tif (graph_width <= max_change) {\n+\t\t\tadd = scale_linear(add, graph_width, max_change);\n+\t\t\tdel = scale_linear(del, graph_width, max_change);\n \t\t}\n \t\tfprintf(options->file, \"%s\", line_prefix);\n \t\tshow_name(options->file, prefix, name, len);\n-\t\tfprintf(options->file, \"%5\"PRIuMAX\"%s\", added + deleted,\n-\t\t\t\tadded + deleted ? \" \" : \"\");\n+\t\tfprintf(options->file, \" %*\"PRIuMAX\"%s\",\n+\t\t\tnumber_width, added + deleted,\n+\t\t\tadded + deleted ? \" \" : \"\");\n \t\tshow_graph(options->file, '+', add, add_c, reset);\n \t\tshow_graph(options->file, '-', del, del_c, reset);\n \t\tfprintf(options->file, \"\\n\");\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 6797512..a65ade4 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -894,4 +894,100 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+name=aaaaaaaaaa\n+name=$name$name$name$name$name$name$name$name$name$name$name$name\n+test_expect_success 'preparation' \"\n+\t> ${name} &&\n+\tgit add ${name} &&\n+\tgit commit -m message &&\n+\techo a > ${name} &&\n+\tgit commit -m message ${name}\n+\"\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n+EOF\n+test_expect_success 'format patch graph width is 80 columns' '\n+\tgit format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 aaaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n+EOF\n+test_expect_success 'format patch --stat=width with long name' '\n+\tgit format-patch --stat=40 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-width=width works long name' '\n+\tgit format-patch --stat-width=40 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat=...,name-width with long name' '\n+\tgit format-patch --stat=60,32 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-name-width with long name' '\n+\tgit format-patch --stat-name-width=32 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'preparation' '\n+\t> abcd &&\n+\tgit add abcd &&\n+\tgit commit -m message &&\n+\tseq 1000 > abcd &&\n+\tgit commit -m message abcd\n+'\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch graph width is 40 columns' '\n+\tgit format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch ignores COLUMNS' '\n+\tCOLUMNS=200 git format-patch --stat --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch --stat=width with big change' '\n+\tgit format-patch --stat=40 --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-width=width with big change' '\n+\tgit format-patch --stat-width=40 --stdout -1 |\n+\t\tgrep -m 1 abcd > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++\n+EOF\n+test_expect_success 'format patch --stat=width with big change and long name' '\n+\tcp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n+\tgit add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n+\tgit commit -m message &&\n+\tgit format-patch --stat-width=60 --stdout -1 |\n+\t\tgrep -m 1 aaaa > actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.7.9.6.ga1838.dirty\n"},{"id":"184736","messageId":"1329263146-19215-2-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1329263146-19215-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 2/3 v4] diff --stat: better alignment for binary files","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-14T23:45:45Z","receivedAt":"2012-02-14T23:45:45Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"The output for binary and unmerged files was not updated in\n'diff --stat': use the full terminal width'. This fixes this\nomission and modifies the graph width logic to include enough\nspace for \"Bin XXX -> YYY bytes\".\n\nIf changes to binary files are mixed with changes to text files,\nchange counts are padded to take at least three columns. And the other\nway around, if change counts require more than three columns, then\n\"Bin\"s is padded to align with the change count. This way, the +- part\nstarts in the same column as \"XXX -> YYY\" part for binary files. This\nmakes the graph easier to parse visually thanks to the empty column.\nThis mimics the old layout of diff --stat.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\n diff.c                 | 39 ++++++++++++++++++++++++++++++++-------\n t/t4012-diff-binary.sh | 17 +++++++++++++++++\n 2 files changed, 49 insertions(+), 7 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 4dc2b5c..0732623 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1326,8 +1326,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n {\n \tint i, len, add, del, adds = 0, dels = 0;\n \tuintmax_t max_change = 0, max_len = 0;\n-\tint total_files = data->nr;\n-\tint width, name_width, graph_width, number_width, count;\n+\tint total_files = data->nr, count;\n+\tint width, name_width, graph_width, number_width = 0, bin_width = 0;\n \tconst char *reset, *add_c, *del_c;\n \tconst char *line_prefix = \"\";\n \tint extra_shown = 0;\n@@ -1363,8 +1363,21 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tif (max_len < len)\n \t\t\tmax_len = len;\n \n-\t\tif (file->is_binary || file->is_unmerged)\n+\t\tif (file->is_unmerged) {\n+\t\t\t/* \"Unmerged\" is 8 characters */\n+\t\t\tbin_width = bin_width < 8 ? 8 : bin_width;\n \t\t\tcontinue;\n+\t\t}\n+\t\tif (file->is_binary) {\n+\t\t\t/* \"Bin XXX -> YYY bytes\" */\n+\t\t\tint w = 14 + decimal_width(file->added)\n+\t\t\t\t+ decimal_width(file->deleted);\n+\t\t\tbin_width = bin_width < w ? w : bin_width;\n+\t\t\t/* Display change counts aligned with \"Bin\" */\n+\t\t\tnumber_width = 3;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (max_change < change)\n \t\t\tmax_change = change;\n \t}\n@@ -1389,10 +1402,19 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t * stat_name_width fixes the maximum width of the filename,\n \t * and is also used to divide available columns if there\n \t * aren't enough.\n+\t *\n+\t * Binary files are displayed with \"Bin XXX -> YYY bytes\"\n+\t * instead of the change count and graph. This part is treated\n+\t * similarly to the graph part, except that it is not\n+\t * \"scaled\". If total width is too small to accomodate the\n+\t * guaranteed minimum width of the filename part and the\n+\t * separators and this message, this message will \"overflow\"\n+\t * making the line longer than the maximum width.\n \t */\n \n \twidth = options->stat_width ? options->stat_width : term_columns();\n-\tnumber_width = decimal_width(max_change);\n+\tnumber_width = decimal_width(max_change) > number_width ?\n+\t\tdecimal_width(max_change) : number_width;\n \n \t/*\n \t * Guarantee 3/8*16==6 for the graph part\n@@ -1403,8 +1425,11 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \n \t/*\n \t * First assign sizes that are wanted, ignoring available width.\n+\t * (strlen(\"Bin XXX -> YYY bytes\") is bin_width + 4)\n \t */\n-\tgraph_width = max_change < 40 ? max_change : 40;\n+\tgraph_width = max_change + 4 > bin_width ? max_change : bin_width - 4;\n+\tif (graph_width > 40)\n+\t\tgraph_width = 40;\n \tname_width = (options->stat_name_width > 0 &&\n \t\t      options->stat_name_width < max_len) ?\n \t\toptions->stat_name_width : max_len;\n@@ -1458,7 +1483,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tif (data->files[i]->is_binary) {\n \t\t\tfprintf(options->file, \"%s\", line_prefix);\n \t\t\tshow_name(options->file, prefix, name, len);\n-\t\t\tfprintf(options->file, \"  Bin \");\n+\t\t\tfprintf(options->file, \" %*s \", number_width, \"Bin\");\n \t\t\tfprintf(options->file, \"%s%\"PRIuMAX\"%s\",\n \t\t\t\tdel_c, deleted, reset);\n \t\t\tfprintf(options->file, \" -> \");\n@@ -1471,7 +1496,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\telse if (data->files[i]->is_unmerged) {\n \t\t\tfprintf(options->file, \"%s\", line_prefix);\n \t\t\tshow_name(options->file, prefix, name, len);\n-\t\t\tfprintf(options->file, \"  Unmerged\\n\");\n+\t\t\tfprintf(options->file, \" Unmerged\\n\");\n \t\t\tcontinue;\n \t\t}\n \ndiff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh\nindex 2d9f9a0..ea0b376 100755\n--- a/t/t4012-diff-binary.sh\n+++ b/t/t4012-diff-binary.sh\n@@ -90,4 +90,21 @@ test_expect_success 'diff --no-index with binary creation' '\n \ttest_cmp expected actual\n '\n \n+cat >expect <<EOF\n+ binfile  |   Bin 0 -> 1026 bytes\n+ textfile | 10000 ++++++++++++++++++++++++++++++++++++++++\n+EOF\n+\n+test_expect_success 'diff with binary files and big change count\n+\n+\tVerify that \"Bin\" and the change count are properly aligned when\n+\tchange count is big' '\n+\techo X | dd of=binfile bs=1k seek=1 &&\n+\tgit add binfile &&\n+\tseq 10000 > textfile &&\n+\tgit add textfile &&\n+\tgit diff --cached --stat binfile textfile | grep \" | \" > actual\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.7.9.6.ga1838.dirty\n"},{"id":"184737","messageId":"1329263146-19215-3-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1329263146-19215-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 3/3 v4] Update diff --stat output in tests and tutorial","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-14T23:45:46Z","receivedAt":"2012-02-14T23:45:46Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\nAll tests pass for me after this change.\n\ngit grep -l -E '^\\s+[-a-z A-Z0-9/{}=>.]+ +\\|  +[0-9]+ +[-+]+' t/ |\n  grep -v apply |\n  xargs sed -i -r 's/^(\\s+[-a-zA-Z0-9/ {}=>.]+ +\\| ) +([0-9]+ +[-+]+)/\\1\\2/; s/^(\\s+[-a-zA-Z0-9/{}=>.]+ +\\| ) +(Bin.*)/\\1\\2/'\n+ manual fixes.\n\n Documentation/gitcore-tutorial.txt                 |  4 +-\n t/t0023-crlf-am.sh                                 |  2 +-\n t/t1200-tutorial.sh                                |  4 +-\n t/t3404-rebase-interactive.sh                      |  2 +-\n t/t3903-stash.sh                                   |  4 +-\n ...ff-tree_--cc_--patch-with-stat_--summary_master |  4 +-\n ...diff-tree_--cc_--patch-with-stat_--summary_side |  6 +-\n .../diff.diff-tree_--cc_--patch-with-stat_master   |  4 +-\n .../diff.diff-tree_--cc_--stat_--summary_master    |  4 +-\n t/t4013/diff.diff-tree_--cc_--stat_--summary_side  |  6 +-\n t/t4013/diff.diff-tree_--cc_--stat_master          |  4 +-\n ...pretty=oneline_--root_--patch-with-stat_initial |  6 +-\n .../diff.diff-tree_--pretty_--patch-with-stat_side |  6 +-\n ...-tree_--pretty_--root_--patch-with-stat_initial |  6 +-\n ...f-tree_--pretty_--root_--stat_--summary_initial |  6 +-\n .../diff.diff-tree_--pretty_--root_--stat_initial  |  6 +-\n ...diff.diff-tree_--root_--patch-with-stat_initial |  6 +-\n t/t4013/diff.diff-tree_-c_--stat_--summary_master  |  4 +-\n t/t4013/diff.diff-tree_-c_--stat_--summary_side    |  6 +-\n t/t4013/diff.diff-tree_-c_--stat_master            |  4 +-\n .../diff.diff_--patch-with-stat_-r_initial..side   |  6 +-\n t/t4013/diff.diff_--patch-with-stat_initial..side  |  6 +-\n t/t4013/diff.diff_--stat_initial..side             |  6 +-\n t/t4013/diff.diff_-r_--stat_initial..side          |  6 +-\n ..._--attach_--stdout_--suffix=.diff_initial..side |  6 +-\n ....format-patch_--attach_--stdout_initial..master | 16 +++---\n ...format-patch_--attach_--stdout_initial..master^ | 10 ++--\n ...ff.format-patch_--attach_--stdout_initial..side |  6 +-\n ...nline_--stdout_--numbered-files_initial..master | 16 +++---\n ...tdout_--subject-prefix=TESTCASE_initial..master | 16 +++---\n ....format-patch_--inline_--stdout_initial..master | 16 +++---\n ...format-patch_--inline_--stdout_initial..master^ | 10 ++--\n ...ormat-patch_--inline_--stdout_initial..master^^ |  6 +-\n ...ff.format-patch_--inline_--stdout_initial..side |  6 +-\n ...tch_--stdout_--cover-letter_-n_initial..master^ | 18 ++++----\n ...at-patch_--stdout_--no-numbered_initial..master | 16 +++---\n ...ormat-patch_--stdout_--numbered_initial..master | 16 +++---\n t/t4013/diff.format-patch_--stdout_initial..master | 16 +++---\n .../diff.format-patch_--stdout_initial..master^    | 10 ++--\n t/t4013/diff.format-patch_--stdout_initial..side   |  6 +-\n ....log_--patch-with-stat_--summary_master_--_dir_ |  6 +-\n t/t4013/diff.log_--patch-with-stat_master          | 16 +++---\n t/t4013/diff.log_--patch-with-stat_master_--_dir_  |  6 +-\n ..._--root_--cc_--patch-with-stat_--summary_master | 26 +++++-----\n ...f.log_--root_--patch-with-stat_--summary_master | 22 ++++----\n t/t4013/diff.log_--root_--patch-with-stat_master   | 22 ++++----\n ...og_--root_-c_--patch-with-stat_--summary_master | 26 +++++-----\n t/t4013/diff.show_--patch-with-stat_--summary_side |  6 +-\n t/t4013/diff.show_--patch-with-stat_side           |  6 +-\n t/t4013/diff.show_--stat_--summary_side            |  6 +-\n t/t4013/diff.show_--stat_side                      |  6 +-\n ...nged_--patch-with-stat_--summary_master_--_dir_ |  6 +-\n t/t4013/diff.whatchanged_--patch-with-stat_master  | 16 +++---\n ...ff.whatchanged_--patch-with-stat_master_--_dir_ |  6 +-\n ..._--root_--cc_--patch-with-stat_--summary_master | 26 +++++-----\n ...anged_--root_--patch-with-stat_--summary_master | 22 ++++----\n ...iff.whatchanged_--root_--patch-with-stat_master | 22 ++++----\n ...ed_--root_-c_--patch-with-stat_--summary_master | 26 +++++-----\n t/t4014-format-patch.sh                            |  2 +-\n t/t4016-diff-quote.sh                              | 14 +++---\n t/t4030-diff-textconv.sh                           |  2 +-\n t/t4043-diff-rename-binary.sh                      |  4 +-\n t/t4045-diff-relative.sh                           |  2 +-\n t/t4047-diff-dirstat.sh                            | 54 +++++++++++-----------\n t/t4049-diff-stat-count.sh                         |  4 +-\n t/t5100/patch0001                                  |  2 +-\n t/t5100/patch0002                                  |  2 +-\n t/t5100/patch0003                                  |  2 +-\n t/t5100/patch0005                                  |  4 +-\n t/t5100/patch0006                                  |  2 +-\n t/t5100/patch0010                                  |  2 +-\n t/t5100/patch0011                                  |  2 +-\n t/t5100/patch0014                                  |  2 +-\n t/t5100/patch0014--scissors                        |  2 +-\n t/t5100/sample.mbox                                | 18 ++++----\n t/t7602-merge-octopus-many.sh                      | 12 ++--\n 76 files changed, 356 insertions(+), 356 deletions(-)\n\ndiff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt\nindex c27d086..b781bbf 100644\n--- a/Documentation/gitcore-tutorial.txt\n+++ b/Documentation/gitcore-tutorial.txt\n@@ -1002,8 +1002,8 @@ would be different)\n ----------------\n Updating from ae3a2da... to a80b4aa....\n Fast-forward (no commit created; -m option ignored)\n- example |    1 +\n- hello   |    1 +\n+ example | 1 +\n+ hello   | 1 +\n  2 files changed, 2 insertions(+), 0 deletions(-)\n ----------------\n \ndiff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh\nindex aaed725..f9bbb91 100755\n--- a/t/t0023-crlf-am.sh\n+++ b/t/t0023-crlf-am.sh\n@@ -11,7 +11,7 @@ Date: Thu, 23 Aug 2007 13:00:00 +0200\n Subject: test1\n \n ---\n- foo |    1 +\n+ foo | 1 +\n  1 files changed, 1 insertions(+), 0 deletions(-)\n  create mode 100644 foo\n \ndiff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh\nindex 5e29e13..77ff21c 100755\n--- a/t/t1200-tutorial.sh\n+++ b/t/t1200-tutorial.sh\n@@ -154,8 +154,8 @@ test_expect_success 'git show-branch' '\n cat > resolve.expect << EOF\n Updating VARIABLE..VARIABLE\n FASTFORWARD (no commit created; -m option ignored)\n- example |    1 +\n- hello   |    1 +\n+ example | 1 +\n+ hello   | 1 +\n  2 files changed, 2 insertions(+), 0 deletions(-)\n EOF\n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex b981572..c8fe1a9 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -323,7 +323,7 @@ test_expect_success 'verbose flag is heeded, even after --continue' '\n \techo resolved > file1 &&\n \tgit add file1 &&\n \tgit rebase --continue > output &&\n-\tgrep \"^ file1 |    2 +-$\" output\n+\tgrep \"^ file1 | 2 +-$\" output\n '\n \n test_expect_success 'multi-squash only fires up editor once' '\ndiff --git a/t/t3903-stash.sh b/t/t3903-stash.sh\nindex dbe2ac1..fbf064e 100755\n--- a/t/t3903-stash.sh\n+++ b/t/t3903-stash.sh\n@@ -443,7 +443,7 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' '\n \tSTASH_ID=$(git stash create) &&\n \tgit reset --hard &&\n \tcat >expected <<-EOF &&\n-\t file |    1 +\n+\t file | 1 +\n \t 1 files changed, 1 insertions(+), 0 deletions(-)\n \tEOF\n \tgit stash show ${STASH_ID} >actual &&\n@@ -481,7 +481,7 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' '\n \tSTASH_ID=$(git stash create) &&\n \tgit reset --hard &&\n \tcat >expected <<-EOF &&\n-\t file |    1 +\n+\t file | 1 +\n \t 1 files changed, 1 insertions(+), 0 deletions(-)\n \tEOF\n \tgit stash show ${STASH_ID} >actual &&\ndiff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master\nindex 3a9f78a..b87f758 100644\n--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master\n@@ -1,7 +1,7 @@\n $ git diff-tree --cc --patch-with-stat --summary master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side\nindex a61ad8c..47665f9 100644\n--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side\n+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side\n@@ -1,8 +1,8 @@\n $ git diff-tree --cc --patch-with-stat --summary side\n c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master\nindex 49f23b9..efe6dcc 100644\n--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master\n+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master\n@@ -1,7 +1,7 @@\n $ git diff-tree --cc --patch-with-stat master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master\nindex cc6eb3b..1b465f0 100644\n--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master\n+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master\n@@ -1,6 +1,6 @@\n $ git diff-tree --cc --stat --summary master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side\nindex 50362be..44fcf4e 100644\n--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side\n+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side\n@@ -1,8 +1,8 @@\n $ git diff-tree --cc --stat --summary side\n c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n $\ndiff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_master\nindex fae7f33..6dffb7f 100644\n--- a/t/t4013/diff.diff-tree_--cc_--stat_master\n+++ b/t/t4013/diff.diff-tree_--cc_--stat_master\n@@ -1,6 +1,6 @@\n $ git diff-tree --cc --stat master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial\nindex d5c333a..a7d91c9 100644\n--- a/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial\n+++ b/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial\n@@ -1,8 +1,8 @@\n $ git diff-tree --pretty=oneline --root --patch-with-stat initial\n 444ac553ac7612cc88969031b02b3767fb8a353a Initial\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side\nindex 4d30e7e..2061f37 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side\n+++ b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial\nindex 7dfa6af..71d912e 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial\nindex 43bfce2..b80dbcc 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial\nindex 9154aa4..88cb5c9 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial\n@@ -5,8 +5,8 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial\nindex 1562b62..748ba93 100644\n--- a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial\n+++ b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial\n@@ -1,8 +1,8 @@\n $ git diff-tree --root --patch-with-stat initial\n 444ac553ac7612cc88969031b02b3767fb8a353a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_master\nindex ac9f641..700c386 100644\n--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master\n+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_master\n@@ -1,6 +1,6 @@\n $ git diff-tree -c --stat --summary master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_side b/t/t4013/diff.diff-tree_-c_--stat_--summary_side\nindex 2afcca1..520aa4f 100644\n--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_side\n+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_side\n@@ -1,8 +1,8 @@\n $ git diff-tree -c --stat --summary side\n c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n $\ndiff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_master\nindex c2fe6a9..cdc7c40 100644\n--- a/t/t4013/diff.diff-tree_-c_--stat_master\n+++ b/t/t4013/diff.diff-tree_-c_--stat_master\n@@ -1,6 +1,6 @@\n $ git diff-tree -c --stat master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side\nindex 9ed317a..abf43a9 100644\n--- a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side\n+++ b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side\n@@ -1,7 +1,7 @@\n $ git diff --patch-with-stat -r initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff_--patch-with-stat_initial..side b/t/t4013/diff.diff_--patch-with-stat_initial..side\nindex 8b50629..f88262e 100644\n--- a/t/t4013/diff.diff_--patch-with-stat_initial..side\n+++ b/t/t4013/diff.diff_--patch-with-stat_initial..side\n@@ -1,7 +1,7 @@\n $ git diff --patch-with-stat initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff_--stat_initial..side b/t/t4013/diff.diff_--stat_initial..side\nindex 0517b5d..17a07be 100644\n--- a/t/t4013/diff.diff_--stat_initial..side\n+++ b/t/t4013/diff.diff_--stat_initial..side\n@@ -1,6 +1,6 @@\n $ git diff --stat initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff_-r_--stat_initial..side b/t/t4013/diff.diff_-r_--stat_initial..side\nindex 245220d..54507eb 100644\n--- a/t/t4013/diff.diff_-r_--stat_initial..side\n+++ b/t/t4013/diff.diff_-r_--stat_initial..side\n@@ -1,6 +1,6 @@\n $ git diff -r --stat initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\nindex 52116d3..6996877 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n@@ -12,9 +12,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\nindex ce49bd6..d56a1a3 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\nindex 5f1b238..b76e61f 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\nindex 4a2364a..769cf32 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n@@ -12,9 +12,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\nindex 43b81eb..0ee7338 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\nindex ca3f60b..fbf3bd4 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\nindex 08f2301..d68e3ee 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\nindex 07f1230..668e38f 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\nindex 29e00ab..caec553 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\nindex 67633d4..6b84b1b 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n@@ -12,9 +12,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\nindex 3b4e113..d8cba57 100644\n--- a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\n+++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\n@@ -10,10 +10,10 @@ A U Thor (2):\n   Second\n   Third\n \n- dir/sub |    4 ++++\n- file0   |    3 +++\n- file1   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 4 ++++\n+ file0   | 3 +++\n+ file1   | 3 +++\n+ file2   | 3 ---\n  4 files changed, 10 insertions(+), 3 deletions(-)\n  create mode 100644 file1\n  delete mode 100644 file2\n@@ -28,9 +28,9 @@ Subject: [DIFFERENT_PREFIX 1/2] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [DIFFERENT_PREFIX 2/2] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master\nindex f7752eb..a2a4726 100644\n--- a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master\n+++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master\n@@ -6,9 +6,9 @@ Subject: [PATCH] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -85,9 +85,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master\nindex 8e67dbf..602f4b0 100644\n--- a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master\n+++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master\n@@ -6,9 +6,9 @@ Subject: [PATCH 1/3] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH 2/3] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -85,9 +85,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH 3/3] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..master\nindex 7b89978..bcf739e 100644\n--- a/t/t4013/diff.format-patch_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--stdout_initial..master\n@@ -6,9 +6,9 @@ Subject: [PATCH 1/3] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH 2/3] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -85,9 +85,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH 3/3] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..master^\nindex b7f9725..7d5ba0f 100644\n--- a/t/t4013/diff.format-patch_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--stdout_initial..master^\n@@ -6,9 +6,9 @@ Subject: [PATCH 1/2] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH 2/2] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_initial..side b/t/t4013/diff.format-patch_--stdout_initial..side\nindex e765088..9ed0ea2 100644\n--- a/t/t4013/diff.format-patch_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--stdout_initial..side\n@@ -5,9 +5,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_\nindex bd7f5c0..e2954d3 100644\n--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_\n+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_\n@@ -12,7 +12,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -31,7 +31,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -53,7 +53,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master\nindex 14595a6..e417873 100644\n--- a/t/t4013/diff.log_--patch-with-stat_master\n+++ b/t/t4013/diff.log_--patch-with-stat_master\n@@ -12,9 +12,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -54,8 +54,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -86,9 +86,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_\nindex 5a4e727..cebec52 100644\n--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_\n+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_\n@@ -12,7 +12,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -31,7 +31,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -53,7 +53,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master\nindex df0aaa9..540633f 100644\n--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master\nindex c11b5f2c..fb289d8 100644\n--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master\n@@ -12,9 +12,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -55,8 +55,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -88,9 +88,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -130,9 +130,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master\nindex 5f0c98f..84f535d 100644\n--- a/t/t4013/diff.log_--root_--patch-with-stat_master\n+++ b/t/t4013/diff.log_--root_--patch-with-stat_master\n@@ -12,9 +12,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -54,8 +54,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -86,9 +86,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -127,9 +127,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master\nindex e62c368..3e89ace 100644\n--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --combined dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.show_--patch-with-stat_--summary_side b/t/t4013/diff.show_--patch-with-stat_--summary_side\nindex 377f2b7..38c1841 100644\n--- a/t/t4013/diff.show_--patch-with-stat_--summary_side\n+++ b/t/t4013/diff.show_--patch-with-stat_--summary_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.show_--patch-with-stat_side b/t/t4013/diff.show_--patch-with-stat_side\nindex fb14c53..38f6be2 100644\n--- a/t/t4013/diff.show_--patch-with-stat_side\n+++ b/t/t4013/diff.show_--patch-with-stat_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.show_--stat_--summary_side b/t/t4013/diff.show_--stat_--summary_side\nindex 5bd5977..e6f30a4 100644\n--- a/t/t4013/diff.show_--stat_--summary_side\n+++ b/t/t4013/diff.show_--stat_--summary_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n $\ndiff --git a/t/t4013/diff.show_--stat_side b/t/t4013/diff.show_--stat_side\nindex 3b22327..58ee49a 100644\n--- a/t/t4013/diff.show_--stat_side\n+++ b/t/t4013/diff.show_--stat_side\n@@ -5,8 +5,8 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_\nindex 6a467cc..ee340b8 100644\n--- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_\n+++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_\n@@ -5,7 +5,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -24,7 +24,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -46,7 +46,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master b/t/t4013/diff.whatchanged_--patch-with-stat_master\nindex 1e1bbe1..4adeab7 100644\n--- a/t/t4013/diff.whatchanged_--patch-with-stat_master\n+++ b/t/t4013/diff.whatchanged_--patch-with-stat_master\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -47,8 +47,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -79,9 +79,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_\nindex 13789f1..63a3043 100644\n--- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_\n+++ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_\n@@ -5,7 +5,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -24,7 +24,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -46,7 +46,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master\nindex e96ff1f..60f3788 100644\n--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master\nindex 0291153..9b7f63f 100644\n--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -48,8 +48,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -81,9 +81,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -123,9 +123,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master\nindex 9b0349c..cba8f3c 100644\n--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master\n+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -47,8 +47,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -79,9 +79,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master\nindex c0aff68..8e24293 100644\n--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --combined dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex a65ade4..91be989 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -519,7 +519,7 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \n cat > expect << EOF\n ---\n- file |   16 ++++++++++++++++\n+ file | 16 ++++++++++++++++\n  1 files changed, 16 insertions(+), 0 deletions(-)\n \n diff --git a/file b/file\ndiff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh\nindex ab0c2f0..e451f2a 100755\n--- a/t/t4016-diff-quote.sh\n+++ b/t/t4016-diff-quote.sh\n@@ -59,13 +59,13 @@ test_expect_success TABS_IN_FILENAMES 'git diff --summary -M HEAD' '\n \n test_expect_success TABS_IN_FILENAMES 'setup expected files' '\n cat >expect <<\\EOF\n- pathname.1 => \"Rpathname\\twith HT.0\"            |    0\n- pathname.3 => \"Rpathname\\nwith LF.0\"            |    0\n- \"pathname\\twith HT.3\" => \"Rpathname\\nwith LF.1\" |    0\n- pathname.2 => Rpathname with SP.0               |    0\n- \"pathname\\twith HT.2\" => Rpathname with SP.1    |    0\n- pathname.0 => Rpathname.0                       |    0\n- \"pathname\\twith HT.0\" => Rpathname.1            |    0\n+ pathname.1 => \"Rpathname\\twith HT.0\"            | 0\n+ pathname.3 => \"Rpathname\\nwith LF.0\"            | 0\n+ \"pathname\\twith HT.3\" => \"Rpathname\\nwith LF.1\" | 0\n+ pathname.2 => Rpathname with SP.0               | 0\n+ \"pathname\\twith HT.2\" => Rpathname with SP.1    | 0\n+ pathname.0 => Rpathname.0                       | 0\n+ \"pathname\\twith HT.0\" => Rpathname.1            | 0\n  7 files changed, 0 insertions(+), 0 deletions(-)\n EOF\n '\ndiff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh\nindex 88c5619..6a6344c 100755\n--- a/t/t4030-diff-textconv.sh\n+++ b/t/t4030-diff-textconv.sh\n@@ -85,7 +85,7 @@ test_expect_success 'status -v produces text' '\n '\n \n cat >expect.stat <<'EOF'\n- file |  Bin 2 -> 4 bytes\n+ file | Bin 2 -> 4 bytes\n  1 files changed, 0 insertions(+), 0 deletions(-)\n EOF\n test_expect_success 'diffstat does not run textconv' '\ndiff --git a/t/t4043-diff-rename-binary.sh b/t/t4043-diff-rename-binary.sh\nindex 0601281..ad0b2da 100755\n--- a/t/t4043-diff-rename-binary.sh\n+++ b/t/t4043-diff-rename-binary.sh\n@@ -23,8 +23,8 @@ test_expect_success 'move the files into a \"sub\" directory' '\n '\n \n cat > expected <<\\EOF\n- bar => sub/bar |  Bin 5 -> 5 bytes\n- foo => sub/foo |    0\n+ bar => sub/bar | Bin 5 -> 5 bytes\n+ foo => sub/foo |   0\n  2 files changed, 0 insertions(+), 0 deletions(-)\n \n diff --git a/bar b/sub/bar\ndiff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh\nindex 8a3c63b..336df82 100755\n--- a/t/t4045-diff-relative.sh\n+++ b/t/t4045-diff-relative.sh\n@@ -32,7 +32,7 @@ test_expect_success \"-p $*\" \"\n check_stat() {\n expect=$1; shift\n cat >expected <<EOF\n- $expect |    1 +\n+ $expect | 1 +\n  1 files changed, 1 insertions(+), 0 deletions(-)\n EOF\n test_expect_success \"--stat $*\" \"\ndiff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh\nindex 29e80a5..75eaf16 100755\n--- a/t/t4047-diff-dirstat.sh\n+++ b/t/t4047-diff-dirstat.sh\n@@ -252,41 +252,41 @@ EOF\n '\n \n cat <<EOF >expect_diff_stat\n- changed/text             |    2 +-\n- dst/copy/changed/text    |   10 ++++++++++\n- dst/copy/rearranged/text |   10 ++++++++++\n- dst/copy/unchanged/text  |   10 ++++++++++\n- dst/move/changed/text    |   10 ++++++++++\n- dst/move/rearranged/text |   10 ++++++++++\n- dst/move/unchanged/text  |   10 ++++++++++\n- rearranged/text          |    2 +-\n- src/move/changed/text    |   10 ----------\n- src/move/rearranged/text |   10 ----------\n- src/move/unchanged/text  |   10 ----------\n+ changed/text             |  2 +-\n+ dst/copy/changed/text    | 10 ++++++++++\n+ dst/copy/rearranged/text | 10 ++++++++++\n+ dst/copy/unchanged/text  | 10 ++++++++++\n+ dst/move/changed/text    | 10 ++++++++++\n+ dst/move/rearranged/text | 10 ++++++++++\n+ dst/move/unchanged/text  | 10 ++++++++++\n+ rearranged/text          |  2 +-\n+ src/move/changed/text    | 10 ----------\n+ src/move/rearranged/text | 10 ----------\n+ src/move/unchanged/text  | 10 ----------\n  11 files changed, 62 insertions(+), 32 deletions(-)\n EOF\n \n cat <<EOF >expect_diff_stat_M\n- changed/text                      |    2 +-\n- dst/copy/changed/text             |   10 ++++++++++\n- dst/copy/rearranged/text          |   10 ++++++++++\n- dst/copy/unchanged/text           |   10 ++++++++++\n- {src => dst}/move/changed/text    |    2 +-\n- {src => dst}/move/rearranged/text |    2 +-\n- {src => dst}/move/unchanged/text  |    0\n- rearranged/text                   |    2 +-\n+ changed/text                      |  2 +-\n+ dst/copy/changed/text             | 10 ++++++++++\n+ dst/copy/rearranged/text          | 10 ++++++++++\n+ dst/copy/unchanged/text           | 10 ++++++++++\n+ {src => dst}/move/changed/text    |  2 +-\n+ {src => dst}/move/rearranged/text |  2 +-\n+ {src => dst}/move/unchanged/text  |  0\n+ rearranged/text                   |  2 +-\n  8 files changed, 34 insertions(+), 4 deletions(-)\n EOF\n \n cat <<EOF >expect_diff_stat_CC\n- changed/text                      |    2 +-\n- {src => dst}/copy/changed/text    |    2 +-\n- {src => dst}/copy/rearranged/text |    2 +-\n- {src => dst}/copy/unchanged/text  |    0\n- {src => dst}/move/changed/text    |    2 +-\n- {src => dst}/move/rearranged/text |    2 +-\n- {src => dst}/move/unchanged/text  |    0\n- rearranged/text                   |    2 +-\n+ changed/text                      | 2 +-\n+ {src => dst}/copy/changed/text    | 2 +-\n+ {src => dst}/copy/rearranged/text | 2 +-\n+ {src => dst}/copy/unchanged/text  | 0\n+ {src => dst}/move/changed/text    | 2 +-\n+ {src => dst}/move/rearranged/text | 2 +-\n+ {src => dst}/move/unchanged/text  | 0\n+ rearranged/text                   | 2 +-\n  8 files changed, 6 insertions(+), 6 deletions(-)\n EOF\n \ndiff --git a/t/t4049-diff-stat-count.sh b/t/t4049-diff-stat-count.sh\nindex 641e70d..5edac4e 100755\n--- a/t/t4049-diff-stat-count.sh\n+++ b/t/t4049-diff-stat-count.sh\n@@ -14,8 +14,8 @@ test_expect_success setup '\n \techo a >a &&\n \techo b >b &&\n \tcat >expect <<-\\EOF\n-\t a |    1 +\n-\t b |    1 +\n+\t a | 1 +\n+\t b | 1 +\n \t 2 files changed, 2 insertions(+), 0 deletions(-)\n \tEOF\n \tgit diff --stat --stat-count=2 >actual &&\ndiff --git a/t/t5100/patch0001 b/t/t5100/patch0001\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0001\n+++ b/t/t5100/patch0001\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0002 b/t/t5100/patch0002\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0002\n+++ b/t/t5100/patch0002\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0003 b/t/t5100/patch0003\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0003\n+++ b/t/t5100/patch0003\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0005 b/t/t5100/patch0005\nindex 7d24b24..ab7a383 100644\n--- a/t/t5100/patch0005\n+++ b/t/t5100/patch0005\n@@ -1,7 +1,7 @@\n ---\n \n- Documentation/git-cvsimport-script.txt |    9 ++++++++-\n- git-cvsimport-script                   |    4 ++--\n+ Documentation/git-cvsimport-script.txt | 9 ++++++++-\n+ git-cvsimport-script                   | 4 ++--\n  2 files changed, 10 insertions(+), 3 deletions(-)\n \n 50452f9c0c2df1f04d83a26266ba704b13861632\ndiff --git a/t/t5100/patch0006 b/t/t5100/patch0006\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0006\n+++ b/t/t5100/patch0006\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0010 b/t/t5100/patch0010\nindex f055481..436821c 100644\n--- a/t/t5100/patch0010\n+++ b/t/t5100/patch0010\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c |    2 +-\n+ builtin-mailinfo.c | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t5100/patch0011 b/t/t5100/patch0011\nindex 8841d3c..0988713 100644\n--- a/t/t5100/patch0011\n+++ b/t/t5100/patch0011\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c  |    4 ++--\n+ builtin-mailinfo.c  | 4 ++--\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\n index 3e5fe51..aabfe5c 100644\ndiff --git a/t/t5100/patch0014 b/t/t5100/patch0014\nindex 124efd2..3f3825f 100644\n--- a/t/t5100/patch0014\n+++ b/t/t5100/patch0014\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++++-\n+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-\n  1 files changed, 36 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t5100/patch0014--scissors b/t/t5100/patch0014--scissors\nindex 124efd2..3f3825f 100644\n--- a/t/t5100/patch0014--scissors\n+++ b/t/t5100/patch0014--scissors\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++++-\n+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-\n  1 files changed, 36 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox\nindex de10312..34a09a0 100644\n--- a/t/t5100/sample.mbox\n+++ b/t/t5100/sample.mbox\n@@ -12,7 +12,7 @@ Subject: [PATCH] a commit.\n Here is a patch from A U Thor.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -52,7 +52,7 @@ two truly blank and another full of spaces in between.\n Hope this helps.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -83,7 +83,7 @@ Message-Id: <nitpicker.12121212@example.net>\n Hopefully this would fix the problem stated there.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -249,8 +249,8 @@ actual flags.\n Signed-off-by: David K=E5gedal <davidk@lysator.liu.se>\n ---\n \n- Documentation/git-cvsimport-script.txt |    9 ++++++++-\n- git-cvsimport-script                   |    4 ++--\n+ Documentation/git-cvsimport-script.txt | 9 ++++++++-\n+ git-cvsimport-script                   | 4 ++--\n  2 files changed, 10 insertions(+), 3 deletions(-)\n \n 50452f9c0c2df1f04d83a26266ba704b13861632\n@@ -379,7 +379,7 @@ Subject: [PATCH] a commit.\n Here is a patch from A U Thor.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -449,7 +449,7 @@ memcmp(\"Subject: \", header[i], 7) will never match.\n Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n Signed-off-by: Junio C Hamano <gitster@pobox.com>\n ---\n- builtin-mailinfo.c |    2 +-\n+ builtin-mailinfo.c | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\n@@ -482,7 +482,7 @@ Content-Transfer-Encoding: quoted-printable\n Here comes a commit log message, and\n its second line is here.\n ---\n- builtin-mailinfo.c  |    4 ++--\n+ builtin-mailinfo.c  | 4 ++--\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\n index 3e5fe51..aabfe5c 100644\n@@ -587,7 +587,7 @@ everything before it in the message body.\n \n Signed-off-by: Junio C Hamano <gitster@pobox.com>\n ---\n- builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++++-\n+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-\n  1 files changed, 36 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh\nindex 61f36ba..5a86e24 100755\n--- a/t/t7602-merge-octopus-many.sh\n+++ b/t/t7602-merge-octopus-many.sh\n@@ -54,9 +54,9 @@ Trying simple merge with c2\n Trying simple merge with c3\n Trying simple merge with c4\n Merge made by the 'octopus' strategy.\n- c2.c |    1 +\n- c3.c |    1 +\n- c4.c |    1 +\n+ c2.c | 1 +\n+ c3.c | 1 +\n+ c4.c | 1 +\n  3 files changed, 3 insertions(+), 0 deletions(-)\n  create mode 100644 c2.c\n  create mode 100644 c3.c\n@@ -73,7 +73,7 @@ cat >expected <<\\EOF\n Already up-to-date with c4\n Trying simple merge with c5\n Merge made by the 'octopus' strategy.\n- c5.c |    1 +\n+ c5.c | 1 +\n  1 files changed, 1 insertions(+), 0 deletions(-)\n  create mode 100644 c5.c\n EOF\n@@ -87,8 +87,8 @@ cat >expected <<\\EOF\n Fast-forwarding to: c1\n Trying simple merge with c2\n Merge made by the 'octopus' strategy.\n- c1.c |    1 +\n- c2.c |    1 +\n+ c1.c | 1 +\n+ c2.c | 1 +\n  2 files changed, 2 insertions(+), 0 deletions(-)\n  create mode 100644 c1.c\n  create mode 100644 c2.c\n-- \n1.7.9.6.ga1838.dirty\n"},{"id":"184739","messageId":"7vr4xx3qns.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329263146-19215-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/3 v4] diff --stat: use the full terminal width","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-15T00:07:35Z","receivedAt":"2012-02-15T00:07:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> I've added 'v4' to the other two patches in this series like to this\n> one, despite them beeing new. I hope that this is proper form.\n\nYeah, we usually say [PATCH v4 1/3] to mean that this is the fourth\nincarnation of the whole series (it is an instruction to reviewers to\ndiscard anything labeled without v$N and $N smaller than 4, and read only\nthe ones marked with \"v4\") and it often happens that the earlier round did\nnot have three patches, so that is perfectly fine.\n"},{"id":"184740","messageId":"7vwr7o3nee.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329263146-19215-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/3 v4] diff --stat: use the full terminal width","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-15T01:18:01Z","receivedAt":"2012-02-15T01:18:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> - comments are updated and the word \"histogram\" is banished\n\nHeh, I still see at least three instances of them in this patch.\n\n> - use decimal_width(max_change) to calculate number of columns\n\nPlease see comments for 3/3 I'll send separately.\n\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> index 6797512..a65ade4 100755\n> --- a/t/t4014-format-patch.sh\n> +++ b/t/t4014-format-patch.sh\n> @@ -894,4 +894,100 @@ test_expect_success 'format patch ignores color.ui' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +name=aaaaaaaaaa\n> +name=$name$name$name$name$name$name$name$name$name$name$name$name\n\nHow long is this name?  120 columns?  I think that should be fine for any\nfilesystem we care about.\n\n> +test_expect_success 'preparation' \"\n> +\t> ${name} &&\n> +\tgit add ${name} &&\n> +\tgit commit -m message &&\n> +\techo a > ${name} &&\n> +\tgit commit -m message ${name}\n> +\"\n\nPlease write these (exactly -- paying close attention to SP) like this:\n\n\t>\"$name\" &&\n\tgit add \"$name\" &&\n        git commit -m message &&\n        echo a >\"$name\" &&\n        git commit -m message \"$name\"\n\nPoints to note:\n\n - Even though you (and the reader) may know that \"$name\" does not contain\n   word-breaking spaces, writing double-quotes around it reduces the\n   mental burden from the readers;\n\n - Strictly speaking, the target of I/O redirection (e.g. >\"$name\") does\n   not have to have quotes around it, but some versions of bash are known\n   to give misguided warnings against it;\n\n - We do not write SP between the redirection and filename, but we do have\n   one SP before the redirection; and\n\n - Unless you want to express concatenation with string that can appear\n   later in words (e.g. \"${name}1\"), avoid ${name} to lessen the mental\n   burden to readers, as \"${\" often signals there is some magic coming\n   (e.g. \"${name#strip}\").\n\n> +cat >expect <<'EOF'\n> + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n> +EOF\n> +test_expect_success 'format patch graph width is 80 columns' '\n\nPlease make sure this test (and all the other new tests) pass with or\nwithout your the patch that updates diff.c, as we need to ensure that\nCOLUMNS=80 or vanilla format-patch produces result that is identical to\nthe old output without regression (again, see comments to [PATCH 3/3]).\n\n> +\tgit format-patch --stat --stdout -1 |\n> +\t\tgrep -m 1 aaaaa > actual &&\n\nDo not use \"grep -m $count\"; it is not portable.\n\nLiteral translation of the above would be:\n\n\tsed -n -e \"/aaaaa/{\n        \tp\n                q\n\t}\"\n\nbut you can perhaps rely on the fact that there is only one path and '|'\ndoes not ppear in the payload or log message, and use this instead:\n\n\tgrep \"|\" >actual\n\nAlso to catch errors in format-patch that unexpectedly dies (after all,\nyou are touching diff machinery with your patch), avoid using pipes, and\nwrite it perhaps like this:\n\n\tgit format-patch --stat --stdout -1 >output &&\n        grep \"|\" >actual &&\n"},{"id":"184741","messageId":"7vpqdg3n7z.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329263146-19215-3-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 3/3 v4] Update diff --stat output in tests and tutorial","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-15T01:21:52Z","receivedAt":"2012-02-15T01:21:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n> ---\n> All tests pass for me after this change.\n\nErr, this is not what I meant when I said \"split that part to a different\npatch\".\n\nIf you didn't have this bit in [PATCH 1/3]\n\n        -               fprintf(options->file, \"%5\"PRIuMAX\"%s\", added + deleted,\n        -                               added + deleted ? \" \" : \"\");\n        +               fprintf(options->file, \" %*\"PRIuMAX\"%s\",\n        +                       number_width, added + deleted,\n\nthen I think most of the changes in [PATCH 3/3] is unnecessary when using\nthe default 80-column output, which is how the test is run.\n\nIn other words, ideally, the [PATCH 1/3] should improve the diffstat\ngeneration code in such a way that it produces output that is identical to\nthe existing test vectors when COLUMNS is set to 80 but takes advantage of\nwider terminal when available.  So either the above change should not be\npart of [PATCH 1/3] at all, or you still chnage this fprintf(), but use\nnumber_width that is hardcoded to 4 instead of using the value computed\nwith decimal_width(max_change).  As to the test part, when a wider COLUMNS\nis given, the code would obviously take advantage of it, so it may:\n\n - contain a change to the test suite somewhere, probably t/test-lib.sh,\n   to set COLUMNS=80 and export it, to make sure that the existing test\n   won't be broken when the number of columns learned from ioctl(1) is\n   different from 80; and\n\n - add a new test that explicitly sets wider COLUMNS and makes sure you\n   get a wider diffstat graph.\n\nand almost no other changes to the expected output.\n\nIf you do not arrange [PATCH 1/3] that way, we cannot verify that it does\nnot introduce any regression to existing users.  Just applying [1/3] would\nstart failing tests, and we cannot tell which failure is a false alarm due\nto this change, and which ones is a real regression that you are producing\nwrong output when COLUMNS is set to 80.\n\nAnd then as a separate patch [PATCH 3/3] at the very end of the series,\nyou would either introduce the above change to fprintf(), or if you\nchanged fprintf() in [PATCH 1/3] but used hardcoded number_width, then\nchange it to use decimal_width().\n\nThat change in turn makes the bulk of this patch to update the expected\noutput necessary.\n\nIf your series is organized that way, we can weigh pros-and-cons of the\nchange to use decimal_width() a lot more easily.\n\nThanks.\n"},{"id":"184750","messageId":"4F3B611E.4060504@viscovery.net","threadId":"29589","inReplyTo":"1329263146-19215-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/3 v4] diff --stat: use the full terminal width","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2012-02-15T07:39:10Z","receivedAt":"2012-02-15T07:39:10Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 2/15/2012 0:45, schrieb Zbigniew Jędrzejewski-Szmek:\n> +test_expect_success 'preparation' '\n> +\t> abcd &&\n> +\tgit add abcd &&\n> +\tgit commit -m message &&\n> +\tseq 1000 > abcd &&\n> +\tgit commit -m message abcd\n\nPlease don't use seq (here and in some more places in this series); we\ndon't have it on Windows. You can write it explicitly:\n\n\ti=0 &&\n\twhile test $i -lt 1000\n\tdo\n\t\ti=$(($i + 1))\n\t\techo $i &&\n\tdone >abcd &&\n\t...\n\n-- Hannes\n"},{"id":"184756","messageId":"1329303808-16989-1-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"7vpqdg3n7z.fsf@alter.siamese.dyndns.org","subject":"[PATCH 1/3 v5] diff --stat: tests for long filenames and big change counts","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-15T11:03:26Z","receivedAt":"2012-02-15T11:03:26Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Eleven tests for various combinations of a long filename and/or big\nchange count and ways to specify widths for diff --stat.\n---\nTests added in previous version of 'diff --stat: use full terminal width'\nare extracted into a separate patch. The tests are usefull independently\nof that patch anyway.\n\nchanges to tests since v4:\n- seq is replaced with a while loop for windows compatibility\n- grep -m 1 is replaced with grep \" | \"\n- redirects are made portable\n- piped output is split into two commands to verify that the first command\n  sucessfully runs to completion\n\n t/t4014-format-patch.sh | 101 ++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 101 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 6797512..f6ebb51 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -894,4 +894,105 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+# 120 character name\n+name=aaaaaaaaaa\n+name=$name$name$name$name$name$name$name$name$name$name$name$name\n+test_expect_success 'preparation' \"\n+\t>\\\"$name\\\" &&\n+\tgit add \\\"$name\\\" &&\n+\tgit commit -m message &&\n+\techo a >\\\"$name\\\" &&\n+\tgit commit -m message \\\"$name\\\"\n+\"\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n+EOF\n+test_expect_success 'format patch graph width defaults to 80 columns' '\n+\tgit format-patch --stat --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n+EOF\n+test_expect_success 'format patch --stat=width with long name' '\n+\tgit format-patch --stat=40 --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-width=width works with long name' '\n+\tgit format-patch --stat-width=40 --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat=...,name-width with long name' '\n+\tgit format-patch --stat=60,29 --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-name-width with long name' '\n+\tgit format-patch --stat-name-width=29 --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'preparation' '\n+\t>abcd &&\n+\tgit add abcd &&\n+\tgit commit -m message &&\n+\ti=0 &&\n+\twhile test $i -lt 1000; do\n+\t\techo $i &&\n+\t\ti=$(($i + 1))\n+\tdone >abcd &&\n+\tgit commit -m message abcd\n+'\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch graph part width is 40 columns' '\n+\tgit format-patch --stat --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch ignores COLUMNS' '\n+\tCOLUMNS=200 git format-patch --stat --stdout -1 >output\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++\n+EOF\n+test_expect_success 'format patch --stat=width with big change' '\n+\tgit format-patch --stat=40 --stdout -1 >output\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'format patch --stat-width=width with big change' '\n+\tgit format-patch --stat-width=40 --stdout -1 >output\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect <<'EOF'\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++\n+EOF\n+test_expect_success 'format patch --stat=width with big change and long name' '\n+\tcp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n+\tgit add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n+\tgit commit -m message &&\n+\tgit format-patch --stat-width=60 --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.7.9.5.g91d5\n"},{"id":"184757","messageId":"1329303808-16989-2-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1329303808-16989-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 2/3 v5] diff --stat: use the full terminal width","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-15T11:03:27Z","receivedAt":"2012-02-15T11:03:27Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Use as many columns as necessary for the filenames and up to 40\ncolumns for the graph.\n\nSome projects (especially in Java), have long filename paths, with\nnested directories or long individual filenames. When files are\nrenamed, the filename part in stat output can be almost useless. If\nthe middle part between { and } is long (because the file was moved to\na completely different directory), then most of the path would be\ntruncated.\n\nIt makes sense to detect and use the full terminal width and display\nfull filenames if possible.\n\nIf commits changing a lot of lines are displayed in a wide terminal\nwindow (200 or more columns), and the +- graph would use the full\nwidth, the output would look bad. Messages wrapped to about 80 columns\nwould be interspersed with very long +- lines. It makes sense to limit\nthe width of the graph part to a fixed value, even if more columns are\navailable. This fixed value is subjectively hard-coded to be 40\ncolumns, which seems to work well for git.git and linux-2.6.git and\nsome other repositories.\n\nIf there isn't enough columns to print both the filename and the\ngraph, at least 5/8 of available space is devoted to filenames. On a\nstandard 80 column terminal, or if not connected to a terminal and\nusing the default of 80 columns, this gives the same partition as\nbefore.\n\nThe --stat output in tests is not affected.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\nThis is the main patch. Presented with the two options (either\nhardcode number_width=4 or remove fprintf(options->file, \"\n%*\"PRIuMAX\"%s\", number_width, ...)), I've taken the middle way:\nnumber_width=4 is hardcoded, but the fprintf is reverted to the previous\nversion. I think that this way the code is most readable, independently\nif later changes.\n\nJunio suggested to:\n - contain a change to the test suite somewhere, probably t/test-lib.sh,\n   to set COLUMNS=80 and export it, to make sure that the existing test\n   won't be broken when the number of columns learned from ioctl(1) is\n   different from 80; and\n\n - add a new test that explicitly sets wider COLUMNS and makes sure you\n   get a wider diffstat graph.\n\nI haven't done this, because $COLUMNS and the actual terminal width is always\nignored in tests. There's even a test to verify that COLUMNS=200 doesn't\nmess up git format-patch output.\n\nA test to check that diff --stat responds to terminal size would be\nnice, but I don't know how to force git-diff to use the real terminal\nsize in tests.\n\nv5:\n- tests are moved to an earlier patch\n- using decimal_width(change count) is moved to a later patch\n- \"histogram\" is really not used\n\nv4:\n- comments are updated and the word \"histogram\" is banished\n- \"mopping up\" is removed (but the minimum width are guaranteed)\n\nv3:\n- use decimal_width(max_change) to calculate number of columns\n  required for change counts\n- rework the logic to divide columns\n- document the logic in comments, update docs\n- add more tests\n\nv2:\n- style fixes\n- some tests for git-format-patch added\n- patches 3 and 4 squashed together, since they touch the same lines\n- graph width is limited to 40 columns, even if there's more space\n- patch descriptions extended and cleared up\n\n\n Documentation/diff-options.txt | 14 ++++---\n diff.c                         | 88 +++++++++++++++++++++++++++------------\n 2 files changed, 69 insertions(+), 33 deletions(-)\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex 9f7cba2..36e4ee3 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -53,13 +53,15 @@ endif::git-format-patch[]\n \tGenerate a diff using the \"patience diff\" algorithm.\n \n --stat[=<width>[,<name-width>[,<count>]]]::\n-\tGenerate a diffstat.  You can override the default\n-\toutput width for 80-column terminal by `--stat=<width>`.\n-\tThe width of the filename part can be controlled by\n-\tgiving another width to it separated by a comma.\n+\tGenerate a diffstat. By default, as much space as necessary\n+\twill be used for the filename part, and up to 40 columns for\n+\tthe graph part. Maximum width defaults to terminal width,\n+\tor 80 columns if not connected to a terminal, and can be\n+\toverriden by `<width>`. The width of the filename part can be\n+\tlimited by giving another width `<name-width>` after a comma.\n \tBy giving a third parameter `<count>`, you can limit the\n-\toutput to the first `<count>` lines, followed by\n-\t`...` if there are more.\n+\toutput to the first `<count>` lines, followed by `...` if\n+\tthere are more.\n +\n These parameters can also be set individually with `--stat-width=<width>`,\n `--stat-name-width=<name-width>` and `--stat-count=<count>`.\ndiff --git a/diff.c b/diff.c\nindex 7e15426..be6d40b 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1327,7 +1327,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \tint i, len, add, del, adds = 0, dels = 0;\n \tuintmax_t max_change = 0, max_len = 0;\n \tint total_files = data->nr;\n-\tint width, name_width, count;\n+\tint width, name_width, graph_width, number_width = 4, count;\n \tconst char *reset, *add_c, *del_c;\n \tconst char *line_prefix = \"\";\n \tint extra_shown = 0;\n@@ -1341,25 +1341,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tline_prefix = msg->buf;\n \t}\n \n-\twidth = options->stat_width ? options->stat_width : 80;\n-\tname_width = options->stat_name_width ? options->stat_name_width : 50;\n \tcount = options->stat_count ? options->stat_count : data->nr;\n \n-\t/* Sanity: give at least 5 columns to the graph,\n-\t * but leave at least 10 columns for the name.\n-\t */\n-\tif (width < 25)\n-\t\twidth = 25;\n-\tif (name_width < 10)\n-\t\tname_width = 10;\n-\telse if (width < name_width + 15)\n-\t\tname_width = width - 15;\n-\n-\t/* Find the longest filename and max number of changes */\n \treset = diff_get_color_opt(options, DIFF_RESET);\n \tadd_c = diff_get_color_opt(options, DIFF_FILE_NEW);\n \tdel_c = diff_get_color_opt(options, DIFF_FILE_OLD);\n \n+\t/*\n+\t * Find the longest filename and max number of changes\n+\t */\n \tfor (i = 0; (i < count) && (i < data->nr); i++) {\n \t\tstruct diffstat_file *file = data->files[i];\n \t\tuintmax_t change = file->added + file->deleted;\n@@ -1380,19 +1370,63 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t}\n \tcount = i; /* min(count, data->nr) */\n \n-\t/* Compute the width of the graph part;\n-\t * 10 is for one blank at the beginning of the line plus\n-\t * \" | count \" between the name and the graph.\n+\t/*\n+\t * We have width = stat_width or term_columns() columns total.\n+\t * We want a maximum of min(max_len, stat_name_width) for the name part.\n+\t * We want a maximum of min(max_change, 40) for the +- part.\n+\t * We also need 1 for \" \" and 4 + decimal_width(max_change)\n+\t * for \" | NNNN \" and one the empty column at the end, altogether\n+\t * 6 + decimal_width(max_change).\n+\t *\n+\t * If there's not enough space, we will use the smaller of\n+\t * stat_name_width (if set) and 5/8*width for the filename,\n+\t * and the rest for constant elements + graph part, but no more\n+\t * than 40 for the graph part.\n+\t * (5/8 gives 50 for filename and 30 for the constant parts + graph\n+\t * for the standard terminal size).\n \t *\n-\t * From here on, name_width is the width of the name area,\n-\t * and width is the width of the graph area.\n+\t * In other words: stat_width limits the maximum width, and\n+\t * stat_name_width fixes the maximum width of the filename,\n+\t * and is also used to divide available columns if there\n+\t * aren't enough.\n \t */\n-\tname_width = (name_width < max_len) ? name_width : max_len;\n-\tif (width < (name_width + 10) + max_change)\n-\t\twidth = width - (name_width + 10);\n-\telse\n-\t\twidth = max_change;\n \n+\twidth = options->stat_width ? options->stat_width : term_columns();\n+\n+\t/*\n+\t * Guarantee 3/8*16==6 for the graph part\n+\t * and 5/8*16==10 for the filename part\n+\t */\n+\tif (width < 16 + 6 + number_width)\n+\t\twidth = 16 + 6 + number_width;\n+\n+\t/*\n+\t * First assign sizes that are wanted, ignoring available width.\n+\t */\n+\tgraph_width = max_change < 40 ? max_change : 40;\n+\tname_width = (options->stat_name_width > 0 &&\n+\t\t      options->stat_name_width < max_len) ?\n+\t\toptions->stat_name_width : max_len;\n+\n+\t/*\n+\t * Adjust adjustable widths not to exceed maximum width\n+\t */\n+\tif (name_width + number_width + 6 + graph_width > width) {\n+\t\tif (graph_width > width * 3/8 - number_width - 6)\n+\t\t\tgraph_width = width * 3/8 - number_width - 6;\n+\t\tif (graph_width > 40)\n+\t\t\tgraph_width =  40;\n+\t\tif (name_width > width - number_width - 6 - graph_width)\n+\t\t\tname_width = width - number_width - 6 - graph_width;\n+\t\telse\n+\t\t\tgraph_width = width - number_width - 6 - name_width;\n+\t}\n+\n+\t/*\n+\t * From here name_width is the width of the name area,\n+\t * and graph_width is the width of the graph area.\n+\t * max_change is used to scale graph properly.\n+\t */\n \tfor (i = 0; i < count; i++) {\n \t\tconst char *prefix = \"\";\n \t\tchar *name = data->files[i]->print_name;\n@@ -1448,9 +1482,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tadds += add;\n \t\tdels += del;\n \n-\t\tif (width <= max_change) {\n-\t\t\tadd = scale_linear(add, width, max_change);\n-\t\t\tdel = scale_linear(del, width, max_change);\n+\t\tif (graph_width <= max_change) {\n+\t\t\tadd = scale_linear(add, graph_width, max_change);\n+\t\t\tdel = scale_linear(del, graph_width, max_change);\n \t\t}\n \t\tfprintf(options->file, \"%s\", line_prefix);\n \t\tshow_name(options->file, prefix, name, len);\n-- \n1.7.9.5.g91d5\n"},{"id":"184758","messageId":"1329303808-16989-3-git-send-email-zbyszek@in.waw.pl","threadId":"29589","inReplyTo":"1329303808-16989-1-git-send-email-zbyszek@in.waw.pl","subject":"[PATCH 3/3 v5] diff --stat: use less columns for change counts","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-15T11:03:28Z","receivedAt":"2012-02-15T11:03:28Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"Number of columns required for change counts is computed based on the\nmaximum number of changed lines. This means that usually a few more\ncolumns will be available for the filenames and the graph.\n\nThe graph width logic is also modified to include enough space for\n\"Bin XXX -> YYY bytes\".\n\nIf changes to binary files are mixed with changes to text files,\nchange counts are padded to take at least three columns. And the other\nway around, if change counts require more than three columns, then\n\"Bin\"s are padded to align with the change count. This way, the +-\npart starts in the same column as \"XXX -> YYY\" part for binary files.\nThis makes the graph easier to parse visually thanks to the empty\ncolumn. This mimics the layout of diff --stat before this change.\n\nTests and the tutorial are updated to reflect the new --stat output.\nOne test for the graph alignment with a binary file change and text\nfile change of more than 999 lines is added.\n\nSigned-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>\n---\nThis is the small patch which causes big changes in output.\nIn previous version this was part of patch 1 (use the full terminal\nwidth) and whole of patches 2 (better aligment for binary files) and 3\n(update diff --stat output).\n\n Documentation/gitcore-tutorial.txt                 |  4 +-\n diff.c                                             | 44 ++++++++++++++---\n t/t0023-crlf-am.sh                                 |  2 +-\n t/t1200-tutorial.sh                                |  4 +-\n t/t3404-rebase-interactive.sh                      |  2 +-\n t/t3903-stash.sh                                   |  4 +-\n t/t4012-diff-binary.sh                             | 19 ++++++++\n ...ff-tree_--cc_--patch-with-stat_--summary_master |  4 +-\n ...diff-tree_--cc_--patch-with-stat_--summary_side |  6 +-\n .../diff.diff-tree_--cc_--patch-with-stat_master   |  4 +-\n .../diff.diff-tree_--cc_--stat_--summary_master    |  4 +-\n t/t4013/diff.diff-tree_--cc_--stat_--summary_side  |  6 +-\n t/t4013/diff.diff-tree_--cc_--stat_master          |  4 +-\n ...pretty=oneline_--root_--patch-with-stat_initial |  6 +-\n .../diff.diff-tree_--pretty_--patch-with-stat_side |  6 +-\n ...-tree_--pretty_--root_--patch-with-stat_initial |  6 +-\n ...f-tree_--pretty_--root_--stat_--summary_initial |  6 +-\n .../diff.diff-tree_--pretty_--root_--stat_initial  |  6 +-\n ...diff.diff-tree_--root_--patch-with-stat_initial |  6 +-\n t/t4013/diff.diff-tree_-c_--stat_--summary_master  |  4 +-\n t/t4013/diff.diff-tree_-c_--stat_--summary_side    |  6 +-\n t/t4013/diff.diff-tree_-c_--stat_master            |  4 +-\n .../diff.diff_--patch-with-stat_-r_initial..side   |  6 +-\n t/t4013/diff.diff_--patch-with-stat_initial..side  |  6 +-\n t/t4013/diff.diff_--stat_initial..side             |  6 +-\n t/t4013/diff.diff_-r_--stat_initial..side          |  6 +-\n ..._--attach_--stdout_--suffix=.diff_initial..side |  6 +-\n ....format-patch_--attach_--stdout_initial..master | 16 +++---\n ...format-patch_--attach_--stdout_initial..master^ | 10 ++--\n ...ff.format-patch_--attach_--stdout_initial..side |  6 +-\n ...nline_--stdout_--numbered-files_initial..master | 16 +++---\n ...tdout_--subject-prefix=TESTCASE_initial..master | 16 +++---\n ....format-patch_--inline_--stdout_initial..master | 16 +++---\n ...format-patch_--inline_--stdout_initial..master^ | 10 ++--\n ...ormat-patch_--inline_--stdout_initial..master^^ |  6 +-\n ...ff.format-patch_--inline_--stdout_initial..side |  6 +-\n ...tch_--stdout_--cover-letter_-n_initial..master^ | 18 ++++----\n ...at-patch_--stdout_--no-numbered_initial..master | 16 +++---\n ...ormat-patch_--stdout_--numbered_initial..master | 16 +++---\n t/t4013/diff.format-patch_--stdout_initial..master | 16 +++---\n .../diff.format-patch_--stdout_initial..master^    | 10 ++--\n t/t4013/diff.format-patch_--stdout_initial..side   |  6 +-\n ....log_--patch-with-stat_--summary_master_--_dir_ |  6 +-\n t/t4013/diff.log_--patch-with-stat_master          | 16 +++---\n t/t4013/diff.log_--patch-with-stat_master_--_dir_  |  6 +-\n ..._--root_--cc_--patch-with-stat_--summary_master | 26 +++++-----\n ...f.log_--root_--patch-with-stat_--summary_master | 22 ++++----\n t/t4013/diff.log_--root_--patch-with-stat_master   | 22 ++++----\n ...og_--root_-c_--patch-with-stat_--summary_master | 26 +++++-----\n t/t4013/diff.show_--patch-with-stat_--summary_side |  6 +-\n t/t4013/diff.show_--patch-with-stat_side           |  6 +-\n t/t4013/diff.show_--stat_--summary_side            |  6 +-\n t/t4013/diff.show_--stat_side                      |  6 +-\n ...nged_--patch-with-stat_--summary_master_--_dir_ |  6 +-\n t/t4013/diff.whatchanged_--patch-with-stat_master  | 16 +++---\n ...ff.whatchanged_--patch-with-stat_master_--_dir_ |  6 +-\n ..._--root_--cc_--patch-with-stat_--summary_master | 26 +++++-----\n ...anged_--root_--patch-with-stat_--summary_master | 22 ++++----\n ...iff.whatchanged_--root_--patch-with-stat_master | 22 ++++----\n ...ed_--root_-c_--patch-with-stat_--summary_master | 26 +++++-----\n t/t4014-format-patch.sh                            | 10 ++--\n t/t4016-diff-quote.sh                              | 14 +++---\n t/t4030-diff-textconv.sh                           |  2 +-\n t/t4043-diff-rename-binary.sh                      |  4 +-\n t/t4045-diff-relative.sh                           |  2 +-\n t/t4047-diff-dirstat.sh                            | 54 +++++++++++-----------\n t/t4049-diff-stat-count.sh                         |  4 +-\n t/t5100/patch0001                                  |  2 +-\n t/t5100/patch0002                                  |  2 +-\n t/t5100/patch0003                                  |  2 +-\n t/t5100/patch0005                                  |  4 +-\n t/t5100/patch0006                                  |  2 +-\n t/t5100/patch0010                                  |  2 +-\n t/t5100/patch0011                                  |  2 +-\n t/t5100/patch0014                                  |  2 +-\n t/t5100/patch0014--scissors                        |  2 +-\n t/t5100/sample.mbox                                | 18 ++++----\n t/t7602-merge-octopus-many.sh                      | 12 ++--\n 78 files changed, 415 insertions(+), 368 deletions(-)\n\ndiff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt\nindex c27d086..b781bbf 100644\n--- a/Documentation/gitcore-tutorial.txt\n+++ b/Documentation/gitcore-tutorial.txt\n@@ -1002,8 +1002,8 @@ would be different)\n ----------------\n Updating from ae3a2da... to a80b4aa....\n Fast-forward (no commit created; -m option ignored)\n- example |    1 +\n- hello   |    1 +\n+ example | 1 +\n+ hello   | 1 +\n  2 files changed, 2 insertions(+), 0 deletions(-)\n ----------------\n \ndiff --git a/diff.c b/diff.c\nindex be6d40b..dd72d35 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1326,8 +1326,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n {\n \tint i, len, add, del, adds = 0, dels = 0;\n \tuintmax_t max_change = 0, max_len = 0;\n-\tint total_files = data->nr;\n-\tint width, name_width, graph_width, number_width = 4, count;\n+\tint total_files = data->nr, count;\n+\tint width, name_width, graph_width, number_width = 0, bin_width = 0;\n \tconst char *reset, *add_c, *del_c;\n \tconst char *line_prefix = \"\";\n \tint extra_shown = 0;\n@@ -1363,8 +1363,21 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tif (max_len < len)\n \t\t\tmax_len = len;\n \n-\t\tif (file->is_binary || file->is_unmerged)\n+\t\tif (file->is_unmerged) {\n+\t\t\t/* \"Unmerged\" is 8 characters */\n+\t\t\tbin_width = bin_width < 8 ? 8 : bin_width;\n \t\t\tcontinue;\n+\t\t}\n+\t\tif (file->is_binary) {\n+\t\t\t/* \"Bin XXX -> YYY bytes\" */\n+\t\t\tint w = 14 + decimal_width(file->added)\n+\t\t\t\t+ decimal_width(file->deleted);\n+\t\t\tbin_width = bin_width < w ? w : bin_width;\n+\t\t\t/* Display change counts aligned with \"Bin\" */\n+\t\t\tnumber_width = 3;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (max_change < change)\n \t\t\tmax_change = change;\n \t}\n@@ -1389,9 +1402,19 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t * stat_name_width fixes the maximum width of the filename,\n \t * and is also used to divide available columns if there\n \t * aren't enough.\n+\t *\n+\t * Binary files are displayed with \"Bin XXX -> YYY bytes\"\n+\t * instead of the change count and graph. This part is treated\n+\t * similarly to the graph part, except that it is not\n+\t * \"scaled\". If total width is too small to accomodate the\n+\t * guaranteed minimum width of the filename part and the\n+\t * separators and this message, this message will \"overflow\"\n+\t * making the line longer than the maximum width.\n \t */\n \n \twidth = options->stat_width ? options->stat_width : term_columns();\n+\tnumber_width = decimal_width(max_change) > number_width ?\n+\t\tdecimal_width(max_change) : number_width;\n \n \t/*\n \t * Guarantee 3/8*16==6 for the graph part\n@@ -1402,8 +1425,12 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \n \t/*\n \t * First assign sizes that are wanted, ignoring available width.\n+\t * strlen(\"Bin XXX -> YYY bytes\") == bin_width, and the part\n+\t * starting from \"XXX\" should fit in graph_width.\n \t */\n-\tgraph_width = max_change < 40 ? max_change : 40;\n+\tgraph_width = max_change + 4 > bin_width ? max_change : bin_width - 4;\n+\tif (graph_width > 40)\n+\t\tgraph_width = 40;\n \tname_width = (options->stat_name_width > 0 &&\n \t\t      options->stat_name_width < max_len) ?\n \t\toptions->stat_name_width : max_len;\n@@ -1457,7 +1484,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\tif (data->files[i]->is_binary) {\n \t\t\tfprintf(options->file, \"%s\", line_prefix);\n \t\t\tshow_name(options->file, prefix, name, len);\n-\t\t\tfprintf(options->file, \"  Bin \");\n+\t\t\tfprintf(options->file, \" %*s \", number_width, \"Bin\");\n \t\t\tfprintf(options->file, \"%s%\"PRIuMAX\"%s\",\n \t\t\t\tdel_c, deleted, reset);\n \t\t\tfprintf(options->file, \" -> \");\n@@ -1470,7 +1497,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\telse if (data->files[i]->is_unmerged) {\n \t\t\tfprintf(options->file, \"%s\", line_prefix);\n \t\t\tshow_name(options->file, prefix, name, len);\n-\t\t\tfprintf(options->file, \"  Unmerged\\n\");\n+\t\t\tfprintf(options->file, \" Unmerged\\n\");\n \t\t\tcontinue;\n \t\t}\n \n@@ -1488,8 +1515,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)\n \t\t}\n \t\tfprintf(options->file, \"%s\", line_prefix);\n \t\tshow_name(options->file, prefix, name, len);\n-\t\tfprintf(options->file, \"%5\"PRIuMAX\"%s\", added + deleted,\n-\t\t\t\tadded + deleted ? \" \" : \"\");\n+\t\tfprintf(options->file, \" %*\"PRIuMAX\"%s\",\n+\t\t\tnumber_width, added + deleted,\n+\t\t\tadded + deleted ? \" \" : \"\");\n \t\tshow_graph(options->file, '+', add, add_c, reset);\n \t\tshow_graph(options->file, '-', del, del_c, reset);\n \t\tfprintf(options->file, \"\\n\");\ndiff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh\nindex aaed725..f9bbb91 100755\n--- a/t/t0023-crlf-am.sh\n+++ b/t/t0023-crlf-am.sh\n@@ -11,7 +11,7 @@ Date: Thu, 23 Aug 2007 13:00:00 +0200\n Subject: test1\n \n ---\n- foo |    1 +\n+ foo | 1 +\n  1 files changed, 1 insertions(+), 0 deletions(-)\n  create mode 100644 foo\n \ndiff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh\nindex 5e29e13..77ff21c 100755\n--- a/t/t1200-tutorial.sh\n+++ b/t/t1200-tutorial.sh\n@@ -154,8 +154,8 @@ test_expect_success 'git show-branch' '\n cat > resolve.expect << EOF\n Updating VARIABLE..VARIABLE\n FASTFORWARD (no commit created; -m option ignored)\n- example |    1 +\n- hello   |    1 +\n+ example | 1 +\n+ hello   | 1 +\n  2 files changed, 2 insertions(+), 0 deletions(-)\n EOF\n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex b981572..c8fe1a9 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -323,7 +323,7 @@ test_expect_success 'verbose flag is heeded, even after --continue' '\n \techo resolved > file1 &&\n \tgit add file1 &&\n \tgit rebase --continue > output &&\n-\tgrep \"^ file1 |    2 +-$\" output\n+\tgrep \"^ file1 | 2 +-$\" output\n '\n \n test_expect_success 'multi-squash only fires up editor once' '\ndiff --git a/t/t3903-stash.sh b/t/t3903-stash.sh\nindex dbe2ac1..fbf064e 100755\n--- a/t/t3903-stash.sh\n+++ b/t/t3903-stash.sh\n@@ -443,7 +443,7 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' '\n \tSTASH_ID=$(git stash create) &&\n \tgit reset --hard &&\n \tcat >expected <<-EOF &&\n-\t file |    1 +\n+\t file | 1 +\n \t 1 files changed, 1 insertions(+), 0 deletions(-)\n \tEOF\n \tgit stash show ${STASH_ID} >actual &&\n@@ -481,7 +481,7 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' '\n \tSTASH_ID=$(git stash create) &&\n \tgit reset --hard &&\n \tcat >expected <<-EOF &&\n-\t file |    1 +\n+\t file | 1 +\n \t 1 files changed, 1 insertions(+), 0 deletions(-)\n \tEOF\n \tgit stash show ${STASH_ID} >actual &&\ndiff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh\nindex 2d9f9a0..9dd48bb 100755\n--- a/t/t4012-diff-binary.sh\n+++ b/t/t4012-diff-binary.sh\n@@ -90,4 +90,23 @@ test_expect_success 'diff --no-index with binary creation' '\n \ttest_cmp expected actual\n '\n \n+cat >expect <<EOF\n+ binfile  |   Bin 0 -> 1026 bytes\n+ textfile | 10000 ++++++++++++++++++++++++++++++++++++++++\n+EOF\n+\n+test_expect_success 'diff --stat with binary files and big change count' '\n+\techo X | dd of=binfile bs=1k seek=1 &&\n+\tgit add binfile &&\n+\ti=0 &&\n+\twhile test $i -lt 10000; do\n+\t\techo $i &&\n+\t\ti=$(($i + 1))\n+\tdone >textfile &&\n+\tgit add textfile &&\n+\tgit diff --cached --stat binfile textfile >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master\nindex 3a9f78a..b87f758 100644\n--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master\n@@ -1,7 +1,7 @@\n $ git diff-tree --cc --patch-with-stat --summary master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side\nindex a61ad8c..47665f9 100644\n--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side\n+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side\n@@ -1,8 +1,8 @@\n $ git diff-tree --cc --patch-with-stat --summary side\n c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master\nindex 49f23b9..efe6dcc 100644\n--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master\n+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master\n@@ -1,7 +1,7 @@\n $ git diff-tree --cc --patch-with-stat master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master\nindex cc6eb3b..1b465f0 100644\n--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master\n+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master\n@@ -1,6 +1,6 @@\n $ git diff-tree --cc --stat --summary master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side\nindex 50362be..44fcf4e 100644\n--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side\n+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side\n@@ -1,8 +1,8 @@\n $ git diff-tree --cc --stat --summary side\n c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n $\ndiff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_master\nindex fae7f33..6dffb7f 100644\n--- a/t/t4013/diff.diff-tree_--cc_--stat_master\n+++ b/t/t4013/diff.diff-tree_--cc_--stat_master\n@@ -1,6 +1,6 @@\n $ git diff-tree --cc --stat master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial\nindex d5c333a..a7d91c9 100644\n--- a/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial\n+++ b/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial\n@@ -1,8 +1,8 @@\n $ git diff-tree --pretty=oneline --root --patch-with-stat initial\n 444ac553ac7612cc88969031b02b3767fb8a353a Initial\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side\nindex 4d30e7e..2061f37 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side\n+++ b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial\nindex 7dfa6af..71d912e 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial\nindex 43bfce2..b80dbcc 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial\nindex 9154aa4..88cb5c9 100644\n--- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial\n+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial\n@@ -5,8 +5,8 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial\nindex 1562b62..748ba93 100644\n--- a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial\n+++ b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial\n@@ -1,8 +1,8 @@\n $ git diff-tree --root --patch-with-stat initial\n 444ac553ac7612cc88969031b02b3767fb8a353a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_master\nindex ac9f641..700c386 100644\n--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master\n+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_master\n@@ -1,6 +1,6 @@\n $ git diff-tree -c --stat --summary master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_side b/t/t4013/diff.diff-tree_-c_--stat_--summary_side\nindex 2afcca1..520aa4f 100644\n--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_side\n+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_side\n@@ -1,8 +1,8 @@\n $ git diff-tree -c --stat --summary side\n c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n $\ndiff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_master\nindex c2fe6a9..cdc7c40 100644\n--- a/t/t4013/diff.diff-tree_-c_--stat_master\n+++ b/t/t4013/diff.diff-tree_-c_--stat_master\n@@ -1,6 +1,6 @@\n $ git diff-tree -c --stat master\n 59d314ad6f356dd08601a4cd5e530381da3e3c64\n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side\nindex 9ed317a..abf43a9 100644\n--- a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side\n+++ b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side\n@@ -1,7 +1,7 @@\n $ git diff --patch-with-stat -r initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff_--patch-with-stat_initial..side b/t/t4013/diff.diff_--patch-with-stat_initial..side\nindex 8b50629..f88262e 100644\n--- a/t/t4013/diff.diff_--patch-with-stat_initial..side\n+++ b/t/t4013/diff.diff_--patch-with-stat_initial..side\n@@ -1,7 +1,7 @@\n $ git diff --patch-with-stat initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.diff_--stat_initial..side b/t/t4013/diff.diff_--stat_initial..side\nindex 0517b5d..17a07be 100644\n--- a/t/t4013/diff.diff_--stat_initial..side\n+++ b/t/t4013/diff.diff_--stat_initial..side\n@@ -1,6 +1,6 @@\n $ git diff --stat initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.diff_-r_--stat_initial..side b/t/t4013/diff.diff_-r_--stat_initial..side\nindex 245220d..54507eb 100644\n--- a/t/t4013/diff.diff_-r_--stat_initial..side\n+++ b/t/t4013/diff.diff_-r_--stat_initial..side\n@@ -1,6 +1,6 @@\n $ git diff -r --stat initial..side\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\nindex 52116d3..6996877 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n@@ -12,9 +12,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\nindex ce49bd6..d56a1a3 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\nindex 5f1b238..b76e61f 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\nindex 4a2364a..769cf32 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n@@ -12,9 +12,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\nindex 43b81eb..0ee7338 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\nindex ca3f60b..fbf3bd4 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\nindex 08f2301..d68e3ee 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -121,9 +121,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\nindex 07f1230..668e38f 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\nindex 29e00ab..caec553 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n@@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\nindex 67633d4..6b84b1b 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n@@ -12,9 +12,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed\n Content-Transfer-Encoding: 8bit\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\nindex 3b4e113..d8cba57 100644\n--- a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\n+++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\n@@ -10,10 +10,10 @@ A U Thor (2):\n   Second\n   Third\n \n- dir/sub |    4 ++++\n- file0   |    3 +++\n- file1   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 4 ++++\n+ file0   | 3 +++\n+ file1   | 3 +++\n+ file2   | 3 ---\n  4 files changed, 10 insertions(+), 3 deletions(-)\n  create mode 100644 file1\n  delete mode 100644 file2\n@@ -28,9 +28,9 @@ Subject: [DIFFERENT_PREFIX 1/2] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -73,8 +73,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [DIFFERENT_PREFIX 2/2] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master\nindex f7752eb..a2a4726 100644\n--- a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master\n+++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master\n@@ -6,9 +6,9 @@ Subject: [PATCH] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -85,9 +85,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master\nindex 8e67dbf..602f4b0 100644\n--- a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master\n+++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master\n@@ -6,9 +6,9 @@ Subject: [PATCH 1/3] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH 2/3] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -85,9 +85,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH 3/3] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..master\nindex 7b89978..bcf739e 100644\n--- a/t/t4013/diff.format-patch_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--stdout_initial..master\n@@ -6,9 +6,9 @@ Subject: [PATCH 1/3] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH 2/3] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -85,9 +85,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH 3/3] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..master^\nindex b7f9725..7d5ba0f 100644\n--- a/t/t4013/diff.format-patch_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--stdout_initial..master^\n@@ -6,9 +6,9 @@ Subject: [PATCH 1/2] Second\n \n This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -51,8 +51,8 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000\n Subject: [PATCH 2/2] Third\n \n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_initial..side b/t/t4013/diff.format-patch_--stdout_initial..side\nindex e765088..9ed0ea2 100644\n--- a/t/t4013/diff.format-patch_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--stdout_initial..side\n@@ -5,9 +5,9 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000\n Subject: [PATCH] Side\n \n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_\nindex bd7f5c0..e2954d3 100644\n--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_\n+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_\n@@ -12,7 +12,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -31,7 +31,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -53,7 +53,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master\nindex 14595a6..e417873 100644\n--- a/t/t4013/diff.log_--patch-with-stat_master\n+++ b/t/t4013/diff.log_--patch-with-stat_master\n@@ -12,9 +12,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -54,8 +54,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -86,9 +86,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_\nindex 5a4e727..cebec52 100644\n--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_\n+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_\n@@ -12,7 +12,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -31,7 +31,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -53,7 +53,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master\nindex df0aaa9..540633f 100644\n--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master\nindex c11b5f2c..fb289d8 100644\n--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master\n@@ -12,9 +12,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -55,8 +55,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -88,9 +88,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -130,9 +130,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master\nindex 5f0c98f..84f535d 100644\n--- a/t/t4013/diff.log_--root_--patch-with-stat_master\n+++ b/t/t4013/diff.log_--root_--patch-with-stat_master\n@@ -12,9 +12,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -54,8 +54,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -86,9 +86,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -127,9 +127,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master\nindex e62c368..3e89ace 100644\n--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --combined dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.show_--patch-with-stat_--summary_side b/t/t4013/diff.show_--patch-with-stat_--summary_side\nindex 377f2b7..38c1841 100644\n--- a/t/t4013/diff.show_--patch-with-stat_--summary_side\n+++ b/t/t4013/diff.show_--patch-with-stat_--summary_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \ndiff --git a/t/t4013/diff.show_--patch-with-stat_side b/t/t4013/diff.show_--patch-with-stat_side\nindex fb14c53..38f6be2 100644\n--- a/t/t4013/diff.show_--patch-with-stat_side\n+++ b/t/t4013/diff.show_--patch-with-stat_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.show_--stat_--summary_side b/t/t4013/diff.show_--stat_--summary_side\nindex 5bd5977..e6f30a4 100644\n--- a/t/t4013/diff.show_--stat_--summary_side\n+++ b/t/t4013/diff.show_--stat_--summary_side\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n $\ndiff --git a/t/t4013/diff.show_--stat_side b/t/t4013/diff.show_--stat_side\nindex 3b22327..58ee49a 100644\n--- a/t/t4013/diff.show_--stat_side\n+++ b/t/t4013/diff.show_--stat_side\n@@ -5,8 +5,8 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n $\ndiff --git a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_\nindex 6a467cc..ee340b8 100644\n--- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_\n+++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_\n@@ -5,7 +5,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -24,7 +24,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -46,7 +46,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master b/t/t4013/diff.whatchanged_--patch-with-stat_master\nindex 1e1bbe1..4adeab7 100644\n--- a/t/t4013/diff.whatchanged_--patch-with-stat_master\n+++ b/t/t4013/diff.whatchanged_--patch-with-stat_master\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -47,8 +47,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -79,9 +79,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_\nindex 13789f1..63a3043 100644\n--- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_\n+++ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_\n@@ -5,7 +5,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -24,7 +24,7 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -46,7 +46,7 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n+ dir/sub | 2 ++\n  1 files changed, 2 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master\nindex e96ff1f..60f3788 100644\n--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --cc dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master\nindex 0291153..9b7f63f 100644\n--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -48,8 +48,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -81,9 +81,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -123,9 +123,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master\nindex 9b0349c..cba8f3c 100644\n--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master\n+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master\n@@ -5,9 +5,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -47,8 +47,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -79,9 +79,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n \n diff --git a/dir/sub b/dir/sub\ndiff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master\nindex c0aff68..8e24293 100644\n--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master\n+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master\n@@ -6,8 +6,8 @@ Date:   Mon Jun 26 00:04:00 2006 +0000\n \n     Merge branch 'side'\n \n- dir/sub |    2 ++\n- file0   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n \n diff --combined dir/sub\n@@ -44,9 +44,9 @@ Date:   Mon Jun 26 00:03:00 2006 +0000\n \n     Side\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file3   |    4 ++++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file3   | 4 ++++\n  3 files changed, 9 insertions(+), 0 deletions(-)\n  create mode 100644 file3\n \n@@ -87,8 +87,8 @@ Date:   Mon Jun 26 00:02:00 2006 +0000\n \n     Third\n ---\n- dir/sub |    2 ++\n- file1   |    3 +++\n+ dir/sub | 2 ++\n+ file1   | 3 +++\n  2 files changed, 5 insertions(+), 0 deletions(-)\n  create mode 100644 file1\n \n@@ -120,9 +120,9 @@ Date:   Mon Jun 26 00:01:00 2006 +0000\n     \n     This is the second commit.\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 ---\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 ---\n  3 files changed, 5 insertions(+), 3 deletions(-)\n  delete mode 100644 file2\n \n@@ -162,9 +162,9 @@ Date:   Mon Jun 26 00:00:00 2006 +0000\n \n     Initial\n ---\n- dir/sub |    2 ++\n- file0   |    3 +++\n- file2   |    3 +++\n+ dir/sub | 2 ++\n+ file0   | 3 +++\n+ file2   | 3 +++\n  3 files changed, 8 insertions(+), 0 deletions(-)\n  create mode 100644 dir/sub\n  create mode 100644 file0\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex f6ebb51..bb430ac 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -519,7 +519,7 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \n cat > expect << EOF\n ---\n- file |   16 ++++++++++++++++\n+ file | 16 ++++++++++++++++\n  1 files changed, 16 insertions(+), 0 deletions(-)\n \n diff --git a/file b/file\n@@ -906,7 +906,7 @@ test_expect_success 'preparation' \"\n \"\n \n cat >expect <<'EOF'\n- ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n EOF\n test_expect_success 'format patch graph width defaults to 80 columns' '\n \tgit format-patch --stat --stdout -1 >output &&\n@@ -915,7 +915,7 @@ test_expect_success 'format patch graph width defaults to 80 columns' '\n '\n \n cat >expect <<'EOF'\n- ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +\n EOF\n test_expect_success 'format patch --stat=width with long name' '\n \tgit format-patch --stat=40 --stdout -1 >output &&\n@@ -930,13 +930,13 @@ test_expect_success 'format patch --stat-width=width works with long name' '\n '\n \n test_expect_success 'format patch --stat=...,name-width with long name' '\n-\tgit format-patch --stat=60,29 --stdout -1 >output &&\n+\tgit format-patch --stat=60,32 --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'format patch --stat-name-width with long name' '\n-\tgit format-patch --stat-name-width=29 --stdout -1 >output &&\n+\tgit format-patch --stat-name-width=32 --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n '\ndiff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh\nindex ab0c2f0..e451f2a 100755\n--- a/t/t4016-diff-quote.sh\n+++ b/t/t4016-diff-quote.sh\n@@ -59,13 +59,13 @@ test_expect_success TABS_IN_FILENAMES 'git diff --summary -M HEAD' '\n \n test_expect_success TABS_IN_FILENAMES 'setup expected files' '\n cat >expect <<\\EOF\n- pathname.1 => \"Rpathname\\twith HT.0\"            |    0\n- pathname.3 => \"Rpathname\\nwith LF.0\"            |    0\n- \"pathname\\twith HT.3\" => \"Rpathname\\nwith LF.1\" |    0\n- pathname.2 => Rpathname with SP.0               |    0\n- \"pathname\\twith HT.2\" => Rpathname with SP.1    |    0\n- pathname.0 => Rpathname.0                       |    0\n- \"pathname\\twith HT.0\" => Rpathname.1            |    0\n+ pathname.1 => \"Rpathname\\twith HT.0\"            | 0\n+ pathname.3 => \"Rpathname\\nwith LF.0\"            | 0\n+ \"pathname\\twith HT.3\" => \"Rpathname\\nwith LF.1\" | 0\n+ pathname.2 => Rpathname with SP.0               | 0\n+ \"pathname\\twith HT.2\" => Rpathname with SP.1    | 0\n+ pathname.0 => Rpathname.0                       | 0\n+ \"pathname\\twith HT.0\" => Rpathname.1            | 0\n  7 files changed, 0 insertions(+), 0 deletions(-)\n EOF\n '\ndiff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh\nindex 88c5619..6a6344c 100755\n--- a/t/t4030-diff-textconv.sh\n+++ b/t/t4030-diff-textconv.sh\n@@ -85,7 +85,7 @@ test_expect_success 'status -v produces text' '\n '\n \n cat >expect.stat <<'EOF'\n- file |  Bin 2 -> 4 bytes\n+ file | Bin 2 -> 4 bytes\n  1 files changed, 0 insertions(+), 0 deletions(-)\n EOF\n test_expect_success 'diffstat does not run textconv' '\ndiff --git a/t/t4043-diff-rename-binary.sh b/t/t4043-diff-rename-binary.sh\nindex 0601281..ad0b2da 100755\n--- a/t/t4043-diff-rename-binary.sh\n+++ b/t/t4043-diff-rename-binary.sh\n@@ -23,8 +23,8 @@ test_expect_success 'move the files into a \"sub\" directory' '\n '\n \n cat > expected <<\\EOF\n- bar => sub/bar |  Bin 5 -> 5 bytes\n- foo => sub/foo |    0\n+ bar => sub/bar | Bin 5 -> 5 bytes\n+ foo => sub/foo |   0\n  2 files changed, 0 insertions(+), 0 deletions(-)\n \n diff --git a/bar b/sub/bar\ndiff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh\nindex 8a3c63b..336df82 100755\n--- a/t/t4045-diff-relative.sh\n+++ b/t/t4045-diff-relative.sh\n@@ -32,7 +32,7 @@ test_expect_success \"-p $*\" \"\n check_stat() {\n expect=$1; shift\n cat >expected <<EOF\n- $expect |    1 +\n+ $expect | 1 +\n  1 files changed, 1 insertions(+), 0 deletions(-)\n EOF\n test_expect_success \"--stat $*\" \"\ndiff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh\nindex 29e80a5..75eaf16 100755\n--- a/t/t4047-diff-dirstat.sh\n+++ b/t/t4047-diff-dirstat.sh\n@@ -252,41 +252,41 @@ EOF\n '\n \n cat <<EOF >expect_diff_stat\n- changed/text             |    2 +-\n- dst/copy/changed/text    |   10 ++++++++++\n- dst/copy/rearranged/text |   10 ++++++++++\n- dst/copy/unchanged/text  |   10 ++++++++++\n- dst/move/changed/text    |   10 ++++++++++\n- dst/move/rearranged/text |   10 ++++++++++\n- dst/move/unchanged/text  |   10 ++++++++++\n- rearranged/text          |    2 +-\n- src/move/changed/text    |   10 ----------\n- src/move/rearranged/text |   10 ----------\n- src/move/unchanged/text  |   10 ----------\n+ changed/text             |  2 +-\n+ dst/copy/changed/text    | 10 ++++++++++\n+ dst/copy/rearranged/text | 10 ++++++++++\n+ dst/copy/unchanged/text  | 10 ++++++++++\n+ dst/move/changed/text    | 10 ++++++++++\n+ dst/move/rearranged/text | 10 ++++++++++\n+ dst/move/unchanged/text  | 10 ++++++++++\n+ rearranged/text          |  2 +-\n+ src/move/changed/text    | 10 ----------\n+ src/move/rearranged/text | 10 ----------\n+ src/move/unchanged/text  | 10 ----------\n  11 files changed, 62 insertions(+), 32 deletions(-)\n EOF\n \n cat <<EOF >expect_diff_stat_M\n- changed/text                      |    2 +-\n- dst/copy/changed/text             |   10 ++++++++++\n- dst/copy/rearranged/text          |   10 ++++++++++\n- dst/copy/unchanged/text           |   10 ++++++++++\n- {src => dst}/move/changed/text    |    2 +-\n- {src => dst}/move/rearranged/text |    2 +-\n- {src => dst}/move/unchanged/text  |    0\n- rearranged/text                   |    2 +-\n+ changed/text                      |  2 +-\n+ dst/copy/changed/text             | 10 ++++++++++\n+ dst/copy/rearranged/text          | 10 ++++++++++\n+ dst/copy/unchanged/text           | 10 ++++++++++\n+ {src => dst}/move/changed/text    |  2 +-\n+ {src => dst}/move/rearranged/text |  2 +-\n+ {src => dst}/move/unchanged/text  |  0\n+ rearranged/text                   |  2 +-\n  8 files changed, 34 insertions(+), 4 deletions(-)\n EOF\n \n cat <<EOF >expect_diff_stat_CC\n- changed/text                      |    2 +-\n- {src => dst}/copy/changed/text    |    2 +-\n- {src => dst}/copy/rearranged/text |    2 +-\n- {src => dst}/copy/unchanged/text  |    0\n- {src => dst}/move/changed/text    |    2 +-\n- {src => dst}/move/rearranged/text |    2 +-\n- {src => dst}/move/unchanged/text  |    0\n- rearranged/text                   |    2 +-\n+ changed/text                      | 2 +-\n+ {src => dst}/copy/changed/text    | 2 +-\n+ {src => dst}/copy/rearranged/text | 2 +-\n+ {src => dst}/copy/unchanged/text  | 0\n+ {src => dst}/move/changed/text    | 2 +-\n+ {src => dst}/move/rearranged/text | 2 +-\n+ {src => dst}/move/unchanged/text  | 0\n+ rearranged/text                   | 2 +-\n  8 files changed, 6 insertions(+), 6 deletions(-)\n EOF\n \ndiff --git a/t/t4049-diff-stat-count.sh b/t/t4049-diff-stat-count.sh\nindex 641e70d..5edac4e 100755\n--- a/t/t4049-diff-stat-count.sh\n+++ b/t/t4049-diff-stat-count.sh\n@@ -14,8 +14,8 @@ test_expect_success setup '\n \techo a >a &&\n \techo b >b &&\n \tcat >expect <<-\\EOF\n-\t a |    1 +\n-\t b |    1 +\n+\t a | 1 +\n+\t b | 1 +\n \t 2 files changed, 2 insertions(+), 0 deletions(-)\n \tEOF\n \tgit diff --stat --stat-count=2 >actual &&\ndiff --git a/t/t5100/patch0001 b/t/t5100/patch0001\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0001\n+++ b/t/t5100/patch0001\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0002 b/t/t5100/patch0002\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0002\n+++ b/t/t5100/patch0002\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0003 b/t/t5100/patch0003\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0003\n+++ b/t/t5100/patch0003\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0005 b/t/t5100/patch0005\nindex 7d24b24..ab7a383 100644\n--- a/t/t5100/patch0005\n+++ b/t/t5100/patch0005\n@@ -1,7 +1,7 @@\n ---\n \n- Documentation/git-cvsimport-script.txt |    9 ++++++++-\n- git-cvsimport-script                   |    4 ++--\n+ Documentation/git-cvsimport-script.txt | 9 ++++++++-\n+ git-cvsimport-script                   | 4 ++--\n  2 files changed, 10 insertions(+), 3 deletions(-)\n \n 50452f9c0c2df1f04d83a26266ba704b13861632\ndiff --git a/t/t5100/patch0006 b/t/t5100/patch0006\nindex 8ce1551..02c9774 100644\n--- a/t/t5100/patch0006\n+++ b/t/t5100/patch0006\n@@ -1,5 +1,5 @@\n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\ndiff --git a/t/t5100/patch0010 b/t/t5100/patch0010\nindex f055481..436821c 100644\n--- a/t/t5100/patch0010\n+++ b/t/t5100/patch0010\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c |    2 +-\n+ builtin-mailinfo.c | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t5100/patch0011 b/t/t5100/patch0011\nindex 8841d3c..0988713 100644\n--- a/t/t5100/patch0011\n+++ b/t/t5100/patch0011\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c  |    4 ++--\n+ builtin-mailinfo.c  | 4 ++--\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\n index 3e5fe51..aabfe5c 100644\ndiff --git a/t/t5100/patch0014 b/t/t5100/patch0014\nindex 124efd2..3f3825f 100644\n--- a/t/t5100/patch0014\n+++ b/t/t5100/patch0014\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++++-\n+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-\n  1 files changed, 36 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t5100/patch0014--scissors b/t/t5100/patch0014--scissors\nindex 124efd2..3f3825f 100644\n--- a/t/t5100/patch0014--scissors\n+++ b/t/t5100/patch0014--scissors\n@@ -1,5 +1,5 @@\n ---\n- builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++++-\n+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-\n  1 files changed, 36 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox\nindex de10312..34a09a0 100644\n--- a/t/t5100/sample.mbox\n+++ b/t/t5100/sample.mbox\n@@ -12,7 +12,7 @@ Subject: [PATCH] a commit.\n Here is a patch from A U Thor.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -52,7 +52,7 @@ two truly blank and another full of spaces in between.\n Hope this helps.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -83,7 +83,7 @@ Message-Id: <nitpicker.12121212@example.net>\n Hopefully this would fix the problem stated there.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -249,8 +249,8 @@ actual flags.\n Signed-off-by: David K=E5gedal <davidk@lysator.liu.se>\n ---\n \n- Documentation/git-cvsimport-script.txt |    9 ++++++++-\n- git-cvsimport-script                   |    4 ++--\n+ Documentation/git-cvsimport-script.txt | 9 ++++++++-\n+ git-cvsimport-script                   | 4 ++--\n  2 files changed, 10 insertions(+), 3 deletions(-)\n \n 50452f9c0c2df1f04d83a26266ba704b13861632\n@@ -379,7 +379,7 @@ Subject: [PATCH] a commit.\n Here is a patch from A U Thor.\n \n ---\n- foo |    2 +-\n+ foo | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/foo b/foo\n@@ -449,7 +449,7 @@ memcmp(\"Subject: \", header[i], 7) will never match.\n Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n Signed-off-by: Junio C Hamano <gitster@pobox.com>\n ---\n- builtin-mailinfo.c |    2 +-\n+ builtin-mailinfo.c | 2 +-\n  1 files changed, 1 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\n@@ -482,7 +482,7 @@ Content-Transfer-Encoding: quoted-printable\n Here comes a commit log message, and\n its second line is here.\n ---\n- builtin-mailinfo.c  |    4 ++--\n+ builtin-mailinfo.c  | 4 ++--\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\n index 3e5fe51..aabfe5c 100644\n@@ -587,7 +587,7 @@ everything before it in the message body.\n \n Signed-off-by: Junio C Hamano <gitster@pobox.com>\n ---\n- builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++++-\n+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-\n  1 files changed, 36 insertions(+), 1 deletions(-)\n \n diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\ndiff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh\nindex 61f36ba..5a86e24 100755\n--- a/t/t7602-merge-octopus-many.sh\n+++ b/t/t7602-merge-octopus-many.sh\n@@ -54,9 +54,9 @@ Trying simple merge with c2\n Trying simple merge with c3\n Trying simple merge with c4\n Merge made by the 'octopus' strategy.\n- c2.c |    1 +\n- c3.c |    1 +\n- c4.c |    1 +\n+ c2.c | 1 +\n+ c3.c | 1 +\n+ c4.c | 1 +\n  3 files changed, 3 insertions(+), 0 deletions(-)\n  create mode 100644 c2.c\n  create mode 100644 c3.c\n@@ -73,7 +73,7 @@ cat >expected <<\\EOF\n Already up-to-date with c4\n Trying simple merge with c5\n Merge made by the 'octopus' strategy.\n- c5.c |    1 +\n+ c5.c | 1 +\n  1 files changed, 1 insertions(+), 0 deletions(-)\n  create mode 100644 c5.c\n EOF\n@@ -87,8 +87,8 @@ cat >expected <<\\EOF\n Fast-forwarding to: c1\n Trying simple merge with c2\n Merge made by the 'octopus' strategy.\n- c1.c |    1 +\n- c2.c |    1 +\n+ c1.c | 1 +\n+ c2.c | 1 +\n  2 files changed, 2 insertions(+), 0 deletions(-)\n  create mode 100644 c1.c\n  create mode 100644 c2.c\n-- \n1.7.9.5.g91d5\n"},{"id":"184759","messageId":"CACsJy8D4sWm8iprprbjU7X5RyPE4fbqiU2f70idByRmpkh70wA@mail.gmail.com","threadId":"29589","inReplyTo":"1329303808-16989-3-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 3/3 v5] diff --stat: use less columns for change counts","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-02-15T12:12:20Z","receivedAt":"2012-02-15T12:12:20Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2012/2/15 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>:\n> Number of columns required for change counts is computed based on the\n> maximum number of changed lines. This means that usually a few more\n> columns will be available for the filenames and the graph.\n\nIf the required number of columns is less than 80 (or even lower), can\nwe maintain current spacing strategy? I just want to avoid mass\nupdates in the test suite. More or less space does not make much\ndifferent for narrow diffstats anyway.\n-- \nDuy\n"},{"id":"184770","messageId":"7vvcn810ml.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329303808-16989-1-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 1/3 v5] diff --stat: tests for long filenames and big change counts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-15T17:12:50Z","receivedAt":"2012-02-15T17:12:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Eleven tests for various combinations of a long filename and/or big\n> change count and ways to specify widths for diff --stat.\n> ---\n\nSign-off? \n\n> Tests added in previous version of 'diff --stat: use full terminal width'\n> are extracted into a separate patch. The tests are usefull independently\n> of that patch anyway.\n\nThanks.\n\n> +# 120 character name\n> +name=aaaaaaaaaa\n> +name=$name$name$name$name$name$name$name$name$name$name$name$name\n> +test_expect_success 'preparation' \"\n> +\t>\\\"$name\\\" &&\n> +\tgit add \\\"$name\\\" &&\n> +\tgit commit -m message &&\n> +\techo a >\\\"$name\\\" &&\n> +\tgit commit -m message \\\"$name\\\"\n> +\"\n\nJust for future reference.\n\nThe last parameter to test_expect_success shell function is `eval`ed by\nthe shell and $name is visible inside it; you do not have to use double\nquote around it and then use backquote to quote the inner double quote.\n\n> +cat >expect <<'EOF'\n> + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n> +EOF\n> +test_expect_success 'format patch graph width defaults to 80 columns' '\n> +\tgit format-patch --stat --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nHrm, this does not seem to pass, making the result of applying [1/3] fail;\nI see that the elided name is shown much shorter than the above expects.\n\nPerhaps this test found a bug in a \"very long name, small changes\" corner\ncase?  If that is the case, we'd mark it as test_expect_failure, and\nexplain the tests that expect failure demonstrates a buggy behaviour, e.g.\n\n\tWhen a pathname is so long that it cannot fit on the column, the\n\tcurrent code truncates it to make sure that the graph part has at\n\tleast N columns (enough room to show a meaningful graph).  If the\n\tactual change is small (e.g. only one line changed), this results\n\tin the final output that is shorter than the width we aim for.  A\n\tcouple of new tests marked with test_expect_failure demonstrate\n\tthis bug.\n\nin the log message (note that I am not sure if that is the nature of the\nbug, or what the actual value of N is).\n\nAnd then a later patch [2/3] that updates the allocation between name and\ngraph will turn test_expect_failure to test_expect_success; that will make\nit clear that your update fixed the bug.\n\n> +cat >expect <<'EOF'\n> + ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n> +EOF\n> +test_expect_success 'format patch --stat=width with long name' '\n> +\tgit format-patch --stat=40 --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nLikewise.\n\n> +test_expect_success 'format patch --stat-width=width works with long name' '\n> +\tgit format-patch --stat-width=40 --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nLikewise.\n\n> +test_expect_success 'format patch --stat=...,name-width with long name' '\n> +\tgit format-patch --stat=60,29 --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n> +test_expect_success 'format patch --stat-name-width with long name' '\n> +\tgit format-patch --stat-name-width=29 --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nLikewise.\n\n> +test_expect_success 'preparation' '\n\nThere was another \"preparation\" in this script already, which originally\nthrew me off while chasing which part of the test is failing. Can you\nreword/retitle this one?\n\n> +cat >expect <<'EOF'\n> + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n> +EOF\n> +test_expect_success 'format patch graph part width is 40 columns' '\n> +\tgit format-patch --stat --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nThis test shouldn't be added in [1/3] because \"cap the graph to 40-col\" is\na new feature that is introduced in the later step.\n\n> +test_expect_success 'format patch ignores COLUMNS' '\n> +\tCOLUMNS=200 git format-patch --stat --stdout -1 >output\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nThis is a good test to have in [1/3], but the expectation should not cap the\ngraph part to 40 columns.  The patch that updates diff.c to implement the\ncap in [2/3] should have an update to the expectation, whose diff hunk may\nlook liks this:\n\n@@ \n cat >expect <<'EOF'\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n- abcd | 1000 ++++++++++++++++++++++++++++++++++++++++ \n EOF\n\nThat would make the effect of the patch clearer.\n\n> +cat >expect <<'EOF'\n> + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++\n> +EOF\n> +test_expect_success 'format patch --stat=width with big change and long name' '\n> +\tcp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n> +\tgit add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n> +\tgit commit -m message &&\n> +\tgit format-patch --stat-width=60 --stdout -1 >output &&\n> +\tgrep \" | \" output >actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_done\n\nThe same comment as the previous one.  Because you change the allocation\nto the graph part in your patch to diff.c, which hasn't happened in [1/3]\nyet, this should expect the existing behaviour (narrower graph) in this\nstep, and then be updated to expect the output shown above in the [2/3]\npatch that changes the implementation in diff.c.\n"},{"id":"184772","messageId":"7vobt00znp.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"7vvcn810ml.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/3 v5] diff --stat: tests for long filenames and big change counts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-15T17:33:46Z","receivedAt":"2012-02-15T17:33:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n>\n>> Eleven tests for various combinations of a long filename and/or big\n>> change count and ways to specify widths for diff --stat.\n>> ---\n>\n> Sign-off? \n> ...\n> The same comment as the previous one.  Because you change the allocation\n> to the graph part in your patch to diff.c, which hasn't happened in [1/3]\n> yet, this should expect the existing behaviour (narrower graph) in this\n> step, and then be updated to expect the output shown above in the [2/3]\n> patch that changes the implementation in diff.c.\n\nThe previous review message in a patch form that can be squashed on top of\nthis patch.\n\n-- >8 --\nSubject: [PATCH] (squash to the previous -- replace the log message with this)\n\ndiff --stat: tests for long filenames and big change counts\n\nIn preparation for updates to the \"diff --stat\" that updates the logic\nto split the allotted columns into the name part and the graph part to\nmake the output more readable, add a handful of tests to document the\ncorner case behaviour in which long filenames and big changes are shown.\n\nWhen a pathname is so long that it cannot fit on the column, the current\ncode truncates it to make sure that the graph part has enough room to show\na meaningful graph.  If the actual change is small (e.g. only one line\nchanged), this results in the final output that is shorter than the width\nwe aim for.  A couple of new tests marked with test_expect_failure\ndemonstrate this bug.\n\n---\n t/t4014-format-patch.sh |   35 +++++++++++++++--------------------\n 1 file changed, 15 insertions(+), 20 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex f6ebb51..0376186 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -897,18 +897,18 @@ test_expect_success 'format patch ignores color.ui' '\n # 120 character name\n name=aaaaaaaaaa\n name=$name$name$name$name$name$name$name$name$name$name$name$name\n-test_expect_success 'preparation' \"\n-\t>\\\"$name\\\" &&\n-\tgit add \\\"$name\\\" &&\n+test_expect_success 'preparation' '\n+\t>\"$name\" &&\n+\tgit add \"$name\" &&\n \tgit commit -m message &&\n-\techo a >\\\"$name\\\" &&\n-\tgit commit -m message \\\"$name\\\"\n-\"\n+\techo a >\"$name\" &&\n+\tgit commit -m message \"$name\"\n+'\n \n cat >expect <<'EOF'\n  ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n EOF\n-test_expect_success 'format patch graph width defaults to 80 columns' '\n+test_expect_failure 'format patch graph width defaults to 80 columns' '\n \tgit format-patch --stat --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n@@ -917,13 +917,13 @@ test_expect_success 'format patch graph width defaults to 80 columns' '\n cat >expect <<'EOF'\n  ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n EOF\n-test_expect_success 'format patch --stat=width with long name' '\n+test_expect_failure 'format patch --stat=width with long name' '\n \tgit format-patch --stat=40 --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'format patch --stat-width=width works with long name' '\n+test_expect_failure 'format patch --stat-width=width works with long name' '\n \tgit format-patch --stat-width=40 --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n@@ -941,26 +941,21 @@ test_expect_success 'format patch --stat-name-width with long name' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'preparation' '\n+test_expect_success 'preparation for big change tests' '\n \t>abcd &&\n \tgit add abcd &&\n \tgit commit -m message &&\n \ti=0 &&\n-\twhile test $i -lt 1000; do\n-\t\techo $i &&\n-\t\ti=$(($i + 1))\n+\twhile test $i -lt 1000\n+\tdo\n+\t\techo $i && i=$(($i + 1))\n \tdone >abcd &&\n \tgit commit -m message abcd\n '\n \n cat >expect <<'EOF'\n- abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n EOF\n-test_expect_success 'format patch graph part width is 40 columns' '\n-\tgit format-patch --stat --stdout -1 >output &&\n-\tgrep \" | \" output >actual &&\n-\ttest_cmp expect actual\n-'\n \n test_expect_success 'format patch ignores COLUMNS' '\n \tCOLUMNS=200 git format-patch --stat --stdout -1 >output\n@@ -984,7 +979,7 @@ test_expect_success 'format patch --stat-width=width with big change' '\n '\n \n cat >expect <<'EOF'\n- ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++\n EOF\n test_expect_success 'format patch --stat=width with big change and long name' '\n \tcp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n-- \n1.7.9.1.237.g00b59\n"},{"id":"184774","messageId":"7vipj80y3p.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"1329303808-16989-2-git-send-email-zbyszek@in.waw.pl","subject":"Re: [PATCH 2/3 v5] diff --stat: use the full terminal width","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-15T18:07:22Z","receivedAt":"2012-02-15T18:07:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> Use as many columns as necessary for the filenames and up to 40\n> columns for the graph.\n\nI started to wonder if it is a good idea to split this step further into\nat least two patches:\n\n - using term_columns() to set the default 'stat-width' instead of\n   hardcoded 80, and do nothing else.  As you discovered, this step will\n   not have to touch any test expectations.\n\n - update the logic to split the stat-width into name part and graph\n   part. I think as a side-effect this will fix the corner case bugs the\n   new tests in your [1/3] seem to have discovered, and the fix will be\n   visible to the part that will update t/t4014 in this step.\n\n> ... I've taken the middle way:\n> number_width=4 is hardcoded, but the fprintf is reverted to the previous\n> version. I think that this way the code is most readable, independently\n> if later changes.\n\nSensible.\n\n> I haven't done this, because $COLUMNS and the actual terminal width is always\n> ignored in tests.\n\nAs long as the tests are not affected by ioctl(1) that is OK. I am not\nexpecting us to be automating the test of that codepath (unless somebody\nhas clever ideas perhaps using pty, but I suspect that would be a separate\npatch anyway).\n\nAfter writing the attached patch that goes on top of this patch to be\nsquashed, I am starting to think that \"maximum 40 columns for the graph\"\nmay be a mild regression for a project with a shallow hierarchy, namely,\nthis part.\n\n cat >expect <<'EOF'\n- abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n EOF\n\nA bug used to waste space by allocating more than necessary as the minimum\nnumber of columns given for the graph part, even when the change turns out\nto be just one line, requiring only one '+' in the graph.  The bug was fixed\nby this patch not to waste space that way.  But now with this \"maximum 40\"\nlimit, we can see that it wastes the space even when the stat-width is 80.\n\nPerhaps the maximum for garph_width should be raised to something like\n\"min(80, stat_width) - name_width\"?\n\n-- >8 --\nSubject: [PATCH] (squash to the previous -- replace the last line of the\n log with the following)\n\nThe effect of this change is visible in the patch to t4014 that fixes a\nfew tests marked with test_expect_failure, and the change to shorten the\nmaximum graph width to 40 columns.\n---\n t/t4014-format-patch.sh |   15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 0376186..88ccc5a 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -908,7 +908,7 @@ test_expect_success 'preparation' '\n cat >expect <<'EOF'\n  ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n EOF\n-test_expect_failure 'format patch graph width defaults to 80 columns' '\n+test_expect_success 'format patch graph width defaults to 80 columns' '\n \tgit format-patch --stat --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n@@ -917,13 +917,13 @@ test_expect_failure 'format patch graph width defaults to 80 columns' '\n cat >expect <<'EOF'\n  ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +\n EOF\n-test_expect_failure 'format patch --stat=width with long name' '\n+test_expect_success 'format patch --stat=width with long name' '\n \tgit format-patch --stat=40 --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n '\n \n-test_expect_failure 'format patch --stat-width=width works with long name' '\n+test_expect_success 'format patch --stat-width=width works with long name' '\n \tgit format-patch --stat-width=40 --stdout -1 >output &&\n \tgrep \" | \" output >actual &&\n \ttest_cmp expect actual\n@@ -954,8 +954,13 @@ test_expect_success 'preparation for big change tests' '\n '\n \n cat >expect <<'EOF'\n- abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++\n EOF\n+test_expect_success 'format patch graph part width is 40 columns' '\n+\tgit format-patch --stat --stdout -1 >output &&\n+\tgrep \" | \" output >actual &&\n+\ttest_cmp expect actual\n+'\n \n test_expect_success 'format patch ignores COLUMNS' '\n \tCOLUMNS=200 git format-patch --stat --stdout -1 >output\n@@ -979,7 +984,7 @@ test_expect_success 'format patch --stat-width=width with big change' '\n '\n \n cat >expect <<'EOF'\n- ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++\n+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++\n EOF\n test_expect_success 'format patch --stat=width with big change and long name' '\n \tcp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n-- \n1.7.9.1.237.g00b59\n"},{"id":"184821","messageId":"4F3CD318.1040600@in.waw.pl","threadId":"29589","inReplyTo":"7vvcn810ml.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/3 v5] diff --stat: tests for long filenames and big change counts","fromName":"Zbigniew Jędrzejewski-Szmek","fromEmail":"zbyszek@in.waw.pl","sentAt":"2012-02-16T09:57:44Z","receivedAt":"2012-02-16T09:57:44Z","isPatch":true,"sender":{"key":"zbyszek@in.waw.pl","avatar":"https://avatars.githubusercontent.com/u/349618?v=4"},"body":"On 02/15/2012 06:12 PM, Junio C Hamano wrote:\n> Zbigniew Jędrzejewski-Szmek<zbyszek@in.waw.pl>  writes:\n>\n>> Eleven tests for various combinations of a long filename and/or big\n>> change count and ways to specify widths for diff --stat.\n>> ---\n>\n> Sign-off?\n\n> Hrm, this does not seem to pass, making the result of applying [1/3] fail;\n> I see that the elided name is shown much shorter than the above expects.\n\nHi,\n\nI'm sorry for not properly testing the patch with tests. I somehow \nconvinced myself that the tests pass. This whole series needs more work, \neven after squashing in your two patches. I'll send a new series, but \nprobably not today. (I'll try to remember the sign-off too, next time).\n--\nZbyszek\n"},{"id":"184832","messageId":"7vd39ezgwt.fsf@alter.siamese.dyndns.org","threadId":"29589","inReplyTo":"4F3CD318.1040600@in.waw.pl","subject":"Re: [PATCH 1/3 v5] diff --stat: tests for long filenames and big change counts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-16T20:01:38Z","receivedAt":"2012-02-16T20:01:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:\n\n> On 02/15/2012 06:12 PM, Junio C Hamano wrote:\n>> Zbigniew Jędrzejewski-Szmek<zbyszek@in.waw.pl>  writes:\n>>\n>>> Eleven tests for various combinations of a long filename and/or big\n>>> change count and ways to specify widths for diff --stat.\n>>> ---\n>>\n>> Sign-off?\n>\n>> Hrm, this does not seem to pass, making the result of applying [1/3] fail;\n>> I see that the elided name is shown much shorter than the above expects.\n>\n> Hi,\n>\n> I'm sorry for not properly testing the patch with tests. I somehow\n> convinced myself that the tests pass. This whole series needs more\n> work, even after squashing in your two patches.\n\nIt is nothing to be sorry about if a series needs more polishing; that is\nwhat the review discussions are for.\n\nI've queued the series after restructuring it, and merged except for [3/3]\nto 'pu', which conflicts too heavily with the nd/diffstat-gramnum topic\nthat is already in 'master'.  I'd say we should concentrate on your first\ntwo patches without the \"num-width\" stuff and get them in first, and then\nlater consider if rerolling the [3/3] patch is worth it after the dust\nsettles.\n\nThanks.\n"}]}