mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-28 10:15:32 -05:00
git finds a repo by looking for a .git in the directory a command runs
in. Lazygit runs its commands in the work tree, so that normally works —
but not when the git dir lives somewhere else entirely, which is what
core.worktree and --work-tree are for. Lazygit chdir'd into such a work
tree and then ran commands that couldn't see any repo from there, so
opening a repo with core.worktree set panicked on startup. It only
worked with --git-dir because that leaves GIT_DIR in the environment for
every command to inherit.
Work out at startup whether git can find the repo from its work tree,
and when it can't, put GIT_DIR and GIT_WORK_TREE on every command the
repo's builder produces. As with the working directory the builder pins
(527124d0e0), these also go into the process env — subprocesses don't
come through the builder — but the commands don't read them from there,
because the process env belongs to whichever repo we have switched to
since.
Working out whether git can find the repo means asking git, rather than
reading the .git file, whose contents can spell the same directory
differently than git does. The extra query is skipped for a repo whose
git dir is simply its .git directory, which is nearly all of them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
62 lines
2.5 KiB
Go
62 lines
2.5 KiB
Go
package commands
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// Every git command we build disables optional locks by default, so that our
|
|
// invocations never contend for index.lock (see git_commands.OptionalLocksEnvVar
|
|
// for the rationale). Commands that want the lock opt back in with
|
|
// CmdObj.RemoveEnvVar.
|
|
func TestGitCmdObjBuilderDisablesOptionalLocksByDefault(t *testing.T) {
|
|
builder := NewGitCmdObjBuilder(
|
|
utils.NewDummyLog(),
|
|
oscommands.NewDummyCmdObjBuilder(oscommands.NewFakeRunner(t)),
|
|
"/path/to/repo",
|
|
nil,
|
|
)
|
|
|
|
assert.Contains(t, builder.New([]string{"git", "status"}).GetEnvVars(), git_commands.OptionalLocksEnvVar+"=0")
|
|
assert.Contains(t, builder.NewShell("git status", "").GetEnvVars(), git_commands.OptionalLocksEnvVar+"=0")
|
|
}
|
|
|
|
// Every command the builder produces runs in the directory of the repo the
|
|
// builder was created for, not in the process's current directory: lazygit
|
|
// chdirs when switching repos, and commands built for the previous repo after
|
|
// that (e.g. by a background refresh still in flight) must keep addressing the
|
|
// repo they were built for.
|
|
func TestGitCmdObjBuilderPinsCommandsToRepoDir(t *testing.T) {
|
|
builder := NewGitCmdObjBuilder(
|
|
utils.NewDummyLog(),
|
|
oscommands.NewDummyCmdObjBuilder(oscommands.NewFakeRunner(t)),
|
|
"/path/to/repo",
|
|
nil,
|
|
)
|
|
|
|
assert.Equal(t, "/path/to/repo", builder.New([]string{"git", "status"}).GetCmd().Dir)
|
|
assert.Equal(t, "/path/to/repo", builder.NewShell("git status", "").GetCmd().Dir)
|
|
}
|
|
|
|
// A repo whose git dir isn't in its worktree can't be found by running a
|
|
// command there, so the builder has to tell every command where it is; see
|
|
// RepoPaths.GitLocationEnvVars. The process env says the same thing, but only
|
|
// for the repo lazygit is in right now, which isn't necessarily this one.
|
|
func TestGitCmdObjBuilderPinsCommandsToGitLocation(t *testing.T) {
|
|
builder := NewGitCmdObjBuilder(
|
|
utils.NewDummyLog(),
|
|
oscommands.NewDummyCmdObjBuilder(oscommands.NewFakeRunner(t)),
|
|
"/path/to/worktree",
|
|
[]string{"GIT_DIR=/path/to/repo/.git", "GIT_WORK_TREE=/path/to/worktree"},
|
|
)
|
|
|
|
assert.Subset(t, builder.New([]string{"git", "status"}).GetEnvVars(),
|
|
[]string{"GIT_DIR=/path/to/repo/.git", "GIT_WORK_TREE=/path/to/worktree"})
|
|
assert.Subset(t, builder.NewShell("git status", "").GetEnvVars(),
|
|
[]string{"GIT_DIR=/path/to/repo/.git", "GIT_WORK_TREE=/path/to/worktree"})
|
|
}
|