repo: add path.grafts with absolute and relative suffix formatting

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> Signed-off-by: Junio C Hamano <gitster@pobox.com>

K Jayatheerth committed Jul 26, 2026 at 16:13 UTC b93d827053a216a02d7d907c1cdf09b38e8b54bb
3 files changed +40
Documentation/git-repo.adoc
+10
@@ -119,6 +119,16 @@ values that they return:
119 `path.gitdir.relative`::
120 The path to the Git repository directory relative to the current working directory.
121
122 +`path.grafts.absolute`::
123 + The canonical absolute path to the repository grafts file.
124 + Respects the `GIT_GRAFT_FILE` environment override. The path is returned
125 + regardless of whether the file currently exists on disk.
126 +
127 +`path.grafts.relative`::
128 + The path to the repository grafts file relative to the current working
129 + directory. Respects the `GIT_GRAFT_FILE` environment override. The path
130 + is returned regardless of whether the file currently exists on disk.
131 +
132 `path.hooks.absolute`::
133 The canonical absolute path to the repository's hooks directory.
134 Respects `core.hooksPath` configuration adjustments.
builtin/repo.c
+24
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
122 return 0;
123 }
124
125 +static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
126 +{
127 + const char *graft_file = repo_get_graft_file(repo);
128 +
129 + if (!graft_file)
130 + return error(_("unable to get graft file"));
131 +
132 + format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
133 + return 0;
134 +}
135 +
136 +static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
137 +{
138 + const char *graft_file = repo_get_graft_file(repo);
139 +
140 + if (!graft_file)
141 + return error(_("unable to get graft file"));
142 +
143 + format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
144 + return 0;
145 +}
146 +
147 static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
148 {
149 struct strbuf hooks_path = STRBUF_INIT;
@@ -258,6 +280,8 @@ static const struct repo_info_field repo_info_field[] = {
280 { "path.commondir.relative", get_path_commondir_relative },
281 { "path.gitdir.absolute", get_path_gitdir_absolute },
282 { "path.gitdir.relative", get_path_gitdir_relative },
283 + { "path.grafts.absolute", get_path_grafts_absolute },
284 + { "path.grafts.relative", get_path_grafts_relative },
285 { "path.hooks.absolute", get_path_hooks_absolute },
286 { "path.hooks.relative", get_path_hooks_relative },
287 { "path.index.absolute", get_path_index_absolute },
t/t1900-repo-info.sh
+6
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
213 '.git' \
214 'GIT_DIR="../.git" && export GIT_DIR'
215
216 +test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
217 +
218 +test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
219 + 'custom-graft-file' \
220 + 'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
221 +
222 test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
223
224 test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \