From: "Michael Montalbo via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Michael Montalbo <mmontalbo@gmail.com>,
Michael Montalbo <mmontalbo@gmail.com>
Subject: [PATCH v3 4/7] diff: extract a line-range diff helper for reuse
Date: Thu, 03 Sep 2026 05:05:16 +0000 [thread overview]
Message-ID: <6b13c13ae72a24504aaa23be8d63571e6197aa1e.1788411919.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2152.v3.git.1788411919.gitgitgadget@gmail.com>
From: Michael Montalbo <mmontalbo@gmail.com>
Extract logic for initializing the line-range filter and running a diff
for a specific line range. This logic is needed for any diff that
targets a line range independent of the current patch display path.
The subsequent commits use this logic to enable additional line range
targeted diff modes.
No logical behavior change.
Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
---
diff.c | 87 ++++++++++++++++++++++++++++++++--------------------------
1 file changed, 48 insertions(+), 39 deletions(-)
diff --git a/diff.c b/diff.c
index cb1a85c624..a7604a773a 100644
--- a/diff.c
+++ b/diff.c
@@ -2517,6 +2517,18 @@ static int quick_consume(void *priv, char *line UNUSED, unsigned long len UNUSED
return 1;
}
+static void line_range_filter_init(struct line_range_filter *filter,
+ const struct range_set *ranges,
+ xdiff_emit_line_fn line_fn,
+ void *cb_data)
+{
+ memset(filter, 0, sizeof(*filter));
+ filter->orig_line_fn = line_fn;
+ filter->orig_cb_data = cb_data;
+ filter->range_sets_to_filter_by = ranges;
+ strbuf_init(&filter->accumulating_hunk.lines, 0);
+}
+
static void begin_range_hunk(struct line_range_filter *filter)
{
filter->accumulating_hunk.active = 1;
@@ -2650,6 +2662,37 @@ static int line_range_line_fn(void *priv, char *line, unsigned long len)
return filter->ret;
}
+
+static int line_range_filter_diff(struct line_range_filter *filter,
+ mmfile_t *mf1, mmfile_t *mf2,
+ xpparam_t *xpp, xdemitconf_t *xecfg)
+{
+ const struct range_set *ranges = filter->range_sets_to_filter_by;
+ long max_span = 0;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ranges->nr; i++) {
+ long span = ranges->ranges[i].end - ranges->ranges[i].start;
+ if (span > max_span)
+ max_span = span;
+ }
+ if (max_span > xecfg->ctxlen)
+ xecfg->ctxlen = max_span;
+
+ /* the filter seeds its per-image position from hunk headers */
+ xecfg->flags &= ~XDL_EMIT_NO_HUNK_HDR;
+
+ ret = xdi_diff_outf(mf1, mf2, line_range_hunk_fn,
+ line_range_line_fn, filter, xpp, xecfg);
+ if (!ret) {
+ flush_range_hunk(filter);
+ ret = filter->ret;
+ }
+ strbuf_release(&filter->accumulating_hunk.lines);
+ return ret;
+}
+
static void pprint_rename(struct strbuf *name, const char *a, const char *b)
{
const char *old_name = a;
@@ -3994,49 +4037,15 @@ static void builtin_diff(const char *name_a,
xdi_diff_outf(&mf1, &mf2, NULL, quick_consume,
&ecbdata, &xpp, &xecfg);
} else if (line_ranges) {
- struct line_range_filter lr_state;
- unsigned int i;
- long max_span = 0;
+ struct line_range_filter lr_filter;
- memset(&lr_state, 0, sizeof(lr_state));
- lr_state.orig_line_fn = fn_out_consume;
- lr_state.orig_cb_data = &ecbdata;
- lr_state.range_sets_to_filter_by = line_ranges;
- strbuf_init(&lr_state.accumulating_hunk.lines, 0);
-
- /*
- * Inflate ctxlen so that all changes within
- * any single range are merged into one xdiff
- * hunk and the inter-change context is emitted.
- * The callback clips back to range boundaries.
- *
- * The optimal ctxlen depends on where changes
- * fall within the range, which is only known
- * after xdiff runs; the max range span is the
- * upper bound that guarantees correctness in a
- * single pass.
- */
- for (i = 0; i < line_ranges->nr; i++) {
- long span = line_ranges->ranges[i].end -
- line_ranges->ranges[i].start;
- if (span > max_span)
- max_span = span;
- }
- if (max_span > xecfg.ctxlen)
- xecfg.ctxlen = max_span;
-
- if (xdi_diff_outf(&mf1, &mf2,
- line_range_hunk_fn,
- line_range_line_fn,
- &lr_state, &xpp, &xecfg))
- die("unable to generate diff for %s",
- one->path);
+ line_range_filter_init(&lr_filter, line_ranges,
+ fn_out_consume, &ecbdata);
- flush_range_hunk(&lr_state);
- if (lr_state.ret)
+ if (line_range_filter_diff(&lr_filter, &mf1, &mf2,
+ &xpp, &xecfg))
die("unable to generate diff for %s",
one->path);
- strbuf_release(&lr_state.accumulating_hunk.lines);
} else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
&ecbdata, &xpp, &xecfg))
die("unable to generate diff for %s", one->path);
--
gitgitgadget
next prev parent reply other threads:[~2026-09-03 5:05 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 18:16 [PATCH 0/7] line-log: range-scope stat, check, and -G under -L Michael Montalbo via GitGitGadget
2026-06-18 18:16 ` [PATCH 1/7] diff: rename and group the line-range filter for clarity Michael Montalbo via GitGitGadget
2026-06-18 18:16 ` [PATCH 2/7] diff: simplify the line-range filter by classifying removals immediately Michael Montalbo via GitGitGadget
2026-06-18 18:16 ` [PATCH 3/7] diff: emit -L hunk headers via xdiff's formatter Michael Montalbo via GitGitGadget
2026-06-18 18:16 ` [PATCH 4/7] diff: extract a line-range diff helper for reuse Michael Montalbo via GitGitGadget
2026-06-18 18:16 ` [PATCH 5/7] line-log: support diff stat formats with -L Michael Montalbo via GitGitGadget
2026-06-18 22:00 ` Junio C Hamano
2026-06-23 2:25 ` Michael Montalbo
2026-06-18 18:16 ` [PATCH 6/7] diff: support --check with -L line ranges Michael Montalbo via GitGitGadget
2026-06-18 18:16 ` [PATCH 7/7] diffcore-pickaxe: scope -G to the -L tracked range Michael Montalbo via GitGitGadget
2026-06-27 17:28 ` [PATCH v2 0/7] line-log: scope stat, check, and -G to -L line ranges Michael Montalbo via GitGitGadget
2026-06-27 17:28 ` [PATCH v2 1/7] diff: rename and group the line-range filter for clarity Michael Montalbo via GitGitGadget
2026-06-27 17:28 ` [PATCH v2 2/7] diff: simplify the line-range filter by classifying removals immediately Michael Montalbo via GitGitGadget
2026-06-27 17:28 ` [PATCH v2 3/7] diff: emit -L hunk headers via xdiff's formatter Michael Montalbo via GitGitGadget
2026-06-27 17:28 ` [PATCH v2 4/7] diff: extract a line-range diff helper for reuse Michael Montalbo via GitGitGadget
2026-06-27 17:28 ` [PATCH v2 5/7] line-log: support diff stat formats with -L Michael Montalbo via GitGitGadget
2026-06-27 17:29 ` [PATCH v2 6/7] diff: support --check with -L line ranges Michael Montalbo via GitGitGadget
2026-06-27 17:29 ` [PATCH v2 7/7] diffcore-pickaxe: scope -G to the -L tracked range Michael Montalbo via GitGitGadget
2026-07-15 21:05 ` [PATCH 0/7] line-log: range-scope stat, check, and -G under -L Michael Montalbo
2026-09-03 5:05 ` [PATCH v3 0/7] line-log: scope stat, check, and -G to -L line ranges Michael Montalbo via GitGitGadget
2026-09-03 5:05 ` [PATCH v3 1/7] diff: rename line-range filter struct and clarify fields Michael Montalbo via GitGitGadget
2026-09-03 5:05 ` [PATCH v3 2/7] diff: simplify the line-range filter by classifying removals immediately Michael Montalbo via GitGitGadget
2026-09-03 5:05 ` [PATCH v3 3/7] diff: emit -L hunk headers via xdiff's formatter Michael Montalbo via GitGitGadget
2026-09-03 5:05 ` Michael Montalbo via GitGitGadget [this message]
2026-09-03 5:05 ` [PATCH v3 5/7] diff: support stat formats with -L Michael Montalbo via GitGitGadget
2026-09-03 5:05 ` [PATCH v3 6/7] diff: support --check with -L line ranges Michael Montalbo via GitGitGadget
2026-09-03 5:05 ` [PATCH v3 7/7] diffcore-pickaxe: limit -G to the -L tracked range Michael Montalbo via GitGitGadget
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=6b13c13ae72a24504aaa23be8d63571e6197aa1e.1788411919.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=mmontalbo@gmail.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