Re: [GSoC PATCH v7 5/5] repo: add the --format flag
- From
Jean-Noël AVILA <jn.avila@free.fr>
- Date
- Aug 1, 2025, 20:27 UTC
- Message-ID
- <12714201.O9o76ZdvQC@cayenne>
- In-Reply-To
- <20250801131111.8115-6-lucasseikioshiro@gmail.com>
On Friday, 1 August 2025 15:11:10 CEST Lucas Seiki Oshiro wrote:
Show 40 quoted lines
> 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@dunelm.org.uk> > Helped-by: Junio C Hamano <gitster@pobox.com> > Helped-by: Justin Tobler <jltobler@gmail.com> > Helped-by: Eric Sunshine <sunshine@sunshineco.com> > Mentored-by: Karthik Nayak <karthik.188@gmail.com> > Mentored-by: Patrick Steinhardt <ps@pks.im> > Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> > --- > 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"
Show 8 quoted lines
> 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
Show 22 quoted lines
> +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
Show 37 quoted lines
> +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)
Show 32 quoted lines
> +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
Show 19 quoted lines
> 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
Show 64 quoted lines
> 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' '
Show 7 quoted lines
> + 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