{"thread":{"id":"3926","subject":"[PATCH] diff --stat: do not drop rename information.","startedAt":"2006-04-20T03:44:40Z","lastAt":"2006-04-20T10:18:12Z","messageCount":3,"participants":["Junio C Hamano","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"18906","messageId":"7vzmig3o7r.fsf@assigned-by-dhcp.cox.net","threadId":"3926","inReplyTo":null,"subject":"[PATCH] diff --stat: do not drop rename information.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-20T03:44:40Z","receivedAt":"2006-04-20T03:44:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When a verbatim rename or copy is detected, we did not show\nanything on the \"diff --stat\" for the filepair.  This makes it\nto show the rename information.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n * In git.git itself, with and without this patch:\n\n        $ git-diff-tree --stat -M ba580ae\n        ba580aeafb52921025de1efe1c50db34393f9907\n         Makefile |    2 +-\n         1 files changed, 1 insertions(+), 1 deletions(-)\n\n        $ git-diff-tree --stat -M ba580ae\n        ba580aeafb52921025de1efe1c50db34393f9907\n         Makefile             |    2 +-\n         diff.c => diff-lib.c |    0\n         2 files changed, 1 insertions(+), 1 deletions(-)\n\n   Since renames are rare, I think this is a good change.  We\n   might want to do the same for \"apply --stat\" as well.\n\n diff-lib.c |   98 ++++++++++++++++++++++++++++++++++++++++++++++++++----------\n 1 files changed, 81 insertions(+), 17 deletions(-)\n\n9ea8da8f01d7fb2159a81edba9e5e7885e6b616e\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 0a832c3..86d1417 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -201,7 +201,8 @@ struct diffstat_t {\n \tint nr;\n \tint alloc;\n \tstruct diffstat_file {\n-\t\tchar *name;\n+\t\tchar *name_a;\n+\t\tchar *name_b;\n \t\tunsigned is_unmerged:1;\n \t\tunsigned is_binary:1;\n \t\tunsigned int added, deleted;\n@@ -209,7 +210,8 @@ struct diffstat_t {\n };\n \n static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,\n-\t\tconst char *name)\n+\t\t\t\t\t  char *name_a,\n+\t\t\t\t\t  char *name_b)\n {\n \tstruct diffstat_file *x;\n \tx = xcalloc(sizeof (*x), 1);\n@@ -219,7 +221,10 @@ static struct diffstat_file *diffstat_ad\n \t\t\t\tdiffstat->alloc * sizeof(x));\n \t}\n \tdiffstat->files[diffstat->nr++] = x;\n-\tx->name = strdup(name);\n+\tx->name_a = strdup(name_a);\n+\tif (name_b)\n+\t\tname_b = strdup(name_b);\n+\tx->name_b = name_b;\n \treturn x;\n }\n \n@@ -234,6 +239,54 @@ static void diffstat_consume(void *priv,\n \t\tx->deleted++;\n }\n \n+static char *find_common_pfx(const char *a, const char *b)\n+{\n+\tconst char *old = a;\n+\tconst char *new = b;\n+\tchar *name = NULL;\n+\tint common_length;\n+\tint len_a = strlen(a);\n+\tint len_b = strlen(b);\n+\n+\t/* Find common prefix */\n+\twhile (1) {\n+\t\tconst char *slash_old, *slash_new;\n+\t\tslash_old = strchr(old, '/');\n+\t\tslash_new = strchr(new, '/');\n+\t\tif (!slash_old ||\n+\t\t    !slash_new ||\n+\t\t    slash_old - old != slash_new - new ||\n+\t\t    memcmp(old, new, slash_new - new))\n+\t\t\tbreak;\n+\t\told = slash_old + 1;\n+\t\tnew = slash_new + 1;\n+\t}\n+\t/* a thru old is the common prefix, and old and new\n+\t * through the end of names are renames.\n+\t * Either give\n+\t * \tcommon{suffix-a => suffix-b}\n+\t * or\n+\t *      name-a => name-b\n+\t * whichever is shorter.\n+\t */\n+\tcommon_length = (old - a);\n+\t/*\n+\t  int squashed_len = (len_a + len_b - common_length + 6);\n+\t  int separate_len = (len_a + len_b) + 4;\n+\t*/\n+\tif (common_length < 2) {\n+\t\t/* no point squashing */\n+\t\tname = xmalloc(len_a + len_b + 5);\n+\t\tsprintf(name, \"%s => %s\", a, b);\n+\t}\n+\telse {\n+\t\tname = xmalloc(len_a + len_b - common_length + 7);\n+\t\tsprintf(name, \"%.*s{%s => %s}\",\n+\t\t\tcommon_length, a, old, new);\n+\t}\n+\treturn name;\n+}\n+\n static const char pluses[] = \"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\";\n static const char minuses[]= \"----------------------------------------------------------------------\";\n \n@@ -249,8 +302,15 @@ static void show_stats(struct diffstat_t\n \n \tfor (i = 0; i < data->nr; i++) {\n \t\tstruct diffstat_file *file = data->files[i];\n-\n-\t\tlen = strlen(file->name);\n+\t\tchar *name = file->name_a;\n+\t\tif (file->name_b && strcmp(name, file->name_b)) {\n+\t\t\tname = find_common_pfx(name, file->name_b);\n+\t\t\tif (name != file->name_a) {\n+\t\t\t\tfree(file->name_a);\n+\t\t\t\tfile->name_a = name;\n+\t\t\t}\n+\t\t}\n+\t\tlen = strlen(name);\n \t\tif (max_len < len)\n \t\t\tmax_len = len;\n \n@@ -261,7 +321,7 @@ static void show_stats(struct diffstat_t\n \t}\n \n \tfor (i = 0; i < data->nr; i++) {\n-\t\tchar *name = data->files[i]->name;\n+\t\tchar *name = data->files[i]->name_a;\n \t\tint added = data->files[i]->added;\n \t\tint deleted = data->files[i]->deleted;\n \n@@ -269,7 +329,7 @@ static void show_stats(struct diffstat_t\n \t\t\tchar *qname = xmalloc(len + 1);\n \t\t\tquote_c_style(name, qname, NULL, 0);\n \t\t\tfree(name);\n-\t\t\tdata->files[i]->name = name = qname;\n+\t\t\tdata->files[i]->name_a = name = qname;\n \t\t}\n \n \t\t/*\n@@ -305,6 +365,8 @@ static void show_stats(struct diffstat_t\n \t\t\tprintf(\" %s%-*s |  Unmerged\\n\", prefix, len, name);\n \t\t\tgoto free_diffstat_file;\n \t\t}\n+\t\telse if (data->files[i]->name_b)\n+\t\t\t;\n \t\telse if (added + deleted == 0) {\n \t\t\ttotal_files--;\n \t\t\tgoto free_diffstat_file;\n@@ -325,7 +387,8 @@ static void show_stats(struct diffstat_t\n \t\t\t\tlen, name, added + deleted,\n \t\t\t\tadd, pluses, del, minuses);\n \tfree_diffstat_file:\n-\t\tfree(data->files[i]->name);\n+\t\tfree(data->files[i]->name_a);\n+\t\tfree(data->files[i]->name_b);\n \t\tfree(data->files[i]);\n \t}\n \tfree(data->files);\n@@ -424,14 +487,15 @@ static void builtin_diff(const char *nam\n \treturn;\n }\n \n-static void builtin_diffstat(const char *name_a, const char *name_b,\n-\t\tstruct diff_filespec *one, struct diff_filespec *two,\n-\t\tstruct diffstat_t *diffstat)\n+static void builtin_diffstat(char *name_a, char *name_b,\n+\t\t\t     struct diff_filespec *one,\n+\t\t\t     struct diff_filespec *two,\n+\t\t\t     struct diffstat_t *diffstat)\n {\n \tmmfile_t mf1, mf2;\n \tstruct diffstat_file *data;\n \n-\tdata = diffstat_add(diffstat, name_a ? name_a : name_b);\n+\tdata = diffstat_add(diffstat, name_a, name_b);\n \n \tif (!one || !two) {\n \t\tdata->is_unmerged = 1;\n@@ -992,10 +1056,10 @@ static void run_diff(struct diff_filepai\n }\n \n static void run_diffstat(struct diff_filepair *p, struct diff_options *o,\n-\t\tstruct diffstat_t *diffstat)\n+\t\t\t struct diffstat_t *diffstat)\n {\n-\tconst char *name;\n-\tconst char *other;\n+\tchar *name;\n+\tchar *other;\n \n \tif (DIFF_PAIR_UNMERGED(p)) {\n \t\t/* unmerged */\n@@ -1374,7 +1438,7 @@ static void diff_flush_patch(struct diff\n }\n \n static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,\n-\t\tstruct diffstat_t *diffstat)\n+\t\t\t    struct diffstat_t *diffstat)\n {\n \tif (diff_unmodified_pair(p))\n \t\treturn;\n@@ -1559,7 +1623,7 @@ void diff_flush(struct diff_options *opt\n \t\tfor (i = 0; i < q->nr; i++) {\n \t\t\tstruct diff_filepair *p = q->queue[i];\n \t\t\tflush_one_pair(p, DIFF_FORMAT_DIFFSTAT, options,\n-\t\t\t\t\tdiffstat);\n+\t\t\t\t       diffstat);\n \t\t}\n \t\tshow_stats(diffstat);\n \t\tfree(diffstat);\n-- \n1.3.0.g6057\n"},{"id":"18911","messageId":"Pine.LNX.4.63.0604201138130.9099@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"3926","inReplyTo":"7vzmig3o7r.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] diff --stat: do not drop rename information.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-04-20T09:40:32Z","receivedAt":"2006-04-20T09:40:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 19 Apr 2006, Junio C Hamano wrote:\n\n> When a verbatim rename or copy is detected, we did not show\n> anything on the \"diff --stat\" for the filepair.  This makes it\n> to show the rename information.\n\nMakes sense. This also shows deletes and adds as \"bla/bla => /dev/null\" \nand \"/dev/null => bla/bla\", right?\n\nCiao,\nDscho\n"},{"id":"18912","messageId":"7v4q0o1rff.fsf@assigned-by-dhcp.cox.net","threadId":"3926","inReplyTo":"Pine.LNX.4.63.0604201138130.9099@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] diff --stat: do not drop rename information.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-20T10:18:12Z","receivedAt":"2006-04-20T10:18:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> ... This also shows deletes and adds as \"bla/bla => /dev/null\" \n> and \"/dev/null => bla/bla\", right?\n\nDunno.  It's still essentially your code ;-).\n\nThe usual \"diffstat\" does not do that, but it might be useful.\nAnother thing that could be done is to fold in mode change\ninformation (usually people care only about chmod +/-x).\n"}]}