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

[PATCH 3/5] for-each-ref: refactor subject and body placeholder parsing

From
Jeff King <peff@peff.net>
Date
Sep 7, 2011, 17:44 UTC
Message-ID
<20110907174407.GC11355@sigill.intra.peff.net>
In-Reply-To
<20110902175323.GA29761@sigill.intra.peff.net>

The find_subpos function was a little hard to use, as well as to read. It would sometimes write into the subject and body pointers, and sometimes not. The body pointer sometimes could be compared to subject, and sometimes not. When actually duplicating the subject, the caller was forced to figure out again how long the subject is (which is not too big a deal when the subject is a single line, but hard to extend).

The refactoring makes the function more straightforward, both to read and to use. We will always put something into the subject and body pointers, and we return explicit lengths for them, too.

This lays the groundwork both for more complex subject parsing (e.g., multiline), as well as splitting the body into subparts (like the text versus the signature).

Signed-off-by: Jeff King <peff@peff.net>
---
Sorry, the patch is a little bit hard to read. It's probably simpler to
just apply and read the resulting function.
 builtin/for-each-ref.c |   54 +++++++++++++++++++++++++----------------------
 1 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 89e75c6..bcea027 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -458,38 +458,42 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
 	}
 }
 
-static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
+static void find_subpos(const char *buf, unsigned long sz,
+			const char **sub, unsigned long *sublen,
+			const char **body, unsigned long *bodylen)
 {
-	while (*buf) {
-		const char *eol = strchr(buf, '\n');
-		if (!eol)
-			return;
-		if (eol[1] == '\n') {
-			buf = eol + 1;
-			break; /* found end of header */
-		}
-		buf = eol + 1;
+	const char *eol;
+	/* skip past header until we hit empty line */
+	while (*buf && *buf != '\n') {
+		eol = strchrnul(buf, '\n');
+		if (*eol)
+			eol++;
+		buf = eol;
 	}
+	/* skip any empty lines */
 	while (*buf == '\n')
 		buf++;
-	if (!*buf)
-		return;
-	*sub = buf; /* first non-empty line */
-	buf = strchr(buf, '\n');
-	if (!buf) {
-		*body = "";
-		return; /* no body */
-	}
+
+	/* subject is first non-empty line */
+	*sub = buf;
+	/* subject goes to end of line */
+	eol = strchrnul(buf, '\n');
+	*sublen = eol - buf;
+	buf = eol;
+
+	/* skip any empty lines */
 	while (*buf == '\n')
-		buf++; /* skip blank between subject and body */
+		buf++;
 	*body = buf;
+	*bodylen = strlen(buf);
 }
 
 /* See grab_values */
 static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 {
 	int i;
-	const char *subpos = NULL, *bodypos = NULL;
+	const char *subpos = NULL, *bodypos;
+	unsigned long sublen, bodylen;
 
 	for (i = 0; i < used_atom_cnt; i++) {
 		const char *name = used_atom[i];
@@ -503,14 +507,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
 		    strcmp(name, "contents"))
 			continue;
 		if (!subpos)
-			find_subpos(buf, sz, &subpos, &bodypos);
-		if (!subpos)
-			return;
+			find_subpos(buf, sz,
+				    &subpos, &sublen,
+				    &bodypos, &bodylen);
 
 		if (!strcmp(name, "subject"))
-			v->s = copy_line(subpos);
+			v->s = xmemdupz(subpos, sublen);
 		else if (!strcmp(name, "body"))
-			v->s = xstrdup(bodypos);
+			v->s = xmemdupz(bodypos, bodylen);
 		else if (!strcmp(name, "contents"))
 			v->s = xstrdup(subpos);
 	}
-- 
1.7.6.10.g62f04
Previous: Jeff KingNext: Jeff King
Message 28 of 32 in “More formatting with 'git tag -l'”
  1. Michał GórnyAug 29, 2011
  2. Jeff KingAug 29, 2011
  3. Michał GórnyAug 29, 2011
  4. Jeff KingAug 29, 2011
  5. Michał GórnyAug 29, 2011
  6. git-for-each-ref: move GPG sigs off %(body) to %(signature).Michał Górny, Aug 30, 2011
  7. Michael J GruberAug 30, 2011
  8. Michał GórnyAug 30, 2011
  9. Jeff KingAug 30, 2011
  10. for-each-ref: add split message parts to %(contents:*).Michał Górny, Aug 31, 2011
  11. Jeff KingAug 31, 2011
  12. 1/2 t7004: factor out gpg setupJeff King, Aug 31, 2011
  13. 2/2 t6300: test new content:* for-each-ref placeholdersJeff King, Aug 31, 2011
  14. Junio C HamanoAug 31, 2011
  15. Jeff KingAug 31, 2011
  16. Michał GórnySep 1, 2011
  17. Junio C HamanoSep 1, 2011
  18. Jeff KingSep 1, 2011
  19. Michał GórnySep 1, 2011
  20. for-each-ref: add split message parts to %(contents:*).Michał Górny, Sep 1, 2011
  21. Jeff KingSep 2, 2011
  22. Michał GórnySep 2, 2011
  23. Jeff KingSep 2, 2011
  24. Jeff KingSep 7, 2011
  25. Michał GórnySep 15, 2011
  26. 1/5 t7004: factor out gpg setupJeff King, Sep 7, 2011
  27. 2/5 t6300: add more body-parsing testsJeff King, Sep 7, 2011
  28. 3/5 for-each-ref: refactor subject and body placeholder parsingJeff King, Sep 7, 2011
  29. 4/5 for-each-ref: handle multiline subjects like --prettyJeff King, Sep 7, 2011
  30. 5/5 for-each-ref: add split message parts to %(contents:*).Jeff King, Sep 7, 2011
  31. Junio C HamanoSep 1, 2011
  32. Jeff KingSep 1, 2011

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.