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)