repo: add path.cdup

Scripts sometimes need the relative path from the current working
directory to the repository's working tree root (cdup). While this
information can be retrieved through `git rev-parse --show-cdup`,
`git repo info` does not currently expose it as a scriptable key.

Introduce the `path.cdup` key to `git repo info`. The key returns the
path from the current working directory to the root of the working tree,
returning the empty string when invoked from the working tree root.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
seen
K Jayatheerth 2026-09-27 17:14:20 +05:30 committed by Junio C Hamano
parent 42235267e4
commit 2db363c17a
3 changed files with 68 additions and 0 deletions

View File

@ -104,6 +104,11 @@ values that they return:
`object.format`::
The object format (hash algorithm) used in the repository.

`path.cdup`::
When the command is invoked from a subdirectory, show the
path of the top-level directory relative to the current
directory (typically a sequence of "../", or an empty string).

`path.commondir.absolute`::
The canonical absolute path to the Git repository's common
directory (the shared `.git` directory containing objects,

View File

@ -78,6 +78,28 @@ static int get_object_format(struct repository *repo, struct strbuf *buf)
return 0;
}

static int get_path_cdup(struct repository *repo, struct strbuf *buf)
{
const char *pfx = repo->prefix;

if (!is_inside_work_tree(repo)) {
const char *worktree = repo_get_work_tree(repo);

if (worktree) {
strbuf_addstr(buf, worktree);
}
}

while (pfx) {
pfx = strchr(pfx, '/');
if (pfx) {
pfx++;
strbuf_addstr(buf, "../");
}
}
return 0;
}

static int get_path_commondir_absolute(struct repository *repo, struct strbuf *buf)
{
const char *common_dir = repo_get_common_dir(repo);
@ -252,6 +274,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.cdup", get_path_cdup },
{ "path.commondir.absolute", get_path_commondir_absolute },
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.git-prefix", get_path_git_prefix },

View File

@ -215,6 +215,46 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'

test_expect_success 'path.cdup at repository root' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
echo "path.cdup=" >expect &&
git repo info path.cdup >actual &&
test_cmp expect actual
)
'

test_expect_success 'path.cdup in subdirectory' '
test_when_finished "rm -rf repo" &&
git init repo &&
mkdir -p repo/sub/dir &&
(
cd repo/sub/dir &&
echo "path.cdup=../../" >expect &&
git repo info path.cdup >actual &&
test_cmp expect actual
)
'

test_expect_success 'path.cdup cwd outside the working tree' '
test_when_finished "rm -rf repo" &&
mkdir -p repo/tmp/x &&
cd repo &&
git init test &&
(
echo path.cdup=$(pwd)/tmp/x >./test/expect &&
cd test &&
GIT_WORK_TREE=../tmp/x &&
export GIT_WORK_TREE &&
GIT_DIR=$(pwd)/.git &&
export GIT_DIR &&
git repo info path.cdup >actual &&
test_cmp expect actual
)
'

test_expect_success 'path.git-prefix at repository root' '
test_when_finished "rm -rf repo" &&
git init repo &&