From: Lucas Seiki Oshiro Date: Sat, 28 Feb 2026 22:05:58 GMT Subject: [PATCH 4/4] repo: add the field path.toplevel Message-ID: <20260228224252.72788-5-lucasseikioshiro@gmail.com> In-Reply-To: <20260228224252.72788-1-lucasseikioshiro@gmail.com> The flag `--show-toplevel` from git-rev-parse is used for retrieving the top level directory path of the repository. This way, it is used for querying repository metadata, fitting in the purpose of git-repo-info. Add a new field `path.toplevel` to the git-repo-info subcommand containing that information. Signed-off-by: Lucas Seiki Oshiro --- builtin/repo.c | 47 +++++++++++++++++++++++++-------- t/t1900-repo-info.sh | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 11 deletions(-) diff --git a/builtin/repo.c b/builtin/repo.c index cff4c6db9b..61cd539e05 100644 --- a/builtin/repo.c +++ b/builtin/repo.c @@ -22,7 +22,8 @@ static const char *const repo_usage[] = { NULL }; -typedef int get_value_fn(struct repository *repo, struct strbuf *buf); +typedef int get_value_fn(struct repository *repo, struct strbuf *buf, + const char *prefix, enum path_format_type format); enum output_format { FORMAT_TABLE, @@ -35,26 +36,46 @@ struct repo_info_field { get_value_fn *get_value; }; -static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf) +static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf, + const char *prefix UNUSED, + enum path_format_type format UNUSED) { strbuf_addstr(buf, is_bare_repository() ? "true" : "false"); return 0; } -static int get_layout_shallow(struct repository *repo, struct strbuf *buf) +static int get_layout_shallow(struct repository *repo, struct strbuf *buf, + const char *prefix UNUSED, + enum path_format_type format UNUSED) { strbuf_addstr(buf, is_repository_shallow(repo) ? "true" : "false"); return 0; } -static int get_object_format(struct repository *repo, struct strbuf *buf) +static int get_object_format(struct repository *repo, struct strbuf *buf, + const char *prefix UNUSED, + enum path_format_type format UNUSED) { strbuf_addstr(buf, repo->hash_algo->name); return 0; } -static int get_references_format(struct repository *repo, struct strbuf *buf) +static int get_path_toplevel(struct repository *repo, struct strbuf *buf, + const char *prefix, enum path_format_type format) +{ + const char *work_tree = repo_get_work_tree(repo); + if (work_tree) + strbuf_add_path(buf, work_tree, prefix, format, + PATH_DEFAULT_UNMODIFIED); + else + return error(_("this operation must be run in a work tree")); + return 0; +} + +static int get_references_format(struct repository *repo, struct strbuf *buf, + const char *prefix UNUSED, + enum path_format_type format UNUSED) { strbuf_addstr(buf, ref_storage_format_to_name(repo->ref_storage_format)); @@ -66,6 +87,7 @@ static const struct repo_info_field repo_info_field[] = { { "layout.bare", get_layout_bare }, { "layout.shallow", get_layout_shallow }, { "object.format", get_object_format }, + { "path.toplevel", get_path_toplevel }, { "references.format", get_references_format }, }; @@ -108,8 +130,9 @@ static void print_field(enum output_format format, const char *key, static int print_fields(int argc, const char **argv, struct repository *repo, + const char *prefix, enum output_format format, - enum path_format_type path_format UNUSED) + enum path_format_type path_format) { int ret = 0; struct strbuf valbuf = STRBUF_INIT; @@ -124,7 +147,7 @@ static int print_fields(int argc, const char **argv, } strbuf_reset(&valbuf); - field->get_value(repo, &valbuf); + field->get_value(repo, &valbuf, prefix, path_format); print_field(format, key, valbuf.buf); } @@ -133,7 +156,9 @@ static int print_fields(int argc, const char **argv, } static int print_all_fields(struct repository *repo, - enum output_format format) + const char *prefix, + enum output_format format, + enum path_format_type path_format) { struct strbuf valbuf = STRBUF_INIT; @@ -141,7 +166,7 @@ static int print_all_fields(struct repository *repo, const struct repo_info_field *field = &repo_info_field[i]; strbuf_reset(&valbuf); - field->get_value(repo, &valbuf); + field->get_value(repo, &valbuf, prefix, path_format); print_field(format, field->key, valbuf.buf); } @@ -239,9 +264,9 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix, die(_("--all and cannot be used together")); if (all_keys) - return print_all_fields(repo, format); + return print_all_fields(repo, prefix, format, path_format); else - return print_fields(argc, argv, repo, format, path_format); + return print_fields(argc, argv, repo, prefix, format, path_format); } struct ref_stats { diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh index f5c76067cb..4985a9cc70 100755 --- a/t/t1900-repo-info.sh +++ b/t/t1900-repo-info.sh @@ -38,6 +38,53 @@ test_repo_info () { ' } +test_repo_info_path () { + label=$1 + repo_name=$2 + key=$3 + relative_path=$4 + default=$5 + + absolute_path=$(cd "$relative_path"; pwd)/"$repo_name" + + case $default in + absolute) + expected_value="$absolute_path" + ;; + relative) + expected_value="$relative_path" + ;; + esac + + test_expect_success "setup: $label" ' + git init "$repo_name" + ' + + test_expect_success "nul: $label" ' + printf "%s\n%s\0" "$key" "$expected_value" >expected && + git -C "$repo_name" repo info --format=nul "$key" >actual && + test_cmp expected actual + ' + + test_expect_success "default: $label" ' + echo "$key=$expected_value" > expected && + git -C "$repo_name" repo info "$key" >actual && + test_cmp expected actual + ' + + test_expect_success "absolute: $label" ' + echo "$key=$absolute_path" > expected && + git -C "$repo_name" repo info --path-format=absolute "$key" >actual && + test_cmp expected actual + ' + + test_expect_success "relative: $label" ' + echo "$key=$relative_path" > expected && + git -C "$repo_name" repo info --path-format=relative "$key" >actual && + test_cmp expected actual + ' +} + test_repo_info 'ref format files is retrieved correctly' \ 'git init --ref-format=files' 'format-files' 'references.format' 'files' @@ -69,6 +116,21 @@ test_repo_info 'object.format = sha1 is retrieved correctly' \ test_repo_info 'object.format = sha256 is retrieved correctly' \ 'git init --object-format=sha256' 'sha256' 'object.format' 'sha256' +test_repo_info_path 'toplevel is retrieved correctly' \ + 'toplevel' 'path.toplevel' './' 'absolute' + +test_expect_success 'git-repo-info fails if an invalid key is requested' ' + echo "error: key ${SQ}foo${SQ} not found" >expected_err && + test_must_fail git repo info foo 2>actual_err && + test_cmp expected_err actual_err +' + +test_expect_success 'git-repo-info outputs data even if there is an invalid field' ' + echo "references.format=$(test_detect_ref_format)" >expected && + test_must_fail git repo info foo references.format bar >actual && + test_cmp expected actual +' + test_expect_success 'values returned in order requested' ' cat >expect <<-\EOF && layout.bare=false -- 2.50.1 (Apple Git-155)