From: "Michał Kępień" <michal@isc.org>
To: git@vger.kernel.org
Subject: [PATCH 1/2] diff: add -I<regex> that ignores matching changes
Date: Thu, 1 Oct 2020 14:06:05 +0200 [thread overview]
Message-ID: <20201001120606.25773-2-michal@isc.org> (raw)
In-Reply-To: <20201001120606.25773-1-michal@isc.org>
Add a new diff option that enables ignoring changes whose all lines
(changed, removed, and added) match a given regular expression. This is
similar to the -I option in standalone diff utilities and can be used
e.g. to look for unrelated changes in commits containing a large number
of automatically applied modifications (e.g. a tree-wide string
replacement). The difference between -G/-S and the new -I option is
that the latter filters output on a per-change basis.
Use the 'ignore' field of xdchange_t for marking a change as ignored or
not. Since the same field is used by --ignore-blank-lines, identical
hunk emitting rules apply for --ignore-blank-lines and -I. These two
options can also be used together at the same time.
Apart from adding a new field to struct diff_options, also define a new
flag, XDF_IGNORE_REGEX, for the 'xdl_opts' field of that structure.
This is done because the xpparam_t structure (which is used for passing
around the regular expression supplied to -I) is not zeroed out in all
call stacks involving xdl_diff() and thus only performing a NULL check
on xpp->ignore_regex could result in xdl_mark_ignorable_regex() treating
garbage on the stack as a regular expression. As the 'flags' field of
xpparam_t is initialized in all call stacks involving xdl_diff(), adding
a flag check avoids that problem.
Signed-off-by: Michał Kępień <michal@isc.org>
---
Documentation/diff-options.txt | 3 +++
diff.c | 16 +++++++++++++++
diff.h | 2 ++
xdiff/xdiff.h | 2 ++
xdiff/xdiffi.c | 36 ++++++++++++++++++++++++++++++++++
5 files changed, 59 insertions(+)
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 573fb9bb71..a7ef3f5645 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -687,6 +687,9 @@ endif::git-format-patch[]
--ignore-blank-lines::
Ignore changes whose lines are all blank.
+-I<regex>::
+ Ignore changes whose all lines match <regex>.
+
--inter-hunk-context=<lines>::
Show the context between diff hunks, up to the specified number
of lines, thereby fusing hunks that are close to each other.
diff --git a/diff.c b/diff.c
index 2bb2f8f57e..c9603c941e 100644
--- a/diff.c
+++ b/diff.c
@@ -3587,6 +3587,7 @@ static void builtin_diff(const char *name_a,
if (header.len && !o->flags.suppress_diff_headers)
ecbdata.header = &header;
xpp.flags = o->xdl_opts;
+ xpp.ignore_regex = o->ignore_regex;
xpp.anchors = o->anchors;
xpp.anchors_nr = o->anchors_nr;
xecfg.ctxlen = o->context;
@@ -3716,6 +3717,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
xpp.flags = o->xdl_opts;
+ xpp.ignore_regex = o->ignore_regex;
xpp.anchors = o->anchors;
xpp.anchors_nr = o->anchors_nr;
xecfg.ctxlen = o->context;
@@ -5203,6 +5205,17 @@ static int diff_opt_patience(const struct option *opt,
return 0;
}
+static int diff_opt_ignore_regex(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct diff_options *options = opt->value;
+
+ BUG_ON_OPT_NEG(unset);
+ options->xdl_opts |= XDF_IGNORE_REGEX;
+ options->ignore_regex = arg;
+ return 0;
+}
+
static int diff_opt_pickaxe_regex(const struct option *opt,
const char *arg, int unset)
{
@@ -5491,6 +5504,9 @@ static void prep_parse_options(struct diff_options *options)
OPT_BIT_F(0, "ignore-blank-lines", &options->xdl_opts,
N_("ignore changes whose lines are all blank"),
XDF_IGNORE_BLANK_LINES, PARSE_OPT_NONEG),
+ OPT_CALLBACK_F('I', NULL, options, N_("<regex>"),
+ N_("ignore changes whose all lines match <regex>"),
+ 0, diff_opt_ignore_regex),
OPT_BIT(0, "indent-heuristic", &options->xdl_opts,
N_("heuristic to shift diff hunk boundaries for easy reading"),
XDF_INDENT_HEURISTIC),
diff --git a/diff.h b/diff.h
index 3de343270f..0b8871c0c1 100644
--- a/diff.h
+++ b/diff.h
@@ -234,6 +234,8 @@ struct diff_options {
*/
const char *pickaxe;
+ const char *ignore_regex;
+
const char *single_follow;
const char *a_prefix, *b_prefix;
const char *line_prefix;
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 032e3a9f41..db28055a5e 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -40,6 +40,7 @@ extern "C" {
XDF_IGNORE_CR_AT_EOL)
#define XDF_IGNORE_BLANK_LINES (1 << 7)
+#define XDF_IGNORE_REGEX (1 << 8)
#define XDF_PATIENCE_DIFF (1 << 14)
#define XDF_HISTOGRAM_DIFF (1 << 15)
@@ -78,6 +79,7 @@ typedef struct s_mmbuffer {
typedef struct s_xpparam {
unsigned long flags;
+ const char *ignore_regex;
/* See Documentation/diff-options.txt. */
char **anchors;
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index bd035139f9..13f7ab95ac 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -1019,6 +1019,39 @@ static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
}
}
+static void
+xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
+ const char *ignore_regex)
+{
+ xdchange_t *xch;
+ regex_t regex;
+
+ if (regcomp(®ex, ignore_regex, REG_EXTENDED | REG_NEWLINE))
+ die("invalid regex: %s", ignore_regex);
+
+ for (xch = xscr; xch; xch = xch->next) {
+ regmatch_t regmatch;
+ xrecord_t **rec;
+ int ignore = 1;
+ long i;
+
+ rec = &xe->xdf1.recs[xch->i1];
+ for (i = 0; i < xch->chg1 && ignore; i++)
+ ignore = !regexec_buf(®ex, rec[i]->ptr, rec[i]->size,
+ 1, ®match, 0);
+
+ rec = &xe->xdf2.recs[xch->i2];
+ for (i = 0; i < xch->chg2 && ignore; i++)
+ ignore = !regexec_buf(®ex, rec[i]->ptr, rec[i]->size,
+ 1, ®match, 0);
+
+ /*
+ * Do not override --ignore-blank-lines.
+ */
+ xch->ignore |= ignore;
+ }
+}
+
int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
xdchange_t *xscr;
@@ -1040,6 +1073,9 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
if (xpp->flags & XDF_IGNORE_BLANK_LINES)
xdl_mark_ignorable(xscr, &xe, xpp->flags);
+ if ((xpp->flags & XDF_IGNORE_REGEX) && xpp->ignore_regex)
+ xdl_mark_ignorable_regex(xscr, &xe, xpp->ignore_regex);
+
if (ef(&xe, xscr, ecb, xecfg) < 0) {
xdl_free_script(xscr);
--
2.28.0
next prev parent reply other threads:[~2020-10-01 12:45 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-01 12:06 [PATCH 0/2] diff: add -I<regex> that ignores matching changes Michał Kępień
2020-10-01 12:06 ` Michał Kępień [this message]
2020-10-01 18:21 ` [PATCH 1/2] " Junio C Hamano
2020-10-07 19:48 ` Michał Kępień
2020-10-07 20:08 ` Junio C Hamano
2020-10-01 12:06 ` [PATCH 2/2] t: add -I<regex> tests Michał Kępień
2020-10-01 17:02 ` [PATCH 0/2] diff: add -I<regex> that ignores matching changes Junio C Hamano
2020-10-12 9:17 ` [PATCH v2 0/3] " Michał Kępień
2020-10-12 9:17 ` [PATCH v2 1/3] merge-base, xdiff: zero out xpparam_t structures Michał Kępień
2020-10-12 11:14 ` Johannes Schindelin
2020-10-12 17:09 ` Junio C Hamano
2020-10-12 19:52 ` Junio C Hamano
2020-10-13 6:35 ` Michał Kępień
2020-10-12 9:17 ` [PATCH v2 2/3] diff: add -I<regex> that ignores matching changes Michał Kępień
2020-10-12 11:20 ` Johannes Schindelin
2020-10-12 20:00 ` Junio C Hamano
2020-10-12 20:39 ` Johannes Schindelin
2020-10-12 21:43 ` Junio C Hamano
2020-10-13 6:37 ` Michał Kępień
2020-10-13 15:49 ` Junio C Hamano
2020-10-13 6:36 ` Michał Kępień
2020-10-13 12:02 ` Johannes Schindelin
2020-10-13 15:53 ` Junio C Hamano
2020-10-13 18:45 ` Michał Kępień
2020-10-12 18:01 ` Junio C Hamano
2020-10-13 6:38 ` Michał Kępień
2020-10-12 20:04 ` Junio C Hamano
2020-10-13 6:38 ` Michał Kępień
2020-10-12 9:17 ` [PATCH v2 3/3] t: add -I<regex> tests Michał Kępień
2020-10-12 11:49 ` Johannes Schindelin
2020-10-13 6:38 ` Michał Kępień
2020-10-13 12:00 ` Johannes Schindelin
2020-10-13 16:00 ` Junio C Hamano
2020-10-13 19:01 ` Michał Kępień
2020-10-15 11:45 ` Johannes Schindelin
2020-10-15 7:24 ` [PATCH v3 0/2] diff: add -I<regex> that ignores matching changes Michał Kępień
2020-10-15 7:24 ` [PATCH v3 1/2] merge-base, xdiff: zero out xpparam_t structures Michał Kępień
2020-10-15 7:24 ` [PATCH v3 2/2] diff: add -I<regex> that ignores matching changes Michał Kępień
2020-10-16 15:32 ` Phillip Wood
2020-10-16 18:04 ` Junio C Hamano
2020-10-19 9:48 ` Michał Kępień
2020-10-16 18:16 ` Junio C Hamano
2020-10-19 9:55 ` Michał Kępień
2020-10-19 17:29 ` Junio C Hamano
2020-10-16 10:00 ` [PATCH v3 0/2] " Johannes Schindelin
2020-10-20 6:48 ` [PATCH v4 " Michał Kępień
2020-10-20 6:48 ` [PATCH v4 1/2] merge-base, xdiff: zero out xpparam_t structures Michał Kępień
2020-10-20 6:48 ` [PATCH v4 2/2] diff: add -I<regex> that ignores matching changes Michał Kępień
2021-02-05 14:13 ` [PATCH 1/2] diff: add an API for deferred freeing Ævar Arnfjörð Bjarmason
2021-02-10 16:00 ` Johannes Schindelin
2021-02-11 3:00 ` Ævar Arnfjörð Bjarmason
2021-02-11 9:40 ` Johannes Schindelin
2021-02-11 10:21 ` Jeff King
2021-02-11 10:45 ` [PATCH v2 0/2] " Ævar Arnfjörð Bjarmason
2021-02-11 10:45 ` [PATCH v2 1/2] " Ævar Arnfjörð Bjarmason
2021-02-11 10:45 ` [PATCH v2 2/2] diff: plug memory leak from regcomp() on {log,diff} -I Ævar Arnfjörð Bjarmason
2021-02-05 14:13 ` [PATCH " Ævar Arnfjörð Bjarmason
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=20201001120606.25773-2-michal@isc.org \
--to=michal@isc.org \
--cc=git@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.