Add the field references.format to the repo-info command. The data retrieved in this field is the same that currently is obtained by running `git rev-parse --show-ref-format`. Mentored-by: Karthik Nayak <karthik.188@xxxxxxxxx> Mentored-by Patrick Steinhardt <ps@xxxxxx> Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@xxxxxxxxx> --- builtin/repo-info.c | 108 +++++++++++++++++++++++++++++++++++++++++-- t/t1900-repo-info.sh | 58 +++++++++++++++++++++++ 2 files changed, 162 insertions(+), 4 deletions(-) diff --git a/builtin/repo-info.c b/builtin/repo-info.c index 6499be0eae..6ce3e6134f 100644 --- a/builtin/repo-info.c +++ b/builtin/repo-info.c @@ -1,21 +1,56 @@ #include "builtin.h" #include "json-writer.h" #include "parse-options.h" +#include "quote.h" +#include "refs.h" enum output_format { FORMAT_JSON, FORMAT_PLAINTEXT }; +enum repo_info_category { + CATEGORY_REFERENCES = 1 << 0 +}; + +enum repo_info_references_field { + FIELD_REFERENCES_FORMAT = 1 << 0 +}; + +struct repo_info_field { + enum repo_info_category category; + union { + enum repo_info_references_field references; + } field; +}; + struct repo_info { struct repository *repo; enum output_format format; + int n_fields; + struct repo_info_field *fields; }; +static struct repo_info_field default_fields[] = { + { + .category = CATEGORY_REFERENCES, + .field.references = FIELD_REFERENCES_FORMAT + } +}; + +static void print_key_value(const char *key, const char *value) { + printf("%s=", key); + quote_c_style(value, NULL, stdout, 0); + putchar('\n'); +} + static void repo_info_init(struct repo_info *repo_info, struct repository *repo, - char *format) + char *format, + int allow_empty, + int argc, const char **argv) { + int i; repo_info->repo = repo; if (format == NULL || !strcmp(format, "json")) @@ -24,19 +59,83 @@ static void repo_info_init(struct repo_info *repo_info, repo_info->format = FORMAT_PLAINTEXT; else die("invalid format %s", format); + + if (argc == 0 && !allow_empty) { + repo_info->n_fields = ARRAY_SIZE(default_fields); + repo_info->fields = default_fields; + } else { + repo_info->n_fields = argc; + ALLOC_ARRAY(repo_info->fields, argc); + + for (i = 0; i < argc; i++) { + const char *arg = argv[i]; + struct repo_info_field *field = repo_info->fields + i; + + if (!strcmp(arg, "references.format")) { + field->category = CATEGORY_REFERENCES; + field->field.references = FIELD_REFERENCES_FORMAT; + } else { + die("invalid field '%s'", arg); + } + } + } } -static void repo_info_print_plaintext(struct repo_info *repo_info UNUSED) +static void repo_info_release(struct repo_info *repo_info) { + if (repo_info->fields != default_fields) free(repo_info->fields); } -static void repo_info_print_json(struct repo_info *repo_info UNUSED) +static void repo_info_print_plaintext(struct repo_info *repo_info) { + struct repository *repo = repo_info->repo; + int i; + for (i = 0; i < repo_info->n_fields; i++) { + struct repo_info_field *field = &repo_info->fields[i]; + switch (field->category) { + case CATEGORY_REFERENCES: + switch (field->field.references) { + case FIELD_REFERENCES_FORMAT: + print_key_value("references.format", + ref_storage_format_to_name( + repo->ref_storage_format)); + break; + } + break; + } + } +} + +static void repo_info_print_json(struct repo_info *repo_info) { struct json_writer jw; + int i; + unsigned int categories = 0; + unsigned int references_fields = 0; + struct repository *repo = repo_info->repo; + + for (i = 0; i < repo_info->n_fields; i++) { + struct repo_info_field *field = repo_info->fields + i; + categories |= field->category; + switch (field->category) { + case CATEGORY_REFERENCES: + references_fields |= field->field.references; + break; + } + } jw_init(&jw); jw_object_begin(&jw, 1); + + if (categories & CATEGORY_REFERENCES) { + jw_object_inline_begin_object(&jw, "references"); + if (references_fields & FIELD_REFERENCES_FORMAT) { + const char *format_name = ref_storage_format_to_name( + repo->ref_storage_format); + jw_object_string(&jw, "format", format_name); + } + jw_end(&jw); + } jw_end(&jw); puts(jw.json.buf); @@ -79,8 +178,9 @@ int cmd_repo_info(int argc, argc = parse_options(argc, argv, prefix, options, repo_info_usage, PARSE_OPT_KEEP_UNKNOWN_OPT); - repo_info_init(&repo_info, repo, format); + repo_info_init(&repo_info, repo, format, allow_empty, argc, argv); repo_info_print(&repo_info); + repo_info_release(&repo_info); return 0; } diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh index db4a6aad17..d6e6f6ed1d 100755 --- a/t/t1900-repo-info.sh +++ b/t/t1900-repo-info.sh @@ -6,6 +6,8 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +DEFAULT_NUMBER_OF_FIELDS=1 + parse_json () { tr '\n' ' ' | "$PERL_PATH" "$TEST_DIRECTORY/t0019/parse_json.perl" } @@ -14,6 +16,45 @@ test_lazy_prereq PERLJSON ' perl -MJSON -e "exit 0" ' +# Test if a field is correctly returned in both plaintext and json formats. +# +# Usage: test_repo_info <label> <init command> <key> <expected value> +# +# Arguments: +# label: the label of the test +# init command: a command that creates a repository called 'repo', configured +# accordingly to what is being tested +# key: the key of the field that is being tested +# expected value: the value that the field should contain +test_repo_info () { + label=$1 + init_command=$2 + key=$3 + expected_value=$4 + + test_expect_success PERLJSON "json: $label" " + test_when_finished 'rm -rf repo' && + '$SHELL_PATH' -c '$init_command' && + cd repo && + echo '$expected_value' >expect && + git repo-info '$key' >output && + cat output | parse_json >parsed && + grep -F 'row[0].$key' parsed | cut -d ' ' -f 2 >value && + cat value | sed 's/^0$/false/' | sed 's/^1$/true/' >actual && + test_cmp expect actual + " + + test_expect_success "plaintext: $label" " + test_when_finished 'rm -rf repo' && + '$SHELL_PATH' -c '$init_command' && + cd repo && + echo '$expected_value' >expect && + git repo-info --format=plaintext '$key' >output && + cat output | cut -d '=' -f 2 >actual && + test_cmp expect actual + " +} + test_expect_success PERLJSON 'json: returns empty output with allow-empty' ' git repo-info --allow-empty --format=json >output && test_line_count = 2 output @@ -24,4 +65,21 @@ test_expect_success 'plaintext: returns empty output with allow-empty' ' test_line_count = 0 output ' +test_repo_info 'ref format files is retrieved correctly' ' + git init --ref-format=files repo' 'references.format' 'files' + +test_repo_info 'ref format reftable is retrieved correctly' ' + git init --ref-format=reftable repo' 'references.format' 'reftable' + +test_expect_success 'plaintext: output all default fields' " + git repo-info --format=plaintext >actual && + test_line_count = $DEFAULT_NUMBER_OF_FIELDS actual +" + +test_expect_success PERLJSON 'json: output all default fields' " + git repo-info --format=json > output && + cat output | parse_json | grep '.*\..*\..*' >actual && + test_line_count = $DEFAULT_NUMBER_OF_FIELDS actual +" + test_done -- 2.39.5 (Apple Git-154)