From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: Stefan Beller <stefanbeller@googlemail.com>
Subject: [PATCH 3/6] diff: preparse --diff-filter string argument
Date: Wed, 17 Jul 2013 17:30:03 -0700 [thread overview]
Message-ID: <1374107406-14357-4-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1374107406-14357-1-git-send-email-gitster@pobox.com>
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>
---
diff.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
diff.h | 5 ++++-
2 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/diff.c b/diff.c
index 0220c19..03f10e6 100644
--- a/diff.c
+++ b/diff.c
@@ -3496,6 +3496,53 @@ 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();
+ 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)
{
const char *arg = av[0];
@@ -3717,7 +3764,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"))
@@ -4513,11 +4563,11 @@ static int match_filter(const struct diff_options *options, const struct diff_fi
{
return (((p->status == DIFF_STATUS_MODIFIED) &&
((p->score &&
- strchr(options->filter, DIFF_STATUS_FILTER_BROKEN)) ||
+ filter_bit_tst(DIFF_STATUS_FILTER_BROKEN, options)) ||
(!p->score &&
- strchr(options->filter, DIFF_STATUS_MODIFIED)))) ||
+ filter_bit_tst(DIFF_STATUS_MODIFIED, options)))) ||
((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)
@@ -4525,14 +4575,13 @@ static void diffcore_apply_filter(struct diff_options *options)
int i;
struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq;
- const char *filter = options->filter;
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++) {
if (match_filter(options, q->queue[i]))
diff --git a/diff.h b/diff.h
index 78b4091..a367207 100644
--- a/diff.h
+++ b/diff.h
@@ -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;
--
1.8.3.3-962-gf04df43
next prev parent reply other threads:[~2013-07-18 0:30 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-14 21:35 [PATCH 1/4] daemon.c:handle: Remove unneeded check for null pointer Stefan Beller
2013-07-14 21:35 ` [PATCH 2/4] commit: Fix a memory leak in determine_author_info Stefan Beller
2013-07-14 21:49 ` Jonathan Nieder
2013-07-14 21:35 ` [PATCH 3/4] diff-no-index: Remove unused variable Stefan Beller
2013-07-14 22:07 ` Jonathan Nieder
2013-07-16 10:28 ` [PATCH 0/2] git diff -q option removal Stefan Beller
2013-07-16 10:28 ` [PATCH 1/2] diff --no-index: remove nonfunctional "-q" handling Stefan Beller
2013-07-16 10:28 ` [PATCH 2/2] diff: Remove -q to stay silent on missing files Stefan Beller
2013-07-17 17:04 ` [PATCH 0/2] git diff -q option removal Junio C Hamano
2013-07-17 18:06 ` Junio C Hamano
2013-07-17 20:05 ` Stefan Beller
2013-07-18 0:30 ` [PATCH 0/6] Deprecating "diff-files -q" Junio C Hamano
2013-07-18 0:30 ` [PATCH 1/6] diff: pass the whole diff_options to diffcore_apply_filter() Junio C Hamano
2013-07-18 0:30 ` [PATCH 2/6] diff: factor out match_filter() Junio C Hamano
2013-07-18 0:30 ` Junio C Hamano [this message]
2013-07-18 0:30 ` [PATCH 4/6] diff: reject unknown change class given to --diff-filter Junio C Hamano
2013-07-18 0:30 ` [PATCH 5/6] diff: allow lowercase letter to specify what change class to exclude Junio C Hamano
2013-07-18 0:30 ` [PATCH 6/6] diff: deprecate -q option to diff-files Junio C Hamano
2013-07-19 3:20 ` [PATCH 7/6] diff: remove "diff-files -q" at Git 2.0 version boundary Junio C Hamano
2013-07-19 3:31 ` [PATCH 6/6] diff: deprecate -q option to diff-files Jonathan Nieder
2013-07-19 7:24 ` Junio C Hamano
2013-07-19 21:01 ` Jonathan Nieder
2013-07-14 21:35 ` [PATCH 4/4] diff.c: Do not initialize a variable, which gets reassigned anyway Stefan Beller
2013-07-14 22:18 ` Jonathan Nieder
2013-07-14 21:48 ` [PATCH 1/4] daemon.c:handle: Remove unneeded check for null pointer Jonathan Nieder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1374107406-14357-4-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=stefanbeller@googlemail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).