public inbox for git@vger.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "Michael Montalbo via GitGitGadget" <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org,  Michael Montalbo <mmontalbo@gmail.com>
Subject: Re: [PATCH v2 2/4] line-log: route -L output through the standard diff pipeline
Date: Tue, 17 Mar 2026 13:52:01 -0700	[thread overview]
Message-ID: <xmqqecliji1a.fsf@gitster.g> (raw)
In-Reply-To: <4e2bc55082e79654ebf0d30fc00479a5eb29f750.1773714095.git.gitgitgadget@gmail.com> (Michael Montalbo via GitGitGadget's message of "Tue, 17 Mar 2026 02:21:33 +0000")

"Michael Montalbo via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Michael Montalbo <mmontalbo@gmail.com>
>
> `git log -L` has always bypassed the standard diff pipeline.
> `dump_diff_hacky()` in line-log.c hand-rolls its own diff headers and
> hunk output, which means most diff formatting options are silently
> ignored.  A NEEDSWORK comment has acknowledged this since the feature
> was introduced:
>
>     /*
>      * NEEDSWORK: manually building a diff here is not the Right
>      * Thing(tm).  log -L should be built into the diff pipeline.
>      */
>
> Remove `dump_diff_hacky()` and its helpers and route -L output through
> `builtin_diff()` / `fn_out_consume()`, the same path used by `git diff`
> and `git log -p`.  The mechanism is a pair of callback wrappers that sit
> between `xdi_diff_outf()` and `fn_out_consume()`, filtering xdiff's
> output to only the tracked line ranges.  To ensure xdiff emits all lines
> within each range as context, the context length is inflated to span the
> largest range.
>
> Wire up the `-L` implies `--patch` default in revision setup rather
> than forcing it at output time, so `line_log_print()` is just
> `diffcore_std()` + `diff_flush()` with no format save/restore.
> Rename detection is a no-op since pairs are already resolved during
> the history walk in `queue_diffs()`, but running `diffcore_std()`
> means `-S`/`-G` (pickaxe), `--orderfile`, and `--diff-filter` now
> work with `-L`, and `diff_resolve_rename_copy()` sets pair statuses
> correctly without manual assignment.
>
> Switch `diff_filepair_dup()` from `xmalloc` to `xcalloc` so that new
> fields (including `line_ranges`) are zero-initialized by default.
>
> As a result, diff formatting options that were previously silently
> ignored (e.g. --word-diff, --no-prefix, -w, --color-moved) now work
> with -L, and output gains `index` lines, `new file mode` headers, and
> funcname context in `@@` headers.  This is a user-visible output change:
> tools that parse -L output may need to handle the additional header
> lines.
>
> The context-length inflation means xdiff may process more output than
> needed for very wide line ranges, but benchmarks on files up to 7800
> lines show no measurable regression.
>
> Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
> ---
>  diff.c                                        | 279 +++++++++++++++++-
>  diffcore.h                                    |  16 +
>  line-log.c                                    | 174 ++---------
>  line-log.h                                    |  14 +-
>  revision.c                                    |   2 +
>  t/t4211-line-log.sh                           |  12 +-
>  t/t4211/sha1/expect.beginning-of-file         |   4 +
>  t/t4211/sha1/expect.end-of-file               |  11 +-
>  t/t4211/sha1/expect.move-support-f            |   5 +
>  t/t4211/sha1/expect.multiple                  |  10 +-
>  t/t4211/sha1/expect.multiple-overlapping      |   7 +
>  t/t4211/sha1/expect.multiple-superset         |   7 +
>  t/t4211/sha1/expect.no-assertion-error        |  12 +-
>  t/t4211/sha1/expect.parallel-change-f-to-main |   7 +
>  t/t4211/sha1/expect.simple-f                  |   4 +
>  t/t4211/sha1/expect.simple-f-to-main          |   5 +
>  t/t4211/sha1/expect.simple-main               |  11 +-
>  t/t4211/sha1/expect.simple-main-to-end        |  11 +-
>  t/t4211/sha1/expect.two-ranges                |  10 +-
>  t/t4211/sha1/expect.vanishes-early            |  10 +-
>  t/t4211/sha256/expect.beginning-of-file       |   4 +
>  t/t4211/sha256/expect.end-of-file             |  11 +-
>  t/t4211/sha256/expect.move-support-f          |   5 +
>  t/t4211/sha256/expect.multiple                |  10 +-
>  t/t4211/sha256/expect.multiple-overlapping    |   7 +
>  t/t4211/sha256/expect.multiple-superset       |   7 +
>  t/t4211/sha256/expect.no-assertion-error      |  12 +-
>  .../sha256/expect.parallel-change-f-to-main   |   7 +
>  t/t4211/sha256/expect.simple-f                |   4 +
>  t/t4211/sha256/expect.simple-f-to-main        |   5 +
>  t/t4211/sha256/expect.simple-main             |  11 +-
>  t/t4211/sha256/expect.simple-main-to-end      |  11 +-
>  t/t4211/sha256/expect.two-ranges              |  10 +-
>  t/t4211/sha256/expect.vanishes-early          |  10 +-
>  34 files changed, 512 insertions(+), 213 deletions(-)

Huge diff to the test material mostly comes from the addition of the
diff headers like the index line, etc., which makes this patch scary
but is very welcome addition.

> @@ -106,6 +117,11 @@ int diff_filespec_is_binary(struct repository *, struct diff_filespec *);
>  struct diff_filepair {
>  	struct diff_filespec *one;
>  	struct diff_filespec *two;
> +	/*
> +	 * Tracked line ranges for -L filtering; borrowed from
> +	 * line_log_data and must not be freed.
> +	 */
> +	const struct range_set *line_ranges;

OK.

> diff --git a/line-log.c b/line-log.c
> index 9d12ece181..858a899cd2 100644
> --- a/line-log.c
> +++ b/line-log.c
> @@ -885,160 +885,6 @@ static void queue_diffs(struct line_log_data *range,
>  	move_diff_queue(queue, &diff_queued_diff);
>  }
>  int line_log_print(struct rev_info *rev, struct commit *commit)
>  {
> -
>  	show_log(rev);
>  	if (!(rev->diffopt.output_format & DIFF_FORMAT_NO_OUTPUT)) {
>  		struct line_log_data *range = lookup_line_range(rev, commit);
> -		dump_diff_hacky(rev, range);
> +		struct line_log_data *r;
> +		const char *prefix = diff_line_prefix(&rev->diffopt);
> +
> +		fprintf(rev->diffopt.file, "%s\n", prefix);
> +
> +		for (r = range; r; r = r->next) {
> +			if (r->pair) {
> +				struct diff_filepair *p =
> +					diff_filepair_dup(r->pair);
> +				p->line_ranges = &r->ranges;
> +				diff_q(&diff_queued_diff, p);
> +			}
> +		}
> +
> +		diffcore_std(&rev->diffopt);
> +		diff_flush(&rev->diffopt);

Very welcome change.

  reply	other threads:[~2026-03-17 20:52 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-07  1:02 [PATCH 0/4] line-log: route -L output through the standard diff pipeline Michael Montalbo via GitGitGadget
2026-03-07  1:02 ` [PATCH 1/4] line-log: fix crash when combined with pickaxe options Michael Montalbo via GitGitGadget
2026-03-07  1:02 ` [PATCH 2/4] line-log: route -L output through the standard diff pipeline Michael Montalbo via GitGitGadget
2026-03-07  1:02 ` [PATCH 3/4] t4211: add tests for -L with standard diff options Michael Montalbo via GitGitGadget
2026-03-07  1:02 ` [PATCH 4/4] doc: note that -L supports patch formatting and pickaxe options Michael Montalbo via GitGitGadget
2026-03-11  8:41   ` Kristoffer Haugsbakk
2026-03-11 17:35     ` Michael Montalbo
2026-03-07  1:28 ` [PATCH 0/4] line-log: route -L output through the standard diff pipeline Junio C Hamano
2026-03-07  1:37   ` Michael Montalbo
2026-03-07  2:05     ` Junio C Hamano
2026-03-07  2:10       ` Michael Montalbo
2026-03-17  2:21 ` [PATCH v2 " Michael Montalbo via GitGitGadget
2026-03-17  2:21   ` [PATCH v2 1/4] line-log: fix crash when combined with pickaxe options Michael Montalbo via GitGitGadget
2026-03-17  2:21   ` [PATCH v2 2/4] line-log: route -L output through the standard diff pipeline Michael Montalbo via GitGitGadget
2026-03-17 20:52     ` Junio C Hamano [this message]
2026-03-17  2:21   ` [PATCH v2 3/4] t4211: add tests for -L with standard diff options Michael Montalbo via GitGitGadget
2026-03-17  2:21   ` [PATCH v2 4/4] doc: note that -L supports patch formatting and pickaxe options 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=xmqqecliji1a.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --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