Merge branch 'lt/diff-stat-show-0-lines'
authorJunio C Hamano <gitster@pobox.com>
Thu, 29 Nov 2012 20:53:54 +0000 (12:53 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 29 Nov 2012 20:53:54 +0000 (12:53 -0800)
"git diff --stat" miscounted the total number of changed lines when
binary files were involved and hidden beyond --stat-count. It also
miscounted the total number of changed files when there were
unmerged paths.

* lt/diff-stat-show-0-lines:
t4049: refocus tests
diff --shortstat: do not count "unmerged" entries
diff --stat: do not count "unmerged" entries
diff --stat: move the "total count" logic to the last loop
diff --stat: use "file" temporary variable to refer to data->files[i]
diff --stat: status of unmodified pair in diff-q is not zero
test: add failing tests for "diff --stat" to t4049

diff.c
t/t4049-diff-stat-count.sh
diff --git a/diff.c b/diff.c
index cb1fd9afcc2ece8c5a4123a451a0cb091baae1e3..732d4c227595873bb94224da618ce5612a7415af 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1497,8 +1497,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
        for (i = 0; (i < count) && (i < data->nr); i++) {
                struct diffstat_file *file = data->files[i];
                uintmax_t change = file->added + file->deleted;
-               if (!data->files[i]->is_interesting &&
-                        (change == 0)) {
+
+               if (!file->is_interesting && (change == 0)) {
                        count++; /* not shown == room for one more */
                        continue;
                }
@@ -1525,7 +1525,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                if (max_change < change)
                        max_change = change;
        }
-       count = i; /* min(count, data->nr) */
+       count = i; /* where we can stop scanning in data->files[] */
 
        /*
         * We have width = stat_width or term_columns() columns total.
@@ -1613,16 +1613,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
         */
        for (i = 0; i < count; i++) {
                const char *prefix = "";
-               char *name = data->files[i]->print_name;
-               uintmax_t added = data->files[i]->added;
-               uintmax_t deleted = data->files[i]->deleted;
+               struct diffstat_file *file = data->files[i];
+               char *name = file->print_name;
+               uintmax_t added = file->added;
+               uintmax_t deleted = file->deleted;
                int name_len;
 
-               if (!data->files[i]->is_interesting &&
-                        (added + deleted == 0)) {
-                       total_files--;
+               if (!file->is_interesting && (added + deleted == 0))
                        continue;
-               }
+
                /*
                 * "scale" the filename
                 */
@@ -1638,7 +1637,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                                name = slash;
                }
 
-               if (data->files[i]->is_binary) {
+               if (file->is_binary) {
                        fprintf(options->file, "%s", line_prefix);
                        show_name(options->file, prefix, name, len);
                        fprintf(options->file, " %*s", number_width, "Bin");
@@ -1655,7 +1654,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                        fprintf(options->file, "\n");
                        continue;
                }
-               else if (data->files[i]->is_unmerged) {
+               else if (file->is_unmerged) {
                        fprintf(options->file, "%s", line_prefix);
                        show_name(options->file, prefix, name, len);
                        fprintf(options->file, " Unmerged\n");
@@ -1667,8 +1666,6 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                 */
                add = added;
                del = deleted;
-               adds += add;
-               dels += del;
 
                if (graph_width <= max_change) {
                        int total = add + del;
@@ -1694,16 +1691,24 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                show_graph(options->file, '-', del, del_c, reset);
                fprintf(options->file, "\n");
        }
-       for (i = count; i < data->nr; i++) {
-               uintmax_t added = data->files[i]->added;
-               uintmax_t deleted = data->files[i]->deleted;
-               if (!data->files[i]->is_interesting &&
-                        (added + deleted == 0)) {
+
+       for (i = 0; i < data->nr; i++) {
+               struct diffstat_file *file = data->files[i];
+               uintmax_t added = file->added;
+               uintmax_t deleted = file->deleted;
+
+               if (file->is_unmerged ||
+                   (!file->is_interesting && (added + deleted == 0))) {
                        total_files--;
                        continue;
                }
-               adds += added;
-               dels += deleted;
+
+               if (!file->is_binary) {
+                       adds += added;
+                       dels += deleted;
+               }
+               if (i < count)
+                       continue;
                if (!extra_shown)
                        fprintf(options->file, "%s ...\n", line_prefix);
                extra_shown = 1;
@@ -1723,9 +1728,8 @@ static void show_shortstats(struct diffstat_t *data, struct diff_options *option
                int added = data->files[i]->added;
                int deleted= data->files[i]->deleted;
 
-               if (data->files[i]->is_unmerged)
-                       continue;
-               if (!data->files[i]->is_interesting && (added + deleted == 0)) {
+               if (data->files[i]->is_unmerged ||
+                   (!data->files[i]->is_interesting && (added + deleted == 0))) {
                        total_files--;
                } else if (!data->files[i]->is_binary) { /* don't count bytes */
                        adds += added;
@@ -2438,7 +2442,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
        }
 
        data = diffstat_add(diffstat, name_a, name_b);
-       data->is_interesting = p->status != 0;
+       data->is_interesting = p->status != DIFF_STATUS_UNKNOWN;
 
        if (!one || !two) {
                data->is_unmerged = 1;
index 7b3ef00533f7b2fc5f8cea7b9d3553365ac69d0c..5b594e878f7561560fb2a8563b7355a32d4d3914 100755 (executable)
@@ -4,20 +4,62 @@
 test_description='diff --stat-count'
 . ./test-lib.sh
 
-test_expect_success setup '
+test_expect_success 'setup' '
        >a &&
        >b &&
        >c &&
        >d &&
        git add a b c d &&
-       chmod +x c d &&
+       git commit -m initial
+'
+
+test_expect_success 'mode-only change show as a 0-line change' '
+       git reset --hard &&
+       test_chmod +x b d &&
+       echo a >a &&
+       echo c >c &&
+       cat >expect <<-\EOF
+        a | 1 +
+        b | 0
+        ...
+        4 files changed, 2 insertions(+)
+       EOF
+       git diff --stat --stat-count=2 HEAD >actual &&
+       test_i18ncmp expect actual
+'
+
+test_expect_success 'binary changes do not count in lines' '
+       git reset --hard &&
+       echo a >a &&
+       echo c >c &&
+       cat "$TEST_DIRECTORY"/test-binary-1.png >d &&
+       cat >expect <<-\EOF
+        a | 1 +
+        c | 1 +
+        ...
+        3 files changed, 2 insertions(+)
+       EOF
+       git diff --stat --stat-count=2 >actual &&
+       test_i18ncmp expect actual
+'
+
+test_expect_success 'exclude unmerged entries from total file count' '
+       git reset --hard &&
        echo a >a &&
        echo b >b &&
+       git ls-files -s a >x &&
+       git rm -f d &&
+       for stage in 1 2 3
+       do
+               sed -e "s/ 0    a/ $stage       d/" x
+       done |
+       git update-index --index-info &&
+       echo d >d &&
        cat >expect <<-\EOF
         a | 1 +
         b | 1 +
         ...
-        4 files changed, 2 insertions(+)
+        3 files changed, 3 insertions(+)
        EOF
        git diff --stat --stat-count=2 >actual &&
        test_i18ncmp expect actual