builtin rebase: support the `verbose` and `diffstat` options

This commit introduces support for the `-v` and `--stat` options of rebase. The --stat option can also be configured via the Git config setting rebase.stat. To support this, we also add a custom rebase_config() function in this commit that will be used instead of (and falls back to calling) git_default_config(). Signed-off-by: Pratik Karki <predatoramigo@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Pratik Karki committed Sep 4, 2018 at 14:27 UTC bff014dac7d949f9a0b42ab256e04ecf1b4b9bb6
1 file changed +58 -2
builtin/rebase.c
+58 -2
@@ -18,6 +18,7 @@
18 #include "lockfile.h"
19 #include "parse-options.h"
20 #include "commit.h"
21 +#include "diff.h"
22
23 static char const * const builtin_rebase_usage[] = {
24 N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
@@ -81,6 +82,8 @@ struct rebase_options {
82 int dont_finish_rebase;
83 enum {
84 REBASE_NO_QUIET = 1<<0,
85 + REBASE_VERBOSE = 1<<1,
86 + REBASE_DIFFSTAT = 1<<2,
87 } flags;
88 struct strbuf git_am_opt;
89 };
@@ -166,6 +169,10 @@ static int run_specific_rebase(struct rebase_options *opts)
169 add_var(&script_snippet, "GIT_QUIET",
170 opts->flags & REBASE_NO_QUIET ? "" : "t");
171 add_var(&script_snippet, "git_am_opt", opts->git_am_opt.buf);
172 + add_var(&script_snippet, "verbose",
173 + opts->flags & REBASE_VERBOSE ? "t" : "");
174 + add_var(&script_snippet, "diffstat",
175 + opts->flags & REBASE_DIFFSTAT ? "t" : "");
176
177 switch (opts->type) {
178 case REBASE_AM:
@@ -311,6 +318,21 @@ static int reset_head(struct object_id *oid, const char *action,
318 return ret;
319 }
320
321 +static int rebase_config(const char *var, const char *value, void *data)
322 +{
323 + struct rebase_options *opts = data;
324 +
325 + if (!strcmp(var, "rebase.stat")) {
326 + if (git_config_bool(var, value))
327 + opts->flags |= REBASE_DIFFSTAT;
328 + else
329 + opts->flags &= !REBASE_DIFFSTAT;
330 + return 0;
331 + }
332 +
333 + return git_default_config(var, value, data);
334 +}
335 +
336 int cmd_rebase(int argc, const char **argv, const char *prefix)
337 {
338 struct rebase_options options = {
@@ -332,7 +354,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
354 N_("allow pre-rebase hook to run")),
355 OPT_NEGBIT('q', "quiet", &options.flags,
356 N_("be quiet. implies --no-stat"),
335 - REBASE_NO_QUIET),
357 + REBASE_NO_QUIET| REBASE_VERBOSE | REBASE_DIFFSTAT),
358 + OPT_BIT('v', "verbose", &options.flags,
359 + N_("display a diffstat of what changed upstream"),
360 + REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
361 + {OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL,
362 + N_("do not show diffstat of what changed upstream"),
363 + PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
364 OPT_END(),
365 };
366
@@ -360,7 +388,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
388 trace_repo_setup(prefix);
389 setup_work_tree();
390
363 - git_config(git_default_config, NULL);
391 + git_config(rebase_config, &options);
392 +
393 argc = parse_options(argc, argv, prefix,
394 builtin_rebase_options,
395 builtin_rebase_usage, 0);
@@ -456,6 +485,33 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
485 argc ? argv[0] : NULL, NULL))
486 die(_("The pre-rebase hook refused to rebase."));
487
488 + if (options.flags & REBASE_DIFFSTAT) {
489 + struct diff_options opts;
490 +
491 + if (options.flags & REBASE_VERBOSE)
492 + printf(_("Changes from %s to %s:\n"),
493 + oid_to_hex(&merge_base),
494 + oid_to_hex(&options.onto->object.oid));
495 +
496 + /* We want color (if set), but no pager */
497 + diff_setup(&opts);
498 + opts.stat_width = -1; /* use full terminal width */
499 + opts.stat_graph_width = -1; /* respect statGraphWidth config */
500 + opts.output_format |=
501 + DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
502 + opts.detect_rename = DIFF_DETECT_RENAME;
503 + diff_setup_done(&opts);
504 + diff_tree_oid(&merge_base, &options.onto->object.oid,
505 + "", &opts);
506 + diffcore_std(&opts);
507 + diff_flush(&opts);
508 + }
509 +
510 + /* Detach HEAD and reset the tree */
511 + if (options.flags & REBASE_NO_QUIET)
512 + printf(_("First, rewinding head to replay your work on top of "
513 + "it...\n"));
514 +
515 strbuf_addf(&msg, "rebase: checkout %s", options.onto_name);
516 if (reset_head(&options.onto->object.oid, "checkout", NULL, 1))
517 die(_("Could not detach HEAD"));