提交 01a2a03c 编写于 作者: J Junio C Hamano

Merge branch 'jc/diff-filter-negation'

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()
......@@ -87,10 +87,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
{
int entries, i;
int diff_unmerged_stage = revs->max_count;
int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
? CE_MATCH_RACY_IS_DIRTY : 0);
if (option & DIFF_SILENT_ON_REMOVED)
handle_deprecated_show_diff_q(&revs->diffopt);
diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
if (diff_unmerged_stage < 0)
......@@ -137,8 +139,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
perror(ce->name);
continue;
}
if (silent_on_removed)
continue;
wt_mode = 0;
}
dpath->mode = wt_mode;
......@@ -204,8 +204,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
perror(ce->name);
continue;
}
if (silent_on_removed)
continue;
diff_addremove(&revs->diffopt, '-', ce->ce_mode,
ce->sha1, !is_null_sha1(ce->sha1),
ce->name, 0);
......
......@@ -187,7 +187,7 @@ void diff_no_index(struct rev_info *revs,
{
int i, prefixlen;
int no_index = 0;
unsigned options = 0;
unsigned deprecated_show_diff_q_option_used = 0;
const char *paths[2];
/* Were we asked to do --no-index explicitly? */
......@@ -225,7 +225,7 @@ void diff_no_index(struct rev_info *revs,
if (!strcmp(argv[i], "--no-index"))
i++;
else if (!strcmp(argv[i], "-q")) {
options |= DIFF_SILENT_ON_REMOVED;
deprecated_show_diff_q_option_used = 1;
i++;
}
else if (!strcmp(argv[i], "--"))
......@@ -260,6 +260,9 @@ void diff_no_index(struct rev_info *revs,
revs->max_count = -2;
diff_setup_done(&revs->diffopt);
if (deprecated_show_diff_q_option_used)
handle_deprecated_show_diff_q(&revs->diffopt);
setup_diff_pager(&revs->diffopt);
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
......
......@@ -3503,6 +3503,88 @@ static int parse_submodule_opt(struct diff_options *options, const char *value)
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;
......@@ -3732,7 +3814,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
return argcount;
}
else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
options->filter = optarg;
int offending = parse_diff_filter_opt(optarg, options);
if (offending)
die("unknown change class '%c' in --diff-filter=%s",
offending, optarg);
return argcount;
}
else if (!strcmp(arg, "--abbrev"))
......@@ -4524,27 +4609,32 @@ void diff_flush(struct diff_options *options)
}
}
static void diffcore_apply_filter(const char *filter)
static int match_filter(const struct diff_options *options, const struct diff_filepair *p)
{
return (((p->status == DIFF_STATUS_MODIFIED) &&
((p->score &&
filter_bit_tst(DIFF_STATUS_FILTER_BROKEN, options)) ||
(!p->score &&
filter_bit_tst(DIFF_STATUS_MODIFIED, options)))) ||
((p->status != DIFF_STATUS_MODIFIED) &&
filter_bit_tst(p->status, options)));
}
static void diffcore_apply_filter(struct diff_options *options)
{
int i;
struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq;
DIFF_QUEUE_CLEAR(&outq);
if (!filter)
if (!options->filter)
return;
if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
if (filter_bit_tst(DIFF_STATUS_FILTER_AON, options)) {
int found;
for (i = found = 0; !found && i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (((p->status == DIFF_STATUS_MODIFIED) &&
((p->score &&
strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
(!p->score &&
strchr(filter, DIFF_STATUS_MODIFIED)))) ||
((p->status != DIFF_STATUS_MODIFIED) &&
strchr(filter, p->status)))
if (match_filter(options, q->queue[i]))
found++;
}
if (found)
......@@ -4562,14 +4652,7 @@ static void diffcore_apply_filter(const char *filter)
/* Only the matching ones */
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (((p->status == DIFF_STATUS_MODIFIED) &&
((p->score &&
strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
(!p->score &&
strchr(filter, DIFF_STATUS_MODIFIED)))) ||
((p->status != DIFF_STATUS_MODIFIED) &&
strchr(filter, p->status)))
if (match_filter(options, p))
diff_q(&outq, p);
else
diff_free_filepair(p);
......@@ -4676,7 +4759,7 @@ void diffcore_std(struct diff_options *options)
if (!options->found_follow)
/* See try_to_follow_renames() in tree-diff.c */
diff_resolve_rename_copy();
diffcore_apply_filter(options->filter);
diffcore_apply_filter(options);
if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
DIFF_OPT_SET(options, HAS_CHANGES);
......
......@@ -103,12 +103,15 @@ enum diff_words_type {
};
struct diff_options {
const char *filter;
const char *orderfile;
const char *pickaxe;
const char *single_follow;
const char *a_prefix, *b_prefix;
unsigned flags;
/* diff-filter bits */
unsigned int filter;
int use_color;
int context;
int interhunkcontext;
......@@ -338,6 +341,8 @@ extern int parse_rename_score(const char **cp_p);
extern long parse_algorithm_value(const char *value);
extern void handle_deprecated_show_diff_q(struct diff_options *);
extern int print_stat_summary(FILE *fp, int files,
int insertions, int deletions);
extern void setup_diff_pager(struct diff_options *);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册