Skip to content

Commit

Permalink
Merge branch 'zj/diff-stat-dyncol'
Browse files Browse the repository at this point in the history
By Zbigniew Jędrzejewski-Szmek (8) and Junio C Hamano (1)
* zj/diff-stat-dyncol:
  : This breaks tests. Perhaps it is not worth using the decimal-width stuff
  : for this series, at least initially.
  diff --stat: add config option to limit graph width
  diff --stat: enable limiting of the graph part
  diff --stat: add a test for output with COLUMNS=40
  diff --stat: use a maximum of 5/8 for the filename part
  merge --stat: use the full terminal width
  log --stat: use the full terminal width
  show --stat: use the full terminal width
  diff --stat: use the full terminal width
  diff --stat: tests for long filenames and big change counts
  • Loading branch information
Junio C Hamano committed Mar 6, 2012
2 parents 556c5e0 + df44483 commit af05021
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 33 deletions.
4 changes: 4 additions & 0 deletions Documentation/diff-config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ directories with less than 10% of the total amount of changed files,
and accumulating child directory counts in the parent directories:
`files,10,cumulative`.

diff.statGraphWidth::
Limit the width of the graph part in --stat output. If set, applies
to all commands generating --stat outuput except format-patch.

diff.external::
If this config variable is set, diff generation is not
performed using the internal diff machinery, but using the
Expand Down
18 changes: 12 additions & 6 deletions Documentation/diff-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,19 @@ endif::git-format-patch[]
Generate a diff using the "histogram diff" algorithm.

--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.
Generate a diffstat. By default, as much space as necessary
will be used for the filename part, and the rest for the graph
part. Maximum width defaults to terminal width, or 80 columns
if not connected to a terminal, and can be overriden by
`<width>`. The width of the filename part can be limited by
giving another width `<name-width>` after a comma. The width
of the graph part can be limited by using
`--stat-graph-width=<width>` (affects all commands generating
a stat graph) or by setting `diff.statGraphWidth=<width>`
(does not affect `git format-patch`).
By giving a third parameter `<count>`, you can limit the
output to the first `<count>` lines, followed by
`...` if there are more.
output to the first `<count>` lines, followed by `...` if
there are more.
+
These parameters can also be set individually with `--stat-width=<width>`,
`--stat-name-width=<name-width>` and `--stat-count=<count>`.
Expand Down
4 changes: 4 additions & 0 deletions builtin/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
/* Otherwise, we are doing the usual "git" diff */
rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;

/* Scale to real terminal size and respect statGraphWidth config */
rev.diffopt.stat_width = -1;
rev.diffopt.stat_graph_width = -1;

/* Default to let external and textconv be used */
DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
Expand Down
4 changes: 4 additions & 0 deletions builtin/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ static void cmd_log_init_defaults(struct rev_info *rev)
get_commit_format(fmt_pretty, rev);
rev->verbose_header = 1;
DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
rev->diffopt.stat_width = -1; /* use full terminal width */
rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */
rev->abbrev_commit = default_abbrev_commit;
rev->show_root_diff = default_show_root;
rev->subject_prefix = fmt_patch_subject_prefix;
Expand Down Expand Up @@ -447,6 +449,8 @@ int cmd_show(int argc, const char **argv, const char *prefix)
rev.diff = 1;
rev.always_show_header = 1;
rev.no_walk = 1;
rev.diffopt.stat_width = -1; /* Scale to real terminal size */

memset(&opt, 0, sizeof(opt));
opt.def = "HEAD";
opt.tweak = show_rev_tweak_rev;
Expand Down
2 changes: 2 additions & 0 deletions builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ static void finish(struct commit *head_commit,
if (new_head && show_diffstat) {
struct diff_options opts;
diff_setup(&opts);
opts.stat_width = -1; /* use full terminal width */
opts.stat_graph_width = -1; /* respect statGraphWidth config */
opts.output_format |=
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME;
Expand Down
1 change: 1 addition & 0 deletions contrib/completion/git-completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,7 @@ _git_config ()
core.whitespace
core.worktree
diff.autorefreshindex
diff.statGraphWidth
diff.external
diff.ignoreSubmodules
diff.mnemonicprefix
Expand Down
114 changes: 87 additions & 27 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static const char *external_diff_cmd_cfg;
int diff_auto_refresh_index = 1;
static int diff_mnemonic_prefix;
static int diff_no_prefix;
static int diff_stat_graph_width;
static int diff_dirstat_permille_default = 30;
static struct diff_options default_diff_options;

Expand Down Expand Up @@ -156,6 +157,10 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
diff_no_prefix = git_config_bool(var, value);
return 0;
}
if (!strcmp(var, "diff.statgraphwidth")) {
diff_stat_graph_width = git_config_int(var, value);
return 0;
}
if (!strcmp(var, "diff.external"))
return git_config_string(&external_diff_cmd_cfg, var, value);
if (!strcmp(var, "diff.wordregex"))
Expand Down Expand Up @@ -1375,7 +1380,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, count;
int width, name_width, graph_width, number_width = 4, count;
const char *reset, *add_c, *del_c;
const char *line_prefix = "";
int extra_shown = 0;
Expand All @@ -1389,25 +1394,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
line_prefix = msg->buf;
}

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.
*/
if (width < 25)
width = 25;
if (name_width < 10)
name_width = 10;
else if (width < name_width + 15)
name_width = width - 15;

/* Find the longest filename and max number of changes */
reset = diff_get_color_opt(options, DIFF_RESET);
add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
del_c = diff_get_color_opt(options, DIFF_FILE_OLD);

/*
* Find the longest filename and max number of changes
*/
for (i = 0; (i < count) && (i < data->nr); i++) {
struct diffstat_file *file = data->files[i];
uintmax_t change = file->added + file->deleted;
Expand All @@ -1428,19 +1423,72 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
}
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
* " | count " between the name and the graph.
/*
* We have width = stat_width or term_columns() columns total.
* We want a maximum of min(max_len, stat_name_width) for the name part.
* We want a maximum of min(max_change, stat_graph_width) for the +- part.
* We also need 1 for " " and 4 + decimal_width(max_change)
* for " | NNNN " and one the empty column at the end, altogether
* 6 + decimal_width(max_change).
*
* If there's not enough space, we will use the smaller of
* stat_name_width (if set) and 5/8*width for the filename,
* and the rest for constant elements + graph part, but no more
* than stat_graph_width for the graph part.
* (5/8 gives 50 for filename and 30 for the constant parts + graph
* for the standard terminal size).
*
* From here on, name_width is the width of the name area,
* and width is the width of the graph area.
* In other words: stat_width limits the maximum width, and
* stat_name_width fixes the maximum width of the filename,
* and is also used to divide available columns if there
* aren't enough.
*/
name_width = (name_width < max_len) ? name_width : max_len;
if (width < (name_width + 10) + max_change)
width = width - (name_width + 10);

if (options->stat_width == -1)
width = term_columns();
else
width = max_change;
width = options->stat_width ? options->stat_width : 80;

if (options->stat_graph_width == -1)
options->stat_graph_width = diff_stat_graph_width;

/*
* Guarantee 3/8*16==6 for the graph part
* and 5/8*16==10 for the filename part
*/
if (width < 16 + 6 + number_width)
width = 16 + 6 + number_width;

/*
* First assign sizes that are wanted, ignoring available width.
*/
graph_width = (options->stat_graph_width &&
options->stat_graph_width < max_change) ?
options->stat_graph_width : max_change;
name_width = (options->stat_name_width > 0 &&
options->stat_name_width < max_len) ?
options->stat_name_width : max_len;

/*
* Adjust adjustable widths not to exceed maximum width
*/
if (name_width + number_width + 6 + graph_width > width) {
if (graph_width > width * 3/8 - number_width - 6)
graph_width = width * 3/8 - number_width - 6;
if (options->stat_graph_width &&
graph_width > options->stat_graph_width)
graph_width = options->stat_graph_width;
if (name_width > width - number_width - 6 - graph_width)
name_width = width - number_width - 6 - graph_width;
else
graph_width = width - number_width - 6 - name_width;
}

/*
* From here name_width is the width of the name area,
* and graph_width is the width of the graph area.
* max_change is used to scale graph properly.
*/
for (i = 0; i < count; i++) {
const char *prefix = "";
char *name = data->files[i]->print_name;
Expand Down Expand Up @@ -1496,18 +1544,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
adds += add;
dels += del;

if (width <= max_change) {
if (graph_width <= max_change) {
int total = add + del;

total = scale_linear(add + del, width, max_change);
total = scale_linear(add + del, graph_width, max_change);
if (total < 2 && add && del)
/* width >= 2 due to the sanity check */
total = 2;
if (add < del) {
add = scale_linear(add, width, max_change);
add = scale_linear(add, graph_width, max_change);
del = total - add;
} else {
del = scale_linear(del, width, max_change);
del = scale_linear(del, graph_width, max_change);
add = total - del;
}
}
Expand Down Expand Up @@ -3299,6 +3347,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 graph_width = options->stat_graph_width;
int count = options->stat_count;
int argcount = 1;

Expand Down Expand Up @@ -3327,6 +3376,16 @@ static int stat_opt(struct diff_options *options, const char **av)
name_width = strtoul(av[1], &end, 10);
argcount = 2;
}
} else if (!prefixcmp(arg, "-graph-width")) {
arg += strlen("-graph-width");
if (*arg == '=')
graph_width = strtoul(arg + 1, &end, 10);
else if (!*arg && !av[1])
die("Option '--stat-graph-width' requires a value");
else if (!*arg) {
graph_width = strtoul(av[1], &end, 10);
argcount = 2;
}
} else if (!prefixcmp(arg, "-count")) {
arg += strlen("-count");
if (*arg == '=')
Expand All @@ -3352,6 +3411,7 @@ static int stat_opt(struct diff_options *options, const char **av)
return 0;
options->output_format |= DIFF_FORMAT_DIFFSTAT;
options->stat_name_width = name_width;
options->stat_graph_width = graph_width;
options->stat_width = width;
options->stat_count = count;
return argcount;
Expand Down
1 change: 1 addition & 0 deletions diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ struct diff_options {

int stat_width;
int stat_name_width;
int stat_graph_width;
int stat_count;
const char *word_regex;
enum diff_words_type word_diff;
Expand Down
Loading

0 comments on commit af05021

Please sign in to comment.