diff mbox series

[4/7] builtin/blame: Expand format when available

Message ID 20250301214652.536439-5-aleks.todorov.1337@gmail.com (mailing list archive)
State New
Headers show
Series Add Format Specifier for Blame | expand

Commit Message

Aleks Todorov March 1, 2025, 9:45 p.m. UTC
When the user-specified format string is available, expand the string by
filling in the details and emit.

We can therefore now emulate the default format with the following
command:

  git blame builtin/blame.c -F '%h %<(17,trunc)%F (%<(20,trunc)%an %ai %>(4)%L) '

Signed-off-by: Aleks Todorov <aleks.todorov.1337@gmail.com>
---
 builtin/blame.c | 112 ++++++++++++++++++++++++++++--------------------
 1 file changed, 65 insertions(+), 47 deletions(-)
diff mbox series

Patch

diff --git a/builtin/blame.c b/builtin/blame.c
index 891ac017f7..d2b605f7a9 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -489,63 +489,81 @@  static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
 		if (color)
 			fputs(color, stdout);
 
-		if (suspect->commit->object.flags & UNINTERESTING) {
-			if (blank_boundary) {
-				memset(hex, ' ', strlen(hex));
-			} else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) {
-				length--;
-				putchar('^');
-			}
-		}
-
-		if (mark_unblamable_lines && ent->unblamable) {
-			length--;
-			putchar('*');
-		}
-		if (mark_ignored_lines && ent->ignored) {
-			length--;
-			putchar('?');
-		}
-
-		printf("%.*s", (int)(length < GIT_MAX_HEXSZ ? length : GIT_MAX_HEXSZ), hex);
-		if (opt & OUTPUT_ANNOTATE_COMPAT) {
-			const char *name;
-			if (opt & OUTPUT_SHOW_EMAIL)
-				name = ci.author_mail.buf;
-			else
-				name = ci.author.buf;
-			printf("\t(%10s\t%10s\t%d)", name,
-			       format_time(ci.author_time, ci.author_tz.buf,
-					   show_raw_time),
-			       ent->lno + 1 + cnt);
+		if (format) {
+			struct strbuf sb = STRBUF_INIT;
+			struct pretty_print_context context = {
+				.fmt = CMIT_FMT_USERFORMAT,
+				.abbrev = abbrev,
+				.is_blame = true,
+				.filename = suspect->path,
+				.line = ent->lno + 1 + cnt,
+			};
+			repo_format_commit_message(the_repository,
+						   suspect->commit, format, &sb,
+						   &context);
+			printf("%s", sb.buf);
+			strbuf_release(&sb);
 		} else {
-			if (opt & OUTPUT_SHOW_SCORE)
-				printf(" %*d %02d",
-				       max_score_digits, ent->score,
-				       ent->suspect->refcnt);
-			if (opt & OUTPUT_SHOW_NAME)
-				printf(" %-*.*s", longest_file, longest_file,
-				       suspect->path);
-			if (opt & OUTPUT_SHOW_NUMBER)
-				printf(" %*d", max_orig_digits,
-				       ent->s_lno + 1 + cnt);
+			if (suspect->commit->object.flags & UNINTERESTING) {
+				if (blank_boundary) {
+					memset(hex, ' ', strlen(hex));
+				} else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) {
+					length--;
+					putchar('^');
+				}
+			}
 
-			if (!(opt & OUTPUT_NO_AUTHOR)) {
+			if (mark_unblamable_lines && ent->unblamable) {
+				length--;
+				putchar('*');
+			}
+			if (mark_ignored_lines && ent->ignored) {
+				length--;
+				putchar('?');
+			}
+
+			printf("%.*s",
+			       (int)(length < GIT_MAX_HEXSZ ? length :
+							      GIT_MAX_HEXSZ),
+			       hex);
+			if (opt & OUTPUT_ANNOTATE_COMPAT) {
 				const char *name;
-				int pad;
 				if (opt & OUTPUT_SHOW_EMAIL)
 					name = ci.author_mail.buf;
 				else
 					name = ci.author.buf;
-				pad = longest_author - utf8_strwidth(name);
-				printf(" (%s%*s %10s",
-				       name, pad, "",
+				printf("\t(%10s\t%10s\t%d)", name,
 				       format_time(ci.author_time,
 						   ci.author_tz.buf,
-						   show_raw_time));
+						   show_raw_time),
+				       ent->lno + 1 + cnt);
+			} else {
+				if (opt & OUTPUT_SHOW_SCORE)
+					printf(" %*d %02d", max_score_digits,
+					       ent->score, ent->suspect->refcnt);
+				if (opt & OUTPUT_SHOW_NAME)
+					printf(" %-*.*s", longest_file,
+					       longest_file, suspect->path);
+				if (opt & OUTPUT_SHOW_NUMBER)
+					printf(" %*d", max_orig_digits,
+					       ent->s_lno + 1 + cnt);
+
+				if (!(opt & OUTPUT_NO_AUTHOR)) {
+					const char *name;
+					int pad;
+					if (opt & OUTPUT_SHOW_EMAIL)
+						name = ci.author_mail.buf;
+					else
+						name = ci.author.buf;
+					pad = longest_author -
+					      utf8_strwidth(name);
+					printf(" (%s%*s %10s", name, pad, "",
+					       format_time(ci.author_time,
+							   ci.author_tz.buf,
+							   show_raw_time));
+				}
+				printf(" %*d) ", max_digits, ent->lno + 1 + cnt);
 			}
-			printf(" %*d) ",
-			       max_digits, ent->lno + 1 + cnt);
 		}
 		if (reset)
 			fputs(reset, stdout);