All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael Montalbo via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "D. Ben Knoble" <ben.knoble@gmail.com>,
	Michael Montalbo <mmontalbo@gmail.com>
Subject: [PATCH v2 0/3] line-log: integrate -L with the standard log output pipeline
Date: Mon, 25 May 2026 19:40:55 +0000	[thread overview]
Message-ID: <pull.2094.v2.git.1779738059.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2094.git.1777349126.gitgitgadget@gmail.com>

Since its introduction, git log -L has short-circuited from
log_tree_commit() into its own output function, bypassing log_tree_diff()
and log_tree_diff_flush(). This skips no_free save/restore,
always_show_header, diff_free() cleanup, and means that pickaxe (-S, -G,
--find-object) and --diff-filter cannot suppress commits whose pairs are all
filtered out, because show_log() runs before diffcore_std().

This series restructures the flow so that -L goes through the same
log_tree_diff() -> log_tree_diff_flush() path as normal single-parent and
merge diffs, then uses that to enable several non-patch diff formats.

Patch 1: revision: move -L setup before output_format-to-diff derivation

Preparatory reorder in setup_revisions(). The -L block sets a default
DIFF_FORMAT_PATCH when no format is requested; move it before the derivation
of revs->diff from output_format so the default is visible to that check. No
behavior change on its own.

Patch 2: line-log: integrate -L output with the standard log-tree pipeline

Rename line_log_print() to line_log_queue_pairs(), stripping it down to only
queue pre-computed filepairs. log_tree_diff_flush() handles show_log(),
diffcore_std(), and diff_flush(). This fixes pickaxe and --diff-filter
suppression, and aligns the commit/diff separator with the rest of log
output. Rejects --full-diff, which is not yet supported when filepairs are
pre-computed.

Patch 3: line-log: allow non-patch diff formats with -L

Expand the allowlist to accept --raw, --name-only, --name-status, and
--summary. These only read filepair metadata already set by the line-log
machinery. Diff stat formats (--stat, --numstat, --shortstat, --dirstat)
remain blocked because they call compute_diffstat() on full blob content and
would show whole-file statistics rather than range-scoped ones.

Changes since v1:

 * Patch 2: use !opt->loginfo return convention in log_tree_diff() to match
   the existing single-parent and merge codepaths, instead of returning
   log_tree_diff_flush() directly.
 * Patch 2: reword the early-return removal to explicitly tie it to the
   pipeline change.
 * Patch 2: soften --full-diff rejection to "not yet supported".
 * Patches 2-3: use test_grep consistently in new tests.
 * Patch 2: replace sed | grep pipe with sed > file && test_grep for proper
   exit status handling.

Michael Montalbo (3):
  revision: move -L setup before output_format-to-diff derivation
  line-log: integrate -L output with the standard log-tree pipeline
  line-log: allow non-patch diff formats with -L

 Documentation/line-range-options.adoc         |  10 +-
 line-log.c                                    |  30 ++----
 line-log.h                                    |   2 +-
 log-tree.c                                    |  10 +-
 revision.c                                    |  24 +++--
 t/t4211-line-log.sh                           | 100 +++++++++++++++---
 t/t4211/sha1/expect.parallel-change-f-to-main |   1 -
 .../sha256/expect.parallel-change-f-to-main   |   1 -
 8 files changed, 121 insertions(+), 57 deletions(-)


base-commit: 9f223ef1c026d91c7ac68cc0211bde255dda6199
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2094%2Fmmontalbo%2Fmm%2Fline-log-use-log-tree-diff-flush-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2094/mmontalbo/mm/line-log-use-log-tree-diff-flush-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/2094

Range-diff vs v1:

 1:  9633eb62c6 = 1:  9633eb62c6 revision: move -L setup before output_format-to-diff derivation
 2:  2d9e0ca015 ! 2:  7acfc5376e line-log: integrate -L output with the standard log-tree pipeline
     @@ Commit message
             log_tree_diff_flush(), mirroring the diff_tree_oid() + flush
             pattern used by the single-parent and merge codepaths.
      
     -     - Remove the early return in log_tree_commit() that bypassed
     -       no_free save/restore, always_show_header, and diff_free().
     +     - Remove the early return in log_tree_commit() that is no longer
     +       needed now that -L output flows through log_tree_diff() and
     +       log_tree_diff_flush(); this restores no_free save/restore,
     +       always_show_header, and diff_free() cleanup.
      
          Because show_log() is now deferred until after diffcore_std() inside
          log_tree_diff_flush(), pickaxe (-S, -G, --find-object) and
     @@ Commit message
          log_tree_diff_flush() only emits one for verbose headers.  This
          matches the rest of log output.
      
     -    Also reject --full-diff, which is meaningless with -L: the filepairs
     -    are pre-computed during the history walk and scoped to tracked paths,
     -    so there is no tree diff to widen.
     +    Also reject --full-diff, which is not yet supported with -L: the
     +    filepairs are pre-computed during the history walk and scoped to
     +    tracked line ranges, so there is currently no full-tree diff to
     +    fall back to for display.
      
          Update tests accordingly.
      
     @@ log-tree.c: static int log_tree_diff(struct rev_info *opt, struct commit *commit
       
      +	if (opt->line_level_traverse) {
      +		line_log_queue_pairs(opt, commit);
     -+		return log_tree_diff_flush(opt);
     ++		log_tree_diff_flush(opt);
     ++		return !opt->loginfo;
      +	}
      +
       	parse_commit_or_die(commit);
     @@ log-tree.c: int log_tree_commit(struct rev_info *opt, struct commit *commit)
      
       ## revision.c ##
      @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
     + 		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");
     + 
       	if (revs->line_level_traverse &&
     - 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
     - 		die(_("-L does not yet support diff formats besides -p and -s"));
     -+	if (revs->line_level_traverse && revs->full_diff)
     -+		die(_("-L is not compatible with --full-diff"));
     +-	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
     +-		die(_("-L does not yet support diff formats besides -p and -s"));
     ++	    (revs->full_diff ||
     ++	     (revs->diffopt.output_format &
     ++	      ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT))))
     ++		die(_("-L does not yet support the requested diff format"));
       
       	if (revs->expand_tabs_in_log < 0)
       		revs->expand_tabs_in_log = revs->expand_tabs_in_log_default;
     @@ t/t4211-line-log.sh: test_expect_success '-L with -G filters to diff-text matche
      +	test_cmp expect actual
      +'
      +
     -+test_expect_success '--full-diff is not supported with -L' '
     ++test_expect_success '--full-diff is not yet supported with -L' '
      +	test_must_fail git log -L1,24:b.c --full-diff 2>err &&
     -+	test_grep "not compatible with --full-diff" err
     ++	test_grep "does not yet support" err
      +'
      +
      +test_expect_success '-L --oneline has no extra blank line before diff' '
      +	git checkout parent-oids &&
      +	git log --oneline -L:func2:file.c -1 >actual &&
      +	# Oneline header on line 1, diff starts immediately on line 2
     -+	sed -n 2p actual | grep "^diff --git"
     ++	sed -n 2p actual >line2 &&
     ++	test_grep "^diff --git" line2
      +'
      +
       test_done
 3:  06c24b416f ! 3:  10a3d8dde2 line-log: allow non-patch diff formats with -L
     @@ Documentation/line-range-options.adoc
      
       ## revision.c ##
      @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
     - 		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");
     - 
       	if (revs->line_level_traverse &&
     --	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
     --		die(_("-L does not yet support diff formats besides -p and -s"));
     -+	    (revs->diffopt.output_format &
     -+	     ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT |
     -+	       DIFF_FORMAT_RAW | DIFF_FORMAT_NAME |
     -+	       DIFF_FORMAT_NAME_STATUS | DIFF_FORMAT_SUMMARY)))
     -+		die(_("-L does not yet support the requested diff format"));
     - 	if (revs->line_level_traverse && revs->full_diff)
     - 		die(_("-L is not compatible with --full-diff"));
     + 	    (revs->full_diff ||
     + 	     (revs->diffopt.output_format &
     +-	      ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT))))
     ++	      ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT |
     ++		DIFF_FORMAT_RAW | DIFF_FORMAT_NAME |
     ++		DIFF_FORMAT_NAME_STATUS | DIFF_FORMAT_SUMMARY))))
     + 		die(_("-L does not yet support the requested diff format"));
       
     + 	if (revs->expand_tabs_in_log < 0)
      
       ## t/t4211-line-log.sh ##
      @@ t/t4211-line-log.sh: test_expect_success '-p shows the default patch output' '
     @@ t/t4211-line-log.sh: test_expect_success '-p shows the default patch output' '
      -	test_must_fail git log -L1,24:b.c --raw
      +test_expect_success '--raw shows mode, oid, status and path' '
      +	git log -L1,24:b.c --raw --format= >actual &&
     -+	grep "^:100644 100644 [0-9a-f]\{7\} [0-9a-f]\{7\} M	b.c$" actual &&
     -+	! grep "^diff --git" actual &&
     -+	! grep "^@@" actual
     ++	test_grep "^:100644 100644 [0-9a-f]\{7\} [0-9a-f]\{7\} M	b.c$" actual &&
     ++	! test_grep "^diff --git" actual &&
     ++	! test_grep "^@@" actual
      +'
      +
      +test_expect_success '--name-only shows path' '
      +	git log -L1,24:b.c --name-only --format= >actual &&
     -+	grep "^b.c$" actual &&
     -+	! grep "^diff --git" actual &&
     -+	! grep "^@@" actual
     ++	test_grep "^b.c$" actual &&
     ++	! test_grep "^diff --git" actual &&
     ++	! test_grep "^@@" actual
      +'
      +
      +test_expect_success '--name-status shows status and path' '
      +	git log -L1,24:b.c --name-status --format= >actual &&
     -+	grep "^M	b.c$" actual &&
     -+	! grep "^diff --git" actual &&
     -+	! grep "^@@" actual
     ++	test_grep "^M	b.c$" actual &&
     ++	! test_grep "^diff --git" actual &&
     ++	! test_grep "^@@" actual
      +'
      +
      +test_expect_success '--stat is not yet supported with -L' '
     @@ t/t4211-line-log.sh: test_expect_success '-p shows the default patch output' '
       
       test_expect_success 'setup for checking fancy rename following' '
      @@ t/t4211-line-log.sh: test_expect_success '-L --oneline has no extra blank line before diff' '
     - 	sed -n 2p actual | grep "^diff --git"
     + 	test_grep "^diff --git" line2
       '
       
      +test_expect_success '--summary shows new file on root commit' '
      +	git checkout parent-oids &&
      +	git log -L:func2:file.c --summary --format= >actual &&
     -+	grep "create mode 100644 file.c" actual
     ++	test_grep "create mode 100644 file.c" actual
      +'
      +
       test_done

-- 
gitgitgadget

  parent reply	other threads:[~2026-05-25 19:41 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28  4:05 [PATCH 0/3] line-log: integrate -L with the standard log output pipeline Michael Montalbo via GitGitGadget
2026-04-28  4:05 ` [PATCH 1/3] revision: move -L setup before output_format-to-diff derivation Michael Montalbo via GitGitGadget
2026-04-28  4:05 ` [PATCH 2/3] line-log: integrate -L output with the standard log-tree pipeline Michael Montalbo via GitGitGadget
2026-04-28  4:05 ` [PATCH 3/3] line-log: allow non-patch diff formats with -L Michael Montalbo via GitGitGadget
2026-05-12  4:01 ` [PATCH 0/3] line-log: integrate -L with the standard log output pipeline Junio C Hamano
2026-05-22 18:48 ` D. Ben Knoble
     [not found] ` <CALnO6CBh7nDCwT=u1xSN2c6_x88t_gNfAaT_B4PzYKr=5i_bNA@mail.gmail.com>
2026-05-24  2:00   ` Michael Montalbo
2026-05-25 19:40 ` Michael Montalbo via GitGitGadget [this message]
2026-05-25 19:40   ` [PATCH v2 1/3] revision: move -L setup before output_format-to-diff derivation Michael Montalbo via GitGitGadget
2026-05-25 19:40   ` [PATCH v2 2/3] line-log: integrate -L output with the standard log-tree pipeline Michael Montalbo via GitGitGadget
2026-05-25 19:40   ` [PATCH v2 3/3] line-log: allow non-patch diff formats with -L Michael Montalbo via GitGitGadget
2026-05-27 20:20   ` [PATCH v2 0/3] line-log: integrate -L with the standard log output pipeline D. Ben Knoble
2026-05-28 18:55     ` Junio C Hamano
2026-05-28 19:31       ` Michael Montalbo
2026-05-28 20:47   ` [PATCH v3 " Michael Montalbo via GitGitGadget
2026-05-28 20:47     ` [PATCH v3 1/3] revision: move -L setup before output_format-to-diff derivation Michael Montalbo via GitGitGadget
2026-05-28 20:47     ` [PATCH v3 2/3] line-log: integrate -L output with the standard log-tree pipeline Michael Montalbo via GitGitGadget
2026-05-28 20:47     ` [PATCH v3 3/3] line-log: allow non-patch diff formats with -L Michael Montalbo via GitGitGadget
2026-05-29 12:04     ` [PATCH v3 0/3] line-log: integrate -L with the standard log output pipeline Ben Knoble
2026-06-01 21:53       ` Junio C Hamano

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=pull.2094.v2.git.1779738059.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=ben.knoble@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 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.