diff: introduce --stat-lines to limit the stat lines
authorMichael J Gruber <git@drmicha.warpmail.net>
Fri, 27 May 2011 12:36:41 +0000 (14:36 +0200)
committerJunio C Hamano <gitster@pobox.com>
Fri, 27 May 2011 17:44:34 +0000 (10:44 -0700)
Often one is interested in the full --stat output only for commits which
change a few files, but not others, because larger restructuring gives a
--stat which fills a few screens.

Introduce a new option --stat-count=<count> which limits the --stat output
to the first <count> lines, followed by a "..." line. It can
also be given as the third parameter in
--stat=<width>,<name-width>,<count>.

Also, the unstuck form is supported analogous to the other two stat
parameters.

Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/diff-options.txt
diff.c
diff.h

index 34f01458c296ce68bcba4c08177aba127fc2333b..000eae02cda10766dbe07c7e0d54d29bc63f4af4 100644 (file)
@@ -48,11 +48,14 @@ endif::git-format-patch[]
 --patience::
        Generate a diff using the "patience diff" algorithm.
 
---stat[=<width>[,<name-width>]]::
+--stat[=<width>[,<name-width>[,<count>]]]::
        Generate a diffstat.  You can override the default
        output width for 80-column terminal by `--stat=<width>`.
        The width of the filename part can be controlled by
        giving another width to it separated by a comma.
+       By giving a third parameter `<count>`, you can limit the
+       output to the first `<count>` lines, followed by
+       `...` if there are more.
 
 --numstat::
        Similar to `\--stat`, but shows number of added and
diff --git a/diff.c b/diff.c
index 0c69354d0a950fe87ab7c0deef16484ac97e987d..82789e30eb7091d9405635438b6c406aac4adb40 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1244,7 +1244,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
        int i, len, add, del, adds = 0, dels = 0;
        uintmax_t max_change = 0, max_len = 0;
        int total_files = data->nr;
-       int width, name_width;
+       int width, name_width, count;
        const char *reset, *add_c, *del_c;
        const char *line_prefix = "";
        struct strbuf *msg = NULL;
@@ -1259,6 +1259,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 
        width = options->stat_width ? options->stat_width : 80;
        name_width = options->stat_name_width ? options->stat_name_width : 50;
+       count = options->stat_count ? options->stat_count : data->nr;
 
        /* Sanity: give at least 5 columns to the graph,
         * but leave at least 10 columns for the name.
@@ -1275,11 +1276,12 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
        add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
        del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
 
-       for (i = 0; i < data->nr; i++) {
+       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_renamed &&
                         (change == 0)) {
+                       count++; /* not shown == room for one more */
                        continue;
                }
                fill_print_name(file);
@@ -1292,6 +1294,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) */
 
        /* Compute the width of the graph part;
         * 10 is for one blank at the beginning of the line plus
@@ -1306,7 +1309,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
        else
                width = max_change;
 
-       for (i = 0; i < data->nr; i++) {
+       for (i = 0; i < count; i++) {
                const char *prefix = "";
                char *name = data->files[i]->print_name;
                uintmax_t added = data->files[i]->added;
@@ -1373,6 +1376,19 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                show_graph(options->file, '-', del, del_c, reset);
                fprintf(options->file, "\n");
        }
+       if (count < data->nr)
+               fprintf(options->file, "%s ...\n", line_prefix);
+       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_renamed &&
+                        (added + deleted == 0)) {
+                       total_files--;
+                       continue;
+               }
+               adds += added;
+               dels += deleted;
+       }
        fprintf(options->file, "%s", line_prefix);
        fprintf(options->file,
               " %d files changed, %d insertions(+), %d deletions(-)\n",
@@ -3109,6 +3125,7 @@ static int stat_opt(struct diff_options *options, const char **av)
        char *end;
        int width = options->stat_width;
        int name_width = options->stat_name_width;
+       int count = options->stat_count;
        int argcount = 1;
 
        arg += strlen("--stat");
@@ -3136,12 +3153,24 @@ static int stat_opt(struct diff_options *options, const char **av)
                                name_width = strtoul(av[1], &end, 10);
                                argcount = 2;
                        }
+               } else if (!prefixcmp(arg, "-count")) {
+                       arg += strlen("-count");
+                       if (*arg == '=')
+                               count = strtoul(arg + 1, &end, 10);
+                       else if (!*arg && !av[1])
+                               die("Option '--stat-count' requires a value");
+                       else if (!*arg) {
+                               count = strtoul(av[1], &end, 10);
+                               argcount = 2;
+                       }
                }
                break;
        case '=':
                width = strtoul(arg+1, &end, 10);
                if (*end == ',')
                        name_width = strtoul(end+1, &end, 10);
+               if (*end == ',')
+                       count = strtoul(end+1, &end, 10);
        }
 
        /* Important! This checks all the error cases! */
@@ -3150,6 +3179,7 @@ static int stat_opt(struct diff_options *options, const char **av)
        options->output_format |= DIFF_FORMAT_DIFFSTAT;
        options->stat_name_width = name_width;
        options->stat_width = width;
+       options->stat_count = count;
        return argcount;
 }
 
@@ -3195,7 +3225,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        else if (!strcmp(arg, "-s"))
                options->output_format |= DIFF_FORMAT_NO_OUTPUT;
        else if (!prefixcmp(arg, "--stat"))
-               /* --stat, --stat-width, or --stat-name-width */
+               /* --stat, --stat-width, --stat-name-width, or --stat-count */
                return stat_opt(options, av);
 
        /* renames options */
diff --git a/diff.h b/diff.h
index 6fe1597785761b0e6961910214a129a2dde5197f..59608f9605839c6caa5a4abca0f5f031a08740bd 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -124,6 +124,7 @@ struct diff_options {
 
        int stat_width;
        int stat_name_width;
+       int stat_count;
        const char *word_regex;
        enum diff_words_type word_diff;