@matheusbsbs / matheus-bagliano / commits / 333f3fb0c5
Fork 0

Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-file

Instead of having multiple interconnected dirstat-related options, teach the --dirstat option itself to accept all behavior modifiers as parameters. - Preserve the current --dirstat=<limit> (where <limit> is an integer specifying a cut-off percentage) - Add --dirstat=cumulative, replacing --cumulative - Add --dirstat=files, replacing --dirstat-by-file - Also add --dirstat=changes and --dirstat=noncumulative for specifying the current default behavior. These allow the user to reset other --dirstat parameters (e.g. 'cumulative' and 'files') occuring earlier on the command line. The deprecated options (--cumulative and --dirstat-by-file) are still functional, although they have been removed from the documentation. Allow multiple parameters to be separated by commas, e.g.: --dirstat=files,10,cumulative Update the documentation accordingly, and add testcases verifying the behavior of the new syntax. Improved-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johan Herland committed Apr 29, 2011 at 11:36 UTC 333f3fb0c5307fed170cae336ab3c056f4d6ca1c
3 files changed +214 -22
Documentation/diff-options.txt
+32 -12
@@ -66,19 +66,39 @@ endif::git-format-patch[]
66 number of modified files, as well as number of added and deleted
67 lines.
68
69 ---dirstat[=<limit>]::
70 - Output the distribution of relative amount of changes (number of lines added or
71 - removed) for each sub-directory. Directories with changes below
72 - a cut-off percent (3% by default) are not shown. The cut-off percent
73 - can be set with `--dirstat=<limit>`. Changes in a child directory are not
74 - counted for the parent directory, unless `--cumulative` is used.
69 +--dirstat[=<param1,param2,...>]::
70 + Output the distribution of relative amount of changes for each
71 + sub-directory. The behavior of `--dirstat` can be customized by
72 + passing it a comma separated list of parameters.
73 + The following parameters are available:
74 +
76 -Note that the `--dirstat` option computes the changes while ignoring
77 -the amount of pure code movements within a file. In other words,
78 -rearranging lines in a file is not counted as much as other changes.
79 -
80 ---dirstat-by-file[=<limit>]::
81 - Same as `--dirstat`, but counts changed files instead of lines.
75 +--
76 +`changes`;;
77 + Compute the dirstat numbers by counting the lines that have been
78 + removed from the source, or added to the destination. This ignores
79 + the amount of pure code movements within a file. In other words,
80 + rearranging lines in a file is not counted as much as other changes.
81 + This is the default behavior when no parameter is given.
82 +`files`;;
83 + Compute the dirstat numbers by counting the number of files changed.
84 + Each changed file counts equally in the dirstat analysis. This is
85 + the computationally cheapest `--dirstat` behavior, since it does
86 + not have to look at the file contents at all.
87 +`cumulative`;;
88 + Count changes in a child directory for the parent directory as well.
89 + Note that when using `cumulative`, the sum of the percentages
90 + reported may exceed 100%. The default (non-cumulative) behavior can
91 + be specified with the `noncumulative` parameter.
92 +<limit>;;
93 + An integer parameter specifies a cut-off percent (3% by default).
94 + Directories contributing less than this percentage of the changes
95 + are not shown in the output.
96 +--
97 ++
98 +Example: The following will count changed files, while ignoring
99 +directories with less than 10% of the total amount of changed files,
100 +and accumulating child directory counts in the parent directories:
101 +`--dirstat=files,10,cumulative`.
102
103 --summary::
104 Output a condensed summary of extended header information
diff.c
+60 -9
@@ -66,6 +66,41 @@ static int parse_diff_color_slot(const char *var, int ofs)
66 return -1;
67 }
68
69 +static int parse_dirstat_params(struct diff_options *options, const char *params)
70 +{
71 + const char *p = params;
72 + while (*p) {
73 + if (!prefixcmp(p, "changes")) {
74 + p += 7;
75 + DIFF_OPT_CLR(options, DIRSTAT_BY_FILE);
76 + } else if (!prefixcmp(p, "files")) {
77 + p += 5;
78 + DIFF_OPT_SET(options, DIRSTAT_BY_FILE);
79 + } else if (!prefixcmp(p, "noncumulative")) {
80 + p += 13;
81 + DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE);
82 + } else if (!prefixcmp(p, "cumulative")) {
83 + p += 10;
84 + DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
85 + } else if (isdigit(*p)) {
86 + char *end;
87 + options->dirstat_percent = strtoul(p, &end, 10);
88 + p = end;
89 + } else
90 + return error("Unknown --dirstat parameter '%s'", p);
91 +
92 + if (*p) {
93 + /* more parameters, swallow separator */
94 + if (*p != ',')
95 + return error("Missing comma separator at char "
96 + "%"PRIuMAX" of '%s'",
97 + (uintmax_t) (p - params), params);
98 + p++;
99 + }
100 + }
101 + return 0;
102 +}
103 +
104 static int git_config_rename(const char *var, const char *value)
105 {
106 if (!value)
@@ -3149,6 +3184,18 @@ static int stat_opt(struct diff_options *options, const char **av)
3184 return argcount;
3185 }
3186
3187 +static int parse_dirstat_opt(struct diff_options *options, const char *params)
3188 +{
3189 + if (parse_dirstat_params(options, params))
3190 + die("Failed to parse --dirstat/-X option parameter");
3191 + /*
3192 + * The caller knows a dirstat-related option is given from the command
3193 + * line; allow it to say "return this_function();"
3194 + */
3195 + options->output_format |= DIFF_FORMAT_DIRSTAT;
3196 + return 1;
3197 +}
3198 +
3199 int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3200 {
3201 const char *arg = av[0];
@@ -3168,15 +3215,19 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3215 options->output_format |= DIFF_FORMAT_NUMSTAT;
3216 else if (!strcmp(arg, "--shortstat"))
3217 options->output_format |= DIFF_FORMAT_SHORTSTAT;
3171 - else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent))
3172 - options->output_format |= DIFF_FORMAT_DIRSTAT;
3173 - else if (!strcmp(arg, "--cumulative")) {
3174 - options->output_format |= DIFF_FORMAT_DIRSTAT;
3175 - DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
3176 - } else if (opt_arg(arg, 0, "dirstat-by-file",
3177 - &options->dirstat_percent)) {
3178 - options->output_format |= DIFF_FORMAT_DIRSTAT;
3179 - DIFF_OPT_SET(options, DIRSTAT_BY_FILE);
3218 + else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
3219 + return parse_dirstat_opt(options, "");
3220 + else if (!prefixcmp(arg, "-X"))
3221 + return parse_dirstat_opt(options, arg + 2);
3222 + else if (!prefixcmp(arg, "--dirstat="))
3223 + return parse_dirstat_opt(options, arg + 10);
3224 + else if (!strcmp(arg, "--cumulative"))
3225 + return parse_dirstat_opt(options, "cumulative");
3226 + else if (!strcmp(arg, "--dirstat-by-file"))
3227 + return parse_dirstat_opt(options, "files");
3228 + else if (!prefixcmp(arg, "--dirstat-by-file=")) {
3229 + parse_dirstat_opt(options, "files");
3230 + return parse_dirstat_opt(options, arg + 18);
3231 }
3232 else if (!strcmp(arg, "--check"))
3233 options->output_format |= DIFF_FORMAT_CHECKDIFF;
t/t4047-diff-dirstat.sh
+122 -1
@@ -330,7 +330,9 @@ EOF
330
331 test_expect_success 'various ways to misspell --dirstat' '
332 test_must_fail git show --dirstat10 &&
333 - test_must_fail git show -X=20
333 + test_must_fail git show --dirstat10,files &&
334 + test_must_fail git show -X=20 &&
335 + test_must_fail git show -X=20,cumulative
336 '
337
338 test_expect_success 'vanilla --dirstat' '
@@ -351,6 +353,39 @@ test_expect_success 'vanilla -X' '
353 test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
354 '
355
356 +test_expect_success 'explicit defaults: --dirstat=changes,noncumulative,3' '
357 + git diff --dirstat=changes,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat &&
358 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
359 + git diff --dirstat=changes,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M &&
360 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
361 + git diff --dirstat=changes,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
362 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
363 +'
364 +
365 +test_expect_success 'explicit defaults: -Xchanges,noncumulative,3' '
366 + git diff -Xchanges,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat &&
367 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
368 + git diff -Xchanges,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M &&
369 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
370 + git diff -Xchanges,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
371 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
372 +'
373 +
374 +test_expect_success 'later options override earlier options:' '
375 + git diff --dirstat=files,10,cumulative,changes,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat &&
376 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
377 + git diff --dirstat=files,10,cumulative,changes,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M &&
378 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
379 + git diff --dirstat=files,10,cumulative,changes,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
380 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
381 + git diff --dirstat=files --dirstat=10 --dirstat=cumulative --dirstat=changes --dirstat=noncumulative -X3 HEAD^..HEAD >actual_diff_dirstat &&
382 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
383 + git diff --dirstat=files --dirstat=10 --dirstat=cumulative --dirstat=changes --dirstat=noncumulative -X3 -M HEAD^..HEAD >actual_diff_dirstat_M &&
384 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
385 + git diff --dirstat=files --dirstat=10 --dirstat=cumulative --dirstat=changes --dirstat=noncumulative -X3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
386 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
387 +'
388 +
389 cat <<EOF >expect_diff_dirstat
390 2.1% changed/
391 10.8% dst/copy/changed/
@@ -454,6 +489,24 @@ test_expect_success '--dirstat=0 --cumulative' '
489 test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
490 '
491
492 +test_expect_success '--dirstat=0,cumulative' '
493 + git diff --dirstat=0,cumulative HEAD^..HEAD >actual_diff_dirstat &&
494 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
495 + git diff --dirstat=0,cumulative -M HEAD^..HEAD >actual_diff_dirstat_M &&
496 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
497 + git diff --dirstat=0,cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
498 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
499 +'
500 +
501 +test_expect_success '-X0,cumulative' '
502 + git diff -X0,cumulative HEAD^..HEAD >actual_diff_dirstat &&
503 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
504 + git diff -X0,cumulative -M HEAD^..HEAD >actual_diff_dirstat_M &&
505 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
506 + git diff -X0,cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
507 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
508 +'
509 +
510 cat <<EOF >expect_diff_dirstat
511 9.0% changed/
512 9.0% dst/copy/changed/
@@ -496,6 +549,15 @@ test_expect_success '--dirstat-by-file' '
549 test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
550 '
551
552 +test_expect_success '--dirstat=files' '
553 + git diff --dirstat=files HEAD^..HEAD >actual_diff_dirstat &&
554 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
555 + git diff --dirstat=files -M HEAD^..HEAD >actual_diff_dirstat_M &&
556 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
557 + git diff --dirstat=files -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
558 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
559 +'
560 +
561 cat <<EOF >expect_diff_dirstat
562 27.2% dst/copy/
563 27.2% dst/move/
@@ -530,6 +592,15 @@ test_expect_success '--dirstat-by-file=10' '
592 test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
593 '
594
595 +test_expect_success '--dirstat=files,10' '
596 + git diff --dirstat=files,10 HEAD^..HEAD >actual_diff_dirstat &&
597 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
598 + git diff --dirstat=files,10 -M HEAD^..HEAD >actual_diff_dirstat_M &&
599 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
600 + git diff --dirstat=files,10 -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
601 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
602 +'
603 +
604 cat <<EOF >expect_diff_dirstat
605 9.0% changed/
606 9.0% dst/copy/changed/
@@ -582,4 +653,54 @@ test_expect_success '--dirstat-by-file --cumulative' '
653 test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
654 '
655
656 +test_expect_success '--dirstat=files,cumulative' '
657 + git diff --dirstat=files,cumulative HEAD^..HEAD >actual_diff_dirstat &&
658 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
659 + git diff --dirstat=files,cumulative -M HEAD^..HEAD >actual_diff_dirstat_M &&
660 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
661 + git diff --dirstat=files,cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
662 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
663 +'
664 +
665 +cat <<EOF >expect_diff_dirstat
666 + 27.2% dst/copy/
667 + 27.2% dst/move/
668 + 54.5% dst/
669 + 27.2% src/move/
670 +EOF
671 +
672 +cat <<EOF >expect_diff_dirstat_M
673 + 14.2% changed/
674 + 14.2% dst/copy/changed/
675 + 14.2% dst/copy/rearranged/
676 + 14.2% dst/copy/unchanged/
677 + 42.8% dst/copy/
678 + 14.2% dst/move/changed/
679 + 14.2% dst/move/rearranged/
680 + 28.5% dst/move/
681 + 71.4% dst/
682 + 14.2% rearranged/
683 +EOF
684 +
685 +cat <<EOF >expect_diff_dirstat_CC
686 + 16.6% changed/
687 + 16.6% dst/copy/changed/
688 + 16.6% dst/copy/rearranged/
689 + 33.3% dst/copy/
690 + 16.6% dst/move/changed/
691 + 16.6% dst/move/rearranged/
692 + 33.3% dst/move/
693 + 66.6% dst/
694 + 16.6% rearranged/
695 +EOF
696 +
697 +test_expect_success '--dirstat=files,cumulative,10' '
698 + git diff --dirstat=files,cumulative,10 HEAD^..HEAD >actual_diff_dirstat &&
699 + test_cmp expect_diff_dirstat actual_diff_dirstat &&
700 + git diff --dirstat=files,cumulative,10 -M HEAD^..HEAD >actual_diff_dirstat_M &&
701 + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M &&
702 + git diff --dirstat=files,cumulative,10 -C -C HEAD^..HEAD >actual_diff_dirstat_CC &&
703 + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC
704 +'
705 +
706 test_done