On Friday, 1 August 2025 15:11:10 CEST Lucas Seiki Oshiro wrote: > Add the --format flag to git-repo-info. By using this flag, the users > can choose the format for obtaining the data they requested. > > Given that this command can be used for generating input for other > applications and for being read by end users, it requires at least two > formats: one for being read by humans and other for being read by > machines. Some other Git commands also have two output formats, notably > git-config which was the inspiration for the two formats that were > chosen here: > > - keyvalue, where the retrieved data is printed one per line, using = > for delimiting the key and the value. This is the default format, > targeted for end users. > - nul, where the retrieved data is separated by null characters, using > the newline character for delimiting the key and the value. This > format is targeted for being read by machines. > > Helped-by: Phillip Wood <phillip.wood@xxxxxxxxxxxxx> > Helped-by: Junio C Hamano <gitster@xxxxxxxxx> > Helped-by: Justin Tobler <jltobler@xxxxxxxxx> > Helped-by: Eric Sunshine <sunshine@xxxxxxxxxxxxxx> > Mentored-by: Karthik Nayak <karthik.188@xxxxxxxxx> > Mentored-by: Patrick Steinhardt <ps@xxxxxx> > Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@xxxxxxxxx> > --- > Documentation/git-repo.adoc | 31 +++++++++++++++++++- > builtin/repo.c | 58 +++++++++++++++++++++++++++++++------ > t/t1900-repo.sh | 21 ++++++++++++-- > 3 files changed, 97 insertions(+), 13 deletions(-) > > diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc > index 140ee3a0aa..b735cf4737 100644 > --- a/Documentation/git-repo.adoc > +++ b/Documentation/git-repo.adoc > @@ -18,12 +18,23 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. > > COMMANDS > -------- > -`info [<key>...]`:: > +`info [--format=<keyvalue|nul>] [<key>...]`:: According to the source code, I understand that this line should read: `info [--format=(keyvalue|nul)] [<key>...]`:: With parentheses, which is that `keyvalue` and `nul` are keywords describing the type of format. > Retrieve metadata-related information about the current repository. Only > the requested data will be returned based on their keys (see "INFO KEYS" > section below). > + > The returned data is lexicographically sorted by the keys. > ++ > +The output format can be chosen through the flag `--format`. Two formats are > +supported: > ++ > +* `keyvalue`: output key-value pairs one per line using the `=` character as > +the delimiter between the key and the value. This is the default. > + > +* `nul`: similar to `keyvalue`, but using a newline character as the delimiter > +between the key and the value and using a null character after each value. > +This format is better suited for being parsed by another applications than > +`keyvalue`. > > INFO KEYS > --------- > @@ -43,6 +54,24 @@ The reference storage format. The valid values are: > + > include::ref-storage-format.adoc[] > > + > +Examples > +-------- > + > +* Retrieves the reference format of the current repository: > ++ > +------------ > +git repo info references.format > +------------ > ++ > + > +* Retrieves whether the current repository is bare and whether it is shallow > +using the `nul` format: > ++ > +------------ > +git repo info --format=nul layout.bare layout.shallow > +------------ > + > SEE ALSO > -------- > linkgit:git-rev-parse[1] > diff --git a/builtin/repo.c b/builtin/repo.c > index 56c3a4027f..4015cf88b7 100644 > --- a/builtin/repo.c > +++ b/builtin/repo.c > @@ -9,12 +9,17 @@ > #include "shallow.h" > > static const char *const repo_usage[] = { > - "git repo info [<key>...]", > + "git repo info [--format=<keyvalue|nul>] [<key>...]", > NULL > }; > > typedef int get_value_fn(struct repository *repo, struct strbuf *buf); > > +enum output_format { > + FORMAT_KEYVALUE, > + FORMAT_NUL_TERMINATED, > +}; > + > struct field { > const char *key; > get_value_fn *get_value; > @@ -74,18 +79,33 @@ static int qsort_strcmp(const void *va, const void *vb) > return strcmp(a, b); > } > > -static int print_fields(int argc, const char **argv, struct repository *repo) > +static int print_fields(int argc, const char **argv, > + struct repository *repo, > + enum output_format format) > { > int ret = 0; > const char *last = ""; > struct strbuf sb = STRBUF_INIT; > > + char kv_sep; > + char field_sep; > + > + switch (format) { > + case FORMAT_KEYVALUE: > + kv_sep = '='; > + field_sep = '\n'; > + break; > + case FORMAT_NUL_TERMINATED: > + kv_sep = '\n'; > + field_sep = '\0'; > + break; > + } > + > QSORT(argv, argc, qsort_strcmp); > > for (int i = 0; i < argc; i++) { > get_value_fn *get_value; > const char *key = argv[i]; > - char *value; > > if (!strcmp(key, last)) > continue; > @@ -100,11 +120,14 @@ static int print_fields(int argc, const char **argv, struct > repository *repo) strbuf_reset(&sb); > get_value(repo, &sb); > > - value = strbuf_detach(&sb, NULL); > - quote_c_style(value, &sb, NULL, 0); > - free(value); > + if (format == FORMAT_KEYVALUE) { > + char *value; > + value = strbuf_detach(&sb, NULL); > + quote_c_style(value, &sb, NULL, 0); > + free(value); > + } > > - printf("%s=%s\n", key, sb.buf); > + printf("%s%c%s%c", key, kv_sep, sb.buf, field_sep); > last = key; > } > > @@ -112,10 +135,27 @@ static int print_fields(int argc, const char **argv, struct > repository *repo) return ret; > } > > -static int repo_info(int argc, const char **argv, const char *prefix UNUSED, > +static int repo_info(int argc, const char **argv, const char *prefix, > struct repository *repo) > { > - return print_fields(argc - 1, argv + 1, repo); > + const char *format_str = "keyvalue"; > + enum output_format format; > + struct option options[] = { > + OPT_STRING(0, "format", &format_str, N_("format"), > + N_("output format")), > + OPT_END() > + }; > + > + argc = parse_options(argc, argv, prefix, options, repo_usage, 0); > + > + if (!strcmp(format_str, "keyvalue")) > + format = FORMAT_KEYVALUE; > + else if (!strcmp(format_str, "nul")) > + format = FORMAT_NUL_TERMINATED; > + else > + die(_("invalid format '%s'"), format_str); > + > + return print_fields(argc, argv, repo, format); > } > > int cmd_repo(int argc, const char **argv, const char *prefix, > diff --git a/t/t1900-repo.sh b/t/t1900-repo.sh > index 6706cb4c44..463ec3af92 100755 > --- a/t/t1900-repo.sh > +++ b/t/t1900-repo.sh > @@ -21,10 +21,17 @@ test_repo_info () { > key=$4 > expected_value=$5 > > - test_expect_success "$label" ' > - eval "$init_command $repo_name" && > + test_expect_success "keyvalue: $label" ' > + eval "$init_command keyvalue-$repo_name" && > echo "$key=$expected_value" >expected && > - git -C $repo_name repo info "$key" >actual && > + git -C keyvalue-$repo_name repo info "$key" >actual && > + test_cmp expected actual > + ' > + > + test_expect_success "nul: $label" ' > + eval "$init_command nul-$repo_name" && > + printf "%s\n%s\0" "$key" "$expected_value" >expected && > + git -C nul-$repo_name repo info --format=nul "$key" >actual && > test_cmp expected actual > ' > } > @@ -45,6 +52,7 @@ test_repo_info 'shallow repository = false is retrieved > correctly' ' git init' 'nonshallow' 'layout.shallow' 'false' > > test_repo_info 'shallow repository = true is retrieved correctly' ' > + test_when_finished "rm -rf remote" && > git init remote && > echo x >remote/x && > git -C remote add x && > @@ -79,4 +87,11 @@ test_expect_success 'output is returned correctly when two keys > are requested' ' git -C two-keys repo info layout.bare references.format > ' > > +test_expect_success 'git-repo-info aborts when requesting an invalid format' ' > + test_when_finished "rm -f err expected" && > + echo "fatal: invalid format '\'foo\''" >expected && > + test_must_fail git repo info --format=foo 2>err && > + test_cmp expected err > +' > + > test_done