Refactor repo_paths.go to use git rev-parse

This changes GetRepoPaths() to pull information from `git rev-parse`
instead of effectively reimplementing git's logic for pathfinding. This
change fixes issues with bare repos, esp. versioned homedir use cases,
by aligning lazygit's path handling to what git itself does.

This change also enables lazygit to run from arbitrary subdirectories of
a repository, including correct handling of symlinks, including "deep"
symlinks into a repo, worktree, a repo's submodules, etc.

Integration tests are now resilient against unintended side effects from
the host's environment variables. Of necessity, $PATH and $TERM are the
only env vars allowed through now.
This commit is contained in:
John Whitley 2023-12-24 08:46:02 -08:00 committed by Stefan Haller
parent 74d937881e
commit 3d9f1e02e5
25 changed files with 590 additions and 442 deletions

View file

@ -4,6 +4,7 @@ import (
iofs "io/fs"
"path/filepath"
"strings"
"sync"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/commands/models"
@ -57,18 +58,14 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
isCurrent := path == worktreePath
isPathMissing := self.pathExists(path)
var gitDir string
gitDir, err := getWorktreeGitDirPath(self.Fs, path)
if err != nil {
self.Log.Warnf("Could not find git dir for worktree %s: %v", path, err)
}
current = &models.Worktree{
IsMain: isMain,
IsCurrent: isCurrent,
IsPathMissing: isPathMissing,
Path: path,
GitDir: gitDir,
// we defer populating GitDir until a loop below so that
// we can parallelize the calls to git rev-parse
GitDir: "",
}
} else if strings.HasPrefix(splitLine, "branch ") {
branch := strings.SplitN(splitLine, " ", 2)[1]
@ -76,6 +73,28 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
}
}
wg := sync.WaitGroup{}
wg.Add(len(worktrees))
for _, worktree := range worktrees {
worktree := worktree
go utils.Safe(func() {
defer wg.Done()
if worktree.IsPathMissing {
return
}
gitDir, err := callGitRevParseWithDir(self.cmd, self.version, worktree.Path, "--absolute-git-dir")
if err != nil {
self.Log.Warnf("Could not find git dir for worktree %s: %v", worktree.Path, err)
return
}
worktree.GitDir = gitDir
})
}
wg.Wait()
names := getUniqueNamesFromPaths(lo.Map(worktrees, func(worktree *models.Worktree, _ int) string {
return worktree.Path
}))