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

[PATCH v10 11/20] ref-filter: introduce refname_atom_parser()

From
Karthik Nayak <karthik.188@gmail.com>
Date
Jan 10, 2017, 08:49 UTC
Message-ID
<20170110084953.15890-12-Karthik.188@gmail.com>
In-Reply-To
<20170110084953.15890-1-Karthik.188@gmail.com>
From: Karthik Nayak <karthik.188@gmail.com>

Using refname_atom_parser_internal(), introduce refname_atom_parser() which will parse the %(symref) and %(refname) atoms. Store the parsed information into the 'used_atom' structure based on the modifiers used along with the atoms.

Now the '%(symref)' atom supports the ':strip' atom modifier. Update the Documentation and tests to reflect this.

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Karthik Nayak <Karthik.188@gmail.com>
---
 Documentation/git-for-each-ref.txt |  5 +++
 ref-filter.c                       | 73 +++++++++++++++++++++-----------------
 t/t6300-for-each-ref.sh            |  9 +++++
 3 files changed, 54 insertions(+), 33 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 14240b407..5de22cf64 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -170,6 +170,11 @@ if::
 	the value between the %(if:...) and %(then) atoms with the
 	given string.
 
+symref::
+	The ref which the given symbolic ref refers to. If not a
+	symbolic ref, nothing is printed. Respects the `:short` and
+	`:strip` options in the same way as `refname` above.
+
 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
 be used to specify the value in the header field.
diff --git a/ref-filter.c b/ref-filter.c
index c1ebc406c..7bfd65633 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -187,6 +187,11 @@ static void objectname_atom_parser(struct used_atom *atom, const char *arg)
 		die(_("unrecognized %%(objectname) argument: %s"), arg);
 }
 
+static void refname_atom_parser(struct used_atom *atom, const char *arg)
+{
+	return refname_atom_parser_internal(&atom->u.refname, arg, atom->name);
+}
+
 static align_type parse_align_position(const char *s)
 {
 	if (!strcmp(s, "right"))
@@ -257,7 +262,7 @@ static struct {
 	cmp_type cmp_type;
 	void (*parser)(struct used_atom *atom, const char *arg);
 } valid_atom[] = {
-	{ "refname" },
+	{ "refname" , FIELD_STR, refname_atom_parser },
 	{ "objecttype" },
 	{ "objectsize", FIELD_ULONG },
 	{ "objectname", FIELD_STR, objectname_atom_parser },
@@ -287,7 +292,7 @@ static struct {
 	{ "contents", FIELD_STR, contents_atom_parser },
 	{ "upstream", FIELD_STR, remote_ref_atom_parser },
 	{ "push", FIELD_STR, remote_ref_atom_parser },
-	{ "symref" },
+	{ "symref", FIELD_STR, refname_atom_parser },
 	{ "flag" },
 	{ "HEAD" },
 	{ "color", FIELD_STR, color_atom_parser },
@@ -1082,21 +1087,16 @@ static inline char *copy_advance(char *dst, const char *src)
 	return dst;
 }
 
-static const char *strip_ref_components(const char *refname, const char *nr_arg)
+static const char *strip_ref_components(const char *refname, unsigned int len)
 {
-	char *end;
-	long nr = strtol(nr_arg, &end, 10);
-	long remaining = nr;
+	long remaining = len;
 	const char *start = refname;
 
-	if (nr < 1 || *end != '\0')
-		die(_(":strip= requires a positive integer argument"));
-
 	while (remaining) {
 		switch (*start++) {
 		case '\0':
-			die(_("ref '%s' does not have %ld components to :strip"),
-			    refname, nr);
+			die(_("ref '%s' does not have %ud components to :strip"),
+			    refname, len);
 		case '/':
 			remaining--;
 			break;
@@ -1105,6 +1105,16 @@ static const char *strip_ref_components(const char *refname, const char *nr_arg)
 	return start;
 }
 
+static const char *show_ref(struct refname_atom *atom, const char *refname)
+{
+	if (atom->option == R_SHORT)
+		return shorten_unambiguous_ref(refname, warn_ambiguous_refs);
+	else if (atom->option == R_STRIP)
+		return strip_ref_components(refname, atom->strip);
+	else
+		return refname;
+}
+
 static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
 				    struct branch *branch, const char **s)
 {
@@ -1177,6 +1187,21 @@ char *get_head_description(void)
 	return strbuf_detach(&desc, NULL);
 }
 
+static const char *get_symref(struct used_atom *atom, struct ref_array_item *ref)
+{
+	if (!ref->symref)
+		return "";
+	else
+		return show_ref(&atom->u.refname, ref->symref);
+}
+
+static const char *get_refname(struct used_atom *atom, struct ref_array_item *ref)
+{
+	if (ref->kind & FILTER_REFS_DETACHED_HEAD)
+		return get_head_description();
+	return show_ref(&atom->u.refname, ref->refname);
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  */
@@ -1205,7 +1230,6 @@ static void populate_value(struct ref_array_item *ref)
 		struct atom_value *v = &ref->value[i];
 		int deref = 0;
 		const char *refname;
-		const char *formatp;
 		struct branch *branch = NULL;
 
 		v->handler = append_atom;
@@ -1216,12 +1240,10 @@ static void populate_value(struct ref_array_item *ref)
 			name++;
 		}
 
-		if (starts_with(name, "refname")) {
-			refname = ref->refname;
-			if (ref->kind & FILTER_REFS_DETACHED_HEAD)
-				refname = get_head_description();
-		} else if (starts_with(name, "symref"))
-			refname = ref->symref ? ref->symref : "";
+		if (starts_with(name, "refname"))
+			refname = get_refname(atom, ref);
+		else if (starts_with(name, "symref"))
+			refname = get_symref(atom, ref);
 		else if (starts_with(name, "upstream")) {
 			const char *branch_name;
 			/* only local branches may have an upstream */
@@ -1297,21 +1319,6 @@ static void populate_value(struct ref_array_item *ref)
 		} else
 			continue;
 
-		formatp = strchr(name, ':');
-		if (formatp) {
-			const char *arg;
-
-			formatp++;
-			if (!strcmp(formatp, "short"))
-				refname = shorten_unambiguous_ref(refname,
-						      warn_ambiguous_refs);
-			else if (skip_prefix(formatp, "strip=", &arg))
-				refname = strip_ref_components(refname, arg);
-			else
-				die(_("unknown %.*s format %s"),
-				    (int)(formatp - name), name, formatp);
-		}
-
 		if (!deref)
 			v->s = refname;
 		else
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 7663a3661..18a9e2565 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -624,4 +624,13 @@ test_expect_success 'Verify usage of %(symref:short) atom' '
 	test_cmp expected actual
 '
 
+cat >expected <<EOF
+master
+EOF
+
+test_expect_success 'Verify usage of %(symref:strip) atom' '
+	git for-each-ref --format="%(symref:strip=2)" refs/heads/sym > actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.11.0
Previous: Karthik NayakNext: Karthik Nayak
Message 13 of 28 in “port branch.c to use ref-filter's printing options”
  1. 00/20 port branch.c to use ref-filter's printing optionsKarthik Nayak, Jan 10, 2017
  2. 01/20 ref-filter: implement %(if), %(then), and %(else) atomsKarthik Nayak, Jan 10, 2017
  3. 03/20 ref-filter: implement %(if:equals=<string>) and %(if:notequals=<string>)Karthik Nayak, Jan 10, 2017
  4. Junio C HamanoJan 10, 2017
  5. Karthik NayakJan 14, 2017
  6. 04/20 ref-filter: modify "%(objectname:short)" to take lengthKarthik Nayak, Jan 10, 2017
  7. 02/20 ref-filter: include reference to 'used_atom' within 'atom_value'Karthik Nayak, Jan 10, 2017
  8. 07/20 ref-filter: make %(upstream:track) prints "[gone]" for invalid upstreamsKarthik Nayak, Jan 10, 2017
  9. 06/20 ref-filter: introduce format_ref_array_item()Karthik Nayak, Jan 10, 2017
  10. 05/20 ref-filter: move get_head_description() from branch.cKarthik Nayak, Jan 10, 2017
  11. 08/20 ref-filter: add support for %(upstream:track,nobracket)Karthik Nayak, Jan 10, 2017
  12. 10/20 ref-filter: introduce refname_atom_parser_internal()Karthik Nayak, Jan 10, 2017
  13. 11/20 ref-filter: introduce refname_atom_parser()Karthik Nayak, Jan 10, 2017
  14. 09/20 ref-filter: make "%(symref)" atom work with the ':short' modifierKarthik Nayak, Jan 10, 2017
  15. 15/20 ref-filter: modify the 'lstrip=<N>' option to work with negative '<N>'Karthik Nayak, Jan 10, 2017
  16. 20/20 branch: implement '--format' optionKarthik Nayak, Jan 10, 2017
  17. 17/20 ref-filter: allow porcelain to translate messages in the outputKarthik Nayak, Jan 10, 2017
  18. 16/20 ref-filter: add an 'rstrip=<N>' option to atoms which deal with refnamesKarthik Nayak, Jan 10, 2017
  19. 19/20 branch: use ref-filter printing APIsKarthik Nayak, Jan 10, 2017
  20. Jacob KellerJan 11, 2017
  21. Karthik NayakJan 14, 2017
  22. Jacob KellerJan 15, 2017
  23. 18/20 branch, tag: use porcelain outputKarthik Nayak, Jan 10, 2017
  24. 14/20 ref-filter: Do not abruptly die when using the 'lstrip=<N>' optionKarthik Nayak, Jan 10, 2017
  25. 12/20 ref-filter: make remote_ref_atom_parser() use refname_atom_parser_internal()Karthik Nayak, Jan 10, 2017
  26. 13/20 ref-filter: rename the 'strip' option to 'lstrip'Karthik Nayak, Jan 10, 2017
  27. Junio C HamanoJan 10, 2017
  28. Karthik NayakJan 14, 2017

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.