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

[PATCH v2 1/3] strbuf_expand: convert "%%" to "%"

From
Jeff King <peff@peff.net>
Date
Jan 13, 2010, 17:35 UTC
Message-ID
<20100113173531.GA16786@coredump.intra.peff.net>
In-Reply-To
<20100113173408.GA16652@coredump.intra.peff.net>

The only way to safely quote arbitrary text in a pretty-print user format is to replace instances of "%" with "%x25". This is slightly unreadable, and many users would expect "%%" to produce a single "%", as that is what printf format specifiers do.

This patch converts "%%" to "%" for all users of strbuf_expand:

 1. git-daemon interpolated paths
 2. pretty-print user formats
 3. merge driver command lines

Case (1) was already doing the conversion itself outside of strbuf_expand. Case (2) is the intended beneficiary of this patch. Case (3) users probably won't notice, but as this is user-facing behavior, consistently providing the quoting mechanism makes sense.

Signed-off-by: Jeff King <peff@coredump.intra.peff.net>
---
Changes from v1:
  - note change in strbuf api docs
 Documentation/pretty-formats.txt       |    1 +
 Documentation/technical/api-strbuf.txt |    4 ++++
 daemon.c                               |    1 -
 strbuf.c                               |    6 ++++++
 t/t6006-rev-list-format.sh             |    7 +++++++
 5 files changed, 18 insertions(+), 1 deletions(-)
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 53a9168..1686a54 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -134,6 +134,7 @@ The placeholders are:
 - '%C(...)': color specification, as described in color.branch.* config option
 - '%m': left, right or boundary mark
 - '%n': newline
+- '%%': a raw '%'
 - '%x00': print a byte from a hex code
 - '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
   linkgit:git-shortlog[1].
diff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt
index a0e0f85..3b1da10 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -199,6 +199,10 @@ character if the letter `n` appears after a `%`.  The function returns
 the length of the placeholder recognized and `strbuf_expand()` skips
 over it.
 +
+The format `%%` is automatically expanded to a single `%` as a quoting
+mechanism; callers do not need to handle the `%` placeholder themselves,
+and the callback function will not be invoked for this placeholder.
++
 All other characters (non-percent and not skipped ones) are copied
 verbatim to the strbuf.  If the callback returned zero, meaning that the
 placeholder is unknown, then the percent sign is copied, too.
diff --git a/daemon.c b/daemon.c
index 918e560..360635e 100644
--- a/daemon.c
+++ b/daemon.c
@@ -147,7 +147,6 @@ static char *path_ok(char *directory)
 			{ "IP", ip_address },
 			{ "P", tcp_port },
 			{ "D", directory },
-			{ "%", "%" },
 			{ NULL }
 		};
 
diff --git a/strbuf.c b/strbuf.c
index a6153dc..6cbc1fc 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -227,6 +227,12 @@ void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
 			break;
 		format = percent + 1;
 
+		if (*format == '%') {
+			strbuf_addch(sb, '%');
+			format++;
+			continue;
+		}
+
 		consumed = fn(sb, format, context);
 		if (consumed)
 			format += consumed;
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 5719315..b0047d3 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -19,6 +19,13 @@ test_cmp expect.$1 output.$1
 "
 }
 
+test_format percent %%h <<'EOF'
+commit 131a310eb913d107dd3c09a65d1651175898735d
+%h
+commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+%h
+EOF
+
 test_format hash %H%n%h <<'EOF'
 commit 131a310eb913d107dd3c09a65d1651175898735d
 131a310eb913d107dd3c09a65d1651175898735d
-- 
1.6.6.140.g92e4d.dirty
Previous: Jeff KingNext: Chris Johnsen
Message 37 of 54 in “edit Author/Date metadata as part of 'git commit' $EDITOR invocation?”
  1. Adam MegaczJan 3, 2010
  2. Sverre RabbelierJan 4, 2010
  3. Adam MegaczJan 4, 2010
  4. Sverre RabbelierJan 4, 2010
  5. David AguilarJan 5, 2010
  6. Nanako ShiraishiJan 5, 2010
  7. Junio C HamanoJan 6, 2010
  8. Adam MegaczJan 8, 2010
  9. Junio C HamanoJan 8, 2010
  10. 1/3 ident.c: remove unused variablesJunio C Hamano, Jan 8, 2010
  11. 2/3 ident.c: check explicit identity for name and email separatelyJunio C Hamano, Jan 8, 2010
  12. Santi BéjarJan 8, 2010
  13. 3/3 ident.c: treat $EMAIL as giving user.email identity explicitlyJunio C Hamano, Jan 8, 2010
  14. Display author and committer after "git commit"Adam Megacz, Jan 11, 2010
  15. Adam MegaczJan 11, 2010
  16. Junio C HamanoJan 11, 2010
  17. Adam MegaczJan 12, 2010
  18. Jeff KingJan 12, 2010
  19. Jeff KingJan 12, 2010
  20. Jeff KingJan 12, 2010
  21. 1/3 strbuf_expand: convert "%%" to "%"Jeff King, Jan 12, 2010
  22. 2/3 strbuf: add strbuf_percentquote_bufJeff King, Jan 12, 2010
  23. Johannes SchindelinJan 12, 2010
  24. Jeff KingJan 12, 2010
  25. Junio C HamanoJan 13, 2010
  26. Jeff KingJan 13, 2010
  27. Junio C HamanoJan 13, 2010
  28. Jeff KingJan 13, 2010
  29. 3/3 commit: show interesting ident information in summaryJeff King, Jan 12, 2010
  30. Junio C HamanoJan 13, 2010
  31. Jeff KingJan 13, 2010
  32. Junio C HamanoJan 13, 2010
  33. Jeff KingJan 13, 2010
  34. Jeff KingJan 13, 2010
  35. Junio C HamanoJan 13, 2010
  36. Jeff KingJan 13, 2010
  37. 1/3 strbuf_expand: convert "%%" to "%"Jeff King, Jan 13, 2010
  38. Chris JohnsenJan 14, 2010
  39. Jeff KingJan 14, 2010
  40. 2/3 strbuf: add strbuf_addbuf_percentquoteJeff King, Jan 13, 2010
  41. 3/3 commit: show interesting ident information in summaryJeff King, Jan 13, 2010
  42. Wincent ColaiutaJan 13, 2010
  43. Jeff KingJan 13, 2010
  44. Wincent ColaiutaJan 13, 2010
  45. Thomas RastJan 14, 2010
  46. Felipe ContrerasJan 14, 2010
  47. Junio C HamanoJan 14, 2010
  48. Felipe ContrerasJan 14, 2010
  49. Junio C HamanoJan 14, 2010
  50. Felipe ContrerasJan 15, 2010
  51. Adam MegaczJan 16, 2010
  52. Matthieu MoyJan 17, 2010
  53. Junio C HamanoJan 17, 2010
  54. Jeff KingJan 17, 2010

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.