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

[PATCH 08/15] for-each-ref: get --pretty using format_commit_message

From
Ramkumar Ramachandra <artagnon@gmail.com>
Date
Jun 4, 2013, 12:35 UTC
Message-ID
<1370349337-20938-9-git-send-email-artagnon@gmail.com>
In-Reply-To
<1370349337-20938-1-git-send-email-artagnon@gmail.com>
From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>

--format is very limited in its capabilities. Introduce --pretty, which extends the existing --format with pretty-formats. In --pretty:

 - Existing --format %(atom) is available. They also accept some pretty
   magic.  For example, you can use "% (atom)" to only display a leading
   space if the atom produces something.
 - %ab to display a hex character 0xab is not available as it may
   conflict with other pretty's placeholders.  Use %xab instead.
 - Many pretty placeholders are designed to work on commits.  While some
   of them should work on tags too, they don't (yet).
 - Unsupported atoms cause for-each-ref to exit early and report.
   Unsupported pretty placeholders are displayed as-is.
 - Pretty placeholders can not be used as a sorting criteria.

--format is considered deprecated. If the user hits a bug specific in --format code, they are advised to migrate to --pretty.

[rr: documentation]
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 Documentation/git-for-each-ref.txt | 22 ++++++++++++-
 builtin/for-each-ref.c             | 67 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index f2e08d1..6135812 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -9,7 +9,8 @@ SYNOPSIS
 --------
 [verse]
 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
-		   [(--sort=<key>)...] [--format=<format>] [<pattern>...]
+		   [(--sort=<key>)...] [--format=<format>|--pretty=<pretty>]
+		   [<pattern>...]
 
 DESCRIPTION
 -----------
@@ -47,6 +48,25 @@ OPTIONS
 	`xx`; for example `%00` interpolates to `\0` (NUL),
 	`%09` to `\t` (TAB) and `%0a` to `\n` (LF).
 
+<pretty>::
+	A format string with supporting placeholders described in the
+	"PRETTY FORMATS" section in linkgit:git-log[1].  Additionally
+	supports placeholders from `<format>`
+	(i.e. `%[*](fieldname)`).
++
+Caveats:
+
+1. Many of the placeholders in "PRETTY FORMATS" are designed to work
+   specifically on commit objects: when non-commit objects are
+   supplied, those placeholders won't work.
+
+2. Does not interpolate `%ab` (where `ab` are hex digits) with the
+   corresponding hex code.  To print a byte from a hex code, use
+   `%xab` (from pretty-formats) instead.
+
+3. Only the placeholders inherited from `<format>` will respect
+   quoting settings.
+
 <pattern>...::
 	If one or more patterns are given, only refs are shown that
 	match against at least one pattern, either using fnmatch(3) or
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index e2d6c5a..576a882 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -962,6 +962,58 @@ static void show_refs(struct refinfo **refs, int maxcount,
 	strbuf_release(&sb);
 }
 
+struct format_one_atom_context {
+	struct refinfo *info;
+	int quote_style;
+};
+
+static size_t format_one_atom(struct strbuf *sb, const char *placeholder,
+			      void *format_context, void *user_data,
+			      struct strbuf *subst)
+{
+	struct format_one_atom_context *ctx = user_data;
+	const char *ep;
+
+	if (*placeholder == '%') {
+		strbuf_addch(sb, '%');
+		return 1;
+	}
+
+	if (*placeholder != '(')
+		return 0;
+
+	ep = strchr(placeholder + 1, ')');
+	if (!ep)
+		return 0;
+	print_value(sb, ctx->info, parse_atom(placeholder + 1, ep),
+		    ctx->quote_style);
+	return ep + 1 - placeholder;
+}
+
+static void show_pretty_refs(struct refinfo **refs, int maxcount,
+			     const char *format, int quote_style)
+{
+	struct pretty_print_context ctx = {0};
+	struct format_one_atom_context fctx;
+	struct strbuf sb = STRBUF_INIT;
+	int i;
+
+	ctx.format = format_one_atom;
+	ctx.user_data = &fctx;
+	fctx.quote_style = quote_style;
+	for (i = 0; i < maxcount; i++) {
+		struct commit *commit = NULL;
+		fctx.info = refs[i];
+		if (sha1_object_info(refs[i]->objectname, NULL) == OBJ_COMMIT)
+			commit = lookup_commit(refs[i]->objectname);
+		strbuf_reset(&sb);
+		format_commit_message(commit, format, &sb, &ctx);
+		strbuf_addch(&sb, '\n');
+		fputs(sb.buf, stdout);
+	}
+	strbuf_release(&sb);
+}
+
 static struct ref_sort *default_sort(void)
 {
 	static const char cstr_name[] = "refname";
@@ -1003,7 +1055,9 @@ static char const * const for_each_ref_usage[] = {
 int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 {
 	int num_refs;
-	const char *format = "%(objectname) %(objecttype)\t%(refname)";
+	const char *default_format = "%(objectname) %(objecttype)\t%(refname)";
+	const char *format = default_format;
+	const char *pretty = NULL;
 	struct ref_sort *sort = NULL, **sort_tail = &sort;
 	int maxcount = 0, quote_style = 0;
 	struct refinfo **refs;
@@ -1022,6 +1076,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 		OPT_GROUP(""),
 		OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
 		OPT_STRING(  0 , "format", &format, N_("format"), N_("format to use for the output")),
+		OPT_STRING(  0 , "pretty", &pretty, N_("format"), N_("alternative format to use for the output")),
 		OPT_CALLBACK(0 , "sort", sort_tail, N_("key"),
 			    N_("field name to sort on"), &opt_parse_sort),
 		OPT_END(),
@@ -1036,7 +1091,10 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 		error("more than one quoting style?");
 		usage_with_options(for_each_ref_usage, opts);
 	}
-	if (verify_format(format))
+	if (format != default_format && pretty)
+		die("--format and --pretty cannot be used together");
+	if ((pretty && verify_format(pretty)) ||
+	    (!pretty && verify_format(format)))
 		usage_with_options(for_each_ref_usage, opts);
 
 	if (!sort)
@@ -1057,6 +1115,9 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 	if (!maxcount || num_refs < maxcount)
 		maxcount = num_refs;
 
-	show_refs(refs, maxcount, format, quote_style);
+	if (pretty)
+		show_pretty_refs(refs, maxcount, pretty, quote_style);
+	else
+		show_refs(refs, maxcount, format, quote_style);
 	return 0;
 }
-- 
1.8.3.GIT
Previous: Ramkumar RamachandraNext: Eric Sunshine
Message 11 of 30 in “Towards a more awesome git-branch”
  1. 00/15 Towards a more awesome git-branchRamkumar Ramachandra, Jun 4, 2013
  2. 01/15 for-each-ref, quote: convert *_quote_print -> *_quote_bufRamkumar Ramachandra, Jun 4, 2013
  3. 02/15 for-each-ref: don't print out elements directlyRamkumar Ramachandra, Jun 4, 2013
  4. Junio C HamanoJun 4, 2013
  5. Duy NguyenJun 4, 2013
  6. 03/15 tar-tree: remove dependency on sq_quote_print()Ramkumar Ramachandra, Jun 4, 2013
  7. 04/15 quote: remove sq_quote_print()Ramkumar Ramachandra, Jun 4, 2013
  8. 05/15 pretty: extend pretty_print_context with callbackRamkumar Ramachandra, Jun 4, 2013
  9. 06/15 pretty: limit recursion in format_commit_one()Ramkumar Ramachandra, Jun 4, 2013
  10. 07/15 pretty: allow passing NULL commit to format_commit_message()Ramkumar Ramachandra, Jun 4, 2013
  11. 08/15 for-each-ref: get --pretty using format_commit_messageRamkumar Ramachandra, Jun 4, 2013
  12. Eric SunshineJun 4, 2013
  13. Duy NguyenJun 5, 2013
  14. Junio C HamanoJun 5, 2013
  15. Duy NguyenJun 6, 2013
  16. 09/15 for-each-ref: teach verify_format() about pretty's syntaxRamkumar Ramachandra, Jun 4, 2013
  17. 10/15 for-each-ref: introduce format specifier %>(*) and %<(*)Ramkumar Ramachandra, Jun 4, 2013
  18. Duy NguyenJun 4, 2013
  19. Ramkumar RamachandraJun 5, 2013
  20. Duy NguyenJun 5, 2013
  21. 11/15 for-each-ref: introduce %(HEAD) markerRamkumar Ramachandra, Jun 4, 2013
  22. 12/15 for-each-ref: introduce %(upstream:track[short])Ramkumar Ramachandra, Jun 4, 2013
  23. Eric SunshineJun 4, 2013
  24. 13/15 for-each-ref: improve responsiveness of %(upstream:track)Ramkumar Ramachandra, Jun 4, 2013
  25. 14/15 pretty: introduce get_pretty_userformatRamkumar Ramachandra, Jun 4, 2013
  26. 15/15 for-each-ref: use get_pretty_userformat in --prettyRamkumar Ramachandra, Jun 4, 2013
  27. Duy NguyenJun 4, 2013
  28. Eric SunshineJun 4, 2013
  29. Duy NguyenJun 4, 2013
  30. Ramkumar RamachandraJun 5, 2013

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.