Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- diff.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ diff.h | 1 + 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/diff.c b/diff.c index 8c448b5..b945ad6 100644 --- a/diff.c +++ b/diff.c @@ -1226,6 +1226,7 @@ struct diffstat_t { unsigned is_renamed:1; uintmax_t added, deleted; } **files; + struct strbuf dynstat; }; static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat, @@ -1779,6 +1780,7 @@ static void free_diffstat_info(struct diffstat_t *diffstat) free(f); } free(diffstat->files); + strbuf_release(&diffstat->dynstat); } struct checkdiff_t { @@ -3332,6 +3334,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_NUMSTAT; else if (!strcmp(arg, "--shortstat")) options->output_format |= DIFF_FORMAT_SHORTSTAT; + else if (!strcmp(arg, "--dynstat")) + options->output_format |= DIFF_FORMAT_DYNSTAT; else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat")) return parse_dirstat_opt(options, ""); else if (!prefixcmp(arg, "-X")) @@ -3922,6 +3926,76 @@ static int check_pair_status(struct diff_filepair *p) } } +static int diff_flush_dynstat(struct diff_options *o, struct diffstat_t *diffstat) +{ + struct diff_queue_struct *q = &diff_queued_diff; + int i, adds = 0, dels = 0, summary_lines = 0, printed_lines = 0, total_files; + + memset(diffstat, 0, sizeof(struct diffstat_t)); + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + if (check_pair_status(p)) + diff_flush_stat(p, o, diffstat); + } + + total_files = diffstat->nr; + if (!total_files) + return o->output_format; + + /* how many lines for --stat ? */ + for (i = 0; i < diffstat->nr; i++) { + struct diffstat_file *f = diffstat->files[i]; + if (!f->is_binary && !f->is_unmerged) { + if (!f->is_renamed && (f->added + f->deleted == 0)) + total_files--; + else { + adds += f->added; + dels += f->deleted; + } + } + } + + /* how many lines for --summary ? */ + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + if ((p->status & (DIFF_STATUS_DELETED | DIFF_STATUS_ADDED | + DIFF_STATUS_COPIED | DIFF_STATUS_RENAMED)) || + p->score) + summary_lines++; + } + + if (printed_lines + total_files < 50) { + o->output_format |= DIFF_FORMAT_DIFFSTAT; + printed_lines += total_files; + if (printed_lines + summary_lines < 50) { + printed_lines += summary_lines; + o->output_format |= DIFF_FORMAT_SUMMARY; + } + } else { + const char *s; + int nr = 0; + show_dirstat(o, &diffstat->dynstat); + s = diffstat->dynstat.buf; + + /* how many lines for --dirstat ? */ + while (s && (s = strchr(s, '\n'))) { + nr++; + s++; + } + if (nr < 50) + printed_lines += nr; + else + strbuf_release(&diffstat->dynstat); + } + + /* how many lines for --patch ? */ + if (adds + dels < 10 && printed_lines < 10) + o->output_format |= DIFF_FORMAT_PATCH; + + o->output_format |= DIFF_FORMAT_SHORTSTAT; + return o->output_format; +} + static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt) { int fmt = opt->output_format; @@ -4201,6 +4275,7 @@ void diff_flush(struct diff_options *options) int i, output_format = options->output_format; int separator = 0; int dirstat_by_line = 0; + struct diffstat_t diffstat; /* * Order: raw, stat, summary, patch @@ -4221,6 +4296,19 @@ void diff_flush(struct diff_options *options) separator++; } + memset(&diffstat, 0, sizeof(struct diffstat_t)); + strbuf_init(&diffstat.dynstat, 0); + if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DYNSTAT)) { + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + if (check_pair_status(p)) + diff_flush_stat(p, options, &diffstat); + } + } + + if (output_format & DIFF_FORMAT_DYNSTAT) + output_format = diff_flush_dynstat(options, &diffstat); + if (output_format & DIFF_FORMAT_DIRSTAT && DIFF_OPT_TST(options, DIRSTAT_BY_LINE)) dirstat_by_line = 1; @@ -4229,25 +4317,19 @@ void diff_flush(struct diff_options *options) if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT) || dirstat_by_line) { - struct diffstat_t diffstat; - - memset(&diffstat, 0, sizeof(struct diffstat_t)); - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (check_pair_status(p)) - diff_flush_stat(p, options, &diffstat); - } if (output_format & DIFF_FORMAT_NUMSTAT) show_numstat(&diffstat, options); if (output_format & DIFF_FORMAT_DIFFSTAT) show_stats(&diffstat, options); + if ((output_format & DIFF_FORMAT_DYNSTAT) && diffstat.dynstat.len) + fputs(diffstat.dynstat.buf, options->file); if (output_format & DIFF_FORMAT_SHORTSTAT) show_shortstats(&diffstat, options); if (output_format & DIFF_FORMAT_DIRSTAT) show_dirstat_by_line(&diffstat, options); - free_diffstat_info(&diffstat); separator++; } + free_diffstat_info(&diffstat); if ((output_format & DIFF_FORMAT_DIRSTAT) && !dirstat_by_line) show_dirstat(options, NULL); diff --git a/diff.h b/diff.h index ae71f4c..6bebad8 100644 --- a/diff.h +++ b/diff.h @@ -39,6 +39,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_FORMAT_PATCH 0x0010 #define DIFF_FORMAT_SHORTSTAT 0x0020 #define DIFF_FORMAT_DIRSTAT 0x0040 +#define DIFF_FORMAT_DYNSTAT 0x0080 /* These override all above */ #define DIFF_FORMAT_NAME 0x0100 -- 1.7.3.1.256.g2539c.dirty -- To unsubscribe from this list: 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