strbuf_expand: convert "%%" to "%"

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 <>
Signed-off-by: Junio C Hamano <>
This commit is contained in:
Jeff King 2010-01-13 12:35:31 -05:00 committed by Junio C Hamano
parent 902f235378
commit 0a0416a34a
5 changed files with 18 additions and 1 deletions

View File

@ -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

View File

@ -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.

View File

@ -147,7 +147,6 @@ static char *path_ok(char *directory)
{ "IP", ip_address },
{ "P", tcp_port },
{ "D", directory },
{ "%", "%" },
{ NULL }

View File

@ -227,6 +227,12 @@ void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
format = percent + 1;
if (*format == '%') {
strbuf_addch(sb, '%');
consumed = fn(sb, format, context);
if (consumed)
format += consumed;

View File

@ -19,6 +19,13 @@ test_cmp expect.$1 output.$1
test_format percent %%h <<'EOF'
commit 131a310eb913d107dd3c09a65d1651175898735d
commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
test_format hash %H%n%h <<'EOF'
commit 131a310eb913d107dd3c09a65d1651175898735d