git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 3/5] Introduce new pretty formats %g[sdD] for reflog information

From
Thomas Rast <trast@student.ethz.ch>
Date
Oct 16, 2009, 14:20 UTC
Message-ID
<8a5b3a586d437f02e2a75edd2786636b605522a7.1255701207.git.trast@student.ethz.ch>
In-Reply-To
<cover.1255701207.git.trast@student.ethz.ch>
Add three new --pretty=format escapes:
  %gD  long  reflog descriptor (e.g. refs/stash@{0})
  %gd  short reflog descriptor (e.g. stash@{0})
  %gs  reflog message

This is achieved by passing down the reflog info, if any, inside the pretty_print_context struct.

We use the newly refactored get_reflog_selector(), and give it some extra functionality to extract a shortened ref. The shortening is cached inside the commit_reflogs struct; the only allocation of it happens in read_complete_reflog(), where it is initialised to 0. Also add another helper get_reflog_message() for the message extraction.

Note that the --format="%h %gD: %gs" tests may not work in real repositories, as the --pretty formatter doesn't know to leave away the ": " on the last commit in an incomplete (because git-gc removed the old part) reflog. This equivalence is nevertheless the main goal of this patch.

Thanks to Jeff King for reviews and the %gd testcase.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 Documentation/pretty-formats.txt |    3 +++
 commit.h                         |    1 +
 log-tree.c                       |    1 +
 pretty.c                         |   17 +++++++++++++++++
 reflog-walk.c                    |   35 ++++++++++++++++++++++++++++++++---
 reflog-walk.h                    |    8 ++++++++
 t/t6006-rev-list-format.sh       |   18 ++++++++++++++++++
 7 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 2a845b1..cc0ea56 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -123,6 +123,9 @@ The placeholders are:
 - '%s': subject
 - '%f': sanitized subject line, suitable for a filename
 - '%b': body
+- '%gD': reflog selector, e.g., `refs/stash@\{1\}`
+- '%gd': shortened reflog selector, e.g., `stash@\{1\}`
+- '%gs': reflog subject
 - '%Cred': switch color to red
 - '%Cgreen': switch color to green
 - '%Cblue': switch color to blue
diff --git a/commit.h b/commit.h
index 011766d..15cb649 100644
--- a/commit.h
+++ b/commit.h
@@ -70,6 +70,7 @@ struct pretty_print_context
 	const char *after_subject;
 	enum date_mode date_mode;
 	int need_8bit_cte;
+	struct reflog_walk_info *reflog_info;
 };
 
 extern int non_ascii(int);
diff --git a/log-tree.c b/log-tree.c
index f57487f..8e782fc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -409,6 +409,7 @@ void show_log(struct rev_info *opt)
 	ctx.date_mode = opt->date_mode;
 	ctx.abbrev = opt->diffopt.abbrev;
 	ctx.after_subject = extra_headers;
+	ctx.reflog_info = opt->reflog_info;
 	pretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);
 
 	if (opt->add_signoff)
diff --git a/pretty.c b/pretty.c
index d6d57eb..fc65fca 100644
--- a/pretty.c
+++ b/pretty.c
@@ -7,6 +7,7 @@
 #include "mailmap.h"
 #include "log-tree.h"
 #include "color.h"
+#include "reflog-walk.h"
 
 static char *user_format;
 
@@ -701,6 +702,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 	case 'd':
 		format_decoration(sb, commit);
 		return 1;
+	case 'g':		/* reflog info */
+		switch(placeholder[1]) {
+		case 'd':	/* reflog selector */
+		case 'D':
+			if (c->pretty_ctx->reflog_info)
+				get_reflog_selector(sb,
+						    c->pretty_ctx->reflog_info,
+						    c->pretty_ctx->date_mode,
+						    (placeholder[1] == 'd'));
+			return 2;
+		case 's':	/* reflog message */
+			if (c->pretty_ctx->reflog_info)
+				get_reflog_message(sb, c->pretty_ctx->reflog_info);
+			return 2;
+		}
+		return 0;	/* unknown %g placeholder */
 	}
 
 	/* For the rest we have to parse the commit header. */
diff --git a/reflog-walk.c b/reflog-walk.c
index 596bafe..caba4f7 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -8,6 +8,7 @@
 
 struct complete_reflogs {
 	char *ref;
+	const char *short_ref;
 	struct reflog_info {
 		unsigned char osha1[20], nsha1[20];
 		char *email;
@@ -243,15 +244,26 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
 
 void get_reflog_selector(struct strbuf *sb,
 			 struct reflog_walk_info *reflog_info,
-			 enum date_mode dmode)
+			 enum date_mode dmode,
+			 int shorten)
 {
 	struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
 	struct reflog_info *info;
+	const char *printed_ref;
 
 	if (!commit_reflog)
 		return;
 
-	strbuf_addf(sb, "%s@{", commit_reflog->reflogs->ref);
+	if (shorten) {
+		if (!commit_reflog->reflogs->short_ref)
+			commit_reflog->reflogs->short_ref
+				= shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);
+		printed_ref = commit_reflog->reflogs->short_ref;
+	} else {
+		printed_ref = commit_reflog->reflogs->ref;
+	}
+
+	strbuf_addf(sb, "%s@{", printed_ref);
 	if (commit_reflog->flag || dmode) {
 		info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
 		strbuf_addstr(sb, show_date(info->timestamp, info->tz, dmode));
@@ -263,6 +275,23 @@ void get_reflog_selector(struct strbuf *sb,
 	strbuf_addch(sb, '}');
 }
 
+void get_reflog_message(struct strbuf *sb,
+			struct reflog_walk_info *reflog_info)
+{
+	struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
+	struct reflog_info *info;
+	size_t len;
+
+	if (!commit_reflog)
+		return;
+
+	info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
+	len = strlen(info->message);
+	if (len > 0)
+		len--; /* strip away trailing newline */
+	strbuf_add(sb, info->message, len);
+}
+
 void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
 	enum date_mode dmode)
 {
@@ -272,7 +301,7 @@ void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
 		struct strbuf selector = STRBUF_INIT;
 
 		info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
-		get_reflog_selector(&selector, reflog_info, dmode);
+		get_reflog_selector(&selector, reflog_info, dmode, 0);
 		if (oneline) {
 			printf("%s: %s", selector.buf, info->message);
 		}
diff --git a/reflog-walk.h b/reflog-walk.h
index 74c9096..7bd2cd4 100644
--- a/reflog-walk.h
+++ b/reflog-walk.h
@@ -3,6 +3,8 @@
 
 #include "cache.h"
 
+struct reflog_walk_info;
+
 extern void init_reflog_walk(struct reflog_walk_info** info);
 extern int add_reflog_for_walk(struct reflog_walk_info *info,
 		struct commit *commit, const char *name);
@@ -10,5 +12,11 @@ extern void fake_reflog_parent(struct reflog_walk_info *info,
 		struct commit *commit);
 extern void show_reflog_message(struct reflog_walk_info *info, int,
 		enum date_mode);
+extern void get_reflog_message(struct strbuf *sb,
+		struct reflog_walk_info *reflog_info);
+extern void get_reflog_selector(struct strbuf *sb,
+		struct reflog_walk_info *reflog_info,
+		enum date_mode dmode,
+		int shorten);
 
 #endif
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 59d1f62..7f61ab0 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -162,4 +162,22 @@ test_expect_success 'empty email' '
 	}
 '
 
+test_expect_success '"%h %gD: %gs" is same as git-reflog' '
+	git reflog >expect &&
+	git log -g --format="%h %gD: %gs" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
+	git reflog --date=raw >expect &&
+	git log -g --format="%h %gD: %gs" --date=raw >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '%gd shortens ref name' '
+	echo "master@{0}" >expect.gd-short &&
+	git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
+	test_cmp expect.gd-short actual.gd-short
+'
+
 test_done
-- 
1.6.5.116.gfe4b9
Previous: Thomas RastNext: Thomas Rast
Message 19 of 31 in “Pretty formats for reflog data”
  1. 0/5 Pretty formats for reflog dataThomas Rast, Oct 15, 2009
  2. 1/5 Refactor pretty_print_commit arguments into a structThomas Rast, Oct 15, 2009
  3. 2/5 reflog-walk: refactor the branch@{num} formattingThomas Rast, Oct 15, 2009
  4. 3/5 Introduce new pretty formats %g[sdD] for reflog informationThomas Rast, Oct 15, 2009
  5. Jeff KingOct 16, 2009
  6. Thomas RastOct 16, 2009
  7. 0/5 Pretty formats for reflog dataThomas Rast, Oct 16, 2009
  8. 1/5 Refactor pretty_print_commit arguments into a structThomas Rast, Oct 16, 2009
  9. Junio C HamanoOct 17, 2009
  10. Thomas RastOct 18, 2009
  11. Junio C HamanoOct 18, 2009
  12. 0/5 Pretty formats for reflog dataThomas Rast, Oct 19, 2009
  13. 1/5 Refactor pretty_print_commit arguments into a structThomas Rast, Oct 19, 2009
  14. 2/5 reflog-walk: refactor the branch@{num} formattingThomas Rast, Oct 19, 2009
  15. 3/5 Introduce new pretty formats %g[sdD] for reflog informationThomas Rast, Oct 19, 2009
  16. 4/5 stash list: use new %g formats instead of sedThomas Rast, Oct 19, 2009
  17. 5/5 stash list: drop the default limit of 10 stashesThomas Rast, Oct 19, 2009
  18. 2/5 reflog-walk: refactor the branch@{num} formattingThomas Rast, Oct 16, 2009
  19. 3/5 Introduce new pretty formats %g[sdD] for reflog informationThomas Rast, Oct 16, 2009
  20. 3/5 Introduce new pretty formats %g[sdD] for reflog informationThomas Rast, Oct 17, 2009
  21. Jakub NarebskiOct 17, 2009
  22. Jeff KingOct 18, 2009
  23. Nanako ShiraishiOct 18, 2009
  24. 4/5 stash list: use new %g formats instead of sedThomas Rast, Oct 16, 2009
  25. 5/5 stash list: drop the default limit of 10 stashesThomas Rast, Oct 16, 2009
  26. Junio C HamanoOct 17, 2009
  27. Jeff KingOct 17, 2009
  28. 4/5 stash list: use new %g formats instead of sedThomas Rast, Oct 15, 2009
  29. 5/5 stash list: drop the default limit of 10 stashesThomas Rast, Oct 15, 2009
  30. Jeff KingOct 16, 2009
  31. Jakub NarebskiOct 16, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.