[GSoC PATCH v8 0/5] repo: add new command for retrieving repository info
From: Lucas Seiki Oshiro <hidden>
Date: 2025-08-06 19:55:57
Hi again!
This 8th version of `git-repo` basically address minor issues from the 7th
version:
- A test wasn't passing in the CI because it assumed that the ref
format was files by default. I fixed that.
- t0450 wasn't passing because the documentation didn't match the
usage string. I fixed that.
- A test generated the output and the expected value but wasn't
comparing them. I also fixed that.
- strbuf management: now we have two strbufs for printing values:
one for unquoted values and other for quoted values
- Test codestyle: now it's ending test case liness with \ instead of
open strings
- Documentation: this version documents that we escape the value in
the `keyvalue` format.
Here's the range-diff versus v7:
1: 51b20490e2 = 1: 3c2ede66be repo: declare the repo command
2: 8be77db9e5 ! 2: 396bee171a repo: add the field references.format
@@ Documentation/git-repo.adoc: COMMANDS
section below).
++
+The returned data is lexicographically sorted by the keys.
+++
++The output format consists of key-value pairs one per line using the `=`
++character as the delimiter between the key and the value. Values containing
++"unusual" characters are quoted as explained for the configuration variable
++`core.quotePath` (see linkgit:git-config[1]). This is the default.
+
+INFO KEYS
+---------
@@ builtin/repo.c
+{
+ int ret = 0;
+ const char *last = "";
-+ struct strbuf sb = STRBUF_INIT;
++ struct strbuf valbuf = STRBUF_INIT;
++ struct strbuf quotbuf = STRBUF_INIT;
+
+ QSORT(argv, argc, qsort_strcmp);
+
+ for (int i = 0; i < argc; i++) {
+ get_value_fn *get_value;
+ const char *key = argv[i];
-+ char *value;
++
++ strbuf_reset(&valbuf);
++ strbuf_reset("buf);
+
+ if (!strcmp(key, last))
+ continue;
+
++ last = key;
+ get_value = get_value_fn_for_key(key);
+
+ if (!get_value) {
@@ builtin/repo.c
+ continue;
+ }
+
-+ strbuf_reset(&sb);
-+ get_value(repo, &sb);
-+
-+ value = strbuf_detach(&sb, NULL);
-+ quote_c_style(value, &sb, NULL, 0);
-+ free(value);
-+
-+ printf("%s=%s\n", key, sb.buf);
-+ last = key;
++ get_value(repo, &valbuf);
++ quote_c_style(valbuf.buf, "buf, NULL, 0);
++ printf("%s=%s\n", key, quotbuf.buf);
+ }
+
-+ strbuf_release(&sb);
++ strbuf_release(&valbuf);
++ strbuf_release("buf);
+ return ret;
+}
+
@@ t/t1900-repo.sh (new)
+#
+# Arguments:
+# label: the label of the test
-+# init command: a command which creates a repository named with its first argument,
-+# accordingly to what is being tested
++# init_command: a command which creates a repository
++# repo_name: the name of the repository that will be created in init_command
+# key: the key of the field that is being tested
-+# expected value: the value that the field should contain
++# expected_value: the value that the field should contain
+test_repo_info () {
+ label=$1
+ init_command=$2
@@ t/t1900-repo.sh (new)
+'
+
+test_expect_success 'git-repo-info outputs data even if there is an invalid field' '
-+ echo "references.format=files" >expected &&
++ echo "references.format=$(test_detect_ref_format)" >expected &&
+ test_must_fail git repo info foo references.format bar >actual &&
+ test_cmp expected actual
+'
3: c93aeafb05 ! 3: 4dbc83c64c repo: add the field layout.bare
@@ builtin/repo.c: struct field {
+static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)
+{
-+ strbuf_addstr(buf,
-+ is_bare_repository() ? "true" : "false");
++ strbuf_addstr(buf, is_bare_repository() ? "true" : "false");
+ return 0;
+}
+
@@ t/t1900-repo.sh: test_repo_info 'ref format files is retrieved correctly' '
test_repo_info 'ref format reftable is retrieved correctly' '
git init --ref-format=reftable' 'format-reftable' 'references.format' 'reftable'
-+test_repo_info 'bare repository = false is retrieved correctly' '
-+ git init' 'bare' 'layout.bare' 'false'
++test_repo_info 'bare repository = false is retrieved correctly' \
++ 'git init' 'nonbare' 'layout.bare' 'false'
+
-+test_repo_info 'bare repository = true is retrieved correctly' '
-+ git init --bare' 'nonbare' 'layout.bare' 'true'
++test_repo_info 'bare repository = true is retrieved correctly' \
++ 'git init --bare' 'bare' 'layout.bare' 'true'
+
test_expect_success 'git-repo-info fails if an invalid key is requested' '
echo "error: key '\'foo\'' not found" >expected_err &&
@@ t/t1900-repo.sh: test_expect_success 'only one value is returned if the same key
'
+test_expect_success 'output is returned correctly when two keys are requested' '
-+ cat >expect <<-\EOF &&
++ cat >expected <<-\EOF &&
+ layout.bare=false
+ references.format=files
+ EOF
+ git init --ref-format=files two-keys &&
-+ git -C two-keys repo info layout.bare references.format
++ git -C two-keys repo info layout.bare references.format > actual &&
++ test_cmp expected actual
+'
++
test_done
4: 4463b85193 ! 4: 5c65a24df4 repo: add the field layout.shallow
@@ builtin/repo.c: static int get_references_format(struct repository *repo, struct
## t/t1900-repo.sh ##
-@@ t/t1900-repo.sh: test_repo_info 'bare repository = false is retrieved correctly' '
- test_repo_info 'bare repository = true is retrieved correctly' '
- git init --bare' 'nonbare' 'layout.bare' 'true'
+@@ t/t1900-repo.sh: test_repo_info 'bare repository = false is retrieved correctly' \
+ test_repo_info 'bare repository = true is retrieved correctly' \
+ 'git init --bare' 'bare' 'layout.bare' 'true'
-+test_repo_info 'shallow repository = false is retrieved correctly' '
-+ git init' 'nonshallow' 'layout.shallow' 'false'
++test_repo_info 'shallow repository = false is retrieved correctly' \
++ 'git init' 'nonshallow' 'layout.shallow' 'false'
+
-+test_repo_info 'shallow repository = true is retrieved correctly' '
-+ git init remote &&
++test_repo_info 'shallow repository = true is retrieved correctly' \
++ 'git init remote &&
+ echo x >remote/x &&
+ git -C remote add x &&
+ git -C remote commit -m x &&
@@ t/t1900-repo.sh: test_repo_info 'bare repository = false is retrieved correctly'
test_expect_success 'git-repo-info fails if an invalid key is requested' '
echo "error: key '\'foo\'' not found" >expected_err &&
test_must_fail git repo info foo 2>actual_err &&
-@@ t/t1900-repo.sh: test_expect_success 'output is returned correctly when two keys are requested' '
- git init --ref-format=files two-keys &&
- git -C two-keys repo info layout.bare references.format
- '
-+
- test_done
5: 90427acf54 ! 5: dc8ea099f5 repo: add the --format flag
@@ Documentation/git-repo.adoc: git-repo - Retrieve information about the repositor
--------
[synopsis]
-git repo info [<key>...]
-+git repo info [--format=<keyvalue|nul>] [<key>...]
++git repo info [--format=(keyvalue|nul)] [<key>...]
DESCRIPTION
-----------
@@ Documentation/git-repo.adoc: THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHAN
COMMANDS
--------
-`info [<key>...]`::
-+`info [--format=<keyvalue|nul>] [<key>...]`::
++`info [--format=(keyvalue|nul)] [<key>...]`::
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 consists of key-value pairs one per line using the `=`
+-character as the delimiter between the key and the value. Values containing
+-"unusual" characters are quoted as explained for the configuration variable
+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.
-+
++the delimiter between the key and the value. Values containing "unusual"
++characters are quoted as explained for the configuration variable
+ `core.quotePath` (see linkgit:git-config[1]). 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`.
-
++`keyvalue`. Unlike in the `keyvalue` format, the values are never quoted.
++
INFO KEYS
---------
+
@@ Documentation/git-repo.adoc: The reference storage format. The valid values are:
+
include::ref-storage-format.adoc[]
@@ builtin/repo.c
static const char *const repo_usage[] = {
- "git repo info [<key>...]",
-+ "git repo info [--format=<keyvalue|nul>] [<key>...]",
++ "git repo info [--format=(keyvalue|nul)] [<key>...]",
NULL
};
@@ builtin/repo.c: static int qsort_strcmp(const void *va, const void *vb)
{
int ret = 0;
const char *last = "";
- struct strbuf sb = STRBUF_INIT;
+@@ builtin/repo.c: static int print_fields(int argc, const char **argv, struct repository *repo)
+ }
-+ 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;
-+ }
+ get_value(repo, &valbuf);
+- quote_c_style(valbuf.buf, "buf, NULL, 0);
+- printf("%s=%s\n", key, quotbuf.buf);
+
- 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;
-@@ builtin/repo.c: 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);
++ switch (format) {
++ case FORMAT_KEYVALUE:
++ quote_c_style(valbuf.buf, "buf, NULL, 0);
++ printf("%s=%s\n", key, quotbuf.buf);
++ break;
++ case FORMAT_NUL_TERMINATED:
++ printf("%s\n%s%c", key, valbuf.buf, '\0');
++ break;
++ default:
++ BUG("%d: not a valid output format", format);
+ }
-
-- printf("%s=%s\n", key, sb.buf);
-+ printf("%s%c%s%c", key, kv_sep, sb.buf, field_sep);
- last = key;
}
+ strbuf_release(&valbuf);
@@ builtin/repo.c: static int print_fields(int argc, const char **argv, struct repository *repo)
return ret;
}
@@ t/t1900-repo.sh: test_repo_info () {
- 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 &&
+- 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
-+ '
++ repo_name_keyvalue="$repo_name"-keyvalue
++ repo_name_nul="$repo_name"-nul
+
-+ 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_expect_success "keyvalue: $label" '
++ eval "$init_command $repo_name_keyvalue" &&
++ echo "$key=$expected_value" > expected &&
++ git -C "$repo_name_keyvalue" repo info "$key" >actual &&
test_cmp expected actual
'
++
++ test_expect_success "nul: $label" '
++ eval "$init_command $repo_name_nul" &&
++ printf "%s\n%s\0" "$key" "$expected_value" >expected &&
++ git -C "$repo_name_nul" repo info --format=nul "$key" >actual &&
++ test_cmp_bin expected actual
++ '
}
-@@ t/t1900-repo.sh: 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 &&
+ test_repo_info 'ref format files is retrieved correctly' '
+@@ t/t1900-repo.sh: test_repo_info 'bare repository = true is retrieved correctly' \
+ test_repo_info 'shallow repository = false is retrieved correctly' \
+ 'git init' 'nonshallow' 'layout.shallow' 'false'
+
+-test_repo_info 'shallow repository = true is retrieved correctly' \
+- 'git init remote &&
++test_expect_success 'setup remote' '
++ git init remote &&
echo x >remote/x &&
git -C remote add x &&
+- git -C remote commit -m x &&
+- git clone --depth 1 "file://$PWD/remote"' 'shallow' 'layout.shallow' 'true'
++ git -C remote commit -m x
++'
++
++test_repo_info 'shallow repository = true is retrieved correctly' \
++ 'git clone --depth 1 "file://$PWD/remote"' 'shallow' 'layout.shallow' 'true'
+
+ test_expect_success 'git-repo-info fails if an invalid key is requested' '
+ echo "error: key '\'foo\'' not found" >expected_err &&
@@ t/t1900-repo.sh: test_expect_success 'output is returned correctly when two keys are requested' '
- git -C two-keys repo info layout.bare references.format
+ test_cmp expected actual
'
+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
Lucas Seiki Oshiro (5):
repo: declare the repo command
repo: add the field references.format
repo: add the field layout.bare
repo: add the field layout.shallow
repo: add the --format flag
.gitignore | 1 +
Documentation/git-repo.adoc | 81 ++++++++++++++++++
Documentation/meson.build | 1 +
Makefile | 1 +
builtin.h | 1 +
builtin/repo.c | 165 ++++++++++++++++++++++++++++++++++++
command-list.txt | 1 +
git.c | 1 +
meson.build | 1 +
t/meson.build | 1 +
t/t1900-repo.sh | 102 ++++++++++++++++++++++
11 files changed, 356 insertions(+)
create mode 100644 Documentation/git-repo.adoc
create mode 100644 builtin/repo.c
create mode 100755 t/t1900-repo.sh
--
2.39.5 (Apple Git-154)