Subject: [GSoC RFC PATCH v2 2/7] repo-info: add the --format flag

From: Lucas Seiki Oshiro <[email-masked]>
Date: Thu, 19 Jun 2025 19:57:46 -0300

Add the --format flag to the repo-info command, allowing the user to
choose between output formats. Use 'json' by default.

Mentored-by: Karthik Nayak <[email-masked]>
Mentored-by Patrick Steinhardt <[email-masked]>
Signed-off-by: Lucas Seiki Oshiro <[email-masked]>
---
 builtin/repo-info.c  | 54 +++++++++++++++++++++++++++++++++++++++++++-
 t/meson.build        |  1 +
 t/t1900-repo-info.sh | 22 ++++++++++++++++++
 3 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100755 t/t1900-repo-info.sh

diff --git a/builtin/repo-info.c b/builtin/repo-info.c
index a5c43e253f..cbe1475e30 100644
--- a/builtin/repo-info.c
+++ b/builtin/repo-info.c
@@ -1,21 +1,73 @@
 #include "builtin.h"
+#include "json-writer.h"
 #include "parse-options.h"
 
+enum output_format {
+	FORMAT_JSON
+};
+
+struct repo_info {
+	struct repository *repo;
+	enum output_format format;
+};
+
+static void repo_info_init(struct repo_info *repo_info,
+			   struct repository *repo,
+			   char *format)
+{
+	repo_info->repo = repo;
+
+	if (format == NULL || !strcmp(format, "json"))
+		repo_info->format = FORMAT_JSON;
+	else
+		die("invalid format %s", format);
+}
+
+static void repo_info_print_json(struct repo_info *repo_info UNUSED)
+{
+	struct json_writer jw;
+
+	jw_init(&jw);
+
+	jw_object_begin(&jw, 1);
+	jw_end(&jw);
+
+	puts(jw.json.buf);
+	jw_release(&jw);
+}
+
+static void repo_info_print(struct repo_info *repo_info)
+{
+	enum output_format format = repo_info->format;
+
+	switch (format) {
+	case FORMAT_JSON:
+		repo_info_print_json(repo_info);
+		break;
+	}
+}
+
 int cmd_repo_info(int argc,
 		  const char **argv,
 		  const char *prefix,
-		  struct repository *repo UNUSED)
+		  struct repository *repo)
 {
 	const char *const repo_info_usage[] = {
 		"git repo-info",
 		NULL
 	};
+	struct repo_info repo_info;
+	char *format = NULL;
 	struct option options[] = {
+		OPT_STRING(0, "format", &format, N_("format"),
+			   N_("output format")),
 		OPT_END()
 	};
 
 	argc = parse_options(argc, argv, prefix, options, repo_info_usage,
 			     PARSE_OPT_KEEP_UNKNOWN_OPT);
+	repo_info_init(&repo_info, repo, format);
+	repo_info_print(&repo_info);
 
 	return 0;
 }
diff --git a/t/meson.build b/t/meson.build
index 50e89e764a..d9ecaba3b7 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -246,6 +246,7 @@ integration_tests = [
   't1700-split-index.sh',
   't1701-racy-split-index.sh',
   't1800-hook.sh',
+  't1900-repo-info.sh',
   't2000-conflict-when-checking-files-out.sh',
   't2002-checkout-cache-u.sh',
   't2003-checkout-cache-mkdir.sh',
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
new file mode 100755
index 0000000000..f634e1a285
--- /dev/null
+++ b/t/t1900-repo-info.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='test git repo-info'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+parse_json () {
+	tr '\n' ' ' | "$PERL_PATH" "$TEST_DIRECTORY/t0019/parse_json.perl"
+}
+
+test_lazy_prereq PERLJSON '
+	perl -MJSON -e "exit 0"
+'
+
+test_expect_success PERLJSON 'json: returns empty output with allow-empty' '
+	git repo-info --format=json >output &&
+	test_line_count = 2 output
+'
+
+test_done
-- 
2.39.5 (Apple Git-154)