diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 7b7b9e8ce9..e112172ca5 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -16,6 +16,11 @@ The width of the filename part can be controlled by giving another width to it separated by a comma. +--numstat:: + Similar to \--stat, but shows number of added and + deleted lines in decimal notation and pathname without + abbreviation, to make it more machine friendly. + --summary:: Output a condensed summary of extended header information such as creations, renames and mode changes. diff --git a/combine-diff.c b/combine-diff.c index 46d9121baf..65c786807b 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -856,8 +856,10 @@ void diff_tree_combined(const unsigned char *sha1, /* show stat against the first parent even * when doing combined diff. */ - if (i == 0 && opt->output_format & DIFF_FORMAT_DIFFSTAT) - diffopts.output_format = DIFF_FORMAT_DIFFSTAT; + int stat_opt = (opt->output_format & + (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT)); + if (i == 0 && stat_opt) + diffopts.output_format = stat_opt; else diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; diff_tree_sha1(parent[i], sha1, "", &diffopts); @@ -887,7 +889,8 @@ void diff_tree_combined(const unsigned char *sha1, } needsep = 1; } - else if (opt->output_format & DIFF_FORMAT_DIFFSTAT) + else if (opt->output_format & + (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT)) needsep = 1; if (opt->output_format & DIFF_FORMAT_PATCH) { if (needsep) diff --git a/diff.c b/diff.c index fb8243261c..2dcad1942c 100644 --- a/diff.c +++ b/diff.c @@ -795,6 +795,23 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) set, total_files, adds, dels, reset); } +static void show_numstat(struct diffstat_t* data, struct diff_options *options) +{ + int i; + + for (i = 0; i < data->nr; i++) { + struct diffstat_file *file = data->files[i]; + + printf("%d\t%d\t", file->added, file->deleted); + if (options->line_termination && + quote_c_style(file->name, NULL, NULL, 0)) + quote_c_style(file->name, NULL, stdout, 0); + else + fputs(file->name, stdout); + putchar(options->line_termination); + } +} + struct checkdiff_t { struct xdiff_emit_state xm; const char *filename; @@ -1731,6 +1748,7 @@ int diff_setup_done(struct diff_options *options) DIFF_FORMAT_CHECKDIFF | DIFF_FORMAT_NO_OUTPUT)) options->output_format &= ~(DIFF_FORMAT_RAW | + DIFF_FORMAT_NUMSTAT | DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH); @@ -1740,6 +1758,7 @@ int diff_setup_done(struct diff_options *options) * recursive bits for other formats here. */ if (options->output_format & (DIFF_FORMAT_PATCH | + DIFF_FORMAT_NUMSTAT | DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_CHECKDIFF)) options->recursive = 1; @@ -1828,6 +1847,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (!strcmp(arg, "--patch-with-raw")) { options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW; } + else if (!strcmp(arg, "--numstat")) { + options->output_format |= DIFF_FORMAT_NUMSTAT; + } else if (!strncmp(arg, "--stat", 6)) { char *end; int width = options->stat_width; @@ -2602,7 +2624,7 @@ void diff_flush(struct diff_options *options) separator++; } - if (output_format & DIFF_FORMAT_DIFFSTAT) { + if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_NUMSTAT)) { struct diffstat_t diffstat; memset(&diffstat, 0, sizeof(struct diffstat_t)); @@ -2612,7 +2634,10 @@ void diff_flush(struct diff_options *options) if (check_pair_status(p)) diff_flush_stat(p, options, &diffstat); } - show_stats(&diffstat, options); + if (output_format & DIFF_FORMAT_NUMSTAT) + show_numstat(&diffstat, options); + if (output_format & DIFF_FORMAT_DIFFSTAT) + show_stats(&diffstat, options); separator++; } diff --git a/diff.h b/diff.h index b48c9914e7..ce3058e437 100644 --- a/diff.h +++ b/diff.h @@ -26,20 +26,21 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_FORMAT_RAW 0x0001 #define DIFF_FORMAT_DIFFSTAT 0x0002 -#define DIFF_FORMAT_SUMMARY 0x0004 -#define DIFF_FORMAT_PATCH 0x0008 +#define DIFF_FORMAT_NUMSTAT 0x0004 +#define DIFF_FORMAT_SUMMARY 0x0008 +#define DIFF_FORMAT_PATCH 0x0010 /* These override all above */ -#define DIFF_FORMAT_NAME 0x0010 -#define DIFF_FORMAT_NAME_STATUS 0x0020 -#define DIFF_FORMAT_CHECKDIFF 0x0040 +#define DIFF_FORMAT_NAME 0x0100 +#define DIFF_FORMAT_NAME_STATUS 0x0200 +#define DIFF_FORMAT_CHECKDIFF 0x0400 /* Same as output_format = 0 but we know that -s flag was given * and we should not give default value to output_format. */ -#define DIFF_FORMAT_NO_OUTPUT 0x0080 +#define DIFF_FORMAT_NO_OUTPUT 0x0800 -#define DIFF_FORMAT_CALLBACK 0x0100 +#define DIFF_FORMAT_CALLBACK 0x1000 struct diff_options { const char *filter; @@ -170,6 +171,7 @@ extern void diffcore_std_no_resolve(struct diff_options *); " --patch-with-raw\n" \ " output both a patch and the diff-raw format.\n" \ " --stat show diffstat instead of patch.\n" \ +" --numstat show numeric diffstat instead of patch.\n" \ " --patch-with-stat\n" \ " output a patch and prepend its diffstat.\n" \ " --name-only show only names of changed files.\n" \