diff options
-rw-r--r-- | Documentation/diff-options.txt | 7 | ||||
-rw-r--r-- | diff.c | 97 | ||||
-rw-r--r-- | diff.h | 2 | ||||
-rwxr-xr-x | t/t4202-log.sh | 13 |
4 files changed, 60 insertions, 59 deletions
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 7e27841a95..3674ac48e9 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -628,11 +628,8 @@ ifndef::git-format-patch[] Also, these upper-case letters can be downcased to exclude. E.g. `--diff-filter=ad` excludes added and deleted paths. + -Note that not all diffs can feature all types. For instance, diffs -from the index to the working tree can never have Added entries -(because the set of paths included in the diff is limited by what is in -the index). Similarly, copied and renamed entries cannot appear if -detection for those types is disabled. +Note that not all diffs can feature all types. For instance, copied and +renamed entries cannot appear if detection for those types is disabled. -S<string>:: Look for differences that change the number of occurrences of @@ -4613,6 +4613,43 @@ void repo_diff_setup(struct repository *r, struct diff_options *options) prep_parse_options(options); } +static const char diff_status_letters[] = { + DIFF_STATUS_ADDED, + DIFF_STATUS_COPIED, + DIFF_STATUS_DELETED, + DIFF_STATUS_MODIFIED, + DIFF_STATUS_RENAMED, + DIFF_STATUS_TYPE_CHANGED, + DIFF_STATUS_UNKNOWN, + DIFF_STATUS_UNMERGED, + DIFF_STATUS_FILTER_AON, + DIFF_STATUS_FILTER_BROKEN, + '\0', +}; + +static unsigned int filter_bit['Z' + 1]; + +static void prepare_filter_bits(void) +{ + int i; + + if (!filter_bit[DIFF_STATUS_ADDED]) { + for (i = 0; diff_status_letters[i]; i++) + filter_bit[(int) diff_status_letters[i]] = (1 << i); + } +} + +static unsigned filter_bit_tst(char status, const struct diff_options *opt) +{ + return opt->filter & filter_bit[(int) status]; +} + +unsigned diff_filter_bit(char status) +{ + prepare_filter_bits(); + return filter_bit[(int) status]; +} + void diff_setup_done(struct diff_options *options) { unsigned check_mask = DIFF_FORMAT_NAME | @@ -4726,6 +4763,12 @@ void diff_setup_done(struct diff_options *options) if (!options->use_color || external_diff()) options->color_moved = 0; + if (options->filter_not) { + if (!options->filter) + options->filter = ~filter_bit[DIFF_STATUS_FILTER_AON]; + options->filter &= ~options->filter_not; + } + FREE_AND_NULL(options->parseopts); } @@ -4817,43 +4860,6 @@ static int parse_dirstat_opt(struct diff_options *options, const char *params) return 1; } -static const char diff_status_letters[] = { - DIFF_STATUS_ADDED, - DIFF_STATUS_COPIED, - DIFF_STATUS_DELETED, - DIFF_STATUS_MODIFIED, - DIFF_STATUS_RENAMED, - DIFF_STATUS_TYPE_CHANGED, - DIFF_STATUS_UNKNOWN, - DIFF_STATUS_UNMERGED, - DIFF_STATUS_FILTER_AON, - DIFF_STATUS_FILTER_BROKEN, - '\0', -}; - -static unsigned int filter_bit['Z' + 1]; - -static void prepare_filter_bits(void) -{ - int i; - - if (!filter_bit[DIFF_STATUS_ADDED]) { - for (i = 0; diff_status_letters[i]; i++) - filter_bit[(int) diff_status_letters[i]] = (1 << i); - } -} - -static unsigned filter_bit_tst(char status, const struct diff_options *opt) -{ - return opt->filter & filter_bit[(int) status]; -} - -unsigned diff_filter_bit(char status) -{ - prepare_filter_bits(); - return filter_bit[(int) status]; -} - static int diff_opt_diff_filter(const struct option *option, const char *optarg, int unset) { @@ -4863,21 +4869,6 @@ static int diff_opt_diff_filter(const struct option *option, BUG_ON_OPT_NEG(unset); prepare_filter_bits(); - /* - * If there is a negation e.g. 'd' in the input, and we haven't - * initialized the filter field with another --diff-filter, start - * from full set of bits, except for AON. - */ - if (!opt->filter) { - for (i = 0; (optch = optarg[i]) != '\0'; i++) { - if (optch < 'a' || 'z' < optch) - continue; - opt->filter = (1 << (ARRAY_SIZE(diff_status_letters) - 1)) - 1; - opt->filter &= ~filter_bit[DIFF_STATUS_FILTER_AON]; - break; - } - } - for (i = 0; (optch = optarg[i]) != '\0'; i++) { unsigned int bit; int negate; @@ -4894,7 +4885,7 @@ static int diff_opt_diff_filter(const struct option *option, return error(_("unknown change class '%c' in --diff-filter=%s"), optarg[i], optarg); if (negate) - opt->filter &= ~bit; + opt->filter_not |= bit; else opt->filter |= bit; } @@ -283,7 +283,7 @@ struct diff_options { struct diff_flags flags; /* diff-filter bits */ - unsigned int filter; + unsigned int filter, filter_not; int use_color; diff --git a/t/t4202-log.sh b/t/t4202-log.sh index dc884107de..a20d578349 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -142,6 +142,19 @@ test_expect_success 'diff-filter=R' ' ' +test_expect_success 'multiple --diff-filter bits' ' + + git log -M --pretty="format:%s" --diff-filter=R HEAD >expect && + git log -M --pretty="format:%s" --diff-filter=Ra HEAD >actual && + test_cmp expect actual && + git log -M --pretty="format:%s" --diff-filter=aR HEAD >actual && + test_cmp expect actual && + git log -M --pretty="format:%s" \ + --diff-filter=a --diff-filter=R HEAD >actual && + test_cmp expect actual + +' + test_expect_success 'diff-filter=C' ' git log -C -C --pretty="format:%s" --diff-filter=C HEAD >actual && |