diff: preparse --diff-filter string argument
Instead of running strchr() on the list of status characters over and over again, parse the --diff-filter option into bitfields and use the bits to see if the change to the filepair matches the status requested. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
08578fa13e
commit
1ecc1cbd3a
63
diff.c
63
diff.c
@ -3496,6 +3496,53 @@ static int parse_submodule_opt(struct diff_options *options, const char *value)
|
|||||||
return 1;
|
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();
|
||||||
|
for (i = 0; (optch = optarg[i]) != '\0'; i++) {
|
||||||
|
unsigned int bit;
|
||||||
|
|
||||||
|
bit = (0 <= optch && optch <= 'Z') ? filter_bit[optch] : 0;
|
||||||
|
if (!bit)
|
||||||
|
continue; /* ignore unknown ones, like we always have */
|
||||||
|
opt->filter |= bit;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||||
{
|
{
|
||||||
const char *arg = av[0];
|
const char *arg = av[0];
|
||||||
@ -3717,7 +3764,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
|||||||
return argcount;
|
return argcount;
|
||||||
}
|
}
|
||||||
else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
|
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;
|
return argcount;
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "--abbrev"))
|
else if (!strcmp(arg, "--abbrev"))
|
||||||
@ -4513,11 +4563,11 @@ static int match_filter(const struct diff_options *options, const struct diff_fi
|
|||||||
{
|
{
|
||||||
return (((p->status == DIFF_STATUS_MODIFIED) &&
|
return (((p->status == DIFF_STATUS_MODIFIED) &&
|
||||||
((p->score &&
|
((p->score &&
|
||||||
strchr(options->filter, DIFF_STATUS_FILTER_BROKEN)) ||
|
filter_bit_tst(DIFF_STATUS_FILTER_BROKEN, options)) ||
|
||||||
(!p->score &&
|
(!p->score &&
|
||||||
strchr(options->filter, DIFF_STATUS_MODIFIED)))) ||
|
filter_bit_tst(DIFF_STATUS_MODIFIED, options)))) ||
|
||||||
((p->status != DIFF_STATUS_MODIFIED) &&
|
((p->status != DIFF_STATUS_MODIFIED) &&
|
||||||
strchr(options->filter, p->status)));
|
filter_bit_tst(p->status, options)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diffcore_apply_filter(struct diff_options *options)
|
static void diffcore_apply_filter(struct diff_options *options)
|
||||||
@ -4525,14 +4575,13 @@ static void diffcore_apply_filter(struct diff_options *options)
|
|||||||
int i;
|
int i;
|
||||||
struct diff_queue_struct *q = &diff_queued_diff;
|
struct diff_queue_struct *q = &diff_queued_diff;
|
||||||
struct diff_queue_struct outq;
|
struct diff_queue_struct outq;
|
||||||
const char *filter = options->filter;
|
|
||||||
|
|
||||||
DIFF_QUEUE_CLEAR(&outq);
|
DIFF_QUEUE_CLEAR(&outq);
|
||||||
|
|
||||||
if (!filter)
|
if (!options->filter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
|
if (filter_bit_tst(DIFF_STATUS_FILTER_AON, options)) {
|
||||||
int found;
|
int found;
|
||||||
for (i = found = 0; !found && i < q->nr; i++) {
|
for (i = found = 0; !found && i < q->nr; i++) {
|
||||||
if (match_filter(options, q->queue[i]))
|
if (match_filter(options, q->queue[i]))
|
||||||
|
5
diff.h
5
diff.h
@ -103,12 +103,15 @@ enum diff_words_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct diff_options {
|
struct diff_options {
|
||||||
const char *filter;
|
|
||||||
const char *orderfile;
|
const char *orderfile;
|
||||||
const char *pickaxe;
|
const char *pickaxe;
|
||||||
const char *single_follow;
|
const char *single_follow;
|
||||||
const char *a_prefix, *b_prefix;
|
const char *a_prefix, *b_prefix;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
|
|
||||||
|
/* diff-filter bits */
|
||||||
|
unsigned int filter;
|
||||||
|
|
||||||
int use_color;
|
int use_color;
|
||||||
int context;
|
int context;
|
||||||
int interhunkcontext;
|
int interhunkcontext;
|
||||||
|
Loading…
Reference in New Issue
Block a user