[PATCH] diff --stat: do not drop rename information.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a verbatim rename or copy is detected, we did not show
anything on the "diff --stat" for the filepair.  This makes it
to show the rename information.

Signed-off-by: Junio C Hamano <junkio@xxxxxxx>

---
 * In git.git itself, with and without this patch:

        $ git-diff-tree --stat -M ba580ae
        ba580aeafb52921025de1efe1c50db34393f9907
         Makefile |    2 +-
         1 files changed, 1 insertions(+), 1 deletions(-)

        $ git-diff-tree --stat -M ba580ae
        ba580aeafb52921025de1efe1c50db34393f9907
         Makefile             |    2 +-
         diff.c => diff-lib.c |    0
         2 files changed, 1 insertions(+), 1 deletions(-)

   Since renames are rare, I think this is a good change.  We
   might want to do the same for "apply --stat" as well.

 diff-lib.c |   98 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 81 insertions(+), 17 deletions(-)

9ea8da8f01d7fb2159a81edba9e5e7885e6b616e
diff --git a/diff-lib.c b/diff-lib.c
index 0a832c3..86d1417 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -201,7 +201,8 @@ struct diffstat_t {
 	int nr;
 	int alloc;
 	struct diffstat_file {
-		char *name;
+		char *name_a;
+		char *name_b;
 		unsigned is_unmerged:1;
 		unsigned is_binary:1;
 		unsigned int added, deleted;
@@ -209,7 +210,8 @@ struct diffstat_t {
 };
 
 static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
-		const char *name)
+					  char *name_a,
+					  char *name_b)
 {
 	struct diffstat_file *x;
 	x = xcalloc(sizeof (*x), 1);
@@ -219,7 +221,10 @@ static struct diffstat_file *diffstat_ad
 				diffstat->alloc * sizeof(x));
 	}
 	diffstat->files[diffstat->nr++] = x;
-	x->name = strdup(name);
+	x->name_a = strdup(name_a);
+	if (name_b)
+		name_b = strdup(name_b);
+	x->name_b = name_b;
 	return x;
 }
 
@@ -234,6 +239,54 @@ static void diffstat_consume(void *priv,
 		x->deleted++;
 }
 
+static char *find_common_pfx(const char *a, const char *b)
+{
+	const char *old = a;
+	const char *new = b;
+	char *name = NULL;
+	int common_length;
+	int len_a = strlen(a);
+	int len_b = strlen(b);
+
+	/* Find common prefix */
+	while (1) {
+		const char *slash_old, *slash_new;
+		slash_old = strchr(old, '/');
+		slash_new = strchr(new, '/');
+		if (!slash_old ||
+		    !slash_new ||
+		    slash_old - old != slash_new - new ||
+		    memcmp(old, new, slash_new - new))
+			break;
+		old = slash_old + 1;
+		new = slash_new + 1;
+	}
+	/* a thru old is the common prefix, and old and new
+	 * through the end of names are renames.
+	 * Either give
+	 * 	common{suffix-a => suffix-b}
+	 * or
+	 *      name-a => name-b
+	 * whichever is shorter.
+	 */
+	common_length = (old - a);
+	/*
+	  int squashed_len = (len_a + len_b - common_length + 6);
+	  int separate_len = (len_a + len_b) + 4;
+	*/
+	if (common_length < 2) {
+		/* no point squashing */
+		name = xmalloc(len_a + len_b + 5);
+		sprintf(name, "%s => %s", a, b);
+	}
+	else {
+		name = xmalloc(len_a + len_b - common_length + 7);
+		sprintf(name, "%.*s{%s => %s}",
+			common_length, a, old, new);
+	}
+	return name;
+}
+
 static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
 static const char minuses[]= "----------------------------------------------------------------------";
 
@@ -249,8 +302,15 @@ static void show_stats(struct diffstat_t
 
 	for (i = 0; i < data->nr; i++) {
 		struct diffstat_file *file = data->files[i];
-
-		len = strlen(file->name);
+		char *name = file->name_a;
+		if (file->name_b && strcmp(name, file->name_b)) {
+			name = find_common_pfx(name, file->name_b);
+			if (name != file->name_a) {
+				free(file->name_a);
+				file->name_a = name;
+			}
+		}
+		len = strlen(name);
 		if (max_len < len)
 			max_len = len;
 
@@ -261,7 +321,7 @@ static void show_stats(struct diffstat_t
 	}
 
 	for (i = 0; i < data->nr; i++) {
-		char *name = data->files[i]->name;
+		char *name = data->files[i]->name_a;
 		int added = data->files[i]->added;
 		int deleted = data->files[i]->deleted;
 
@@ -269,7 +329,7 @@ static void show_stats(struct diffstat_t
 			char *qname = xmalloc(len + 1);
 			quote_c_style(name, qname, NULL, 0);
 			free(name);
-			data->files[i]->name = name = qname;
+			data->files[i]->name_a = name = qname;
 		}
 
 		/*
@@ -305,6 +365,8 @@ static void show_stats(struct diffstat_t
 			printf(" %s%-*s |  Unmerged\n", prefix, len, name);
 			goto free_diffstat_file;
 		}
+		else if (data->files[i]->name_b)
+			;
 		else if (added + deleted == 0) {
 			total_files--;
 			goto free_diffstat_file;
@@ -325,7 +387,8 @@ static void show_stats(struct diffstat_t
 				len, name, added + deleted,
 				add, pluses, del, minuses);
 	free_diffstat_file:
-		free(data->files[i]->name);
+		free(data->files[i]->name_a);
+		free(data->files[i]->name_b);
 		free(data->files[i]);
 	}
 	free(data->files);
@@ -424,14 +487,15 @@ static void builtin_diff(const char *nam
 	return;
 }
 
-static void builtin_diffstat(const char *name_a, const char *name_b,
-		struct diff_filespec *one, struct diff_filespec *two,
-		struct diffstat_t *diffstat)
+static void builtin_diffstat(char *name_a, char *name_b,
+			     struct diff_filespec *one,
+			     struct diff_filespec *two,
+			     struct diffstat_t *diffstat)
 {
 	mmfile_t mf1, mf2;
 	struct diffstat_file *data;
 
-	data = diffstat_add(diffstat, name_a ? name_a : name_b);
+	data = diffstat_add(diffstat, name_a, name_b);
 
 	if (!one || !two) {
 		data->is_unmerged = 1;
@@ -992,10 +1056,10 @@ static void run_diff(struct diff_filepai
 }
 
 static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
-		struct diffstat_t *diffstat)
+			 struct diffstat_t *diffstat)
 {
-	const char *name;
-	const char *other;
+	char *name;
+	char *other;
 
 	if (DIFF_PAIR_UNMERGED(p)) {
 		/* unmerged */
@@ -1374,7 +1438,7 @@ static void diff_flush_patch(struct diff
 }
 
 static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
-		struct diffstat_t *diffstat)
+			    struct diffstat_t *diffstat)
 {
 	if (diff_unmodified_pair(p))
 		return;
@@ -1559,7 +1623,7 @@ void diff_flush(struct diff_options *opt
 		for (i = 0; i < q->nr; i++) {
 			struct diff_filepair *p = q->queue[i];
 			flush_one_pair(p, DIFF_FORMAT_DIFFSTAT, options,
-					diffstat);
+				       diffstat);
 		}
 		show_stats(diffstat);
 		free(diffstat);
-- 
1.3.0.g6057


-
: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]