pretty: add diff-stat log placeholders
PATCH 1/1 pretty: add diff-stat log placeholders
From: Andrey Zarubin <[email protected]>
Currently, users who want per-commit line/file change counts in a custom log format must post-process git log --shortstat output because the pretty formatter exposes no equivalent placeholders.
Introduce %(diff-stat:files), %(diff-stat:insertions), %(diff-stat:deletions), and %(diff-stat:lines), computed from the same diffstat machinery as --shortstat and cached once per commit during format expansion.
Short aliases are provided as %aF, %aA, and %aR. The requested %aI and %aD forms are unavailable because those names already expand to author dates, so use additions/removals mnemonics instead.
When log output is already walking a diff, the formatter reuses the current diff queue. Otherwise it computes a private summary lazily, so formats without these placeholders still pay no diff cost.
---
pretty: add diff-stat log placeholders
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2284%2Fzarandr%2Fmaster-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2284/zarandr/master-v1
Pull-Request: https://github.com/git/git/pull/2284
Documentation/pretty-formats.adoc | 12 +++ builtin/log.c | 5 + diff.c | 32 ++++-- diff.h | 8 ++ log-tree.c | 2 + pretty.c | 166 ++++++++++++++++++++++++++++++ pretty.h | 3 + t/t4205-log-pretty-formats.sh | 162 +++++++++++++++++++++++++++++ 8 files changed, 381 insertions(+), 9 deletions(-)
Documentation/pretty-formats.adoc +12 -0
@@ -294,6 +294,18 @@ tags are added or removed at the same time. `exclude=<pattern>`;; Do not consider tags matching the given `glob(7)` _<pattern>_, excluding the `refs/tags/` prefix. +++%(diff-stat:files)++:: show the number of files changed +++%(diff-stat:insertions)++:: show the number of inserted lines +++%(diff-stat:deletions)++:: show the number of deleted lines +++%(diff-stat:lines)++:: show the total number of inserted and deleted lines ++ + These placeholders are computed like `--shortstat`. By default, + merge commits expand to `0` unless a merge diff mode such as `-m`, + `-c`, or `--cc` is in effect. ++%aF+:: short alias for `%(diff-stat:files)` ++%aA+:: short alias for `%(diff-stat:insertions)` ++%aR+:: short alias for `%(diff-stat:deletions)` + +%S+:: ref name given on the command line by which the commit was reached (like `git log --source`), only works with `git log` +%e+:: encoding
builtin/log.c +5 -0
@@ -321,6 +321,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,memset (&w,0 ,sizeof (w));userformat_find_requirements (NULL , &w); +if (w.diffstat) { + rev->diff =1 ; + rev->diffopt.output_format |=DIFF_FORMAT_NO_OUTPUT ; + } +if (!rev->show_notes_given && (!rev->pretty_given || w.notes)) rev->show_notes =1 ;if (rev->show_notes)
diff.c +23 -9
@@ -3195,12 +3195,14 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)strbuf_release (&out); } -static void show_shortstats (struct diffstat_t *data,struct diff_options *options) +void summarize_diffstat (struct diffstat_t *data, +struct diff_stat_summary *summary) { -int i, adds =0 , dels =0 , total_files = data->nr; +int i; -if (data->nr ==0 ) -return ; + summary->files = data->nr; + summary->insertions =0 ; + summary->deletions =0 ;for (i =0 ; i < data->nr; i++) {int added = data->files[i]->added;
@@ -3208,13 +3210,25 @@ static void show_shortstats(struct diffstat_t *data, struct diff_options *optionif (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; - dels += deleted; + summary->files--; + }else if (!data->files[i]->is_binary) { + summary->insertions += added; + summary->deletions += deleted; } } -print_stat_summary_inserts_deletes (options, total_files, adds, dels); +} + +static void show_shortstats (struct diffstat_t *data,struct diff_options *options) +{ +struct diff_stat_summary summary; + +if (data->nr ==0 ) +return ; + +summarize_diffstat (data, &summary); +print_stat_summary_inserts_deletes (options, summary.files, + summary.insertions, + summary.deletions); }static void show_numstat (struct diffstat_t *data,struct diff_options *options)
diff.h +8 -0
@@ -449,6 +449,12 @@ struct diffstat_t { } **files; }; +struct diff_stat_summary { +int files; +int insertions; +int deletions; +}; +enum color_diff {DIFF_RESET =0 ,DIFF_CONTEXT =1 ,
@@ -581,6 +587,8 @@ struct diff_filepair *diff_unmerge(struct diff_options *, const char *path);void compute_diffstat (struct diff_options *options,struct diffstat_t *diffstat,struct diff_queue_struct *q); +void summarize_diffstat (struct diffstat_t *diffstat, +struct diff_stat_summary *summary);void free_diffstat_info (struct diffstat_t *diffstat);#define DIFF_SETUP_REVERSE 1
log-tree.c +2 -0
@@ -881,6 +881,8 @@ void show_log(struct rev_info *opt) ctx.expand_tabs_in_log = opt->expand_tabs_in_log; ctx.output_encoding =get_log_output_encoding (); ctx.rev = opt; + ctx.diff_parent = parent; + ctx.diff_queue_present = diff_queued_diff.nr >0 ;if (opt->from_ident.mail_begin && opt->from_ident.name_begin) ctx.from_ident = &opt->from_ident;if (opt->graph)
pretty.c +166 -0
208 lines not on this page · raw message
pretty.h +3 -0
@@ -58,6 +58,8 @@ struct pretty_print_context {*/ struct string_list in_body_headers;int graph_width; +const struct commit *diff_parent; + unsigned diff_queue_present:1; };/* Check whether commit format is mail. */
@@ -75,6 +77,7 @@ struct userformat_want { unsigned notes:1; unsigned source:1; unsigned decorate:1; + unsigned diffstat:1; };void userformat_find_requirements (const char *fmt,struct userformat_want *w);
t/t4205-log-pretty-formats.sh +162 -0
166 lines not on this page · raw message
base-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0
Signature · 1 line
gitgitgadget
Quoted 17 lines · Andrey Zarubin via GitGitGadget
From: Andrey Zarubin <[email protected]>
Currently, users who want per-commit line/file change counts in a custom log format must post-process
git log --shortstatoutput because the pretty formatter exposes no equivalent placeholders.Introduce
%(diff-stat:files),%(diff-stat:insertions),%(diff-stat:deletions), and%(diff-stat:lines), computed from the same diffstat machinery as--shortstatand cached once per commit during format expansion.Short aliases are provided as
%aF,%aA, and%aR. The requested%aIand%aDforms are unavailable because those names already expand to author dates, so use additions/removals mnemonics instead.
Quoted 8 lines
When log output is already walking a diff, the formatter reuses the current diff queue. Otherwise it computes a private summary lazily, so formats without these placeholders still pay no diff cost.
Signed-off-by Andrey Zarubin <[email protected]>---
pretty: add diff-stat log placeholders
Personally I find this a bit on the other side of the line between sensible and insanity. Will we next be adding a new placeholder to show the summary (i.e. list of created, deleted, and renamed paths) and another placeholder to show the entire patch text?
Quoted 25 lines · Junio C Hamano
Quoted 22 lines · Andrey Zarubin via GitGitGadget
From: Andrey Zarubin <[email protected]>
Currently, users who want per-commit line/file change counts in a custom log format must post-process
git log --shortstatoutput because the pretty formatter exposes no equivalent placeholders.Introduce
%(diff-stat:files),%(diff-stat:insertions),%(diff-stat:deletions), and%(diff-stat:lines), computed from the same diffstat machinery as--shortstatand cached once per commit during format expansion.Short aliases are provided as
%aF,%aA, and%aR. The requested%aIand%aDforms are unavailable because those names already expand to author dates, so use additions/removals mnemonics instead.When log output is already walking a diff, the formatter reuses the current diff queue. Otherwise it computes a private summary lazily, so formats without these placeholders still pay no diff cost.
Quoted 8 lines
Quoted 3 lines
Signed-off-by Andrey Zarubin <[email protected]>---
pretty: add diff-stat log placeholdersPersonally I find this a bit on the other side of the line between sensible and insanity. Will we next be adding a new placeholder to show the summary (i.e. list of created, deleted, and renamed paths) and another placeholder to show the entire patch text?
I see the concern, and I agree that placeholders for --summary or full patch text would cross that line.
The distinction I had in mind is that these are bounded scalar values, not diff output. They are the same three counters already produced by --shortstat, and the main use case is one-line structured log output where today callers have to run git log --shortstat and parse/correlate the human-oriented output after the fact.
Path summaries and patch text are qualitatively different: they are multi-line, formatting-heavy, affected by quoting/color/output choices, and would effectively embed diff output inside the pretty formatter. I would not want this change to imply support for that direction.
If the short aliases make this feel too much like expanding the kitchen sink, I can drop them and keep only the explicit %(diff-stat:<field>) forms. I think the long forms make the intended scope clearer: numeric shortstat counters only.