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

Re: [PATCH 2/4] log and rev-list: Fixed newline termination issues with --graph

From
Junio C Hamano <gitster@pobox.com>
Date
Apr 8, 2008, 00:11 UTC
Message-ID
<7vmyo5nr2h.fsf@gitster.siamese.dyndns.org>
In-Reply-To
<7vwsnaoxlz.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
>  (2) Presence of %n in "--pretty=format:..." means a multi-line output and
>      uses separator as before; lack of %n means it is a one-line format
>      and uses terminator.

After thinking about this a bit more, I think a slight variant of the above probably is the least intrusive both from code and semantics point of view, and would match end-user expectations pretty well.

This attached patch introduces a single bit "use_terminator" in "struct rev_info", which is normally false (i.e. most formats use separator semantics) but by flipping it to true, you can ask for terminator semantics just like oneline format does.

The function get_commit_format(), which is what parses "--pretty=" option, now takes a pointer to "struct rev_info" and updates its commit_format and use_terminator fields. It used to return the value of type "enum cmit_fmt", but all the callers assigned it to rev->commit_format.

There are only two cases the code turns use_terminator on. Obviously, the traditional oneline format (--pretty=oneline) is one of them, and the new case is --pretty=format:... that does not end with "%n".

When the custom format "--pretty=format:" is:
	"A: %an <%ae>%nC: %cn <%ce>%n"

it represents a record with two lines (author and committer), and these are output with an extra LF in between, just like the regular --pretty without customization will get an extra separator. The custom format

	"A: %an <%ae> C: %cn <%ce>"

will give a one-line-per-commit output, each of which is terminated with LF. And

	"A: %an <%ae>%nC: %cn <%ce>"
will give two line per commit without extra separator.
---
 builtin-commit.c |    2 +-
 builtin-log.c    |    3 ++-
 commit.h         |    3 ++-
 log-tree.c       |    4 ++--
 pretty.c         |   25 ++++++++++++++++++-------
 revision.c       |    2 +-
 revision.h       |    3 ++-
 7 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/builtin-commit.c b/builtin-commit.c
index 660a345..8bf3503 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -810,7 +810,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
 
 	rev.verbose_header = 1;
 	rev.show_root_diff = 1;
-	rev.commit_format = get_commit_format("format:%h: %s");
+	get_commit_format("format:%h: %s", &rev);
 	rev.always_show_header = 0;
 	rev.diffopt.detect_rename = 1;
 	rev.diffopt.rename_limit = 100;
diff --git a/builtin-log.c b/builtin-log.c
index 5c00725..1670d0b 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -56,7 +56,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
 	rev->abbrev = DEFAULT_ABBREV;
 	rev->commit_format = CMIT_FMT_DEFAULT;
 	if (fmt_pretty)
-		rev->commit_format = get_commit_format(fmt_pretty);
+		get_commit_format(fmt_pretty, rev);
 	rev->verbose_header = 1;
 	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
 	rev->show_root_diff = default_show_root;
@@ -400,6 +400,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix)
 	 * allow us to set a different default.
 	 */
 	rev.commit_format = CMIT_FMT_ONELINE;
+	rev.use_terminator = 1;
 	rev.always_show_header = 1;
 
 	/*
diff --git a/commit.h b/commit.h
index 2f63bc8..2d94d41 100644
--- a/commit.h
+++ b/commit.h
@@ -63,7 +63,8 @@ enum cmit_fmt {
 };
 
 extern int non_ascii(int);
-extern enum cmit_fmt get_commit_format(const char *arg);
+struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
+extern void get_commit_format(const char *arg, struct rev_info *);
 extern void format_commit_message(const struct commit *commit,
                                   const void *format, struct strbuf *sb);
 extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
diff --git a/log-tree.c b/log-tree.c
index 5b29639..d246147 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -249,9 +249,9 @@ void show_log(struct rev_info *opt, const char *sep)
 	 *    not have an empty line between entries.
 	 */
 	extra = "";
-	if (*sep != '\n' && opt->commit_format == CMIT_FMT_ONELINE)
+	if (*sep != '\n' && opt->use_terminator)
 		extra = "\n";
-	if (opt->shown_one && opt->commit_format != CMIT_FMT_ONELINE)
+	if (opt->shown_one && !opt->use_terminator)
 		putchar(opt->diffopt.line_termination);
 	opt->shown_one = 1;
 
diff --git a/pretty.c b/pretty.c
index 16bfb86..365e387 100644
--- a/pretty.c
+++ b/pretty.c
@@ -21,23 +21,34 @@ static struct cmt_fmt_map {
 
 static char *user_format;
 
-enum cmit_fmt get_commit_format(const char *arg)
+void get_commit_format(const char *arg, struct rev_info *rev)
 {
 	int i;
 
-	if (!arg || !*arg)
-		return CMIT_FMT_DEFAULT;
+	rev->use_terminator = 0;
+	if (!arg || !*arg) {
+		rev->commit_format = CMIT_FMT_DEFAULT;
+		return;
+	}
 	if (*arg == '=')
 		arg++;
 	if (!prefixcmp(arg, "format:")) {
+		size_t len = strlen(arg + 7);
 		free(user_format);
 		user_format = xstrdup(arg + 7);
-		return CMIT_FMT_USERFORMAT;
+		if (len < 2 || strcmp(user_format + len - 2, "%n"))
+			rev->use_terminator = 1;
+		rev->commit_format = CMIT_FMT_USERFORMAT;
+		return;
 	}
-	for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
+	for (i = 0; i < ARRAY_SIZE(cmt_fmts) - 1; i++) {
 		if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) &&
-		    !strncmp(arg, cmt_fmts[i].n, strlen(arg)))
-			return cmt_fmts[i].v;
+		    !strncmp(arg, cmt_fmts[i].n, strlen(arg))) {
+			if (cmt_fmts[i].v == CMIT_FMT_ONELINE)
+				rev->use_terminator = 0;
+			rev->commit_format = cmt_fmts[i].v;
+			return;
+		}
 	}
 
 	die("invalid --pretty format: %s", arg);
diff --git a/revision.c b/revision.c
index 196fedc..781c503 100644
--- a/revision.c
+++ b/revision.c
@@ -1198,7 +1198,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
 			}
 			if (!prefixcmp(arg, "--pretty")) {
 				revs->verbose_header = 1;
-				revs->commit_format = get_commit_format(arg+8);
+				get_commit_format(arg+8, revs);
 				continue;
 			}
 			if (!strcmp(arg, "--root")) {
diff --git a/revision.h b/revision.h
index c8b3b94..31217f8 100644
--- a/revision.h
+++ b/revision.h
@@ -64,7 +64,8 @@ struct rev_info {
 
 	/* Format info */
 	unsigned int	shown_one:1,
-			abbrev_commit:1;
+			abbrev_commit:1,
+			use_terminator:1;
 	enum date_mode date_mode;
 
 	const char **ignore_packed; /* pretend objects in these are unpacked */
Previous: Jakub NarebskiNext: Govind Salinas
Message 16 of 37 in “Add history graph API”
  1. 1/4 Add history graph APIAdam Simpkins, Apr 6, 2008
  2. 2/4 graph API: Added additional utility functions to the graph APIAdam Simpkins, Apr 6, 2008
  3. 3/4 git log and git rev-list: Add --graph optionAdam Simpkins, Apr 6, 2008
  4. 4/4 git log: Updated --graph to work even when the commit list is prunedAdam Simpkins, Apr 6, 2008
  5. 5/5 Document the new --graph option for log and rev-listAdam Simpkins, Apr 6, 2008
  6. 1/4 graph API: Fixed coding style problemsAdam Simpkins, Apr 7, 2008
  7. 2/4 log and rev-list: Fixed newline termination issues with --graphAdam Simpkins, Apr 7, 2008
  8. 3/4 log and rev-list: Fix --graph output with --pretty=emailAdam Simpkins, Apr 7, 2008
  9. 4/4 log and rev-list: Improve --graph output when commits have been prunedAdam Simpkins, Apr 7, 2008
  10. Junio C HamanoApr 7, 2008
  11. Junio C HamanoApr 7, 2008
  12. Jeff KingApr 7, 2008
  13. Junio C HamanoApr 7, 2008
  14. Adam SimpkinsApr 7, 2008
  15. Jakub NarebskiApr 7, 2008
  16. Junio C HamanoApr 8, 2008
  17. Govind SalinasApr 8, 2008
  18. Junio C HamanoApr 8, 2008
  19. Teemu LikonenApr 6, 2008
  20. Adam SimpkinsApr 6, 2008
  21. Teemu LikonenApr 6, 2008
  22. Adam SimpkinsApr 6, 2008
  23. Johannes SchindelinApr 6, 2008
  24. Adam SimpkinsApr 6, 2008
  25. Teemu LikonenApr 7, 2008
  26. Adam SimpkinsApr 7, 2008
  27. Teemu LikonenApr 7, 2008
  28. Johannes SchindelinApr 6, 2008
  29. Adam SimpkinsApr 6, 2008
  30. Johannes SchindelinApr 6, 2008
  31. Adam SimpkinsApr 6, 2008
  32. Linus TorvaldsApr 7, 2008
  33. Junio C HamanoApr 7, 2008
  34. bash: Add command line completion of --graph (git log)Teemu Likonen, Apr 6, 2008
  35. bash: Add more command line option completions for 'git log'Teemu Likonen, Apr 7, 2008
  36. Teemu LikonenApr 7, 2008
  37. Adam SimpkinsApr 7, 2008

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.