public inbox for git@vger.kernel.org 
 help / color / mirror / Atom feed
From: Toon Claes <toon@iotcl•com>
To: git@vger•kernel.org
Cc: Toon Claes <toon@iotcl•com>,
	Kristoffer Haugsbakk <kristofferhaugsbakk@fastmail•com>,
	Derrick Stolee <stolee@gmail•com>, Taylor Blau <me@ttaylorr•com>,
	Junio C Hamano <gitster@pobox•com>
Subject: [PATCH v5 5/6] last-modified: support --extended format
Date: Wed, 16 Jul 2025 15:35:17 +0200	[thread overview]
Message-ID: <20250716133518.1788126-5-toon@iotcl.com> (raw)
In-Reply-To: <20250716133206.1787549-1-toon@iotcl.com>

On many forges when they display a tree view, they show which commit
last modified each entry of the tree. The command git-last-modified(1)
was introduced to feed the data for this view. But it only returned the
commit OID and the path.

Add option --extended to git-last-modified(1). In combination with the
path and the commit OID, it shows the raw commit data which can be used
directly to feed the tree view on a forge.

Signed-off-by: Toon Claes <toon@iotcl•com>
---
 Documentation/git-last-modified.adoc | 46 ++++++++++++++++++++++++++++
 builtin/last-modified.c              | 46 +++++++++++++++++++++++-----
 t/t8020-last-modified.sh             | 22 +++++++++++++
 3 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc
index 89138ebeb7..af028c7b74 100644
--- a/Documentation/git-last-modified.adoc
+++ b/Documentation/git-last-modified.adoc
@@ -27,6 +27,14 @@ OPTIONS
 -t::
 	Show tree entry itself as well as subtrees.  Implies `-r`.

+-z::
+
+	Instead of separating output entries with newlines, use a NUL byte to
+	delimit them. See 'OUTPUT' for more details.
+
+--extended::
+	Show output in extended format. See 'OUTPUT' below.
+
 <revision-range>::
 	Only traverse commits in the specified revision range. When no
 	`<revision-range>` is specified, it defaults to `HEAD` (i.e. the whole
@@ -39,6 +47,44 @@ OPTIONS
 	Without an optional path parameter, all files and subdirectories
 	in path traversal the are included in the output.

+OUTPUT
+------
+
+The default format prints for each path:
+
+	<oid> TAB <path> LF
+
+When the commit is at boundary, it's prefixed with a caret `^`.
+
+Or when option `-z` is given:
+
+	<oid> TAB <path> NUL
+
+When `--extended` is provided, the output will be in the format:
+
+	path SP <path> LF
+	commit SP <oid> LF
+	tree SP <tree> LF
+	parent SP <parent> LF
+	author SP <author> LF
+	    <message>
+
+Each line of the commit message is indented with four spaces.
+
+Unless together with `--extended` option `-z` is given, then the output is:
+
+	path SP <path> NUL
+	commit SP <oid> LF
+	tree SP <tree> LF
+	parent SP <parent> LF
+	author SP <author> LF
+	<message>
+
+In this situation the commit message is not indented.
+
+A path containing SP or special characters is enclosed in double-quotes in the C
+style as needed, unless option `-z` is provided.
+
 SEE ALSO
 --------
 linkgit:git-blame[1],
diff --git a/builtin/last-modified.c b/builtin/last-modified.c
index 466df04fba..71c66e8782 100644
--- a/builtin/last-modified.c
+++ b/builtin/last-modified.c
@@ -12,6 +12,7 @@
 #include "object-name.h"
 #include "object.h"
 #include "parse-options.h"
+#include "pretty.h"
 #include "quote.h"
 #include "repository.h"
 #include "revision.h"
@@ -39,6 +40,7 @@ struct last_modified {
 	struct hashmap paths;
 	struct rev_info rev;
 	int recursive, tree_in_recursive;
+	int extended;
 };

 static void last_modified_release(struct last_modified *lm)
@@ -244,14 +246,42 @@ static void show_entry(const char *path, const struct commit *commit, void *d)
 {
 	struct last_modified *lm = d;

-	if (commit->object.flags & BOUNDARY)
-		putchar('^');
-	printf("%s\t", oid_to_hex(&commit->object.oid));
+	if (lm->extended) {
+		struct strbuf buf = STRBUF_INIT;
+		struct pretty_print_context pp = { 0 };

-	if (lm->rev.diffopt.line_termination)
-		write_name_quoted(path, stdout, '\n');
-	else
-		printf("%s%c", path, '\0');
+		pp.abbrev = lm->rev.abbrev;
+		pp.date_mode = lm->rev.date_mode;
+		pp.date_mode_explicit = lm->rev.date_mode_explicit;
+		pp.fmt = CMIT_FMT_RAW;
+		pp.color = lm->rev.diffopt.use_color;
+		pp.rev = &lm->rev;
+		pp.no_indent = !lm->rev.diffopt.line_termination;
+
+		pretty_print_commit(&pp, commit, &buf);
+
+		printf("path ");
+		if (lm->rev.diffopt.line_termination)
+			write_name_quoted(path, stdout, '\n');
+		else
+			printf("%s%c", path, '\0');
+
+		printf("commit %s%s\n",
+		       (commit->object.flags & BOUNDARY) ? "^" : "",
+		       oid_to_hex(&commit->object.oid));
+		printf("%s%c", buf.buf, lm->rev.diffopt.line_termination);
+
+		strbuf_release(&buf);
+	} else {
+		printf("%s%s\t",
+		       (commit->object.flags & BOUNDARY) ? "^" : "",
+		       oid_to_hex(&commit->object.oid));
+
+		if (lm->rev.diffopt.line_termination)
+			write_name_quoted(path, stdout, '\n');
+		else
+			printf("%s%c", path, '\0');
+	}

 	fflush(stdout);
 }
@@ -306,6 +336,8 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix,
 			 N_("recurse into subtrees")),
 		OPT_BOOL('t', "tree-in-recursive", &lm.tree_in_recursive,
 			 N_("recurse into subtrees and include the tree entries too")),
+		OPT_BOOL(0, "extended", &lm.extended,
+			 N_("extended format will include the commit message in the output")),
 		OPT_END()
 	};

diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh
index 05c113a1f8..008ea708ab 100755
--- a/t/t8020-last-modified.sh
+++ b/t/t8020-last-modified.sh
@@ -48,6 +48,28 @@ test_expect_success 'last-modified non-recursive' '
 	EOF
 '

+test_expect_success 'last-modified extended output' '
+	check_last_modified --extended <<-\EOF
+	path a
+	commit 3
+	tree e9a947598482012e54c9c5d3635d5b526b43a6a4
+	parent 2
+	author A U Thor <author@example•com> 1112912113 -0700
+	committer C O Mitter <committer@example•com> 1112912113 -0700
+
+	    3
+
+	path file
+	commit 1
+	tree f27c6ae26adb8396d3861976ba268f87ad8afa0b
+	author A U Thor <author@example•com> 1112911993 -0700
+	committer C O Mitter <committer@example•com> 1112911993 -0700
+
+	    1
+
+	EOF
+'
+
 test_expect_success 'last-modified recursive' '
 	check_last_modified -r <<-\EOF
 	3 a/b/file
--
2.50.1.327.g047016eb4a

  parent reply	other threads:[~2025-07-16 13:36 UTC|newest]

Thread overview: 135+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-22 17:46 [PATCH RFC 0/5] Introduce git-blame-tree(1) command Toon Claes
2025-04-22 17:46 ` [PATCH RFC 1/5] blame-tree: introduce new subcommand to blame files Toon Claes
2025-04-24 16:19   ` Junio C Hamano
2025-05-07 13:13     ` Toon Claes
2025-04-22 17:46 ` [PATCH RFC 2/5] t/perf: add blame-tree perf script Toon Claes
2025-04-22 17:46 ` [PATCH RFC 3/5] blame-tree: use Bloom filters when available Toon Claes
2025-04-22 17:46 ` [PATCH RFC 4/5] blame-tree: implement faster algorithm Toon Claes
2025-04-22 17:46 ` [PATCH RFC 5/5] blame-tree.c: initialize revision machinery without walk Toon Claes
2025-04-23 13:26 ` [PATCH RFC 0/5] Introduce git-blame-tree(1) command Marc Branchaud
2025-05-07 14:22   ` Toon Claes
2025-05-07 20:23     ` Marc Branchaud
2025-05-07 20:45       ` Junio C Hamano
2025-05-08 13:26         ` Marc Branchaud
2025-05-08 14:26           ` Junio C Hamano
2025-05-08 15:12             ` Marc Branchaud
2025-05-14 14:42               ` Toon Claes
2025-05-14 19:29                 ` Junio C Hamano
2025-05-14 21:15                   ` Marc Branchaud
2025-05-15 13:29                     ` Patrick Steinhardt
2025-05-15 16:39                       ` Junio C Hamano
2025-05-15 17:39                         ` Marc Branchaud
2025-05-15 19:30                           ` Jeff King
2025-05-16  4:38                             ` Patrick Steinhardt
2025-05-20  8:49                               ` Toon Claes
2025-05-15 17:30                       ` Marc Branchaud
2025-05-16  4:30                         ` Patrick Steinhardt
2025-05-14 21:15                 ` Marc Branchaud
2025-05-07 20:49       ` Kristoffer Haugsbakk
2025-05-08 13:20         ` D. Ben Knoble
2025-05-08 13:26         ` Marc Branchaud
2025-05-08 13:18       ` D. Ben Knoble
2025-05-23  9:33 ` [PATCH RFC v2 0/5] Introduce git-last-modified(1) command Toon Claes
2025-05-23  9:33   ` [PATCH RFC v2 1/5] last-modified: new subcommand to show when files were last modified Toon Claes
2025-05-25 20:07     ` Justin Tobler
2025-06-05  8:32       ` Toon Claes
2025-05-27 10:39     ` Patrick Steinhardt
2025-06-13  9:34       ` Toon Claes
2025-06-13  9:52         ` Kristoffer Haugsbakk
2025-05-23  9:33   ` [PATCH RFC v2 2/5] t/perf: add last-modified perf script Toon Claes
2025-05-23  9:33   ` [PATCH RFC v2 3/5] last-modified: use Bloom filters when available Toon Claes
2025-05-27 10:40     ` Patrick Steinhardt
2025-06-13 11:05       ` Toon Claes
2025-05-23  9:33   ` [PATCH RFC v2 4/5] last-modified: implement faster algorithm Toon Claes
2025-05-27 10:39     ` Patrick Steinhardt
2025-05-23  9:33   ` [PATCH RFC v2 5/5] last-modified: initialize revision machinery without walk Toon Claes
2025-05-27 10:39     ` Patrick Steinhardt
2025-07-01 20:35   ` [PATCH RFC v2 0/5] Introduce git-last-modified(1) command Kristoffer Haugsbakk
2025-07-01 21:06     ` Junio C Hamano
2025-07-01 21:30       ` Kristoffer Haugsbakk
2025-07-02 13:00         ` Toon Claes
2025-07-09 15:53           ` Toon Claes
2025-07-09 17:00             ` Junio C Hamano
2025-06-30 18:49 ` [PATCH RFC v3 0/3] " Toon Claes
2025-06-30 18:49   ` [PATCH RFC v3 1/3] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-01 20:20     ` Kristoffer Haugsbakk
2025-07-02 11:51     ` Junio C Hamano
2025-06-30 18:49   ` [PATCH RFC v3 2/3] t/perf: add last-modified perf script Toon Claes
2025-06-30 18:49   ` [PATCH RFC v3 3/3] last-modified: use Bloom filters when available Toon Claes
2025-07-01 23:01   ` [PATCH RFC v3 0/3] Introduce git-last-modified(1) command Junio C Hamano
2025-07-09 15:26   ` [PATCH v4 " Toon Claes
2025-07-09 21:57     ` Junio C Hamano
2025-07-10 18:37       ` Junio C Hamano
2025-07-16 13:32     ` [PATCH v5 0/6] " Toon Claes
2025-07-16 13:35       ` [PATCH v5 1/6] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-18  0:02         ` Taylor Blau
2025-07-19  6:44           ` Jeff King
2025-07-22 15:50           ` Toon Claes
2025-08-01  9:09           ` Christian Couder
2025-08-01 16:59             ` Junio C Hamano
2025-07-16 13:35       ` [PATCH v5 2/6] t/perf: add last-modified perf script Toon Claes
2025-07-18  0:08         ` Taylor Blau
2025-07-22 15:52           ` Toon Claes
2025-07-16 13:35       ` [PATCH v5 3/6] last-modified: use Bloom filters when available Toon Claes
2025-07-18  0:16         ` Taylor Blau
2025-07-22 16:02           ` Toon Claes
2025-07-16 13:35       ` [PATCH v5 4/6] pretty: allow caller to disable indentation Toon Claes
2025-07-16 15:50         ` Junio C Hamano
2025-07-17 16:31           ` Toon Claes
2025-07-16 13:35       ` Toon Claes [this message]
2025-07-16 16:09         ` [PATCH v5 5/6] last-modified: support --extended format Junio C Hamano
2025-07-17 16:31           ` Toon Claes
2025-07-17 22:37         ` Junio C Hamano
2025-07-18 17:36           ` Junio C Hamano
2025-07-22 16:06             ` Toon Claes
2025-07-16 13:42       ` [PATCH v5 6/6] fixup! last-modified: use Bloom filters when available Toon Claes
2025-07-17 23:39       ` [PATCH v5 0/6] Introduce git-last-modified(1) command Taylor Blau
2025-07-22 15:35         ` Toon Claes
2025-07-30 17:59           ` Toon Claes
2025-07-31  7:45             ` Patrick Steinhardt
2025-07-30 17:55       ` [PATCH v6 0/4] " Toon Claes
2025-07-31 18:40         ` Junio C Hamano
2025-07-31 23:57           ` Junio C Hamano
2025-08-05  9:33         ` [PATCH v7 0/3] " Toon Claes
2025-08-05 14:34           ` Patrick Steinhardt
2025-08-05 16:21             ` Junio C Hamano
2025-08-05 16:34           ` Junio C Hamano
2025-08-05 16:55             ` Toon Claes
2025-08-05 17:20               ` Jean-Noël AVILA
2025-08-05 21:46                 ` Junio C Hamano
2025-08-06 12:01                   ` Toon Claes
2025-08-06 15:38                     ` Junio C Hamano
2025-08-28 22:44                       ` Junio C Hamano
2025-08-05 18:28               ` Junio C Hamano
2025-08-05  9:33         ` [PATCH v7 1/3] last-modified: new subcommand to show when files were last modified Toon Claes
2025-08-05  9:33         ` [PATCH v7 2/3] t/perf: add last-modified perf script Toon Claes
2025-08-05  9:33         ` [PATCH v7 3/3] last-modified: use Bloom filters when available Toon Claes
2025-07-30 17:55       ` [PATCH v6 1/4] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-31  6:42         ` Patrick Steinhardt
2025-08-01 16:22           ` Toon Claes
2025-08-01 17:09             ` Junio C Hamano
2025-08-04  6:34               ` Patrick Steinhardt
2025-08-04 17:14                 ` Junio C Hamano
2025-08-05  5:35                   ` Toon Claes
2025-08-01 20:34             ` Jean-Noël AVILA
2025-08-05  5:36               ` Toon Claes
2025-08-04  6:33             ` Patrick Steinhardt
2025-08-01 10:18         ` Christian Couder
2025-08-01 10:22           ` Patrick Steinhardt
2025-08-01 17:06             ` Junio C Hamano
2025-08-02  8:18               ` Christian Couder
2025-08-02 11:31                 ` Christian Couder
2025-08-02 13:38                   ` Christian Couder
2025-08-02 16:26                     ` Junio C Hamano
2025-08-04  6:35               ` Patrick Steinhardt
2025-07-30 17:55       ` [PATCH v6 2/4] t/perf: add last-modified perf script Toon Claes
2025-07-30 17:55       ` [PATCH v6 3/4] commit-graph: export prepare_commit_graph() Toon Claes
2025-07-31  6:42         ` Patrick Steinhardt
2025-07-30 17:55       ` [PATCH v6 4/4] last-modified: use Bloom filters when available Toon Claes
2025-07-31  6:43         ` Patrick Steinhardt
2025-08-01 16:23           ` Toon Claes
2025-08-04  6:33             ` Patrick Steinhardt
2025-07-09 15:26   ` [PATCH v4 1/3] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-09 15:26   ` [PATCH v4 2/3] t/perf: add last-modified perf script Toon Claes
2025-07-09 15:26   ` [PATCH v4 3/3] last-modified: use Bloom filters when available Toon Claes
2025-07-16 13:35   ` [PATCH v5 6/6] fixup! " Toon Claes

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=20250716133518.1788126-5-toon@iotcl.com \
    --to=toon@iotcl$(echo .)com \
    --cc=git@vger$(echo .)kernel.org \
    --cc=gitster@pobox$(echo .)com \
    --cc=kristofferhaugsbakk@fastmail$(echo .)com \
    --cc=me@ttaylorr$(echo .)com \
    --cc=stolee@gmail$(echo .)com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
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