Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions lib/core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,27 @@
declare _ctx_repo_root _ctx_base_dir _ctx_prefix
declare _ctx_is_main _ctx_worktree_path _ctx_branch

# Discover the root of the current git repository
# Returns: absolute path to repo root
# Discover the root of the main git repository
# Works correctly from both the main repo and from inside worktrees.
# Returns: absolute path to main repo root
# Exit code: 0 on success, 1 if not in a git repo
discover_repo_root() {
local root
root=$(git rev-parse --show-toplevel 2>/dev/null)
local root git_common_dir
git_common_dir=$(git rev-parse --git-common-dir 2>/dev/null)

if [ -z "$git_common_dir" ]; then
log_error "Not in a git repository"
return 1
fi

# --git-common-dir returns:
# ".git" (relative) when in the main repo
# "/absolute/path/to/repo/.git" when in a worktree
if [ "$git_common_dir" = ".git" ]; then
root=$(git rev-parse --show-toplevel 2>/dev/null)
else
root="${git_common_dir%/.git}"
fi

if [ -z "$root" ]; then
log_error "Not in a git repository"
Expand Down
7 changes: 7 additions & 0 deletions tests/cmd_go.bats
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,10 @@ teardown() {
# stderr should contain human-readable info
[[ "$stderr" == *"Worktree"* ]] || [[ "$stderr" == *"Branch"* ]]
}

@test "cmd_go 1 from inside a worktree resolves to main repo" {
cd "$TEST_WORKTREES_DIR/go-test"
run cmd_go 1
[ "$status" -eq 0 ]
[[ "$output" == *"$TEST_REPO"* ]]
}
19 changes: 19 additions & 0 deletions tests/cmd_list.bats
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,22 @@ teardown() {
[[ "$output" == *"BRANCH"* ]]
[[ "$output" == *"PATH"* ]]
}

@test "cmd_list from inside a worktree shows all worktrees" {
create_test_worktree "wt-inside"
cd "$TEST_WORKTREES_DIR/wt-inside"
run cmd_list
[ "$status" -eq 0 ]
[[ "$output" == *"[main repo]"* ]]
[[ "$output" == *"wt-inside"* ]]
[[ "$output" == *"$TEST_REPO"* ]]
}

@test "cmd_list --porcelain from inside a worktree includes main repo" {
create_test_worktree "wt-porcelain"
cd "$TEST_WORKTREES_DIR/wt-porcelain"
local output
output=$(cmd_list --porcelain)
[[ "$output" == *"$TEST_REPO"* ]]
[[ "$output" == *"wt-porcelain"* ]]
}
20 changes: 20 additions & 0 deletions tests/core_resolve_target.bats
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,23 @@ teardown() {
run resolve_worktree "nope" "$TEST_REPO" "$TEST_WORKTREES_DIR" ""
[ "$status" -eq 1 ]
}

# ── discover_repo_root from worktree ──────────────────────────────────────────

@test "discover_repo_root returns main repo root when called from a worktree" {
create_test_worktree "inside-wt"
cd "$TEST_WORKTREES_DIR/inside-wt"
local root expected
root=$(discover_repo_root)
# Resolve symlinks (macOS: /var -> /private/var) for comparison
expected=$(cd "$TEST_REPO" && pwd -P)
[ "$root" = "$expected" ]
}

@test "discover_repo_root returns main repo root when called from main repo" {
cd "$TEST_REPO"
local root expected
root=$(discover_repo_root)
expected=$(pwd -P)
[ "$root" = "$expected" ]
}