Merge branch 'jc/diff-filter-negation'
authorJunio C Hamano <gitster@pobox.com>
Mon, 9 Sep 2013 21:28:35 +0000 (14:28 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 9 Sep 2013 21:28:35 +0000 (14:28 -0700)
Teach "git diff --diff-filter" to express "I do not want to see
these classes of changes" more directly by listing only the
unwanted ones in lowercase (e.g. "--diff-filter=d" will show
everything but deletion) and deprecate "diff-files -q" which did
the same thing as "--diff-filter=d".

* jc/diff-filter-negation:
diff: deprecate -q option to diff-files
diff: allow lowercase letter to specify what change class to exclude
diff: reject unknown change class given to --diff-filter
diff: preparse --diff-filter string argument
diff: factor out match_filter()
diff: pass the whole diff_options to diffcore_apply_filter()

1  2 
diff-lib.c
diff-no-index.c
diff.c
diff --cc diff-lib.c
Simple merge
diff --cc diff-no-index.c
Simple merge
diff --cc diff.c
index 061694b5ea9f860a03d569b7a6bc438b9bcbf8a7,78819ba1513acbd726076873bab92a5183f2827b..a04a34d0487f231481a7c9c475ac4a3e92b5ed2d
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -3503,11 -3496,88 +3503,93 @@@ static int parse_submodule_opt(struct d
        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];
+ }
+ static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt)
+ {
+       int i, optch;
+       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;
+               if ('a' <= optch && optch <= 'z') {
+                       negate = 1;
+                       optch = toupper(optch);
+               } else {
+                       negate = 0;
+               }
+               bit = (0 <= optch && optch <= 'Z') ? filter_bit[optch] : 0;
+               if (!bit)
+                       return optarg[i];
+               if (negate)
+                       opt->filter &= ~bit;
+               else
+                       opt->filter |= bit;
+       }
+       return 0;
+ }
+ /* Used only by "diff-files" and "diff --no-index" */
+ void handle_deprecated_show_diff_q(struct diff_options *opt)
+ {
+       warning("'diff -q' and 'diff-files -q' are deprecated.");
+       warning("Use 'diff --diff-filter=d' instead to ignore deleted filepairs.");
+       parse_diff_filter_opt("d", opt);
+ }
 +static void enable_patch_output(int *fmt) {
 +      *fmt &= ~DIFF_FORMAT_NO_OUTPUT;
 +      *fmt |= DIFF_FORMAT_PATCH;
 +}
 +
  int diff_opt_parse(struct diff_options *options, const char **av, int ac)
  {
        const char *arg = av[0];