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

[PATCH 4/5] ref-filter: truncate atom names in error messages

From
Jeff King <peff@peff.net>
Date
Dec 14, 2022, 16:23 UTC
Message-ID
<Y5n4mb/S/RORb+N7@coredump.intra.peff.net>
In-Reply-To
<Y5n3S7cnD7s/AIRL@coredump.intra.peff.net>

If you pass a bogus argument to %(refname), you may end up with a message like this:

  $ git for-each-ref --format='%(refname:foo)'
  fatal: unrecognized %(refname:foo) argument: foo
which is confusing. It should just say:
  fatal: unrecognized %(refname) argument: foo

which is clearer, and is consistent with most other atom parsers. Those other parsers do not have the same problem because they pass the atom name from a string literal in the parser function. But because the parser for %(refname) also handles %(upstream) and %(push), it instead uses atom->name, which includes the arguments. The oid atom parser which handles %(tree), %(parent), etc suffers from the same problem.

It seems like the cleanest fix would be for atom->name to be _just_ the name, since there's already a separate "args" field. But since that field is also used for other things, we can't change it easily (e.g., it's how we find things in the used_atoms array, and clearly %(refname) and %(refname:short) are not the same thing).

Instead, we'll teach our error_bad_arg() function to stop at the first ":". This is a little hacky, as we're effectively re-parsing the name, but the format is simple enough to do this as a one-liner, and this localizes the change to the error-reporting code.

We'll give the same treatment to err_no_arg(). None of its callers use this atom->name trick, but it's worth future-proofing it while we're here.

Signed-off-by: Jeff King <peff@peff.net>
---
 ref-filter.c            | 12 ++++++++----
 t/t6300-for-each-ref.sh |  6 ++++++
 2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 271d619da9..f40bc4d9c9 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -230,13 +230,17 @@ static int strbuf_addf_ret(struct strbuf *sb, int ret, const char *fmt, ...)
 
 static int err_no_arg(struct strbuf *sb, const char *name)
 {
-	strbuf_addf(sb, _("%%(%s) does not take arguments"), name);
+	size_t namelen = strchrnul(name, ':') - name;
+	strbuf_addf(sb, _("%%(%.*s) does not take arguments"),
+		    (int)namelen, name);
 	return -1;
 }
 
 static int err_bad_arg(struct strbuf *sb, const char *name, const char *arg)
 {
-	strbuf_addf(sb, _("unrecognized %%(%s) argument: %s"), name, arg);
+	size_t namelen = strchrnul(name, ':') - name;
+	strbuf_addf(sb, _("unrecognized %%(%.*s) argument: %s"),
+		    (int)namelen, name, arg);
 	return -1;
 }
 
@@ -274,7 +278,7 @@ static int refname_atom_parser_internal(struct refname_atom *atom, const char *a
 		if (strtol_i(arg, 10, &atom->rstrip))
 			return strbuf_addf_ret(err, -1, _("Integer value expected refname:rstrip=%s"), arg);
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), name, arg);
+		return err_bad_arg(err, name, arg);
 	return 0;
 }
 
@@ -471,7 +475,7 @@ static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
 		if (atom->u.oid.length < MINIMUM_ABBREV)
 			atom->u.oid.length = MINIMUM_ABBREV;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), atom->name, arg);
+		return err_bad_arg(err, atom->name, arg);
 	return 0;
 }
 
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 010ba5a2cb..2ae1fc721b 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -1254,6 +1254,12 @@ test_expect_success 'subject atom rejects unknown arguments' '
 	test_cmp expect err
 '
 
+test_expect_success 'refname atom rejects unknown arguments' '
+	test_must_fail git for-each-ref --format="%(refname:foo)" 2>err &&
+	echo "fatal: unrecognized %(refname) argument: foo" >expect &&
+	test_cmp expect err
+'
+
 test_expect_success 'trailer parsing not fooled by --- line' '
 	git commit --allow-empty -F - <<-\EOF &&
 	this is the subject
-- 
2.39.0.550.g5015380a67
Previous: Jeff KingNext: Taylor Blau
Message 8 of 12 in “minor ref-filter error-reporting bug-fixes”
  1. 0/5 minor ref-filter error-reporting bug-fixesJeff King, Dec 14, 2022
  2. 1/5 ref-filter: reject arguments to %(HEAD)Jeff King, Dec 14, 2022
  3. 2/5 ref-filter: factor out "%(foo) does not take arguments" errorsJeff King, Dec 14, 2022
  4. Taylor BlauDec 14, 2022
  5. Taylor BlauDec 14, 2022
  6. Jeff KingDec 14, 2022
  7. 3/5 ref-filter: factor out "unrecognized %(foo) arg" errorsJeff King, Dec 14, 2022
  8. 4/5 ref-filter: truncate atom names in error messagesJeff King, Dec 14, 2022
  9. Taylor BlauDec 14, 2022
  10. Jeff KingDec 14, 2022
  11. 5/5 ref-filter: convert email atom parser to use err_bad_arg()Jeff King, Dec 14, 2022
  12. Taylor BlauDec 14, 2022

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.