Git development
 help / color / mirror / Atom feed
* [GSoC Patch 0/7] repo: add more path keys to git repo info
@ 2026-07-16  1:21 K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
                   ` (9 more replies)
  0 siblings, 10 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

Series adds keys to git repo info.
Keys output paths of repository components:
* path.toplevel: repository tree.
* path.superproject-working-tree: superproject tree from submodules.
* path.objects: repository objects.
* path.hooks: repository hooks.
* path.index: repository index.
* path.grafts: repository grafts.
* path.git-prefix: prefix offset.

Keys support suffixes for format.
Commits contain documentation and tests.

K Jayatheerth (7):
  repo: add path.toplevel with absolute and relative suffix formatting
  repo: add path.superproject-working-tree with absolute and relative
    suffixes
  repo: add path.objects with absolute and relative suffix formatting
  repo: add path.hooks with absolute and relative suffix formatting
  repo: add path.index with absolute and relative suffix formatting
  repo: add path.grafts with absolute and relative suffix formatting
  repo: add path.git-prefix path key validation

 Documentation/git-repo.adoc |  58 +++++++++++++
 builtin/repo.c              | 167 ++++++++++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 108 +++++++++++++++++++++++
 3 files changed, 333 insertions(+)

-- 
2.55.GIT


^ permalink raw reply	[flat|nested] 51+ messages in thread

* [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

Scripts frequently need to find the root directory of a repository's
working tree. Currently, this requires using `git rev-parse --show-toplevel`
or inferring it from other path components.

Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
to `git repo info`. This allows scripts to retrieve the top-level
working tree path in a predictable, strictly formatted manner without
relying on `rev-parse`.

If requested in a bare repository where no working tree exists, the
command returns an empty string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 28 ++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 30 ++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..e34abe5fea 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.toplevel.absolute`::
+	The canonical absolute path to the top-level directory of the
+	repository's working tree. Outputs an empty string if the repository
+	is bare.
+
+`path.toplevel.relative`::
+	The path to the top-level directory of the repository's working
+	tree relative to the current working directory. Outputs an empty
+	string if the repository is bare.
+
 `references.format`::
 	The reference storage format. The valid values are:
 +
diff --git a/builtin/repo.c b/builtin/repo.c
index 042d6de558..194757eb18 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -121,6 +121,32 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree) {
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree) {
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_references_format(struct repository *repo, struct strbuf *buf)
 {
 	strbuf_addstr(buf,
@@ -137,6 +163,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.toplevel.absolute", get_path_toplevel_absolute },
+	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
 };
 
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index ae8c22c817..fbb9063ee5 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,4 +213,34 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.toplevel absolute and relative' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		mkdir -p repo/sub &&
+		cd repo/sub &&
+
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.toplevel.absolute=$ROOT" >expect.abs &&
+		git repo info path.toplevel.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.toplevel.relative=../" >expect.rel &&
+		git repo info path.toplevel.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.toplevel returns empty in a bare repository' '
+	test_when_finished "rm -rf bare.git" &&
+	git init --bare bare.git &&
+	(
+		cd bare.git &&
+		echo "path.toplevel.absolute=" >expect &&
+		git repo info path.toplevel.absolute >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_done
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

Scripts working in multi-repository setups often need to identify the
top-level working tree of a superproject from within a submodule.
Currently, this is only exposed via `git rev-parse
--show-superproject-working-tree`.

Introduce `path.superproject-working-tree.absolute` and
`path.superproject-working-tree.relative` keys to `git repo info`.
This exposes the core submodule context via a scriptable config-like key
using standard format rules.

If requested when not inside a submodule, the command returns an empty
string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 33 +++++++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e34abe5fea..03aa57942f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.superproject-working-tree.absolute`::
+	The canonical absolute path to the working tree root of the superproject
+	if the current repository is an initialized submodule. Outputs an empty
+	string if not in a submodule.
+
+`path.superproject-working-tree.relative`::
+	The path to the working tree root of the superproject relative to the
+	current working directory if the current repository is an initialized
+	submodule. Outputs an empty string if not in a submodule.
+
 `path.toplevel.absolute`::
 	The canonical absolute path to the top-level directory of the
 	repository's working tree. Outputs an empty string if the repository
diff --git a/builtin/repo.c b/builtin/repo.c
index 194757eb18..82359473e9 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -18,6 +18,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
+#include "submodule.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "utf8.h"
@@ -121,6 +122,36 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	strbuf_release(&superproject);
+	return 0;
+}
+
+static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&superproject);
+	return 0;
+}
+
 static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *work_tree = repo_get_work_tree(repo);
@@ -163,6 +194,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
+	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
 	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index fbb9063ee5..220b3d4d3d 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,40 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.superproject-working-tree absolute and relative' '
+	test_when_finished "rm -rf sub super" &&
+	git init sub &&
+	test_commit -C sub initial &&
+	git init super &&
+	(
+		cd super &&
+		git -c protocol.file.allow=always submodule add "../sub" sub &&
+		git commit -m "add submodule" &&
+
+		cd sub &&
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
+		git repo info path.superproject-working-tree.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.superproject-working-tree.relative=../" >expect.rel &&
+		git repo info path.superproject-working-tree.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo "path.superproject-working-tree.absolute=" >expect &&
+		git repo info path.superproject-working-tree.absolute >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_expect_success 'path.toplevel absolute and relative' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 4/7] repo: add path.hooks " K Jayatheerth
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

Tools and deployment hooks frequently query the location of the object
database directory. Currently, this relies on legacy parsing methods or
manually inspecting `git rev-parse --git-path objects`.

Introduce `path.objects.absolute` and `path.objects.relative` keys to
`git repo info`. This allows tools to discover the object database
location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
environment variable overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  9 +++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  7 +++++++
 3 files changed, 40 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 03aa57942f..8429a44b43 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,15 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.objects.absolute`::
+	The canonical absolute path to the repository's object database directory.
+	Respects the `GIT_OBJECT_DIRECTORY` environment override.
+
+`path.objects.relative`::
+	The path to the repository's object database directory relative to the
+	current working directory. Respects the `GIT_OBJECT_DIRECTORY`
+	environment override.
+
 `path.superproject-working-tree.absolute`::
 	The canonical absolute path to the working tree root of the superproject
 	if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index 82359473e9..d6bdd5bcfa 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *obj_dir = repo_get_object_directory(repo);
+
+	if (!obj_dir)
+		return error(_("unable to get object directory"));
+
+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_objects_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *obj_dir = repo_get_object_directory(repo);
+
+	if (!obj_dir)
+		return error(_("unable to get object directory"));
+
+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
 {
 	struct strbuf superproject = STRBUF_INIT;
@@ -194,6 +216,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.objects.absolute", get_path_objects_absolute },
+	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
 	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 220b3d4d3d..260f4fde43 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,13 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'objects standard' 'objects' '.git/objects'
+
+test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
+	'custom-objects' \
+	'GIT_OBJECT_DIRECTORY="$ROOT/custom-objects" && export GIT_OBJECT_DIRECTORY &&
+	 mkdir -p "$ROOT/custom-objects"'
+
 test_expect_success 'path.superproject-working-tree absolute and relative' '
 	test_when_finished "rm -rf sub super" &&
 	git init sub &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch 4/7] repo: add path.hooks with absolute and relative suffix formatting
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (2 preceding siblings ...)
  2026-07-16  1:21 ` [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 5/7] repo: add path.index " K Jayatheerth
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

External tool integrations and validation systems need a stable way to
identify where the repository hooks are stored. Currently, this involves
relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
manually.

Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This allows tools to discover the active hooks location
natively, ensuring proper resolution regardless of whether Git is using
the standard `.git/hooks` structure or a custom `core.hooksPath` setup.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 22 ++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 8429a44b43..7bc1c51310 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.hooks.absolute`::
+	The canonical absolute path to the repository's hooks directory.
+	Respects `core.hooksPath` configuration adjustments.
+
+`path.hooks.relative`::
+	The path to the repository's hooks directory relative to the current
+	working directory. Respects `core.hooksPath` configuration adjustments.
+
 `path.objects.absolute`::
 	The canonical absolute path to the repository's object database directory.
 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index d6bdd5bcfa..c921de222d 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,26 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
+static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
 static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *obj_dir = repo_get_object_directory(repo);
@@ -216,6 +236,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.hooks.absolute", get_path_hooks_absolute },
+	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.objects.absolute", get_path_objects_absolute },
 	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 260f4fde43..cd3f856d04 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
+
+test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
+	'custom-hooks' \
+	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+
 test_repo_info_path 'objects standard' 'objects' '.git/objects'
 
 test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch 5/7] repo: add path.index with absolute and relative suffix formatting
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (3 preceding siblings ...)
  2026-07-16  1:21 ` [GSoC Patch 4/7] repo: add path.hooks " K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 6/7] repo: add path.grafts " K Jayatheerth
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

External script workflows and formatting layers require straightforward
access to the location of the index staging file. Currently, tracking
this necessitates a legacy call to `git rev-parse --git-path index` or
`--show-toplevel` logic abstractions.

Introduce `path.index.absolute` and `path.index.relative` keys to
`git repo info`. This allows tooling utilities to discover the active
index context cleanly while scaling transparently with localized
`GIT_INDEX_FILE` environment overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 38 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 7bc1c51310..3a837c573e 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -127,6 +127,14 @@ values that they return:
 	The path to the repository's hooks directory relative to the current
 	working directory. Respects `core.hooksPath` configuration adjustments.
 
+`path.index.absolute`::
+	The canonical absolute path to the repository's current index file.
+	Respects the `GIT_INDEX_FILE` environment override.
+
+`path.index.relative`::
+	The path to the repository's current index file relative to the current
+	working directory. Respects the `GIT_INDEX_FILE` environment override.
+
 `path.objects.absolute`::
 	The canonical absolute path to the repository's object database directory.
 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index c921de222d..66bf4c67cc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -142,6 +142,28 @@ static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_index_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_index_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *obj_dir = repo_get_object_directory(repo);
@@ -238,6 +260,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
+	{ "path.index.absolute", get_path_index_absolute },
+	{ "path.index.relative", get_path_index_relative },
 	{ "path.objects.absolute", get_path_objects_absolute },
 	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index cd3f856d04..04e6b8553c 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -219,6 +219,12 @@ test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
 	'custom-hooks' \
 	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
 
+test_repo_info_path 'index standard' 'index' '.git/index'
+
+test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
+	'custom-index-file' \
+	'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
+
 test_repo_info_path 'objects standard' 'objects' '.git/objects'
 
 test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch 6/7] repo: add path.grafts with absolute and relative suffix formatting
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (4 preceding siblings ...)
  2026-07-16  1:21 ` [GSoC Patch 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

External toolchains managing specialized history rewrites or legacy
history splices require access to the location of the repository grafts
file. Currently, this requires a legacy call to `git rev-parse --git-path info/grafts`.

Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
`git repo info`. This allows scripting layers to query the active grafts
context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
environment variable overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 38 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 3a837c573e..6c962620ec 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.grafts.absolute`::
+	The canonical absolute path to the repository grafts file.
+	Respects the `GIT_GRAFT_FILE` environment override.
+
+`path.grafts.relative`::
+	The path to the repository grafts file relative to the current working
+	directory. Respects the `GIT_GRAFT_FILE` environment override.
+
 `path.hooks.absolute`::
 	The canonical absolute path to the repository's hooks directory.
 	Respects `core.hooksPath` configuration adjustments.
diff --git a/builtin/repo.c b/builtin/repo.c
index 66bf4c67cc..a97ad71649 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
 {
 	struct strbuf hooks_path = STRBUF_INIT;
@@ -258,6 +280,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.grafts.absolute", get_path_grafts_absolute },
+	{ "path.grafts.relative", get_path_grafts_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.index.absolute", get_path_index_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 04e6b8553c..6c47989df7 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
+
+test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
+	'custom-graft-file' \
+	'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
+
 test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
 
 test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch 7/7] repo: add path.git-prefix path key validation
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (5 preceding siblings ...)
  2026-07-16  1:21 ` [GSoC Patch 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-16  1:21 ` K Jayatheerth
  2026-07-16  3:23   ` Junio C Hamano
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16  1:21 UTC (permalink / raw)
  To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth

Scripts and command-line prompt integrations frequently need to know their
relative depth inside a repository working tree layout. Currently, this
is retrieved using `git rev-parse --show-prefix`.

Introduce the `path.git-prefix` key to `git repo info`. This mirrors the
prefix location tracking framework as a standalone key, returning the
exact relative path offset complete with a trailing slash, or an empty
string if run directly at the repository 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>
---
 Documentation/git-repo.adoc |  5 +++++
 builtin/repo.c              | 12 ++++++++++++
 t/t1900-repo-info.sh        | 19 +++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 6c962620ec..5ba2ab1612 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,11 @@ values that they return:
 	The path to the Git repository's common directory relative to
 	the current working directory.
 
+`path.git-prefix`::
+	The relative path from the top-level directory of the working tree to
+	the current working directory (including a trailing slash). Outputs an
+	empty string if executed at the root of the working tree.
+
 `path.gitdir.absolute`::
 	The canonical absolute path to the Git repository directory (the `.git` directory).
 
diff --git a/builtin/repo.c b/builtin/repo.c
index a97ad71649..00d5064281 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -1,3 +1,4 @@
+#include "compat/posix.h"
 #define USE_THE_REPOSITORY_VARIABLE
 
 #include "builtin.h"
@@ -100,6 +101,16 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
 	return 0;
 }
 
+static int get_path_git_prefix(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	/*
+	 * startup_info->prefix is NULL if we are at the working tree root.
+	 * We add an empty string to ensure the buffer is cleanly initialized.
+	 */
+	strbuf_addstr(buf, startup_info->prefix ? startup_info->prefix : "");
+	return 0;
+}
+
 static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *git_dir = repo_get_git_dir(repo);
@@ -278,6 +289,7 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "object.format", get_object_format },
 	{ "path.commondir.absolute", get_path_commondir_absolute },
 	{ "path.commondir.relative", get_path_commondir_relative },
+	{ "path.git-prefix", get_path_git_prefix },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.grafts.absolute", get_path_grafts_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 6c47989df7..3e5e42f6d3 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -207,6 +207,25 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.git-prefix at root and in a subdirectory' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+
+		echo "path.git-prefix=" >expect.root &&
+		git repo info path.git-prefix >actual.root &&
+		test_cmp expect.root actual.root &&
+
+		mkdir -p sub/dir &&
+		cd sub/dir &&
+
+		echo "path.git-prefix=sub/dir/" >expect.sub &&
+		git repo info path.git-prefix >actual.sub &&
+		test_cmp expect.sub actual.sub
+	)
+'
+
 test_repo_info_path 'gitdir standard' 'gitdir' '.git'
 
 test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch 7/7] repo: add path.git-prefix path key validation
  2026-07-16  1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
@ 2026-07-16  3:23   ` Junio C Hamano
  2026-07-16 15:36     ` K Jayatheerth
  0 siblings, 1 reply; 51+ messages in thread
From: Junio C Hamano @ 2026-07-16  3:23 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, jltobler, lucasseikioshiro

K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:

> diff --git a/builtin/repo.c b/builtin/repo.c
> index a97ad71649..00d5064281 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -1,3 +1,4 @@
> +#include "compat/posix.h"
>  #define USE_THE_REPOSITORY_VARIABLE
>  #include "builtin.h"

The first include must be <git-compat-util.h> or common include
files that include <git-compat-util.h> as the first thing, like
<builtin.h>.

As the file already includes <builtin.h>, extra inclusion of
<compat/posix.h> before everything else is an absolute no-no.

By the way, I do not see any "validation" in the patch as the title
claims.  Perhaps retitle it to "repo: add path.git-prefix key" or
something simpler like that?


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch 7/7] repo: add path.git-prefix path key validation
  2026-07-16  3:23   ` Junio C Hamano
@ 2026-07-16 15:36     ` K Jayatheerth
  0 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-16 15:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, jltobler, lucasseikioshiro

Hey Junio,

On Thu, Jul 16, 2026 at 8:53 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:
>
> > diff --git a/builtin/repo.c b/builtin/repo.c
> > index a97ad71649..00d5064281 100644
> > --- a/builtin/repo.c
> > +++ b/builtin/repo.c
> > @@ -1,3 +1,4 @@
> > +#include "compat/posix.h"
> >  #define USE_THE_REPOSITORY_VARIABLE
> >  #include "builtin.h"
>
> The first include must be <git-compat-util.h> or common include
> files that include <git-compat-util.h> as the first thing, like
> <builtin.h>.
>
> As the file already includes <builtin.h>, extra inclusion of
> <compat/posix.h> before everything else is an absolute no-no.
>


Oh no, that's just my editor adding headers automatically.
Thanks for pointing this out, I will fix it.

> By the way, I do not see any "validation" in the patch as the title
> claims.  Perhaps retitle it to "repo: add path.git-prefix key" or
> something simpler like that?
>

True, I will correct that as well.

Regards,
- K Jayatheerth

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 0/7] repo: add more path keys to git repo info
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (6 preceding siblings ...)
  2026-07-16  1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
                     ` (6 more replies)
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
  9 siblings, 7 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Series adds keys to git repo info.
Keys output paths of repository components:
* path.toplevel: repository tree.
* path.superproject-working-tree: superproject tree from submodules.
* path.objects: repository objects.
* path.hooks: repository hooks.
* path.index: repository index.
* path.grafts: repository grafts.
* path.git-prefix: prefix offset.

Keys support suffixes for format.
Commits contain documentation and tests.

K Jayatheerth (7):
  repo: add path.toplevel with absolute and relative suffix formatting
  repo: add path.superproject-working-tree with absolute and relative
    suffixes
  repo: add path.objects with absolute and relative suffix formatting
  repo: add path.hooks with absolute and relative suffix formatting
  repo: add path.index with absolute and relative suffix formatting
  repo: add path.grafts with absolute and relative suffix formatting
  repo: add path.git-prefix path key

 Documentation/git-repo.adoc |  58 +++++++++++++
 builtin/repo.c              | 166 ++++++++++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 108 +++++++++++++++++++++++
 3 files changed, 332 insertions(+)

-- 
2.55.GIT

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Scripts frequently need to find the root directory of a repository's
working tree. Currently, this requires using `git rev-parse --show-toplevel`
or inferring it from other path components.

Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
to `git repo info`. This allows scripts to retrieve the top-level
working tree path in a predictable, strictly formatted manner without
relying on `rev-parse`.

If requested in a bare repository where no working tree exists, the
command returns an empty string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 28 ++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 30 ++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..e34abe5fea 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.toplevel.absolute`::
+	The canonical absolute path to the top-level directory of the
+	repository's working tree. Outputs an empty string if the repository
+	is bare.
+
+`path.toplevel.relative`::
+	The path to the top-level directory of the repository's working
+	tree relative to the current working directory. Outputs an empty
+	string if the repository is bare.
+
 `references.format`::
 	The reference storage format. The valid values are:
 +
diff --git a/builtin/repo.c b/builtin/repo.c
index 042d6de558..194757eb18 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -121,6 +121,32 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree) {
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree) {
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_references_format(struct repository *repo, struct strbuf *buf)
 {
 	strbuf_addstr(buf,
@@ -137,6 +163,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.toplevel.absolute", get_path_toplevel_absolute },
+	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
 };
 
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index ae8c22c817..fbb9063ee5 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,4 +213,34 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.toplevel absolute and relative' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		mkdir -p repo/sub &&
+		cd repo/sub &&
+
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.toplevel.absolute=$ROOT" >expect.abs &&
+		git repo info path.toplevel.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.toplevel.relative=../" >expect.rel &&
+		git repo info path.toplevel.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.toplevel returns empty in a bare repository' '
+	test_when_finished "rm -rf bare.git" &&
+	git init --bare bare.git &&
+	(
+		cd bare.git &&
+		echo "path.toplevel.absolute=" >expect &&
+		git repo info path.toplevel.absolute >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_done
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Scripts working in multi-repository setups often need to identify the
top-level working tree of a superproject from within a submodule.
Currently, this is only exposed via `git rev-parse
--show-superproject-working-tree`.

Introduce `path.superproject-working-tree.absolute` and
`path.superproject-working-tree.relative` keys to `git repo info`.
This exposes the core submodule context via a scriptable config-like key
using standard format rules.

If requested when not inside a submodule, the command returns an empty
string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 33 +++++++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e34abe5fea..03aa57942f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.superproject-working-tree.absolute`::
+	The canonical absolute path to the working tree root of the superproject
+	if the current repository is an initialized submodule. Outputs an empty
+	string if not in a submodule.
+
+`path.superproject-working-tree.relative`::
+	The path to the working tree root of the superproject relative to the
+	current working directory if the current repository is an initialized
+	submodule. Outputs an empty string if not in a submodule.
+
 `path.toplevel.absolute`::
 	The canonical absolute path to the top-level directory of the
 	repository's working tree. Outputs an empty string if the repository
diff --git a/builtin/repo.c b/builtin/repo.c
index 194757eb18..82359473e9 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -18,6 +18,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
+#include "submodule.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "utf8.h"
@@ -121,6 +122,36 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	strbuf_release(&superproject);
+	return 0;
+}
+
+static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&superproject);
+	return 0;
+}
+
 static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *work_tree = repo_get_work_tree(repo);
@@ -163,6 +194,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
+	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
 	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index fbb9063ee5..220b3d4d3d 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,40 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.superproject-working-tree absolute and relative' '
+	test_when_finished "rm -rf sub super" &&
+	git init sub &&
+	test_commit -C sub initial &&
+	git init super &&
+	(
+		cd super &&
+		git -c protocol.file.allow=always submodule add "../sub" sub &&
+		git commit -m "add submodule" &&
+
+		cd sub &&
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
+		git repo info path.superproject-working-tree.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.superproject-working-tree.relative=../" >expect.rel &&
+		git repo info path.superproject-working-tree.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo "path.superproject-working-tree.absolute=" >expect &&
+		git repo info path.superproject-working-tree.absolute >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_expect_success 'path.toplevel absolute and relative' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 4/7] repo: add path.hooks " K Jayatheerth
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Tools and deployment hooks frequently query the location of the object
database directory. Currently, this relies on legacy parsing methods or
manually inspecting `git rev-parse --git-path objects`.

Introduce `path.objects.absolute` and `path.objects.relative` keys to
`git repo info`. This allows tools to discover the object database
location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
environment variable overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  9 +++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  7 +++++++
 3 files changed, 40 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 03aa57942f..8429a44b43 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,15 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.objects.absolute`::
+	The canonical absolute path to the repository's object database directory.
+	Respects the `GIT_OBJECT_DIRECTORY` environment override.
+
+`path.objects.relative`::
+	The path to the repository's object database directory relative to the
+	current working directory. Respects the `GIT_OBJECT_DIRECTORY`
+	environment override.
+
 `path.superproject-working-tree.absolute`::
 	The canonical absolute path to the working tree root of the superproject
 	if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index 82359473e9..d6bdd5bcfa 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *obj_dir = repo_get_object_directory(repo);
+
+	if (!obj_dir)
+		return error(_("unable to get object directory"));
+
+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_objects_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *obj_dir = repo_get_object_directory(repo);
+
+	if (!obj_dir)
+		return error(_("unable to get object directory"));
+
+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
 {
 	struct strbuf superproject = STRBUF_INIT;
@@ -194,6 +216,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.objects.absolute", get_path_objects_absolute },
+	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
 	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 220b3d4d3d..260f4fde43 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,13 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'objects standard' 'objects' '.git/objects'
+
+test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
+	'custom-objects' \
+	'GIT_OBJECT_DIRECTORY="$ROOT/custom-objects" && export GIT_OBJECT_DIRECTORY &&
+	 mkdir -p "$ROOT/custom-objects"'
+
 test_expect_success 'path.superproject-working-tree absolute and relative' '
 	test_when_finished "rm -rf sub super" &&
 	git init sub &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 4/7] repo: add path.hooks with absolute and relative suffix formatting
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (2 preceding siblings ...)
  2026-07-17 13:30   ` [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

External tool integrations and validation systems need a stable way to
identify where the repository hooks are stored. Currently, this involves
relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
manually.

Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This allows tools to discover the active hooks location
natively, ensuring proper resolution regardless of whether Git is using
the standard `.git/hooks` structure or a custom `core.hooksPath` setup.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 22 ++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 8429a44b43..7bc1c51310 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.hooks.absolute`::
+	The canonical absolute path to the repository's hooks directory.
+	Respects `core.hooksPath` configuration adjustments.
+
+`path.hooks.relative`::
+	The path to the repository's hooks directory relative to the current
+	working directory. Respects `core.hooksPath` configuration adjustments.
+
 `path.objects.absolute`::
 	The canonical absolute path to the repository's object database directory.
 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index d6bdd5bcfa..c921de222d 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,26 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
+static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
 static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *obj_dir = repo_get_object_directory(repo);
@@ -216,6 +236,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.hooks.absolute", get_path_hooks_absolute },
+	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.objects.absolute", get_path_objects_absolute },
 	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 260f4fde43..cd3f856d04 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
+
+test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
+	'custom-hooks' \
+	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+
 test_repo_info_path 'objects standard' 'objects' '.git/objects'
 
 test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 5/7] repo: add path.index with absolute and relative suffix formatting
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (3 preceding siblings ...)
  2026-07-17 13:30   ` [GSoC Patch v2 4/7] repo: add path.hooks " K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  2026-07-20  0:35     ` Lucas Seiki Oshiro
  2026-07-17 13:30   ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
  2026-07-17 13:30   ` [GSoC Patch v2 7/7] repo: add path.git-prefix path key K Jayatheerth
  6 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

External script workflows and formatting layers require straightforward
access to the location of the index staging file. Currently, tracking
this necessitates a legacy call to `git rev-parse --git-path index` or
`--show-toplevel` logic abstractions.

Introduce `path.index.absolute` and `path.index.relative` keys to
`git repo info`. This allows tooling utilities to discover the active
index context cleanly while scaling transparently with localized
`GIT_INDEX_FILE` environment overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 38 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 7bc1c51310..3a837c573e 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -127,6 +127,14 @@ values that they return:
 	The path to the repository's hooks directory relative to the current
 	working directory. Respects `core.hooksPath` configuration adjustments.
 
+`path.index.absolute`::
+	The canonical absolute path to the repository's current index file.
+	Respects the `GIT_INDEX_FILE` environment override.
+
+`path.index.relative`::
+	The path to the repository's current index file relative to the current
+	working directory. Respects the `GIT_INDEX_FILE` environment override.
+
 `path.objects.absolute`::
 	The canonical absolute path to the repository's object database directory.
 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index c921de222d..66bf4c67cc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -142,6 +142,28 @@ static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_index_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_index_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *obj_dir = repo_get_object_directory(repo);
@@ -238,6 +260,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
+	{ "path.index.absolute", get_path_index_absolute },
+	{ "path.index.relative", get_path_index_relative },
 	{ "path.objects.absolute", get_path_objects_absolute },
 	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index cd3f856d04..04e6b8553c 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -219,6 +219,12 @@ test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
 	'custom-hooks' \
 	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
 
+test_repo_info_path 'index standard' 'index' '.git/index'
+
+test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
+	'custom-index-file' \
+	'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
+
 test_repo_info_path 'objects standard' 'objects' '.git/objects'
 
 test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (4 preceding siblings ...)
  2026-07-17 13:30   ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  2026-07-20  0:20     ` Lucas Seiki Oshiro
  2026-07-17 13:30   ` [GSoC Patch v2 7/7] repo: add path.git-prefix path key K Jayatheerth
  6 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

External toolchains managing specialized history rewrites or legacy
history splices require access to the location of the repository grafts
file. Currently, this requires a legacy call to `git rev-parse --git-path info/grafts`.

Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
`git repo info`. This allows scripting layers to query the active grafts
context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
environment variable overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 38 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 3a837c573e..6c962620ec 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.grafts.absolute`::
+	The canonical absolute path to the repository grafts file.
+	Respects the `GIT_GRAFT_FILE` environment override.
+
+`path.grafts.relative`::
+	The path to the repository grafts file relative to the current working
+	directory. Respects the `GIT_GRAFT_FILE` environment override.
+
 `path.hooks.absolute`::
 	The canonical absolute path to the repository's hooks directory.
 	Respects `core.hooksPath` configuration adjustments.
diff --git a/builtin/repo.c b/builtin/repo.c
index 66bf4c67cc..a97ad71649 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
 {
 	struct strbuf hooks_path = STRBUF_INIT;
@@ -258,6 +280,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.grafts.absolute", get_path_grafts_absolute },
+	{ "path.grafts.relative", get_path_grafts_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.index.absolute", get_path_index_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 04e6b8553c..6c47989df7 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
+
+test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
+	'custom-graft-file' \
+	'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
+
 test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
 
 test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC Patch v2 7/7] repo: add path.git-prefix path key
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (5 preceding siblings ...)
  2026-07-17 13:30   ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-17 13:30   ` K Jayatheerth
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Scripts and command-line prompt integrations frequently need to know their
relative depth inside a repository working tree layout. Currently, this
is retrieved using `git rev-parse --show-prefix`.

Introduce the `path.git-prefix` key to `git repo info`. This mirrors the
prefix location tracking framework as a standalone key, returning the
exact relative path offset complete with a trailing slash, or an empty
string if run directly at the repository 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>
---
 Documentation/git-repo.adoc |  5 +++++
 builtin/repo.c              | 11 +++++++++++
 t/t1900-repo-info.sh        | 19 +++++++++++++++++++
 3 files changed, 35 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 6c962620ec..5ba2ab1612 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,11 @@ values that they return:
 	The path to the Git repository's common directory relative to
 	the current working directory.
 
+`path.git-prefix`::
+	The relative path from the top-level directory of the working tree to
+	the current working directory (including a trailing slash). Outputs an
+	empty string if executed at the root of the working tree.
+
 `path.gitdir.absolute`::
 	The canonical absolute path to the Git repository directory (the `.git` directory).
 
diff --git a/builtin/repo.c b/builtin/repo.c
index a97ad71649..b93c140c74 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -100,6 +100,16 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
 	return 0;
 }
 
+static int get_path_git_prefix(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	/*
+	 * startup_info->prefix is NULL if we are at the working tree root.
+	 * We add an empty string to ensure the buffer is cleanly initialized.
+	 */
+	strbuf_addstr(buf, startup_info->prefix ? startup_info->prefix : "");
+	return 0;
+}
+
 static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *git_dir = repo_get_git_dir(repo);
@@ -278,6 +288,7 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "object.format", get_object_format },
 	{ "path.commondir.absolute", get_path_commondir_absolute },
 	{ "path.commondir.relative", get_path_commondir_relative },
+	{ "path.git-prefix", get_path_git_prefix },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.grafts.absolute", get_path_grafts_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 6c47989df7..3e5e42f6d3 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -207,6 +207,25 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.git-prefix at root and in a subdirectory' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+
+		echo "path.git-prefix=" >expect.root &&
+		git repo info path.git-prefix >actual.root &&
+		test_cmp expect.root actual.root &&
+
+		mkdir -p sub/dir &&
+		cd sub/dir &&
+
+		echo "path.git-prefix=sub/dir/" >expect.sub &&
+		git repo info path.git-prefix >actual.sub &&
+		test_cmp expect.sub actual.sub
+	)
+'
+
 test_repo_info_path 'gitdir standard' 'gitdir' '.git'
 
 test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
  2026-07-17 13:30   ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-20  0:20     ` Lucas Seiki Oshiro
  2026-07-20  4:01       ` Junio C Hamano
  0 siblings, 1 reply; 51+ messages in thread
From: Lucas Seiki Oshiro @ 2026-07-20  0:20 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, jltobler, Junio C Hamano


> Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
> `git repo info`. This allows scripting layers to query the active grafts
> context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
> environment variable overrides.

I ran `git repo info path.grafts.relative` in a repository with no
`grafts` file, and it returned `.git/info/grafts`, which obviously
doesn't exist.

Wouldn't it be better if we check if that file exists before
returning this value?

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v2 5/7] repo: add path.index with absolute and relative suffix formatting
  2026-07-17 13:30   ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-20  0:35     ` Lucas Seiki Oshiro
  2026-07-24 17:49       ` K Jayatheerth
  0 siblings, 1 reply; 51+ messages in thread
From: Lucas Seiki Oshiro @ 2026-07-20  0:35 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, jltobler, Junio C Hamano


> Introduce `path.index.absolute` and `path.index.relative` keys to
> `git repo info`. This allows tooling utilities to discover the active
> index context cleanly while scaling transparently with localized
> `GIT_INDEX_FILE` environment overrides.

Note that bare repositories doesn't need to have an index file. Maybe
it would be better if you return an empty value in those cases.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
  2026-07-20  0:20     ` Lucas Seiki Oshiro
@ 2026-07-20  4:01       ` Junio C Hamano
  2026-07-21  2:19         ` K Jayatheerth
  0 siblings, 1 reply; 51+ messages in thread
From: Junio C Hamano @ 2026-07-20  4:01 UTC (permalink / raw)
  To: Lucas Seiki Oshiro; +Cc: K Jayatheerth, git, jltobler

Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> writes:

>> Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
>> `git repo info`. This allows scripting layers to query the active grafts
>> context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
>> environment variable overrides.
>
> I ran `git repo info path.grafts.relative` in a repository with no
> `grafts` file, and it returned `.git/info/grafts`, which obviously
> doesn't exist.
>
> Wouldn't it be better if we check if that file exists before
> returning this value?

That is an interesting question, but I think it depends on who is
querying and for what purpose.

If a script is asking where to write the file, then the author wants
to know where the file is supposed to be, even if no such file
exists yet.  Since the file format is public, they are free to write
their own tools to manipulate it.

Thanks.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
  2026-07-20  4:01       ` Junio C Hamano
@ 2026-07-21  2:19         ` K Jayatheerth
  0 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-21  2:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Lucas Seiki Oshiro, git, jltobler

Hey Lucas and Junio,

On Mon, Jul 20, 2026 at 9:31 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> writes:
>
> >> Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
> >> `git repo info`. This allows scripting layers to query the active grafts
> >> context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
> >> environment variable overrides.
> >
> > I ran `git repo info path.grafts.relative` in a repository with no
> > `grafts` file, and it returned `.git/info/grafts`, which obviously
> > doesn't exist.
> >
> > Wouldn't it be better if we check if that file exists before
> > returning this value?
>
> That is an interesting question, but I think it depends on who is
> querying and for what purpose.
>
> If a script is asking where to write the file, then the author wants
> to know where the file is supposed to be, even if no such file
> exists yet.  Since the file format is public, they are free to write
> their own tools to manipulate it.
>
> Thanks.

That's tough.
I think I align with Junio here.

I just used rev-parse as my compass to work on this command.
Just to clarify
Should I send a v3 changing something?

Regards,
- K Jayatheerth

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v2 5/7] repo: add path.index with absolute and relative suffix formatting
  2026-07-20  0:35     ` Lucas Seiki Oshiro
@ 2026-07-24 17:49       ` K Jayatheerth
  2026-07-24 19:21         ` Junio C Hamano
  0 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-24 17:49 UTC (permalink / raw)
  To: Lucas Seiki Oshiro; +Cc: git, jltobler, Junio C Hamano

Hey Lucas and Junio,

On Mon, Jul 20, 2026 at 6:05 AM Lucas Seiki Oshiro
<lucasseikioshiro@gmail.com> wrote:
>
>
> > Introduce `path.index.absolute` and `path.index.relative` keys to
> > `git repo info`. This allows tooling utilities to discover the active
> > index context cleanly while scaling transparently with localized
> > `GIT_INDEX_FILE` environment overrides.
>
> Note that bare repositories doesn't need to have an index file. Maybe
> it would be better if you return an empty value in those cases.

I wanted to follow up on this series.

I am a bit unsure about how to proceed with this specific case,
especially after Junio's feedback on the grafts patch.

For path.grafts, Junio mentioned that we should return the expected
path even if the file doesn't exist yet,
so scripts know where to write it. I am wondering if a similar logic
should apply to path.index in bare repositories.

While bare repos don't have a working tree (and therefore usually no index),
scripts do sometimes set GIT_INDEX_FILE to build temporary indexes for
tree manipulation.

Should we strictly return an empty string for bare repos (similar to
how we handle path.toplevel),
or should we return the default <gitdir>/index path in case a script
wants to know where it would be?

If this confusion is clear I can send a new version!

Thank you,
Regards

- K Jayatheerth

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v2 5/7] repo: add path.index with absolute and relative suffix formatting
  2026-07-24 17:49       ` K Jayatheerth
@ 2026-07-24 19:21         ` Junio C Hamano
  0 siblings, 0 replies; 51+ messages in thread
From: Junio C Hamano @ 2026-07-24 19:21 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: Lucas Seiki Oshiro, git, jltobler

K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:

> While bare repos don't have a working tree (and therefore usually no index),
> scripts do sometimes set GIT_INDEX_FILE to build temporary indexes for
> tree manipulation.
>
> Should we strictly return an empty string for bare repos (similar to
> how we handle path.toplevel),
> or should we return the default <gitdir>/index path in case a script
> wants to know where it would be?

The path to the top level can be an empty string if you are already
at the top level, which is neither an error nor an unusual
condition.  I do not understand the contrast you are drawing here.

I expect "tell me where the index is" to return <gitdir>/index,
$GIT_INDEX_FILE, or whatever Git sets during setup.  In other words,
whatever repo's '.index_file' member holds when control reaches
repo_read_index().

If a script checks that location and finds no file, that is the
natural way to learn there is no index.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [GSoC Patch v3 0/7] repo: add more path keys to git repo info
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (7 preceding siblings ...)
  2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-07-26 10:43 ` K Jayatheerth
  2026-07-26 10:43   ` [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
                     ` (7 more replies)
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
  9 siblings, 8 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

Series adds keys to git repo info.
Keys output paths of repository components:
* path.toplevel: repository tree.
* path.superproject-working-tree: superproject tree from submodules.
* path.objects: repository objects.
* path.hooks: repository hooks.
* path.index: repository index.
* path.grafts: repository grafts.
* path.git-prefix: prefix offset.

Keys support suffixes for format.
Commits contain documentation and tests.

Changes since v2:
* path.index: no functional change; documented that the returned path
  reflects the default/configured index location even in a bare
  repository or when the file doesn't exist yet, and added a test
  covering path.index inside a bare repository.
* path.grafts: no functional change; documented that the path is
  returned even if the grafts file doesn't currently exist on disk.
* path.git-prefix: no change since v2 (already addressed the stray
  include and misleading "validation" in the subject).

K Jayatheerth (7):
  repo: add path.toplevel with absolute and relative suffix formatting
  repo: add path.superproject-working-tree with absolute and relative
    suffixes
  repo: add path.objects with absolute and relative suffix formatting
  repo: add path.hooks with absolute and relative suffix formatting
  repo: add path.index with absolute and relative suffix formatting
  repo: add path.grafts with absolute and relative suffix formatting
  repo: add path.git-prefix path key

 Documentation/git-repo.adoc |  64 ++++++++++++++
 builtin/repo.c              | 166 ++++++++++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 125 +++++++++++++++++++++++++++
 3 files changed, 355 insertions(+)

Range-diff against v2:
1:  297d625ea1 = 1:  297d625ea1 repo: add path.toplevel with absolute and relative suffix formatting
2:  8a84aaa2a1 = 2:  8a84aaa2a1 repo: add path.superproject-working-tree with absolute and relative suffixes
3:  159166ce85 = 3:  159166ce85 repo: add path.objects with absolute and relative suffix formatting
4:  ff5e382043 = 4:  ff5e382043 repo: add path.hooks with absolute and relative suffix formatting
5:  d906735e3d ! 5:  917d3a5076 repo: add path.index with absolute and relative suffix formatting
    @@ Documentation/git-repo.adoc: values that they return:
      
     +`path.index.absolute`::
     +	The canonical absolute path to the repository's current index file.
    -+	Respects the `GIT_INDEX_FILE` environment override.
    ++	Respects the `GIT_INDEX_FILE` environment override. The returned path
    ++	reflects the configured/default index location regardless of whether the
    ++	repository is bare or whether the file currently exists.
     +
     +`path.index.relative`::
     +	The path to the repository's current index file relative to the current
     +	working directory. Respects the `GIT_INDEX_FILE` environment override.
    ++	The returned path reflects the configured/default index location regardless
    ++	of whether the repository is bare or whether the file currently exists.
     +
      `path.objects.absolute`::
      	The canonical absolute path to the repository's object database directory.
    @@ t/t1900-repo-info.sh: test_repo_info_path 'hooks with core.hooksPath override' '
     +test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
     +	'custom-index-file' \
     +	'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
    ++
    ++test_expect_success 'path.index in a bare repository returns default index location' '
    ++	test_when_finished "rm -rf bare.git" &&
    ++	git init --bare bare.git &&
    ++	(
    ++		cd bare.git &&
    ++		ROOT="$(test-tool path-utils real_path .)" &&
    ++
    ++		echo "path.index.absolute=$ROOT/index" >expect.abs &&
    ++		git repo info path.index.absolute >actual.abs &&
    ++		test_cmp expect.abs actual.abs &&
    ++
    ++		echo "path.index.relative=index" >expect.rel &&
    ++		git repo info path.index.relative >actual.rel &&
    ++		test_cmp expect.rel actual.rel
    ++	)
    ++'
     +
      test_repo_info_path 'objects standard' 'objects' '.git/objects'
      
6:  2d21f9536c ! 6:  d47a5701d5 repo: add path.grafts with absolute and relative suffix formatting
    @@ Documentation/git-repo.adoc: values that they return:
      
     +`path.grafts.absolute`::
     +	The canonical absolute path to the repository grafts file.
    -+	Respects the `GIT_GRAFT_FILE` environment override.
    ++	Respects the `GIT_GRAFT_FILE` environment override. The path is returned
    ++	regardless of whether the file currently exists on disk.
     +
     +`path.grafts.relative`::
     +	The path to the repository grafts file relative to the current working
    -+	directory. Respects the `GIT_GRAFT_FILE` environment override.
    ++	directory. Respects the `GIT_GRAFT_FILE` environment override. The path
    ++	is returned regardless of whether the file currently exists on disk.
     +
      `path.hooks.absolute`::
      	The canonical absolute path to the repository's hooks directory.
7:  1dbe191176 = 7:  fd90b0b3b5 repo: add path.git-prefix path key
-- 
2.55.GIT


^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-27  8:45     ` Junio C Hamano
  2026-07-28 16:36     ` Justin Tobler
  2026-07-26 10:43   ` [PATCH v3 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
                     ` (6 subsequent siblings)
  7 siblings, 2 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

Scripts frequently need to find the root directory of a repository's
working tree. Currently, this requires using `git rev-parse --show-toplevel`
or inferring it from other path components.

Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
to `git repo info`. This allows scripts to retrieve the top-level
working tree path in a predictable, strictly formatted manner without
relying on `rev-parse`.

If requested in a bare repository where no working tree exists, the
command returns an empty string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 28 ++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 30 ++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..e34abe5fea 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.toplevel.absolute`::
+	The canonical absolute path to the top-level directory of the
+	repository's working tree. Outputs an empty string if the repository
+	is bare.
+
+`path.toplevel.relative`::
+	The path to the top-level directory of the repository's working
+	tree relative to the current working directory. Outputs an empty
+	string if the repository is bare.
+
 `references.format`::
 	The reference storage format. The valid values are:
 +
diff --git a/builtin/repo.c b/builtin/repo.c
index 042d6de558..194757eb18 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -121,6 +121,32 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree) {
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree) {
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_references_format(struct repository *repo, struct strbuf *buf)
 {
 	strbuf_addstr(buf,
@@ -137,6 +163,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.toplevel.absolute", get_path_toplevel_absolute },
+	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
 };
 
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index ae8c22c817..fbb9063ee5 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,4 +213,34 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.toplevel absolute and relative' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		mkdir -p repo/sub &&
+		cd repo/sub &&
+
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.toplevel.absolute=$ROOT" >expect.abs &&
+		git repo info path.toplevel.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.toplevel.relative=../" >expect.rel &&
+		git repo info path.toplevel.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.toplevel returns empty in a bare repository' '
+	test_when_finished "rm -rf bare.git" &&
+	git init --bare bare.git &&
+	(
+		cd bare.git &&
+		echo "path.toplevel.absolute=" >expect &&
+		git repo info path.toplevel.absolute >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_done
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v3 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-07-26 10:43   ` [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-28 16:43     ` Justin Tobler
  2026-07-26 10:43   ` [PATCH v3 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

Scripts working in multi-repository setups often need to identify the
top-level working tree of a superproject from within a submodule.
Currently, this is only exposed via `git rev-parse
--show-superproject-working-tree`.

Introduce `path.superproject-working-tree.absolute` and
`path.superproject-working-tree.relative` keys to `git repo info`.
This exposes the core submodule context via a scriptable config-like key
using standard format rules.

If requested when not inside a submodule, the command returns an empty
string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 33 +++++++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e34abe5fea..03aa57942f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.superproject-working-tree.absolute`::
+	The canonical absolute path to the working tree root of the superproject
+	if the current repository is an initialized submodule. Outputs an empty
+	string if not in a submodule.
+
+`path.superproject-working-tree.relative`::
+	The path to the working tree root of the superproject relative to the
+	current working directory if the current repository is an initialized
+	submodule. Outputs an empty string if not in a submodule.
+
 `path.toplevel.absolute`::
 	The canonical absolute path to the top-level directory of the
 	repository's working tree. Outputs an empty string if the repository
diff --git a/builtin/repo.c b/builtin/repo.c
index 194757eb18..82359473e9 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -18,6 +18,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
+#include "submodule.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "utf8.h"
@@ -121,6 +122,36 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	strbuf_release(&superproject);
+	return 0;
+}
+
+static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		strbuf_addstr(buf, "");
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&superproject);
+	return 0;
+}
+
 static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *work_tree = repo_get_work_tree(repo);
@@ -163,6 +194,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
+	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
 	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index fbb9063ee5..220b3d4d3d 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,40 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.superproject-working-tree absolute and relative' '
+	test_when_finished "rm -rf sub super" &&
+	git init sub &&
+	test_commit -C sub initial &&
+	git init super &&
+	(
+		cd super &&
+		git -c protocol.file.allow=always submodule add "../sub" sub &&
+		git commit -m "add submodule" &&
+
+		cd sub &&
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
+		git repo info path.superproject-working-tree.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.superproject-working-tree.relative=../" >expect.rel &&
+		git repo info path.superproject-working-tree.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo "path.superproject-working-tree.absolute=" >expect &&
+		git repo info path.superproject-working-tree.absolute >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_expect_success 'path.toplevel absolute and relative' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v3 3/7] repo: add path.objects with absolute and relative suffix formatting
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
  2026-07-26 10:43   ` [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
  2026-07-26 10:43   ` [PATCH v3 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-28 17:12     ` Justin Tobler
  2026-07-26 10:43   ` [PATCH v3 4/7] repo: add path.hooks " K Jayatheerth
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

Tools and deployment hooks frequently query the location of the object
database directory. Currently, this relies on legacy parsing methods or
manually inspecting `git rev-parse --git-path objects`.

Introduce `path.objects.absolute` and `path.objects.relative` keys to
`git repo info`. This allows tools to discover the object database
location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
environment variable overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  9 +++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  7 +++++++
 3 files changed, 40 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 03aa57942f..8429a44b43 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,15 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.objects.absolute`::
+	The canonical absolute path to the repository's object database directory.
+	Respects the `GIT_OBJECT_DIRECTORY` environment override.
+
+`path.objects.relative`::
+	The path to the repository's object database directory relative to the
+	current working directory. Respects the `GIT_OBJECT_DIRECTORY`
+	environment override.
+
 `path.superproject-working-tree.absolute`::
 	The canonical absolute path to the working tree root of the superproject
 	if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index 82359473e9..d6bdd5bcfa 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *obj_dir = repo_get_object_directory(repo);
+
+	if (!obj_dir)
+		return error(_("unable to get object directory"));
+
+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_objects_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *obj_dir = repo_get_object_directory(repo);
+
+	if (!obj_dir)
+		return error(_("unable to get object directory"));
+
+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
 {
 	struct strbuf superproject = STRBUF_INIT;
@@ -194,6 +216,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.objects.absolute", get_path_objects_absolute },
+	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
 	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 220b3d4d3d..260f4fde43 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,13 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'objects standard' 'objects' '.git/objects'
+
+test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
+	'custom-objects' \
+	'GIT_OBJECT_DIRECTORY="$ROOT/custom-objects" && export GIT_OBJECT_DIRECTORY &&
+	 mkdir -p "$ROOT/custom-objects"'
+
 test_expect_success 'path.superproject-working-tree absolute and relative' '
 	test_when_finished "rm -rf sub super" &&
 	git init sub &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v3 4/7] repo: add path.hooks with absolute and relative suffix formatting
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (2 preceding siblings ...)
  2026-07-26 10:43   ` [PATCH v3 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-28 19:00     ` Justin Tobler
  2026-07-26 10:43   ` [PATCH v3 5/7] repo: add path.index " K Jayatheerth
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

External tool integrations and validation systems need a stable way to
identify where the repository hooks are stored. Currently, this involves
relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
manually.

Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This allows tools to discover the active hooks location
natively, ensuring proper resolution regardless of whether Git is using
the standard `.git/hooks` structure or a custom `core.hooksPath` setup.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  8 ++++++++
 builtin/repo.c              | 22 ++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 8429a44b43..7bc1c51310 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.hooks.absolute`::
+	The canonical absolute path to the repository's hooks directory.
+	Respects `core.hooksPath` configuration adjustments.
+
+`path.hooks.relative`::
+	The path to the repository's hooks directory relative to the current
+	working directory. Respects `core.hooksPath` configuration adjustments.
+
 `path.objects.absolute`::
 	The canonical absolute path to the repository's object database directory.
 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index d6bdd5bcfa..c921de222d 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,26 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
+static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
 static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *obj_dir = repo_get_object_directory(repo);
@@ -216,6 +236,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.hooks.absolute", get_path_hooks_absolute },
+	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.objects.absolute", get_path_objects_absolute },
 	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 260f4fde43..cd3f856d04 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
+
+test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
+	'custom-hooks' \
+	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+
 test_repo_info_path 'objects standard' 'objects' '.git/objects'
 
 test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v3 5/7] repo: add path.index with absolute and relative suffix formatting
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (3 preceding siblings ...)
  2026-07-26 10:43   ` [PATCH v3 4/7] repo: add path.hooks " K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-26 10:43   ` [PATCH v3 6/7] repo: add path.grafts " K Jayatheerth
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

External script workflows and formatting layers require straightforward
access to the location of the index staging file. Currently, tracking
this necessitates a legacy call to `git rev-parse --git-path index` or
`--show-toplevel` logic abstractions.

Introduce `path.index.absolute` and `path.index.relative` keys to
`git repo info`. This allows tooling utilities to discover the active
index context cleanly while scaling transparently with localized
`GIT_INDEX_FILE` environment overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 12 ++++++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 23 +++++++++++++++++++++++
 3 files changed, 59 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 7bc1c51310..34c4f7d61c 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -127,6 +127,18 @@ values that they return:
 	The path to the repository's hooks directory relative to the current
 	working directory. Respects `core.hooksPath` configuration adjustments.
 
+`path.index.absolute`::
+	The canonical absolute path to the repository's current index file.
+	Respects the `GIT_INDEX_FILE` environment override. The returned path
+	reflects the configured/default index location regardless of whether the
+	repository is bare or whether the file currently exists.
+
+`path.index.relative`::
+	The path to the repository's current index file relative to the current
+	working directory. Respects the `GIT_INDEX_FILE` environment override.
+	The returned path reflects the configured/default index location regardless
+	of whether the repository is bare or whether the file currently exists.
+
 `path.objects.absolute`::
 	The canonical absolute path to the repository's object database directory.
 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index c921de222d..66bf4c67cc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -142,6 +142,28 @@ static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_index_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_index_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *obj_dir = repo_get_object_directory(repo);
@@ -238,6 +260,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
+	{ "path.index.absolute", get_path_index_absolute },
+	{ "path.index.relative", get_path_index_relative },
 	{ "path.objects.absolute", get_path_objects_absolute },
 	{ "path.objects.relative", get_path_objects_relative },
 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index cd3f856d04..dee1db2a49 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -219,6 +219,29 @@ test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
 	'custom-hooks' \
 	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
 
+test_repo_info_path 'index standard' 'index' '.git/index'
+
+test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
+	'custom-index-file' \
+	'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
+
+test_expect_success 'path.index in a bare repository returns default index location' '
+	test_when_finished "rm -rf bare.git" &&
+	git init --bare bare.git &&
+	(
+		cd bare.git &&
+		ROOT="$(test-tool path-utils real_path .)" &&
+
+		echo "path.index.absolute=$ROOT/index" >expect.abs &&
+		git repo info path.index.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.index.relative=index" >expect.rel &&
+		git repo info path.index.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
 test_repo_info_path 'objects standard' 'objects' '.git/objects'
 
 test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v3 6/7] repo: add path.grafts with absolute and relative suffix formatting
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (4 preceding siblings ...)
  2026-07-26 10:43   ` [PATCH v3 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-26 10:43   ` [PATCH v3 7/7] repo: add path.git-prefix path key K Jayatheerth
  2026-07-26 16:29   ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info Junio C Hamano
  7 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

External toolchains managing specialized history rewrites or legacy
history splices require access to the location of the repository grafts
file. Currently, this requires a legacy call to `git rev-parse --git-path info/grafts`.

Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
`git repo info`. This allows scripting layers to query the active grafts
context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
environment variable overrides.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 40 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 34c4f7d61c..def888da91 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.grafts.absolute`::
+	The canonical absolute path to the repository grafts file.
+	Respects the `GIT_GRAFT_FILE` environment override. The path is returned
+	regardless of whether the file currently exists on disk.
+
+`path.grafts.relative`::
+	The path to the repository grafts file relative to the current working
+	directory. Respects the `GIT_GRAFT_FILE` environment override. The path
+	is returned regardless of whether the file currently exists on disk.
+
 `path.hooks.absolute`::
 	The canonical absolute path to the repository's hooks directory.
 	Respects `core.hooksPath` configuration adjustments.
diff --git a/builtin/repo.c b/builtin/repo.c
index 66bf4c67cc..a97ad71649 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
 {
 	struct strbuf hooks_path = STRBUF_INIT;
@@ -258,6 +280,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.grafts.absolute", get_path_grafts_absolute },
+	{ "path.grafts.relative", get_path_grafts_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.index.absolute", get_path_index_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index dee1db2a49..15a4ec9b78 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
+
+test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
+	'custom-graft-file' \
+	'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
+
 test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
 
 test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v3 7/7] repo: add path.git-prefix path key
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (5 preceding siblings ...)
  2026-07-26 10:43   ` [PATCH v3 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-26 10:43   ` K Jayatheerth
  2026-07-26 16:29   ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info Junio C Hamano
  7 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 10:43 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, gitster, jltobler, lucasseikioshiro

Scripts and command-line prompt integrations frequently need to know their
relative depth inside a repository working tree layout. Currently, this
is retrieved using `git rev-parse --show-prefix`.

Introduce the `path.git-prefix` key to `git repo info`. This mirrors the
prefix location tracking framework as a standalone key, returning the
exact relative path offset complete with a trailing slash, or an empty
string if run directly at the repository 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>
---
 Documentation/git-repo.adoc |  5 +++++
 builtin/repo.c              | 11 +++++++++++
 t/t1900-repo-info.sh        | 19 +++++++++++++++++++
 3 files changed, 35 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index def888da91..98282ea668 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,11 @@ values that they return:
 	The path to the Git repository's common directory relative to
 	the current working directory.
 
+`path.git-prefix`::
+	The relative path from the top-level directory of the working tree to
+	the current working directory (including a trailing slash). Outputs an
+	empty string if executed at the root of the working tree.
+
 `path.gitdir.absolute`::
 	The canonical absolute path to the Git repository directory (the `.git` directory).
 
diff --git a/builtin/repo.c b/builtin/repo.c
index a97ad71649..b93c140c74 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -100,6 +100,16 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
 	return 0;
 }
 
+static int get_path_git_prefix(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	/*
+	 * startup_info->prefix is NULL if we are at the working tree root.
+	 * We add an empty string to ensure the buffer is cleanly initialized.
+	 */
+	strbuf_addstr(buf, startup_info->prefix ? startup_info->prefix : "");
+	return 0;
+}
+
 static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *git_dir = repo_get_git_dir(repo);
@@ -278,6 +288,7 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "object.format", get_object_format },
 	{ "path.commondir.absolute", get_path_commondir_absolute },
 	{ "path.commondir.relative", get_path_commondir_relative },
+	{ "path.git-prefix", get_path_git_prefix },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.grafts.absolute", get_path_grafts_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 15a4ec9b78..2879e54668 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -207,6 +207,25 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.git-prefix at root and in a subdirectory' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+
+		echo "path.git-prefix=" >expect.root &&
+		git repo info path.git-prefix >actual.root &&
+		test_cmp expect.root actual.root &&
+
+		mkdir -p sub/dir &&
+		cd sub/dir &&
+
+		echo "path.git-prefix=sub/dir/" >expect.sub &&
+		git repo info path.git-prefix >actual.sub &&
+		test_cmp expect.sub actual.sub
+	)
+'
+
 test_repo_info_path 'gitdir standard' 'gitdir' '.git'
 
 test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v3 0/7] repo: add more path keys to git repo info
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
                     ` (6 preceding siblings ...)
  2026-07-26 10:43   ` [PATCH v3 7/7] repo: add path.git-prefix path key K Jayatheerth
@ 2026-07-26 16:29   ` Junio C Hamano
  2026-07-26 17:00     ` K Jayatheerth
  2026-07-27  0:57     ` Lucas Seiki Oshiro
  7 siblings, 2 replies; 51+ messages in thread
From: Junio C Hamano @ 2026-07-26 16:29 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, jltobler, lucasseikioshiro

K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:

> Series adds keys to git repo info.
> Keys output paths of repository components:
> * path.toplevel: repository tree.
> * path.superproject-working-tree: superproject tree from submodules.
> * path.objects: repository objects.
> * path.hooks: repository hooks.
> * path.index: repository index.
> * path.grafts: repository grafts.
> * path.git-prefix: prefix offset.

I guess the issues I had at the design level in the previous
iteration is gone ;-)

I'd love to hear real reviews from others on these patches, but
at least I didn't spot anything glaringly wrong anymore.

Thanks.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v3 0/7] repo: add more path keys to git repo info
  2026-07-26 16:29   ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info Junio C Hamano
@ 2026-07-26 17:00     ` K Jayatheerth
  2026-07-27  0:57     ` Lucas Seiki Oshiro
  1 sibling, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-26 17:00 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, jltobler, lucasseikioshiro

On Sun, Jul 26, 2026 at 9:59 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:
>
> > Series adds keys to git repo info.
> > Keys output paths of repository components:
> > * path.toplevel: repository tree.
> > * path.superproject-working-tree: superproject tree from submodules.
> > * path.objects: repository objects.
> > * path.hooks: repository hooks.
> > * path.index: repository index.
> > * path.grafts: repository grafts.
> > * path.git-prefix: prefix offset.
>
> I guess the issues I had at the design level in the previous
> iteration is gone ;-)
>
> I'd love to hear real reviews from others on these patches, but
> at least I didn't spot anything glaringly wrong anymore.
>
> Thanks.

Sure,
until then I will work on the histogram patches in git repo structure.

Thanks for validating!

Regards,
- K Jayatheerth

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v3 0/7] repo: add more path keys to git repo info
  2026-07-26 16:29   ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info Junio C Hamano
  2026-07-26 17:00     ` K Jayatheerth
@ 2026-07-27  0:57     ` Lucas Seiki Oshiro
  2026-07-27  5:55       ` Junio C Hamano
  1 sibling, 1 reply; 51+ messages in thread
From: Lucas Seiki Oshiro @ 2026-07-27  0:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: K Jayatheerth, git, jltobler


> I'd love to hear real reviews from others on these patches, but
> at least I didn't spot anything glaringly wrong anymore.

It looks good to me :-)


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [GSoC Patch v3 0/7] repo: add more path keys to git repo info
  2026-07-27  0:57     ` Lucas Seiki Oshiro
@ 2026-07-27  5:55       ` Junio C Hamano
  0 siblings, 0 replies; 51+ messages in thread
From: Junio C Hamano @ 2026-07-27  5:55 UTC (permalink / raw)
  To: Lucas Seiki Oshiro; +Cc: K Jayatheerth, git, jltobler

Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> writes:

>> I'd love to hear real reviews from others on these patches, but
>> at least I didn't spot anything glaringly wrong anymore.
>
> It looks good to me :-)

Can you try to make your review sound a bit more credible to
readers?

It is much harder to give positive reviews than to merely point out
a few breakages in a patch, but there are still things reviewers can
do.  Thinking aloud to follow the author's line of thought is a
technique I have found over the years to work well in demonstrating
that your Ack is backed by having actually read and understood the
patch.  There may be other techniques experienced reviewers (by now
you know who they are after reading what they wrote on your patches
and others') use when giving positive reviews.

Thanks.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-26 10:43   ` [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-27  8:45     ` Junio C Hamano
  2026-07-28  1:21       ` K Jayatheerth
  2026-07-28 16:36     ` Justin Tobler
  1 sibling, 1 reply; 51+ messages in thread
From: Junio C Hamano @ 2026-07-27  8:45 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, jltobler, lucasseikioshiro

K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:

> +static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
> +{
> +	const char *work_tree = repo_get_work_tree(repo);
> +
> +	if (!work_tree) {
> +		strbuf_addstr(buf, "");
> +		return 0;
> +	}
> +
> +	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
> +	return 0;
> +}

I can manage to wiggle it in, of course, but I thought we lost the
'.prefix' member from 'startup_info' in the recent tip of 'master'.
As the topic is not targeting 'maint' as a bugfix, perhaps we want
to use a more up-to-date 'master' as the base of the topic?

Thanks.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-27  8:45     ` Junio C Hamano
@ 2026-07-28  1:21       ` K Jayatheerth
  0 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-28  1:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, jltobler, lucasseikioshiro

On Mon, Jul 27, 2026 at 2:15 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:

> > +     format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
> > +     return 0;
> > +}
>
> I can manage to wiggle it in, of course, but I thought we lost the
> '.prefix' member from 'startup_info' in the recent tip of 'master'.

Indeed.

> As the topic is not targeting 'maint' as a bugfix, perhaps we want
> to use a more up-to-date 'master' as the base of the topic?
>
> Thanks.

I see Patrick has changed the prefix member to the repo struct.
Didn't notice that before!

I will use the latest master branch for v4

Regards,
- K Jayatheerth

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-26 10:43   ` [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
  2026-07-27  8:45     ` Junio C Hamano
@ 2026-07-28 16:36     ` Justin Tobler
  2026-07-29 16:36       ` K Jayatheerth
  1 sibling, 1 reply; 51+ messages in thread
From: Justin Tobler @ 2026-07-28 16:36 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, gitster, lucasseikioshiro

On 26/07/26 04:13PM, K Jayatheerth wrote:
> Scripts frequently need to find the root directory of a repository's
> working tree. Currently, this requires using `git rev-parse --show-toplevel`
> or inferring it from other path components.
> 
> Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
> to `git repo info`. This allows scripts to retrieve the top-level
> working tree path in a predictable, strictly formatted manner without
> relying on `rev-parse`.

Ok, this seems like suitable information to also look up under
git-repo-info.

> If requested in a bare repository where no working tree exists, the
> command returns an empty string.

This matches the existing behavior in git-rev-parse(1). Makes sense.

> Mentored-by: Justin Tobler <jltobler@gmail.com>
> Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
> Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
> ---
>  Documentation/git-repo.adoc | 10 ++++++++++
>  builtin/repo.c              | 28 ++++++++++++++++++++++++++++
>  t/t1900-repo-info.sh        | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 68 insertions(+)
> 
> diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
> index ed7d80c690..e34abe5fea 100644
> --- a/Documentation/git-repo.adoc
> +++ b/Documentation/git-repo.adoc
> @@ -119,6 +119,16 @@ values that they return:
>  `path.gitdir.relative`::
>  	The path to the Git repository directory relative to the current working directory.
>  
> +`path.toplevel.absolute`::
> +	The canonical absolute path to the top-level directory of the
> +	repository's working tree. Outputs an empty string if the repository
> +	is bare.
> +
> +`path.toplevel.relative`::
> +	The path to the top-level directory of the repository's working
> +	tree relative to the current working directory. Outputs an empty
> +	string if the repository is bare.
> +
>  `references.format`::
>  	The reference storage format. The valid values are:
>  +
> diff --git a/builtin/repo.c b/builtin/repo.c
> index 042d6de558..194757eb18 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -121,6 +121,32 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
>  	return 0;
>  }
>  
> +static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
> +{
> +	const char *work_tree = repo_get_work_tree(repo);
> +
> +	if (!work_tree) {
> +		strbuf_addstr(buf, "");

The strbuf here is already NULL-terminated when its initialized. I don't
think this should be necessary.

> +		return 0;
> +	}
> +
> +	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
> +	return 0;
> +}
> +
> +static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
> +{
> +	const char *work_tree = repo_get_work_tree(repo);
> +
> +	if (!work_tree) {
> +		strbuf_addstr(buf, "");

Same here.

> +		return 0;
> +	}
> +
> +	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
> +	return 0;
> +}
> +
>  static int get_references_format(struct repository *repo, struct strbuf *buf)
>  {
>  	strbuf_addstr(buf,
> @@ -137,6 +163,8 @@ static const struct repo_info_field repo_info_field[] = {
>  	{ "path.commondir.relative", get_path_commondir_relative },
>  	{ "path.gitdir.absolute", get_path_gitdir_absolute },
>  	{ "path.gitdir.relative", get_path_gitdir_relative },
> +	{ "path.toplevel.absolute", get_path_toplevel_absolute },
> +	{ "path.toplevel.relative", get_path_toplevel_relative },
>  	{ "references.format", get_references_format },
>  };
>  
> diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
> index ae8c22c817..fbb9063ee5 100755
> --- a/t/t1900-repo-info.sh
> +++ b/t/t1900-repo-info.sh
> @@ -213,4 +213,34 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
>  	'.git' \
>  	'GIT_DIR="../.git" && export GIT_DIR'
>  
> +test_expect_success 'path.toplevel absolute and relative' '
> +	test_when_finished "rm -rf repo" &&
> +	git init repo &&
> +	(
> +		mkdir -p repo/sub &&
> +		cd repo/sub &&
> +
> +		ROOT="$(test-tool path-utils real_path ..)" &&
> +
> +		echo "path.toplevel.absolute=$ROOT" >expect.abs &&
> +		git repo info path.toplevel.absolute >actual.abs &&
> +		test_cmp expect.abs actual.abs &&
> +
> +		echo "path.toplevel.relative=../" >expect.rel &&
> +		git repo info path.toplevel.relative >actual.rel &&
> +		test_cmp expect.rel actual.rel
> +	)
> +'
> +
> +test_expect_success 'path.toplevel returns empty in a bare repository' '
> +	test_when_finished "rm -rf bare.git" &&
> +	git init --bare bare.git &&
> +	(
> +		cd bare.git &&
> +		echo "path.toplevel.absolute=" >expect &&
> +		git repo info path.toplevel.absolute >actual &&
> +		test_cmp expect actual

In this test we are only checking the absolute path. It probably
wouldn't hurt to also check the relative path too.

-Justin

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes
  2026-07-26 10:43   ` [PATCH v3 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
@ 2026-07-28 16:43     ` Justin Tobler
  0 siblings, 0 replies; 51+ messages in thread
From: Justin Tobler @ 2026-07-28 16:43 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, gitster, lucasseikioshiro

On 26/07/26 04:13PM, K Jayatheerth wrote:
> Scripts working in multi-repository setups often need to identify the
> top-level working tree of a superproject from within a submodule.
> Currently, this is only exposed via `git rev-parse
> --show-superproject-working-tree`.
> 
> Introduce `path.superproject-working-tree.absolute` and
> `path.superproject-working-tree.relative` keys to `git repo info`.
> This exposes the core submodule context via a scriptable config-like key
> using standard format rules.

Ok, this also seems like a good fit to include as a key in
git-repo-info, but "superproject-working-tree" is a bit of a mouthful
IMO. An alternative could potentially be "superproject-root"? Maybe its
best to just be consistent with the option name in git-rev-parse(1) and
keep it the same though.

> If requested when not inside a submodule, the command returns an empty
> string.
> 
> Mentored-by: Justin Tobler <jltobler@gmail.com>
> Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
> Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
> ---
>  Documentation/git-repo.adoc | 10 ++++++++++
>  builtin/repo.c              | 33 +++++++++++++++++++++++++++++++++
>  t/t1900-repo-info.sh        | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
> index e34abe5fea..03aa57942f 100644
> --- a/Documentation/git-repo.adoc
> +++ b/Documentation/git-repo.adoc
> @@ -119,6 +119,16 @@ values that they return:
>  `path.gitdir.relative`::
>  	The path to the Git repository directory relative to the current working directory.
>  
> +`path.superproject-working-tree.absolute`::
> +	The canonical absolute path to the working tree root of the superproject
> +	if the current repository is an initialized submodule. Outputs an empty
> +	string if not in a submodule.
> +
> +`path.superproject-working-tree.relative`::
> +	The path to the working tree root of the superproject relative to the
> +	current working directory if the current repository is an initialized
> +	submodule. Outputs an empty string if not in a submodule.
> +
>  `path.toplevel.absolute`::
>  	The canonical absolute path to the top-level directory of the
>  	repository's working tree. Outputs an empty string if the repository
> diff --git a/builtin/repo.c b/builtin/repo.c
> index 194757eb18..82359473e9 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -18,6 +18,7 @@
>  #include "strbuf.h"
>  #include "string-list.h"
>  #include "shallow.h"
> +#include "submodule.h"
>  #include "tree.h"
>  #include "tree-walk.h"
>  #include "utf8.h"
> @@ -121,6 +122,36 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
>  	return 0;
>  }
>  
> +static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
> +{
> +	struct strbuf superproject = STRBUF_INIT;
> +
> +	if (!get_superproject_working_tree(&superproject)) {
> +		strbuf_release(&superproject);
> +		strbuf_addstr(buf, "");

Same comment here as in the previous patch...

> +		return 0;
> +	}
> +
> +	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
> +	strbuf_release(&superproject);
> +	return 0;
> +}
> +
> +static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
> +{
> +	struct strbuf superproject = STRBUF_INIT;
> +
> +	if (!get_superproject_working_tree(&superproject)) {
> +		strbuf_release(&superproject);
> +		strbuf_addstr(buf, "");

...and here as well...

> +		return 0;
> +	}
> +
> +	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
> +	strbuf_release(&superproject);
> +	return 0;
> +}
> +
>  static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
>  {
>  	const char *work_tree = repo_get_work_tree(repo);
> @@ -163,6 +194,8 @@ static const struct repo_info_field repo_info_field[] = {
>  	{ "path.commondir.relative", get_path_commondir_relative },
>  	{ "path.gitdir.absolute", get_path_gitdir_absolute },
>  	{ "path.gitdir.relative", get_path_gitdir_relative },
> +	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
> +	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
>  	{ "path.toplevel.absolute", get_path_toplevel_absolute },
>  	{ "path.toplevel.relative", get_path_toplevel_relative },
>  	{ "references.format", get_references_format },
> diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
> index fbb9063ee5..220b3d4d3d 100755
> --- a/t/t1900-repo-info.sh
> +++ b/t/t1900-repo-info.sh
> @@ -213,6 +213,40 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
>  	'.git' \
>  	'GIT_DIR="../.git" && export GIT_DIR'
>  
> +test_expect_success 'path.superproject-working-tree absolute and relative' '
> +	test_when_finished "rm -rf sub super" &&
> +	git init sub &&
> +	test_commit -C sub initial &&
> +	git init super &&
> +	(
> +		cd super &&
> +		git -c protocol.file.allow=always submodule add "../sub" sub &&
> +		git commit -m "add submodule" &&
> +
> +		cd sub &&
> +		ROOT="$(test-tool path-utils real_path ..)" &&
> +
> +		echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
> +		git repo info path.superproject-working-tree.absolute >actual.abs &&
> +		test_cmp expect.abs actual.abs &&
> +
> +		echo "path.superproject-working-tree.relative=../" >expect.rel &&
> +		git repo info path.superproject-working-tree.relative >actual.rel &&
> +		test_cmp expect.rel actual.rel
> +	)
> +'
> +
> +test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
> +	test_when_finished "rm -rf repo" &&
> +	git init repo &&
> +	(
> +		cd repo &&
> +		echo "path.superproject-working-tree.absolute=" >expect &&
> +		git repo info path.superproject-working-tree.absolute >actual &&
> +		test_cmp expect actual

... and here as well. :)

-Justin

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 3/7] repo: add path.objects with absolute and relative suffix formatting
  2026-07-26 10:43   ` [PATCH v3 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-28 17:12     ` Justin Tobler
  0 siblings, 0 replies; 51+ messages in thread
From: Justin Tobler @ 2026-07-28 17:12 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, gitster, lucasseikioshiro, ps

On 26/07/26 04:13PM, K Jayatheerth wrote:
> Tools and deployment hooks frequently query the location of the object
> database directory. Currently, this relies on legacy parsing methods or
> manually inspecting `git rev-parse --git-path objects`.

"Tools and deployment hooks" seems a bit overly specific. Maybe instead
we could just say "Scripts operating on a repository may need to query
the location of the object database directory"?

Also, I'm not entirely sure what is meant by "legacy parsing methods"
here.

> Introduce `path.objects.absolute` and `path.objects.relative` keys to
> `git repo info`. This allows tools to discover the object database
> location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
> environment variable overrides.

In the context of pluggable ODBs, this proposed key is a little more
interesting because a non-"files" ODB source in the future may not even
have a filesystem path to an objects directory. When this becomes more
relevant, we could just adapt these keys to return an empty string in
such cases, but it does also make me question whether it is information
that we should further expose in the first place if it does eventually
becomes an internal detail of a specific ODB source.

It probably doesn't matter too much, but I've CC'd Patrick for his
thoughts too.

[snip]
> diff --git a/builtin/repo.c b/builtin/repo.c
> index 82359473e9..d6bdd5bcfa 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
>  	return 0;
>  }
>  
> +static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
> +{
> +	const char *obj_dir = repo_get_object_directory(repo);
> +
> +	if (!obj_dir)
> +		return error(_("unable to get object directory"));
> +
> +	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);

For the absolute path, do we actually need to provide the prefix? It
might make it more clear that its the aboslute path if we just pass ""
instead?

-Justin

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 4/7] repo: add path.hooks with absolute and relative suffix formatting
  2026-07-26 10:43   ` [PATCH v3 4/7] repo: add path.hooks " K Jayatheerth
@ 2026-07-28 19:00     ` Justin Tobler
  0 siblings, 0 replies; 51+ messages in thread
From: Justin Tobler @ 2026-07-28 19:00 UTC (permalink / raw)
  To: K Jayatheerth; +Cc: git, gitster, lucasseikioshiro

On 26/07/26 04:13PM, K Jayatheerth wrote:
> External tool integrations and validation systems need a stable way to
> identify where the repository hooks are stored. Currently, this involves
> relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
> manually.

Similar to the comment in the previous patch, "External tool
intergations and validation systems" seems overly specific IMO. Also,
"need" is a bit strongly worded as I'm sure its not a requirement for
every external script/tool.

> Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
> `git repo info`. This allows tools to discover the active hooks location
> natively, ensuring proper resolution regardless of whether Git is using
> the standard `.git/hooks` structure or a custom `core.hooksPath` setup.

Per hooks path documentation:

  The path can be either absolute or relative. A relative path is taken
  as relative to the directory where the hooks are run.
  
  ...

  You  can also disable all hooks entirely by setting core.hooksPath to
  /dev/null.

Should we handle this /dev/null case specially? It looks like:

  $ git -c core.hooksPath=/dev/null rev-parse --git-path hooks

just prints '/dev/null'. I do wonder if this makes much sense though in
context of the relative path version of this key. From some quick
testing, it appears the git-rev-parse(1) version of this option always
prints the absolute path if that is what is configured (it appears to
ignore --path-format). Maybe we should just special case /dev/null and
return an empty string? I'm not entirely sure what the best route is
here though.

-Justin

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-07-28 16:36     ` Justin Tobler
@ 2026-07-29 16:36       ` K Jayatheerth
  0 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-07-29 16:36 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git, gitster, lucasseikioshiro, Patrick Steinhardt

Hey Justin,

Thanks for the detailed review.

On Tue, Jul 28, 2026 at 10:06 PM Justin Tobler <jltobler@gmail.com> wrote:
>
> On 26/07/26 04:13PM, K Jayatheerth wrote:
> > Scripts frequently need to find the root directory of a repository's
> > working tree. Currently, this requires using `git rev-parse --show-toplevel`
> > or inferring it from other path components.
> >
> > Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
> > to `git repo info`. This allows scripts to retrieve the top-level
> > working tree path in a predictable, strictly formatted manner without
> > relying on `rev-parse`.
>
> Ok, this seems like suitable information to also look up under
> git-repo-info.
>
> > If requested in a bare repository where no working tree exists, the
> > command returns an empty string.
>
> This matches the existing behavior in git-rev-parse(1). Makes sense.
>


Yes, that is correct.


> >
> > +static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
> > +{
> > +     const char *work_tree = repo_get_work_tree(repo);
> > +
> > +     if (!work_tree) {
> > +             strbuf_addstr(buf, "");
>
> The strbuf here is already NULL-terminated when its initialized. I don't
> think this should be necessary.
>


Very nice point indeed
I will change that everywhere I have added that.


> > +     if (!work_tree) {
> > +             strbuf_addstr(buf, "");
>
> Same here.
>

> > +test_expect_success 'path.toplevel returns empty in a bare repository' '
> > +     test_when_finished "rm -rf bare.git" &&
> > +     git init --bare bare.git &&
> > +     (
> > +             cd bare.git &&
> > +             echo "path.toplevel.absolute=" >expect &&
> > +             git repo info path.toplevel.absolute >actual &&
> > +             test_cmp expect actual
>
> In this test we are only checking the absolute path. It probably
> wouldn't hurt to also check the relative path too.
>


Good catch. I'll add relative-path tests in both places.


> > Introduce `path.superproject-working-tree.absolute` and
> > `path.superproject-working-tree.relative` keys to `git repo info`.
> > This exposes the core submodule context via a scriptable config-like key
> > using standard format rules.
>
> Ok, this also seems like a good fit to include as a key in
> git-repo-info, but "superproject-working-tree" is a bit of a mouthful
> IMO. An alternative could potentially be "superproject-root"? Maybe its
> best to just be consistent with the option name in git-rev-parse(1) and
> keep it the same though.


show-superproject-working-tree is what git rev parse uses.
I am a bit unclear about this.
Since it is meant to be a scripting command, I don't know if it being
a long name matters much.
At the same time, I don't think we can keep the exact
"show-superproject-working-tree" as the key's name.
As the "show" is indirectly covered by "path." so the "show" is just
redundant if you ask me (I might be wrong here).
That is actually why I kept the rest of the name similar and omitted
the prefix from the flag name.

In other words, I am fine with the name being either one.
That said, I am more inclined with the "superproject-root".
I think the name explains exactly what it does.
Whereas "superproject-working-tree" was not that clear to me when I
first read it (Might be subjective to me).


> > +static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
> > +{
> > +     struct strbuf superproject = STRBUF_INIT;
> > +
> > +     if (!get_superproject_working_tree(&superproject)) {
> > +             strbuf_release(&superproject);
> > +             strbuf_addstr(buf, "");
>
> Same comment here as in the previous patch...
>
> > +     struct strbuf superproject = STRBUF_INIT;
> > +
> > +     if (!get_superproject_working_tree(&superproject)) {
> > +             strbuf_release(&superproject);
> > +             strbuf_addstr(buf, "");
>
> ...and here as well...
>
> > +             return 0;
> > +     }
> > +
> > +     format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
> > +     strbuf_release(&superproject);
> > +     return 0;
> > +}
> > +
> > +test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
> > +     test_when_finished "rm -rf repo" &&
> > +     git init repo &&
> > +     (
> > +             cd repo &&
> > +             echo "path.superproject-working-tree.absolute=" >expect &&
> > +             git repo info path.superproject-working-tree.absolute >actual &&
> > +             test_cmp expect actual
>
> ... and here as well. :)
>


Good catch. I'll add a relative-path test there as well.


> > Tools and deployment hooks frequently query the location of the object
> > database directory. Currently, this relies on legacy parsing methods or
> > manually inspecting `git rev-parse --git-path objects`.
>
> "Tools and deployment hooks" seems a bit overly specific. Maybe instead
> we could just say "Scripts operating on a repository may need to query
> the location of the object database directory"?
>


I think your version is consistent with other patches as well.
I wanted to ask if it is not a good practice to write commit messages
which are very specific.
I also wanted to know what constitutes being overly specific so that I
can avoid doing it again.


> Also, I'm not entirely sure what is meant by "legacy parsing methods"
> here.
>


Something scripts have historically done: parse git rev-parse
--git-dir (or read .git/config by hand)
and manually append /objects, rather than asking for the object
directory directly
which breaks if GIT_OBJECT_DIRECTORY is set.
I'll reword the commit message to just say that explicitly instead of
the vague "legacy parsing methods" phrase.


> > Introduce `path.objects.absolute` and `path.objects.relative` keys to
> > `git repo info`. This allows tools to discover the object database
> > location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
> > environment variable overrides.
>
> In the context of pluggable ODBs, this proposed key is a little more
> interesting because a non-"files" ODB source in the future may not even
> have a filesystem path to an objects directory. When this becomes more
> relevant, we could just adapt these keys to return an empty string in
> such cases, but it does also make me question whether it is information
> that we should further expose in the first place if it does eventually
> becomes an internal detail of a specific ODB source.
>
> It probably doesn't matter too much, but I've CC'd Patrick for his
> thoughts too.
>


Thanks for looping in Patrick!

That's a fair concern.
My thinking is that the "files" backend is going to be the reality for
the vast majority of
repositories for a long time yet, and scripts asking for path.objects
today are almost certainly
assuming a filesystem-backed ODB anyway (that's the whole reason
they'd want the path).
So I don't think we're locking ourselves into a bad abstraction by
adding it now.

If/when a non-filesystem ODB source becomes real,
we'd have two reasonable options:
return an empty string for that key (same pattern we already use for
path.toplevel/superproject-working-tree when the concept doesn't
apply),
or deprecate the key outright if it turns out to be meaningless in that world.
Either way it doesn't block adding it now, worst case we're removing
or narrowing a key later, not stuck with something actively wrong.



> > +static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
> > +{
> > +     const char *obj_dir = repo_get_object_directory(repo);
> > +
> > +     if (!obj_dir)
> > +             return error(_("unable to get object directory"));
> > +
> > +     format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
>
> For the absolute path, do we actually need to provide the prefix? It
> might make it more clear that its the aboslute path if we just pass ""
> instead?
>


This point was raised in the foundational patch as well.
It won't change the output for sure, so I will pass "" instead.


On Wed, Jul 29, 2026 at 12:30 AM Justin Tobler <jltobler@gmail.com> wrote:
>
> On 26/07/26 04:13PM, K Jayatheerth wrote:
> > External tool integrations and validation systems need a stable way to
> > identify where the repository hooks are stored. Currently, this involves
> > relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
> > manually.
>
> Similar to the comment in the previous patch, "External tool
> intergations and validation systems" seems overly specific IMO. Also,
> "need" is a bit strongly worded as I'm sure its not a requirement for
> every external script/tool.
>


Got it, I will try it to be not overly specific as well.
Maybe something like:
Scripts operating on a repository may want a stable way to identify
where the repository hooks are stored. Currently, this involves
relying on `git rev-parse --git-path hooks` or querying
`core.hooksPath` manually.

Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This allows scripts to discover the active hooks
location, ensuring proper resolution regardless of whether Git is
using the standard `.git/hooks` structure or a custom
`core.hooksPath` setup.


> > Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
> > `git repo info`. This allows tools to discover the active hooks location
> > natively, ensuring proper resolution regardless of whether Git is using
> > the standard `.git/hooks` structure or a custom `core.hooksPath` setup.
>
> Per hooks path documentation:
>
>   The path can be either absolute or relative. A relative path is taken
>   as relative to the directory where the hooks are run.
>
>   ...
>
>   You  can also disable all hooks entirely by setting core.hooksPath to
>   /dev/null.
>
> Should we handle this /dev/null case specially? It looks like:
>
>   $ git -c core.hooksPath=/dev/null rev-parse --git-path hooks
>
> just prints '/dev/null'. I do wonder if this makes much sense though in
> context of the relative path version of this key. From some quick
> testing, it appears the git-rev-parse(1) version of this option always
> prints the absolute path if that is what is configured (it appears to
> ignore --path-format). Maybe we should just special case /dev/null and
> return an empty string? I'm not entirely sure what the best route is
> here though.
>


After thinking about it
I would lean towards not special-casing it. A few reasons:

/dev/null is just a valid (if unusual) value of core.hooksPath as far
as Git is concerned, the field is documented to reflect
whatever core.hooksPath resolves to, and rev-parse --git-path hooks
already treats it as an ordinary path.
If we special-case it to an empty string, we'd be the only place in
Git that treats /dev/null as meaningfully different from any other
hooksPath value.

Empty string is already used by other keys in this series
to mean "this concept doesn't apply here" (no working tree, not a submodule).
Using empty string for "hooks are disabled" would overload that
meaning with something different, "the path exists but you shouldn't
use it"
and a script can't tell the two apart without also knowing the
hooksPath convention, which defeats the purpose of adding a structured
key in the first place.

Any script that's checking for /dev/null already has to know that
convention when
using the existing rev-parse interface, so we're not creating new
surprises, just carrying forward a pre-existing quirk of
core.hooksPath semantics.

For the relative version:
I'll let format_path/relative_path do whatever it already does for a
path that isn't under the prefix
(I'd guess it falls back to printing the absolute path, similar to how
rev-parse seems to ignore --path-format for this case).
That keeps behavior consistent with the existing tool rather than
introducing new special-casing for path.hooks.relative specifically.

I'll add a test covering core.hooksPath=/dev/null to lock in whichever
behavior we land on,
and I can add a doc note under path.hooks.absolute/path.hooks.relative
mentioning that /dev/null is passed through unchanged if that's the
value in use,
similar to how the existing hooksPath docs describe it.
Let me know if you still think empty-string is preferable despite the
above,  happy to go either way once we agree on the reasoning.

Thanks again for the detailed review!

Regards,
- K Jayatheerth

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 0/7] repo: add more path keys to git repo info
  2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
                   ` (8 preceding siblings ...)
  2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-08-06 10:15 ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
                     ` (6 more replies)
  9 siblings, 7 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Series adds keys to git repo info.

Keys output paths of repository components:
* path.toplevel: repository tree.
* path.superproject-root: superproject tree from submodules.
* path.hooks: repository hooks.
* path.index: repository index.
* path.grafts: repository grafts.
* path.git-prefix: prefix offset.

The patch also removes an unused header.

Keys support suffixes for format.
Commits contain documentation and tests.

Changes since v3:
* The prefix member has been shifted from startup_info to repo,
  therefore we now omit the header and use repo->prefix everywhere.
  Development of these patches is now based on the latest branch.

* Since strbuf is NUL-terminated, remove all
  `strbuf_addstr(buf, "");` lines from the patches.

* Add relative-path test cases alongside the existing absolute-path
  test cases wherever we don't use the existing helper.

* Renamed `superproject-working-tree` to `superproject-root` because
  I feel the latter is a bit clearer. That said, I'm happy with
  either name, so if you prefer `superproject-working-tree`, I'm
  perfectly fine reverting it.

* Changed almost all the commit messages to make them not overly
  specific.

* Dropped `path.objects` from this series. During a sync discussion
  with my mentors, we concluded that this key should wait, since the
  object database's on-disk layout is expected to change
  significantly as pluggable ODB backends are introduced.

* Removed `repo->prefix` from the absolute path functions (the
  absolute-path variants now pass "" instead).

* Added a `/dev/null` test case for `core.hooksPath`, guarded against
  MINGW since /dev/null doesn't resolve to a real canonicalizable
  path on Windows.

K Jayatheerth (7):
  repo: add path.toplevel with absolute and relative suffix formatting
  repo: add path.superproject-root with absolute and relative suffixes
  repo: add path.hooks with absolute and relative suffixes
  repo: add path.index with absolute and relative suffixes
  repo: add path.grafts with absolute and relative suffixes
  repo: add path.git-prefix
  repo: remove unused setup.h include

 Documentation/git-repo.adoc |  57 +++++++++++++
 builtin/repo.c              | 137 +++++++++++++++++++++++++++++++-
 t/t1900-repo-info.sh        | 154 +++++++++++++++++++++++++++++++++++-
 3 files changed, 345 insertions(+), 3 deletions(-)

Range-diff against v3:
1:  baed121c74 ! 1:  3880485020 repo: add path.toplevel with absolute and relative suffix formatting
    @@ Commit message
     
         Scripts frequently need to find the root directory of a repository's
         working tree. Currently, this requires using `git rev-parse --show-toplevel`
    -    or inferring it from other path components.
    +    or inferring it from other repository information.
     
         Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
         to `git repo info`. This allows scripts to retrieve the top-level
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +{
     +	const char *work_tree = repo_get_work_tree(repo);
     +
    -+	if (!work_tree) {
    -+		strbuf_addstr(buf, "");
    ++	if (!work_tree)
     +		return 0;
    -+	}
     +
    -+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
    ++	format_path(buf, work_tree, "", PATH_FORMAT_CANONICAL);
     +	return 0;
     +}
     +
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +{
     +	const char *work_tree = repo_get_work_tree(repo);
     +
    -+	if (!work_tree) {
    -+		strbuf_addstr(buf, "");
    ++	if (!work_tree)
     +		return 0;
    -+	}
     +
    -+	format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
    ++	format_path(buf, work_tree, repo->prefix, PATH_FORMAT_RELATIVE);
     +	return 0;
     +}
     +
    @@ t/t1900-repo-info.sh: test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir
     +	)
     +'
     +
    -+test_expect_success 'path.toplevel returns empty in a bare repository' '
    ++test_expect_success 'path.toplevel absolute and relative in a bare repository' '
     +	test_when_finished "rm -rf bare.git" &&
     +	git init --bare bare.git &&
     +	(
     +		cd bare.git &&
    -+		echo "path.toplevel.absolute=" >expect &&
    -+		git repo info path.toplevel.absolute >actual &&
    -+		test_cmp expect actual
    ++
    ++		echo "path.toplevel.absolute=" >expect.abs &&
    ++		git repo info path.toplevel.absolute >actual.abs &&
    ++		test_cmp expect.abs actual.abs &&
    ++
    ++		echo "path.toplevel.relative=" >expect.rel &&
    ++		git repo info path.toplevel.relative >actual.rel &&
    ++		test_cmp expect.rel actual.rel
     +	)
     +'
     +
2:  2f363b6358 ! 2:  1b7b0d286c repo: add path.superproject-working-tree with absolute and relative suffixes
    @@ Metadata
     Author: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
      ## Commit message ##
    -    repo: add path.superproject-working-tree with absolute and relative suffixes
    +    repo: add path.superproject-root with absolute and relative suffixes
     
         Scripts working in multi-repository setups often need to identify the
         top-level working tree of a superproject from within a submodule.
         Currently, this is only exposed via `git rev-parse
         --show-superproject-working-tree`.
     
    -    Introduce `path.superproject-working-tree.absolute` and
    -    `path.superproject-working-tree.relative` keys to `git repo info`.
    +    Introduce `path.superproject-root.absolute` and
    +    `path.superproject-root.relative` keys to `git repo info`.
         This exposes the core submodule context via a scriptable config-like key
         using standard format rules.
     
    @@ Documentation/git-repo.adoc: values that they return:
      `path.gitdir.relative`::
      	The path to the Git repository directory relative to the current working directory.
      
    -+`path.superproject-working-tree.absolute`::
    ++`path.superproject-root.absolute`::
     +	The canonical absolute path to the working tree root of the superproject
     +	if the current repository is an initialized submodule. Outputs an empty
     +	string if not in a submodule.
     +
    -+`path.superproject-working-tree.relative`::
    ++`path.superproject-root.relative`::
     +	The path to the working tree root of the superproject relative to the
     +	current working directory if the current repository is an initialized
     +	submodule. Outputs an empty string if not in a submodule.
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +
     +	if (!get_superproject_working_tree(&superproject)) {
     +		strbuf_release(&superproject);
    -+		strbuf_addstr(buf, "");
     +		return 0;
     +	}
     +
    -+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
    ++	format_path(buf, superproject.buf, "", PATH_FORMAT_CANONICAL);
     +	strbuf_release(&superproject);
     +	return 0;
     +}
     +
    -+static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
    ++static int get_path_superproject_relative(struct repository *repo, struct strbuf *buf)
     +{
     +	struct strbuf superproject = STRBUF_INIT;
     +
     +	if (!get_superproject_working_tree(&superproject)) {
     +		strbuf_release(&superproject);
    -+		strbuf_addstr(buf, "");
     +		return 0;
     +	}
     +
    -+	format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
    ++	format_path(buf, superproject.buf, repo->prefix, PATH_FORMAT_RELATIVE);
     +	strbuf_release(&superproject);
     +	return 0;
     +}
    @@ builtin/repo.c: static const struct repo_info_field repo_info_field[] = {
      	{ "path.commondir.relative", get_path_commondir_relative },
      	{ "path.gitdir.absolute", get_path_gitdir_absolute },
      	{ "path.gitdir.relative", get_path_gitdir_relative },
    -+	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
    -+	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
    ++	{ "path.superproject-root.absolute", get_path_superproject_absolute },
    ++	{ "path.superproject-root.relative", get_path_superproject_relative },
      	{ "path.toplevel.absolute", get_path_toplevel_absolute },
      	{ "path.toplevel.relative", get_path_toplevel_relative },
      	{ "references.format", get_references_format },
    @@ t/t1900-repo-info.sh: test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir
      	'.git' \
      	'GIT_DIR="../.git" && export GIT_DIR'
      
    -+test_expect_success 'path.superproject-working-tree absolute and relative' '
    ++test_expect_success 'path.superproject-root absolute and relative' '
     +	test_when_finished "rm -rf sub super" &&
     +	git init sub &&
     +	test_commit -C sub initial &&
    @@ t/t1900-repo-info.sh: test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir
     +		cd sub &&
     +		ROOT="$(test-tool path-utils real_path ..)" &&
     +
    -+		echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
    -+		git repo info path.superproject-working-tree.absolute >actual.abs &&
    ++		echo "path.superproject-root.absolute=$ROOT" >expect.abs &&
    ++		git repo info path.superproject-root.absolute >actual.abs &&
     +		test_cmp expect.abs actual.abs &&
     +
    -+		echo "path.superproject-working-tree.relative=../" >expect.rel &&
    -+		git repo info path.superproject-working-tree.relative >actual.rel &&
    ++		echo "path.superproject-root.relative=../" >expect.rel &&
    ++		git repo info path.superproject-root.relative >actual.rel &&
     +		test_cmp expect.rel actual.rel
     +	)
     +'
     +
    -+test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
    ++test_expect_success 'path.superproject-root returns empty when not in a submodule' '
     +	test_when_finished "rm -rf repo" &&
     +	git init repo &&
     +	(
     +		cd repo &&
    -+		echo "path.superproject-working-tree.absolute=" >expect &&
    -+		git repo info path.superproject-working-tree.absolute >actual &&
    -+		test_cmp expect actual
    ++
    ++		echo "path.superproject-root.absolute=" >expect.abs &&
    ++		git repo info path.superproject-root.absolute >actual.abs &&
    ++		test_cmp expect.abs actual.abs &&
    ++
    ++		echo "path.superproject-root.relative=" >expect.rel &&
    ++		git repo info path.superproject-root.relative >actual.rel &&
    ++		test_cmp expect.rel actual.rel
     +	)
     +'
     +
4:  e3facc7989 ! 3:  517f621eb0 repo: add path.hooks with absolute and relative suffix formatting
    @@ Metadata
     Author: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
      ## Commit message ##
    -    repo: add path.hooks with absolute and relative suffix formatting
    +    repo: add path.hooks with absolute and relative suffixes
     
    -    External tool integrations and validation systems need a stable way to
    -    identify where the repository hooks are stored. Currently, this involves
    -    relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
    -    manually.
    +    Hooks are an integral part of a repository's configuration and are
    +    commonly used by tooling to automate repository-specific workflows.
    +    Currently, scripts typically retrieve the hooks directory by invoking
    +    `git rev-parse --git-path hooks`.
     
         Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
    -    `git repo info`. This allows tools to discover the active hooks location
    -    natively, ensuring proper resolution regardless of whether Git is using
    -    the standard `.git/hooks` structure or a custom `core.hooksPath` setup.
    +    `git repo info`. This exposes the hooks directory as a scriptable
    +    config-like key using standard format rules, allowing scripts to
    +    retrieve it through the same interface as other repository path
    +    information.
     
         Mentored-by: Justin Tobler <jltobler@gmail.com>
         Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
    @@ Documentation/git-repo.adoc: values that they return:
      
     +`path.hooks.absolute`::
     +	The canonical absolute path to the repository's hooks directory.
    -+	Respects `core.hooksPath` configuration adjustments.
    ++	Respects the `core.hooksPath` configuration. If `core.hooksPath` is
    ++	set to `/dev/null`, that value is returned unchanged.
     +
     +`path.hooks.relative`::
     +	The path to the repository's hooks directory relative to the current
    -+	working directory. Respects `core.hooksPath` configuration adjustments.
    ++	working directory. Respects the `core.hooksPath` configuration.
     +
    - `path.objects.absolute`::
    - 	The canonical absolute path to the repository's object database directory.
    - 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
    + `path.superproject-root.absolute`::
    + 	The canonical absolute path to the working tree root of the superproject
    + 	if the current repository is an initialized submodule. Outputs an empty
     
      ## builtin/repo.c ##
     @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +	struct strbuf hooks_path = STRBUF_INIT;
     +
     +	repo_git_path_replace(repo, &hooks_path, "hooks");
    -+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
    ++	format_path(buf, hooks_path.buf, "", PATH_FORMAT_CANONICAL);
     +	strbuf_release(&hooks_path);
     +	return 0;
     +}
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +	struct strbuf hooks_path = STRBUF_INIT;
     +
     +	repo_git_path_replace(repo, &hooks_path, "hooks");
    -+	format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
    ++	format_path(buf, hooks_path.buf, repo->prefix, PATH_FORMAT_RELATIVE);
     +	strbuf_release(&hooks_path);
     +	return 0;
     +}
     +
    - static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
    + static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
      {
    - 	const char *obj_dir = repo_get_object_directory(repo);
    + 	struct strbuf superproject = STRBUF_INIT;
     @@ builtin/repo.c: static const struct repo_info_field repo_info_field[] = {
      	{ "path.commondir.relative", get_path_commondir_relative },
      	{ "path.gitdir.absolute", get_path_gitdir_absolute },
      	{ "path.gitdir.relative", get_path_gitdir_relative },
     +	{ "path.hooks.absolute", get_path_hooks_absolute },
     +	{ "path.hooks.relative", get_path_hooks_relative },
    - 	{ "path.objects.absolute", get_path_objects_absolute },
    - 	{ "path.objects.relative", get_path_objects_relative },
    - 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
    + 	{ "path.superproject-root.absolute", get_path_superproject_absolute },
    + 	{ "path.superproject-root.relative", get_path_superproject_relative },
    + 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
     
      ## t/t1900-repo-info.sh ##
    +@@ t/t1900-repo-info.sh: test_repo_info_path () {
    + 			cd repo/sub &&
    + 			ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
    + 			eval "$init_command" &&
    +-			echo "path.$field_name.absolute=$ROOT/$expected_dir" >expect &&
    ++			case "$expected_dir" in
    ++			/*) EXPECT_ABS="$expected_dir" ;;
    ++			*) EXPECT_ABS="$ROOT/$expected_dir" ;;
    ++			esac &&
    ++			echo "path.$field_name.absolute=$EXPECT_ABS" >expect &&
    + 			git repo info "path.$field_name.absolute" >actual &&
    + 			test_cmp expect actual
    + 		)
    +@@ t/t1900-repo-info.sh: test_repo_info_path () {
    + 			cd repo/sub &&
    + 			ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
    + 			eval "$init_command" &&
    +-			echo "path.$field_name.relative=../$expected_dir" >expect &&
    ++			case "$expected_dir" in
    ++			/*) EXPECT_REL="$(test-tool path-utils relative_path "$expected_dir" "$PWD")" ;;
    ++			*) EXPECT_REL="../$expected_dir" ;;
    ++			esac &&
    ++			echo "path.$field_name.relative=$EXPECT_REL" >expect &&
    + 			git repo info "path.$field_name.relative" >actual &&
    + 			test_cmp expect actual
    + 		)
     @@ t/t1900-repo-info.sh: test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
      	'.git' \
      	'GIT_DIR="../.git" && export GIT_DIR'
      
    -+test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
    ++test_repo_info_path 'hooks standard' 'hooks' '.git/hooks'
     +
     +test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
     +	'custom-hooks' \
     +	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
     +
    - test_repo_info_path 'objects standard' 'objects' '.git/objects'
    - 
    - test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
    ++# /dev/null is not a real, canonicalizable filesystem path on Windows,
    ++# so path resolution for core.hooksPath=/dev/null cannot be expected to
    ++# produce a literal "/dev/null" the way it does on POSIX systems.
    ++if ! test_have_prereq MINGW
    ++then
    ++	test_repo_info_path 'hooks with core.hooksPath=/dev/null' 'hooks' \
    ++		'/dev/null' \
    ++		'git config core.hooksPath /dev/null'
    ++fi
    ++
    + test_expect_success 'path.superproject-root absolute and relative' '
    + 	test_when_finished "rm -rf sub super" &&
    + 	git init sub &&
5:  ab157b8b49 ! 4:  37d28712de repo: add path.index with absolute and relative suffix formatting
    @@ Metadata
     Author: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
      ## Commit message ##
    -    repo: add path.index with absolute and relative suffix formatting
    +    repo: add path.index with absolute and relative suffixes
     
    -    External script workflows and formatting layers require straightforward
    -    access to the location of the index staging file. Currently, tracking
    -    this necessitates a legacy call to `git rev-parse --git-path index` or
    -    `--show-toplevel` logic abstractions.
    +    The repository index is a fundamental component used by Git and related
    +    tooling to track the working tree state. Scripts that interact with the
    +    index currently retrieve its location by invoking
    +    `git rev-parse --git-path index`.
     
         Introduce `path.index.absolute` and `path.index.relative` keys to
    -    `git repo info`. This allows tooling utilities to discover the active
    -    index context cleanly while scaling transparently with localized
    -    `GIT_INDEX_FILE` environment overrides.
    +    `git repo info`. This exposes the index file location as a scriptable
    +    config-like key using standard format rules, allowing scripts to
    +    retrieve it through the same interface as other repository path
    +    information.
     
         Mentored-by: Justin Tobler <jltobler@gmail.com>
         Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
    @@ Commit message
      ## Documentation/git-repo.adoc ##
     @@ Documentation/git-repo.adoc: values that they return:
      	The path to the repository's hooks directory relative to the current
    - 	working directory. Respects `core.hooksPath` configuration adjustments.
    + 	working directory. Respects the `core.hooksPath` configuration.
      
     +`path.index.absolute`::
     +	The canonical absolute path to the repository's current index file.
    -+	Respects the `GIT_INDEX_FILE` environment override. The returned path
    -+	reflects the configured/default index location regardless of whether the
    -+	repository is bare or whether the file currently exists.
    ++	Respects the `GIT_INDEX_FILE` environment override. Returns the
    ++	configured index path even if the repository is bare or the file does
    ++	not exist.
     +
     +`path.index.relative`::
     +	The path to the repository's current index file relative to the current
     +	working directory. Respects the `GIT_INDEX_FILE` environment override.
    -+	The returned path reflects the configured/default index location regardless
    -+	of whether the repository is bare or whether the file currently exists.
    ++	Returns the configured index path even if the repository is bare or the
    ++	file does not exist.
     +
    - `path.objects.absolute`::
    - 	The canonical absolute path to the repository's object database directory.
    - 	Respects the `GIT_OBJECT_DIRECTORY` environment override.
    + `path.superproject-root.absolute`::
    + 	The canonical absolute path to the working tree root of the superproject
    + 	if the current repository is an initialized submodule. Outputs an empty
     
      ## builtin/repo.c ##
     @@ builtin/repo.c: static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
    @@ builtin/repo.c: static int get_path_hooks_relative(struct repository *repo, stru
     +	if (!index_file)
     +		return error(_("unable to get index file"));
     +
    -+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
    ++	format_path(buf, index_file, "", PATH_FORMAT_CANONICAL);
     +	return 0;
     +}
     +
    @@ builtin/repo.c: static int get_path_hooks_relative(struct repository *repo, stru
     +	if (!index_file)
     +		return error(_("unable to get index file"));
     +
    -+	format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
    ++	format_path(buf, index_file, repo->prefix, PATH_FORMAT_RELATIVE);
     +	return 0;
     +}
     +
    - static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
    + static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
      {
    - 	const char *obj_dir = repo_get_object_directory(repo);
    + 	struct strbuf superproject = STRBUF_INIT;
     @@ builtin/repo.c: static const struct repo_info_field repo_info_field[] = {
      	{ "path.gitdir.relative", get_path_gitdir_relative },
      	{ "path.hooks.absolute", get_path_hooks_absolute },
      	{ "path.hooks.relative", get_path_hooks_relative },
     +	{ "path.index.absolute", get_path_index_absolute },
     +	{ "path.index.relative", get_path_index_relative },
    - 	{ "path.objects.absolute", get_path_objects_absolute },
    - 	{ "path.objects.relative", get_path_objects_relative },
    - 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
    + 	{ "path.superproject-root.absolute", get_path_superproject_absolute },
    + 	{ "path.superproject-root.relative", get_path_superproject_relative },
    + 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
     
      ## t/t1900-repo-info.sh ##
    -@@ t/t1900-repo-info.sh: test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
    - 	'custom-hooks' \
    - 	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
    +@@ t/t1900-repo-info.sh: then
    + 		'git config core.hooksPath /dev/null'
    + fi
      
     +test_repo_info_path 'index standard' 'index' '.git/index'
     +
    @@ t/t1900-repo-info.sh: test_repo_info_path 'hooks with core.hooksPath override' '
     +	)
     +'
     +
    - test_repo_info_path 'objects standard' 'objects' '.git/objects'
    - 
    - test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
    + test_expect_success 'path.superproject-root absolute and relative' '
    + 	test_when_finished "rm -rf sub super" &&
    + 	git init sub &&
6:  d80719367b ! 5:  d88340f5a6 repo: add path.grafts with absolute and relative suffix formatting
    @@ Metadata
     Author: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
      ## Commit message ##
    -    repo: add path.grafts with absolute and relative suffix formatting
    +    repo: add path.grafts with absolute and relative suffixes
     
    -    External toolchains managing specialized history rewrites or legacy
    -    history splices require access to the location of the repository grafts
    -    file. Currently, this requires a legacy call to `git rev-parse --git-path info/grafts`.
    +    The repository grafts file specifies alternate parent relationships for
    +    commits and may be used by repository tooling that needs to inspect or
    +    manage grafts. Scripts currently retrieve its location by invoking
    +    `git rev-parse --git-path info/grafts`.
     
         Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
    -    `git repo info`. This allows scripting layers to query the active grafts
    -    context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
    -    environment variable overrides.
    +    `git repo info`. This exposes the grafts file location as a scriptable
    +    config-like key using standard format rules, allowing scripts to
    +    retrieve it through the same interface as other repository path
    +    information.
     
         Mentored-by: Justin Tobler <jltobler@gmail.com>
         Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
    @@ Documentation/git-repo.adoc: values that they return:
      	The path to the Git repository directory relative to the current working directory.
      
     +`path.grafts.absolute`::
    -+	The canonical absolute path to the repository grafts file.
    -+	Respects the `GIT_GRAFT_FILE` environment override. The path is returned
    -+	regardless of whether the file currently exists on disk.
    ++	The canonical absolute path to the repository's graft file.
    ++	Respects the `GIT_GRAFT_FILE` environment override. The path is
    ++	returned regardless of whether the file currently exists on disk.
     +
     +`path.grafts.relative`::
    -+	The path to the repository grafts file relative to the current working
    -+	directory. Respects the `GIT_GRAFT_FILE` environment override. The path
    -+	is returned regardless of whether the file currently exists on disk.
    ++	The path to the repository's graft file relative to the current
    ++	working directory. Respects the `GIT_GRAFT_FILE` environment
    ++	override. The path is returned regardless of whether the file
    ++	currently exists on disk.
     +
      `path.hooks.absolute`::
      	The canonical absolute path to the repository's hooks directory.
    - 	Respects `core.hooksPath` configuration adjustments.
    + 	Respects the `core.hooksPath` configuration. If `core.hooksPath` is
     
      ## builtin/repo.c ##
     @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +	if (!graft_file)
     +		return error(_("unable to get graft file"));
     +
    -+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
    ++	format_path(buf, graft_file, "", PATH_FORMAT_CANONICAL);
     +	return 0;
     +}
     +
    @@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, str
     +	if (!graft_file)
     +		return error(_("unable to get graft file"));
     +
    -+	format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
    ++	format_path(buf, graft_file, repo->prefix, PATH_FORMAT_RELATIVE);
     +	return 0;
     +}
     +
    @@ t/t1900-repo-info.sh: test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir
     +	'custom-graft-file' \
     +	'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
     +
    - test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
    + test_repo_info_path 'hooks standard' 'hooks' '.git/hooks'
      
      test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
7:  ac6aee77e8 ! 6:  38b19d8bfd repo: add path.git-prefix path key
    @@ Metadata
     Author: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
      ## Commit message ##
    -    repo: add path.git-prefix path key
    +    repo: add path.git-prefix
     
    -    Scripts and command-line prompt integrations frequently need to know their
    -    relative depth inside a repository working tree layout. Currently, this
    -    is retrieved using `git rev-parse --show-prefix`.
    +    Scripts sometimes need the path from the repository's working tree root
    +    to the current working directory. While this information can be derived
    +    through existing Git commands, `git repo info` does not currently expose
    +    it as a scriptable key.
     
    -    Introduce the `path.git-prefix` key to `git repo info`. This mirrors the
    -    prefix location tracking framework as a standalone key, returning the
    -    exact relative path offset complete with a trailing slash, or an empty
    -    string if run directly at the repository working tree root.
    +    Introduce the `path.git-prefix` key to `git repo info`. The key returns
    +    the path from the working tree root to the current working directory,
    +    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>
    @@ Documentation/git-repo.adoc: values that they return:
      	the current working directory.
      
     +`path.git-prefix`::
    -+	The relative path from the top-level directory of the working tree to
    -+	the current working directory (including a trailing slash). Outputs an
    -+	empty string if executed at the root of the working tree.
    ++	The path from the root of the working tree to the current working
    ++	directory. Returns the empty string when the current working directory
    ++	is the root of the working tree.
     +
      `path.gitdir.absolute`::
      	The canonical absolute path to the Git repository directory (the `.git` directory).
    @@ builtin/repo.c: static int get_path_commondir_relative(struct repository *repo,
      	return 0;
      }
      
    -+static int get_path_git_prefix(struct repository *repo UNUSED, struct strbuf *buf)
    ++static int get_path_git_prefix(struct repository *repo, struct strbuf *buf)
     +{
     +	/*
    -+	 * startup_info->prefix is NULL if we are at the working tree root.
    -+	 * We add an empty string to ensure the buffer is cleanly initialized.
    ++	 * repo->prefix is NULL when the current working directory is
    ++	 * the worktree root.
     +	 */
    -+	strbuf_addstr(buf, startup_info->prefix ? startup_info->prefix : "");
    ++	strbuf_addstr(buf, repo->prefix ? repo->prefix : "");
     +	return 0;
     +}
     +
    @@ t/t1900-repo-info.sh: test_repo_info_path 'commondir with only GIT_DIR' 'commond
      	'.git' \
      	'GIT_DIR="../.git" && export GIT_DIR'
      
    -+test_expect_success 'path.git-prefix at root and in a subdirectory' '
    ++test_expect_success 'path.git-prefix at repository root' '
     +	test_when_finished "rm -rf repo" &&
     +	git init repo &&
     +	(
     +		cd repo &&
    ++		echo "path.git-prefix=" >expect &&
    ++		git repo info path.git-prefix >actual &&
    ++		test_cmp expect actual
    ++	)
    ++'
     +
    -+		echo "path.git-prefix=" >expect.root &&
    -+		git repo info path.git-prefix >actual.root &&
    -+		test_cmp expect.root actual.root &&
    -+
    -+		mkdir -p sub/dir &&
    -+		cd sub/dir &&
    -+
    -+		echo "path.git-prefix=sub/dir/" >expect.sub &&
    -+		git repo info path.git-prefix >actual.sub &&
    -+		test_cmp expect.sub actual.sub
    ++test_expect_success 'path.git-prefix in subdirectory' '
    ++	test_when_finished "rm -rf repo" &&
    ++	git init repo &&
    ++	mkdir -p repo/sub/dir &&
    ++	(
    ++		cd repo/sub/dir &&
    ++		echo "path.git-prefix=sub/dir/" >expect &&
    ++		git repo info path.git-prefix >actual &&
    ++		test_cmp expect actual
     +	)
     +'
     +
3:  736c8e0576 ! 7:  f28ee4e169 repo: add path.objects with absolute and relative suffix formatting
    @@ Metadata
     Author: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
      ## Commit message ##
    -    repo: add path.objects with absolute and relative suffix formatting
    +    repo: remove unused setup.h include
     
    -    Tools and deployment hooks frequently query the location of the object
    -    database directory. Currently, this relies on legacy parsing methods or
    -    manually inspecting `git rev-parse --git-path objects`.
    +    The repository prefix is now stored in `struct repository`, so
    +    builtin/repo.c no longer uses any declarations from setup.h.
     
    -    Introduce `path.objects.absolute` and `path.objects.relative` keys to
    -    `git repo info`. This allows tools to discover the object database
    -    location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
    -    environment variable overrides.
    +    Remove the now-unused include.
     
         Mentored-by: Justin Tobler <jltobler@gmail.com>
         Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
         Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
     
    - ## Documentation/git-repo.adoc ##
    -@@ Documentation/git-repo.adoc: values that they return:
    - `path.gitdir.relative`::
    - 	The path to the Git repository directory relative to the current working directory.
    - 
    -+`path.objects.absolute`::
    -+	The canonical absolute path to the repository's object database directory.
    -+	Respects the `GIT_OBJECT_DIRECTORY` environment override.
    -+
    -+`path.objects.relative`::
    -+	The path to the repository's object database directory relative to the
    -+	current working directory. Respects the `GIT_OBJECT_DIRECTORY`
    -+	environment override.
    -+
    - `path.superproject-working-tree.absolute`::
    - 	The canonical absolute path to the working tree root of the superproject
    - 	if the current repository is an initialized submodule. Outputs an empty
    -
      ## builtin/repo.c ##
    -@@ builtin/repo.c: static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
    - 	return 0;
    - }
    - 
    -+static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
    -+{
    -+	const char *obj_dir = repo_get_object_directory(repo);
    -+
    -+	if (!obj_dir)
    -+		return error(_("unable to get object directory"));
    -+
    -+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
    -+	return 0;
    -+}
    -+
    -+static int get_path_objects_relative(struct repository *repo, struct strbuf *buf)
    -+{
    -+	const char *obj_dir = repo_get_object_directory(repo);
    -+
    -+	if (!obj_dir)
    -+		return error(_("unable to get object directory"));
    -+
    -+	format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
    -+	return 0;
    -+}
    -+
    - static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
    - {
    - 	struct strbuf superproject = STRBUF_INIT;
    -@@ builtin/repo.c: static const struct repo_info_field repo_info_field[] = {
    - 	{ "path.commondir.relative", get_path_commondir_relative },
    - 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
    - 	{ "path.gitdir.relative", get_path_gitdir_relative },
    -+	{ "path.objects.absolute", get_path_objects_absolute },
    -+	{ "path.objects.relative", get_path_objects_relative },
    - 	{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
    - 	{ "path.superproject-working-tree.relative", get_path_superproject_relative },
    - 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
    -
    - ## t/t1900-repo-info.sh ##
    -@@ t/t1900-repo-info.sh: test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
    - 	'.git' \
    - 	'GIT_DIR="../.git" && export GIT_DIR'
    - 
    -+test_repo_info_path 'objects standard' 'objects' '.git/objects'
    -+
    -+test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
    -+	'custom-objects' \
    -+	'GIT_OBJECT_DIRECTORY="$ROOT/custom-objects" && export GIT_OBJECT_DIRECTORY &&
    -+	 mkdir -p "$ROOT/custom-objects"'
    -+
    - test_expect_success 'path.superproject-working-tree absolute and relative' '
    - 	test_when_finished "rm -rf sub super" &&
    - 	git init sub &&
    +@@
    + #include "ref-filter.h"
    + #include "refs.h"
    + #include "revision.h"
    +-#include "setup.h"
    + #include "strbuf.h"
    + #include "string-list.h"
    + #include "shallow.h"
-- 
2.55.GIT

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 1/7] repo: add path.toplevel with absolute and relative suffix formatting
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 2/7] repo: add path.superproject-root with absolute and relative suffixes K Jayatheerth
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Scripts frequently need to find the root directory of a repository's
working tree. Currently, this requires using `git rev-parse --show-toplevel`
or inferring it from other repository information.

Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
to `git repo info`. This allows scripts to retrieve the top-level
working tree path in a predictable, strictly formatted manner without
relying on `rev-parse`.

If requested in a bare repository where no working tree exists, the
command returns an empty string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..e34abe5fea 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.toplevel.absolute`::
+	The canonical absolute path to the top-level directory of the
+	repository's working tree. Outputs an empty string if the repository
+	is bare.
+
+`path.toplevel.relative`::
+	The path to the top-level directory of the repository's working
+	tree relative to the current working directory. Outputs an empty
+	string if the repository is bare.
+
 `references.format`::
 	The reference storage format. The valid values are:
 +
diff --git a/builtin/repo.c b/builtin/repo.c
index 84e012f83f..c31e9cfa70 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -121,6 +121,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree)
+		return 0;
+
+	format_path(buf, work_tree, "", PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *work_tree = repo_get_work_tree(repo);
+
+	if (!work_tree)
+		return 0;
+
+	format_path(buf, work_tree, repo->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_references_format(struct repository *repo, struct strbuf *buf)
 {
 	strbuf_addstr(buf,
@@ -137,6 +159,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.toplevel.absolute", get_path_toplevel_absolute },
+	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
 };
 
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index c85d390f43..9417d1ab65 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,4 +213,39 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.toplevel absolute and relative' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		mkdir -p repo/sub &&
+		cd repo/sub &&
+
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.toplevel.absolute=$ROOT" >expect.abs &&
+		git repo info path.toplevel.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.toplevel.relative=../" >expect.rel &&
+		git repo info path.toplevel.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.toplevel absolute and relative in a bare repository' '
+	test_when_finished "rm -rf bare.git" &&
+	git init --bare bare.git &&
+	(
+		cd bare.git &&
+
+		echo "path.toplevel.absolute=" >expect.abs &&
+		git repo info path.toplevel.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.toplevel.relative=" >expect.rel &&
+		git repo info path.toplevel.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
 test_done
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 2/7] repo: add path.superproject-root with absolute and relative suffixes
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 3/7] repo: add path.hooks " K Jayatheerth
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Scripts working in multi-repository setups often need to identify the
top-level working tree of a superproject from within a submodule.
Currently, this is only exposed via `git rev-parse
--show-superproject-working-tree`.

Introduce `path.superproject-root.absolute` and
`path.superproject-root.relative` keys to `git repo info`.
This exposes the core submodule context via a scriptable config-like key
using standard format rules.

If requested when not inside a submodule, the command returns an empty
string.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 10 ++++++++++
 builtin/repo.c              | 31 +++++++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 39 +++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e34abe5fea..e524a07f53 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.superproject-root.absolute`::
+	The canonical absolute path to the working tree root of the superproject
+	if the current repository is an initialized submodule. Outputs an empty
+	string if not in a submodule.
+
+`path.superproject-root.relative`::
+	The path to the working tree root of the superproject relative to the
+	current working directory if the current repository is an initialized
+	submodule. Outputs an empty string if not in a submodule.
+
 `path.toplevel.absolute`::
 	The canonical absolute path to the top-level directory of the
 	repository's working tree. Outputs an empty string if the repository
diff --git a/builtin/repo.c b/builtin/repo.c
index c31e9cfa70..47c4fce293 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -18,6 +18,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
+#include "submodule.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "utf8.h"
@@ -121,6 +122,34 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, "", PATH_FORMAT_CANONICAL);
+	strbuf_release(&superproject);
+	return 0;
+}
+
+static int get_path_superproject_relative(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf superproject = STRBUF_INIT;
+
+	if (!get_superproject_working_tree(&superproject)) {
+		strbuf_release(&superproject);
+		return 0;
+	}
+
+	format_path(buf, superproject.buf, repo->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&superproject);
+	return 0;
+}
+
 static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *work_tree = repo_get_work_tree(repo);
@@ -159,6 +188,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.superproject-root.absolute", get_path_superproject_absolute },
+	{ "path.superproject-root.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
 	{ "path.toplevel.relative", get_path_toplevel_relative },
 	{ "references.format", get_references_format },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 9417d1ab65..eec576a1d9 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,45 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.superproject-root absolute and relative' '
+	test_when_finished "rm -rf sub super" &&
+	git init sub &&
+	test_commit -C sub initial &&
+	git init super &&
+	(
+		cd super &&
+		git -c protocol.file.allow=always submodule add "../sub" sub &&
+		git commit -m "add submodule" &&
+
+		cd sub &&
+		ROOT="$(test-tool path-utils real_path ..)" &&
+
+		echo "path.superproject-root.absolute=$ROOT" >expect.abs &&
+		git repo info path.superproject-root.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.superproject-root.relative=../" >expect.rel &&
+		git repo info path.superproject-root.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
+test_expect_success 'path.superproject-root returns empty when not in a submodule' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+
+		echo "path.superproject-root.absolute=" >expect.abs &&
+		git repo info path.superproject-root.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.superproject-root.relative=" >expect.rel &&
+		git repo info path.superproject-root.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
 test_expect_success 'path.toplevel absolute and relative' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 3/7] repo: add path.hooks with absolute and relative suffixes
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 2/7] repo: add path.superproject-root with absolute and relative suffixes K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 4/7] repo: add path.index " K Jayatheerth
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Hooks are an integral part of a repository's configuration and are
commonly used by tooling to automate repository-specific workflows.
Currently, scripts typically retrieve the hooks directory by invoking
`git rev-parse --git-path hooks`.

Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This exposes the hooks directory as a scriptable
config-like key using standard format rules, allowing scripts to
retrieve it through the same interface as other repository path
information.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc |  9 +++++++++
 builtin/repo.c              | 22 ++++++++++++++++++++++
 t/t1900-repo-info.sh        | 28 ++++++++++++++++++++++++++--
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e524a07f53..20836cf8f6 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,15 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.hooks.absolute`::
+	The canonical absolute path to the repository's hooks directory.
+	Respects the `core.hooksPath` configuration. If `core.hooksPath` is
+	set to `/dev/null`, that value is returned unchanged.
+
+`path.hooks.relative`::
+	The path to the repository's hooks directory relative to the current
+	working directory. Respects the `core.hooksPath` configuration.
+
 `path.superproject-root.absolute`::
 	The canonical absolute path to the working tree root of the superproject
 	if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index 47c4fce293..d7c451a771 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,26 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, "", PATH_FORMAT_CANONICAL);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
+static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
+{
+	struct strbuf hooks_path = STRBUF_INIT;
+
+	repo_git_path_replace(repo, &hooks_path, "hooks");
+	format_path(buf, hooks_path.buf, repo->prefix, PATH_FORMAT_RELATIVE);
+	strbuf_release(&hooks_path);
+	return 0;
+}
+
 static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
 {
 	struct strbuf superproject = STRBUF_INIT;
@@ -188,6 +208,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.hooks.absolute", get_path_hooks_absolute },
+	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.superproject-root.absolute", get_path_superproject_absolute },
 	{ "path.superproject-root.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index eec576a1d9..1da5db4942 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -174,7 +174,11 @@ test_repo_info_path () {
 			cd repo/sub &&
 			ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
 			eval "$init_command" &&
-			echo "path.$field_name.absolute=$ROOT/$expected_dir" >expect &&
+			case "$expected_dir" in
+			/*) EXPECT_ABS="$expected_dir" ;;
+			*) EXPECT_ABS="$ROOT/$expected_dir" ;;
+			esac &&
+			echo "path.$field_name.absolute=$EXPECT_ABS" >expect &&
 			git repo info "path.$field_name.absolute" >actual &&
 			test_cmp expect actual
 		)
@@ -188,7 +192,11 @@ test_repo_info_path () {
 			cd repo/sub &&
 			ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
 			eval "$init_command" &&
-			echo "path.$field_name.relative=../$expected_dir" >expect &&
+			case "$expected_dir" in
+			/*) EXPECT_REL="$(test-tool path-utils relative_path "$expected_dir" "$PWD")" ;;
+			*) EXPECT_REL="../$expected_dir" ;;
+			esac &&
+			echo "path.$field_name.relative=$EXPECT_REL" >expect &&
 			git repo info "path.$field_name.relative" >actual &&
 			test_cmp expect actual
 		)
@@ -213,6 +221,22 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'hooks standard' 'hooks' '.git/hooks'
+
+test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
+	'custom-hooks' \
+	'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+
+# /dev/null is not a real, canonicalizable filesystem path on Windows,
+# so path resolution for core.hooksPath=/dev/null cannot be expected to
+# produce a literal "/dev/null" the way it does on POSIX systems.
+if ! test_have_prereq MINGW
+then
+	test_repo_info_path 'hooks with core.hooksPath=/dev/null' 'hooks' \
+		'/dev/null' \
+		'git config core.hooksPath /dev/null'
+fi
+
 test_expect_success 'path.superproject-root absolute and relative' '
 	test_when_finished "rm -rf sub super" &&
 	git init sub &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 4/7] repo: add path.index with absolute and relative suffixes
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
                     ` (2 preceding siblings ...)
  2026-08-06 10:15   ` [GSoC PATCH v4 3/7] repo: add path.hooks " K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 5/7] repo: add path.grafts " K Jayatheerth
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

The repository index is a fundamental component used by Git and related
tooling to track the working tree state. Scripts that interact with the
index currently retrieve its location by invoking
`git rev-parse --git-path index`.

Introduce `path.index.absolute` and `path.index.relative` keys to
`git repo info`. This exposes the index file location as a scriptable
config-like key using standard format rules, allowing scripts to
retrieve it through the same interface as other repository path
information.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 12 ++++++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        | 23 +++++++++++++++++++++++
 3 files changed, 59 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 20836cf8f6..08ef47750c 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -128,6 +128,18 @@ values that they return:
 	The path to the repository's hooks directory relative to the current
 	working directory. Respects the `core.hooksPath` configuration.
 
+`path.index.absolute`::
+	The canonical absolute path to the repository's current index file.
+	Respects the `GIT_INDEX_FILE` environment override. Returns the
+	configured index path even if the repository is bare or the file does
+	not exist.
+
+`path.index.relative`::
+	The path to the repository's current index file relative to the current
+	working directory. Respects the `GIT_INDEX_FILE` environment override.
+	Returns the configured index path even if the repository is bare or the
+	file does not exist.
+
 `path.superproject-root.absolute`::
 	The canonical absolute path to the working tree root of the superproject
 	if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index d7c451a771..2a15327094 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -142,6 +142,28 @@ static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_index_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, "", PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_index_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *index_file = repo_get_index_file(repo);
+
+	if (!index_file)
+		return error(_("unable to get index file"));
+
+	format_path(buf, index_file, repo->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
 {
 	struct strbuf superproject = STRBUF_INIT;
@@ -210,6 +232,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
+	{ "path.index.absolute", get_path_index_absolute },
+	{ "path.index.relative", get_path_index_relative },
 	{ "path.superproject-root.absolute", get_path_superproject_absolute },
 	{ "path.superproject-root.relative", get_path_superproject_relative },
 	{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 1da5db4942..431a4842d4 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -237,6 +237,29 @@ then
 		'git config core.hooksPath /dev/null'
 fi
 
+test_repo_info_path 'index standard' 'index' '.git/index'
+
+test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
+	'custom-index-file' \
+	'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
+
+test_expect_success 'path.index in a bare repository returns default index location' '
+	test_when_finished "rm -rf bare.git" &&
+	git init --bare bare.git &&
+	(
+		cd bare.git &&
+		ROOT="$(test-tool path-utils real_path .)" &&
+
+		echo "path.index.absolute=$ROOT/index" >expect.abs &&
+		git repo info path.index.absolute >actual.abs &&
+		test_cmp expect.abs actual.abs &&
+
+		echo "path.index.relative=index" >expect.rel &&
+		git repo info path.index.relative >actual.rel &&
+		test_cmp expect.rel actual.rel
+	)
+'
+
 test_expect_success 'path.superproject-root absolute and relative' '
 	test_when_finished "rm -rf sub super" &&
 	git init sub &&
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 5/7] repo: add path.grafts with absolute and relative suffixes
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
                     ` (3 preceding siblings ...)
  2026-08-06 10:15   ` [GSoC PATCH v4 4/7] repo: add path.index " K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 6/7] repo: add path.git-prefix K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 7/7] repo: remove unused setup.h include K Jayatheerth
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

The repository grafts file specifies alternate parent relationships for
commits and may be used by repository tooling that needs to inspect or
manage grafts. Scripts currently retrieve its location by invoking
`git rev-parse --git-path info/grafts`.

Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
`git repo info`. This exposes the grafts file location as a scriptable
config-like key using standard format rules, allowing scripts to
retrieve it through the same interface as other repository path
information.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 Documentation/git-repo.adoc | 11 +++++++++++
 builtin/repo.c              | 24 ++++++++++++++++++++++++
 t/t1900-repo-info.sh        |  6 ++++++
 3 files changed, 41 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 08ef47750c..868ab0ed9f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,17 @@ values that they return:
 `path.gitdir.relative`::
 	The path to the Git repository directory relative to the current working directory.
 
+`path.grafts.absolute`::
+	The canonical absolute path to the repository's graft file.
+	Respects the `GIT_GRAFT_FILE` environment override. The path is
+	returned regardless of whether the file currently exists on disk.
+
+`path.grafts.relative`::
+	The path to the repository's graft file relative to the current
+	working directory. Respects the `GIT_GRAFT_FILE` environment
+	override. The path is returned regardless of whether the file
+	currently exists on disk.
+
 `path.hooks.absolute`::
 	The canonical absolute path to the repository's hooks directory.
 	Respects the `core.hooksPath` configuration. If `core.hooksPath` is
diff --git a/builtin/repo.c b/builtin/repo.c
index 2a15327094..779240109d 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
 	return 0;
 }
 
+static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, "", PATH_FORMAT_CANONICAL);
+	return 0;
+}
+
+static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
+{
+	const char *graft_file = repo_get_graft_file(repo);
+
+	if (!graft_file)
+		return error(_("unable to get graft file"));
+
+	format_path(buf, graft_file, repo->prefix, PATH_FORMAT_RELATIVE);
+	return 0;
+}
+
 static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
 {
 	struct strbuf hooks_path = STRBUF_INIT;
@@ -230,6 +252,8 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "path.commondir.relative", get_path_commondir_relative },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
+	{ "path.grafts.absolute", get_path_grafts_absolute },
+	{ "path.grafts.relative", get_path_grafts_relative },
 	{ "path.hooks.absolute", get_path_hooks_absolute },
 	{ "path.hooks.relative", get_path_hooks_relative },
 	{ "path.index.absolute", get_path_index_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 431a4842d4..adc4a92487 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -221,6 +221,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
+
+test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
+	'custom-graft-file' \
+	'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
+
 test_repo_info_path 'hooks standard' 'hooks' '.git/hooks'
 
 test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 6/7] repo: add path.git-prefix
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
                     ` (4 preceding siblings ...)
  2026-08-06 10:15   ` [GSoC PATCH v4 5/7] repo: add path.grafts " K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  2026-08-06 10:15   ` [GSoC PATCH v4 7/7] repo: remove unused setup.h include K Jayatheerth
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

Scripts sometimes need the path from the repository's working tree root
to the current working directory. While this information can be derived
through existing Git commands, `git repo info` does not currently expose
it as a scriptable key.

Introduce the `path.git-prefix` key to `git repo info`. The key returns
the path from the working tree root to the current working directory,
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>
---
 Documentation/git-repo.adoc |  5 +++++
 builtin/repo.c              | 11 +++++++++++
 t/t1900-repo-info.sh        | 23 +++++++++++++++++++++++
 3 files changed, 39 insertions(+)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 868ab0ed9f..fb5aceae8f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,11 @@ values that they return:
 	The path to the Git repository's common directory relative to
 	the current working directory.
 
+`path.git-prefix`::
+	The path from the root of the working tree to the current working
+	directory. Returns the empty string when the current working directory
+	is the root of the working tree.
+
 `path.gitdir.absolute`::
 	The canonical absolute path to the Git repository directory (the `.git` directory).
 
diff --git a/builtin/repo.c b/builtin/repo.c
index 779240109d..c0f99b6869 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -100,6 +100,16 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
 	return 0;
 }
 
+static int get_path_git_prefix(struct repository *repo, struct strbuf *buf)
+{
+	/*
+	 * repo->prefix is NULL when the current working directory is
+	 * the worktree root.
+	 */
+	strbuf_addstr(buf, repo->prefix ? repo->prefix : "");
+	return 0;
+}
+
 static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
 {
 	const char *git_dir = repo_get_git_dir(repo);
@@ -250,6 +260,7 @@ static const struct repo_info_field repo_info_field[] = {
 	{ "object.format", get_object_format },
 	{ "path.commondir.absolute", get_path_commondir_absolute },
 	{ "path.commondir.relative", get_path_commondir_relative },
+	{ "path.git-prefix", get_path_git_prefix },
 	{ "path.gitdir.absolute", get_path_gitdir_absolute },
 	{ "path.gitdir.relative", get_path_gitdir_relative },
 	{ "path.grafts.absolute", get_path_grafts_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index adc4a92487..b689445b7a 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -215,6 +215,29 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
 	'.git' \
 	'GIT_DIR="../.git" && export GIT_DIR'
 
+test_expect_success 'path.git-prefix at repository root' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo "path.git-prefix=" >expect &&
+		git repo info path.git-prefix >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'path.git-prefix in subdirectory' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	mkdir -p repo/sub/dir &&
+	(
+		cd repo/sub/dir &&
+		echo "path.git-prefix=sub/dir/" >expect &&
+		git repo info path.git-prefix >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_repo_info_path 'gitdir standard' 'gitdir' '.git'
 
 test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
-- 
2.55.GIT


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [GSoC PATCH v4 7/7] repo: remove unused setup.h include
  2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
                     ` (5 preceding siblings ...)
  2026-08-06 10:15   ` [GSoC PATCH v4 6/7] repo: add path.git-prefix K Jayatheerth
@ 2026-08-06 10:15   ` K Jayatheerth
  6 siblings, 0 replies; 51+ messages in thread
From: K Jayatheerth @ 2026-08-06 10:15 UTC (permalink / raw)
  To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro

The repository prefix is now stored in `struct repository`, so
builtin/repo.c no longer uses any declarations from setup.h.

Remove the now-unused include.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 builtin/repo.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/builtin/repo.c b/builtin/repo.c
index c0f99b6869..8e9f6296b8 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -14,7 +14,6 @@
 #include "ref-filter.h"
 #include "refs.h"
 #include "revision.h"
-#include "setup.h"
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
-- 
2.55.GIT

^ permalink raw reply related	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2026-08-06 10:26 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16  1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 4/7] repo: add path.hooks " K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 5/7] repo: add path.index " K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 6/7] repo: add path.grafts " K Jayatheerth
2026-07-16  1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
2026-07-16  3:23   ` Junio C Hamano
2026-07-16 15:36     ` K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-17 13:30   ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
2026-07-17 13:30   ` [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
2026-07-17 13:30   ` [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
2026-07-17 13:30   ` [GSoC Patch v2 4/7] repo: add path.hooks " K Jayatheerth
2026-07-17 13:30   ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
2026-07-20  0:35     ` Lucas Seiki Oshiro
2026-07-24 17:49       ` K Jayatheerth
2026-07-24 19:21         ` Junio C Hamano
2026-07-17 13:30   ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
2026-07-20  0:20     ` Lucas Seiki Oshiro
2026-07-20  4:01       ` Junio C Hamano
2026-07-21  2:19         ` K Jayatheerth
2026-07-17 13:30   ` [GSoC Patch v2 7/7] repo: add path.git-prefix path key K Jayatheerth
2026-07-26 10:43 ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-26 10:43   ` [PATCH v3 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
2026-07-27  8:45     ` Junio C Hamano
2026-07-28  1:21       ` K Jayatheerth
2026-07-28 16:36     ` Justin Tobler
2026-07-29 16:36       ` K Jayatheerth
2026-07-26 10:43   ` [PATCH v3 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
2026-07-28 16:43     ` Justin Tobler
2026-07-26 10:43   ` [PATCH v3 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
2026-07-28 17:12     ` Justin Tobler
2026-07-26 10:43   ` [PATCH v3 4/7] repo: add path.hooks " K Jayatheerth
2026-07-28 19:00     ` Justin Tobler
2026-07-26 10:43   ` [PATCH v3 5/7] repo: add path.index " K Jayatheerth
2026-07-26 10:43   ` [PATCH v3 6/7] repo: add path.grafts " K Jayatheerth
2026-07-26 10:43   ` [PATCH v3 7/7] repo: add path.git-prefix path key K Jayatheerth
2026-07-26 16:29   ` [GSoC Patch v3 0/7] repo: add more path keys to git repo info Junio C Hamano
2026-07-26 17:00     ` K Jayatheerth
2026-07-27  0:57     ` Lucas Seiki Oshiro
2026-07-27  5:55       ` Junio C Hamano
2026-08-06 10:15 ` [GSoC PATCH v4 " K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 2/7] repo: add path.superproject-root with absolute and relative suffixes K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 3/7] repo: add path.hooks " K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 4/7] repo: add path.index " K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 5/7] repo: add path.grafts " K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 6/7] repo: add path.git-prefix K Jayatheerth
2026-08-06 10:15   ` [GSoC PATCH v4 7/7] repo: remove unused setup.h include K Jayatheerth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox