]> git.ipfire.org Git - thirdparty/git.git/commitdiff
repo: add path.commondir with absolute and relative suffix formatting
authorK Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Wed, 24 Jun 2026 03:37:47 +0000 (09:07 +0530)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Jun 2026 04:15:52 +0000 (21:15 -0700)
Scripts working with worktree setups need a reliable way to discover
the common directory, which diverges from the git directory when
multiple worktrees are in use. There is no way to retrieve this path
from git repo info today.

Introduce path.commondir.absolute and path.commondir.relative keys.
Exposing explicit format variants rather than a single key with a
default avoids ambiguity for scripts that require predictable output.

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>
Documentation/git-repo.adoc
builtin/repo.c
t/t1900-repo-info.sh

index 42262c198347e55659e8584113fa102c1571b0e6..890c34051da8de5723a1ba7648bca2d5a0b18b18 100644 (file)
@@ -104,6 +104,15 @@ values that they return:
 `object.format`::
        The object format (hash algorithm) used in the repository.
 
+`path.commondir.absolute`::
+       The canonical absolute path to the Git repository's common
+       directory (the shared `.git` directory containing objects,
+       refs, and global configuration).
+
+`path.commondir.relative`::
+       The path to the Git repository's common directory relative to
+       the current working directory.
+
 `references.format`::
        The reference storage format. The valid values are:
 +
index 71a5c1c29c05fe4b285abe9cf313e20f555247ef..4c3fbc26b967cf060f32d200a7ef4678e3bc14d6 100644 (file)
@@ -7,12 +7,14 @@
 #include "hex.h"
 #include "odb.h"
 #include "parse-options.h"
+#include "path.h"
 #include "path-walk.h"
 #include "progress.h"
 #include "quote.h"
 #include "ref-filter.h"
 #include "refs.h"
 #include "revision.h"
+#include "setup.h"
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
@@ -75,6 +77,28 @@ static int get_object_format(struct repository *repo, struct strbuf *buf)
        return 0;
 }
 
+static int get_path_commondir_absolute(struct repository *repo, struct strbuf *buf)
+{
+       const char *common_dir = repo_get_common_dir(repo);
+
+       if (!common_dir)
+               return error(_("unable to get common directory"));
+
+       format_path(buf, common_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+       return 0;
+}
+
+static int get_path_commondir_relative(struct repository *repo, struct strbuf *buf)
+{
+       const char *common_dir = repo_get_common_dir(repo);
+
+       if (!common_dir)
+               return error(_("unable to get common directory"));
+
+       format_path(buf, common_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+       return 0;
+}
+
 static int get_references_format(struct repository *repo, struct strbuf *buf)
 {
        strbuf_addstr(buf,
@@ -87,6 +111,8 @@ static const struct repo_info_field repo_info_field[] = {
        { "layout.bare", get_layout_bare },
        { "layout.shallow", get_layout_shallow },
        { "object.format", get_object_format },
+       { "path.commondir.absolute", get_path_commondir_absolute },
+       { "path.commondir.relative", get_path_commondir_relative },
        { "references.format", get_references_format },
 };
 
index 39bb77dda0c327951a59778cfbaae7dfd488ebf9..09158d29f927a4e8e79a17399aabe8e8899eca8a 100755 (executable)
@@ -155,4 +155,56 @@ test_expect_success 'git repo info -h shows only repo info usage' '
        test_grep ! "git repo structure" actual
 '
 
+# Helper function to test path keys in both absolute and relative formats.
+# $1: label for the test
+# $2: field_name (e.g., commondir)
+# $3: expected_dir (the directory name, e.g., .git or custom-common)
+# $4: init_command (extra setup like exporting env vars)
+test_repo_info_path () {
+       label=$1
+       field_name=$2
+       expected_dir=$3
+       init_command=$4
+
+       test_expect_success "absolute: $label" '
+               test_when_finished "rm -rf repo" &&
+               git init repo &&
+               (
+                       mkdir -p repo/sub &&
+                       cd repo/sub &&
+                       ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
+                       eval "$init_command" &&
+                       echo "path.$field_name.absolute=$ROOT/$expected_dir" >expect &&
+                       git repo info "path.$field_name.absolute" >actual &&
+                       test_cmp expect actual
+               )
+       '
+
+       test_expect_success "relative: $label" '
+               test_when_finished "rm -rf repo" &&
+               git init repo &&
+               (
+                       mkdir -p repo/sub &&
+                       cd repo/sub &&
+                       ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
+                       eval "$init_command" &&
+                       echo "path.$field_name.relative=../$expected_dir" >expect &&
+                       git repo info "path.$field_name.relative" >actual &&
+                       test_cmp expect actual
+               )
+       '
+}
+
+test_repo_info_path 'commondir standard' 'commondir' '.git'
+
+test_repo_info_path 'commondir with GIT_COMMON_DIR and GIT_DIR' 'commondir' \
+       'custom-common' \
+       'GIT_COMMON_DIR="$ROOT/custom-common" && export GIT_COMMON_DIR &&
+        GIT_DIR="../.git" && export GIT_DIR &&
+        git init --bare "$ROOT/custom-common"'
+
+test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
+       '.git' \
+       'GIT_DIR="../.git" && export GIT_DIR'
+
 test_done