summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-07-27 21:52:24 +1000
committerJesse Duffield <jessedduffield@gmail.com>2023-07-30 18:35:23 +1000
commit2b24c15938c5ceb29a9b2d525aa1318b8bc8a87b (patch)
tree23727dd77a11b9ec456344dc2c482cb9879c8849
parente874f94cf8fb8928110a0165852a8967fa823a5c (diff)
Add test for opening lazygit in the worktree of a bare repo
-rw-r--r--pkg/commands/git.go60
-rw-r--r--pkg/commands/git_commands/worktree_loader.go5
-rw-r--r--pkg/integration/components/shell.go10
-rw-r--r--pkg/integration/tests/test_list.go1
-rw-r--r--pkg/integration/tests/worktree/bare_repo.go61
5 files changed, 109 insertions, 28 deletions
diff --git a/pkg/commands/git.go b/pkg/commands/git.go
index c2c53948a..3f7e823e7 100644
--- a/pkg/commands/git.go
+++ b/pkg/commands/git.go
@@ -1,6 +1,7 @@
package commands
import (
+ "fmt"
"os"
"path/filepath"
"strings"
@@ -66,13 +67,16 @@ func NewGitCommand(
return nil, err
}
- repo, err := setupRepository(gogit.PlainOpenWithOptions, gogit.PlainOpenOptions{DetectDotGit: false, EnableDotGitCommonDir: true}, cmn.Tr.GitconfigParseErr)
+ dotGitDir, err := findDotGitDir(os.Stat, os.ReadFile)
if err != nil {
return nil, err
}
- dotGitDir, err := findDotGitDir(os.Stat, os.ReadFile)
+ repository, err := gogit.PlainOpenWithOptions(dotGitDir, &gogit.PlainOpenOptions{DetectDotGit: false, EnableDotGitCommonDir: true})
if err != nil {
+ if strings.Contains(err.Error(), `unquoted '\' must be followed by new line`) {
+ return nil, errors.New(cmn.Tr.GitconfigParseErr)
+ }
return nil, err
}
@@ -82,7 +86,7 @@ func NewGitCommand(
osCommand,
gitConfig,
dotGitDir,
- repo,
+ repository,
syncMutex,
), nil
}
@@ -218,8 +222,8 @@ func navigateToRepoRootDirectory(stat func(string) (os.FileInfo, error), chdir f
}
}
-// resolvePath takes a path containing a symlink and returns the true path
-func resolvePath(path string) (string, error) {
+// takes a path containing a symlink and returns the true path
+func resolveSymlink(path string) (string, error) {
l, err := os.Lstat(path)
if err != nil {
return "", err
@@ -232,27 +236,17 @@ func resolvePath(path string) (string, error) {
return filepath.EvalSymlinks(path)
}
-func setupRepository(openGitRepository func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error), options gogit.PlainOpenOptions, gitConfigParseErrorStr string) (*gogit.Repository, error) {
- unresolvedPath := env.GetGitDirEnv()
- if unresolvedPath == "" {
- var err error
- unresolvedPath, err = os.Getwd()
- if err != nil {
- return nil, err
- }
- }
-
- path, err := resolvePath(unresolvedPath)
- if err != nil {
- return nil, err
- }
-
+func setupRepository(
+ openGitRepository func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error),
+ options gogit.PlainOpenOptions,
+ gitConfigParseErrorStr string,
+ path string,
+) (*gogit.Repository, error) {
repository, err := openGitRepository(path, &options)
if err != nil {
if strings.Contains(err.Error(), `unquoted '\' must be followed by new line`) {
return nil, errors.New(gitConfigParseErrorStr)
}
-
return nil, err
}
@@ -260,26 +254,38 @@ func setupRepository(openGitRepository func(string, *gogit.PlainOpenOptions) (*g
}
func findDotGitDir(stat func(string) (os.FileInfo, error), readFile func(filename string) ([]byte, error)) (string, error) {
- if env.GetGitDirEnv() != "" {
- return env.GetGitDirEnv(), nil
+ unresolvedPath := env.GetGitDirEnv()
+ if unresolvedPath == "" {
+ var err error
+ unresolvedPath, err = os.Getwd()
+ if err != nil {
+ return "", err
+ }
+ unresolvedPath = filepath.Join(unresolvedPath, ".git")
}
- f, err := stat(".git")
+ path, err := resolveSymlink(unresolvedPath)
+ if err != nil {
+ return "", err
+ }
+
+ f, err := stat(path)
if err != nil {
return "", err
}
if f.IsDir() {
- return ".git", nil
+ return path, nil
}
- fileBytes, err := readFile(".git")
+ fileBytes, err := readFile(path)
if err != nil {
return "", err
}
+
fileContent := string(fileBytes)
if !strings.HasPrefix(fileContent, "gitdir: ") {
- return "", errors.New(".git is a file which suggests we are in a submodule or a worktree but the file's contents do not contain a gitdir pointing to the actual .git directory")
+ return "", errors.New(fmt.Sprintf("%s is a file which suggests we are in a submodule or a worktree but the file's contents do not contain a gitdir pointing to the actual .git directory", path))
}
return strings.TrimSpace(strings.TrimPrefix(fileContent, "gitdir: ")), nil
}
diff --git a/pkg/commands/git_commands/worktree_loader.go b/pkg/commands/git_commands/worktree_loader.go
index 6c73eaa13..bbd8367f3 100644
--- a/pkg/commands/git_commands/worktree_loader.go
+++ b/pkg/commands/git_commands/worktree_loader.go
@@ -46,6 +46,11 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
current = nil
continue
}
+ if splitLine == "bare" {
+ current = nil
+ continue
+ }
+
if strings.HasPrefix(splitLine, "worktree ") {
path := strings.SplitN(splitLine, " ", 2)[1]
isMain := path == currentRepoPath
diff --git a/pkg/integration/components/shell.go b/pkg/integration/components/shell.go
index 741135e2f..ce98e575a 100644
--- a/pkg/integration/components/shell.go
+++ b/pkg/integration/components/shell.go
@@ -85,7 +85,7 @@ func (self *Shell) CreateFile(path string, content string) *Shell {
func (self *Shell) DeleteFile(path string) *Shell {
fullPath := filepath.Join(self.dir, path)
- err := os.Remove(fullPath)
+ err := os.RemoveAll(fullPath)
if err != nil {
self.fail(fmt.Sprintf("error deleting file: %s\n%s", fullPath, err))
}
@@ -328,3 +328,11 @@ func (self *Shell) CopyFile(source string, destination string) *Shell {
return self
}
+
+// NOTE: this only takes effect before running the test;
+// the test will still run in the original directory
+func (self *Shell) Chdir(path string) *Shell {
+ self.dir = filepath.Join(self.dir, path)
+
+ return self
+}
diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go
index 361fa2064..62a4fae29 100644
--- a/pkg/integration/tests/test_list.go
+++ b/pkg/integration/tests/test_list.go
@@ -223,6 +223,7 @@ var tests = []*components.IntegrationTest{
worktree.AddFromBranch,
worktree.AddFromBranchDetached,
worktree.AddFromCommit,
+ worktree.BareRepo,
worktree.Bisect,
worktree.Crud,
worktree.CustomCommand,
diff --git a/pkg/integration/tests/worktree/bare_repo.go b/pkg/integration/tests/worktree/bare_repo.go
new file mode 100644
index 000000000..af0133227
--- /dev/null
+++ b/pkg/integration/tests/worktree/bare_repo.go
@@ -0,0 +1,61 @@
+package worktree
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var BareRepo = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Open lazygit in the worktree of a bare repo",
+ ExtraCmdArgs: []string{},
+ Skip: false,
+ SetupConfig: func(config *config.AppConfig) {},
+ SetupRepo: func(shell *Shell) {
+ // we're going to have a directory structure like this:
+ // project
+ // - .bare
+ // - repo (a worktree)
+ // - worktree2 (another worktree)
+ //
+ // The first repo is called 'repo' because that's the
+ // directory that all lazygit tests start in
+
+ shell.NewBranch("mybranch")
+ shell.CreateFileAndAdd("blah", "blah")
+ shell.Commit("initial commit")
+
+ shell.RunCommand([]string{"git", "clone", "--bare", ".", "../.bare"})
+
+ shell.DeleteFile(".git")
+
+ shell.Chdir("..")
+
+ // This is the dir we were just in (and the dir that lazygit starts in when the test runs)
+ // We're going to replace it with a worktree
+ shell.DeleteFile("repo")
+
+ shell.RunCommand([]string{"git", "--git-dir", ".bare", "worktree", "add", "-b", "repo", "repo", "mybranch"})
+ shell.RunCommand([]string{"git", "--git-dir", ".bare", "worktree", "add", "-b", "worktree2", "worktree2", "mybranch"})
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.Views().Branches().
+ Lines(
+ Contains("repo"),
+ Contains("mybranch"),
+ Contains("worktree2 (worktree)"),
+ )
+
+ t.Views().Worktrees().
+ Focus().
+ Lines(
+ Contains("repo").IsSelected(),
+ Contains("worktree2"),
+ ).
+ NavigateToLine(Contains("worktree2")).
+ Press(keys.Universal.Select).
+ Lines(
+ Contains("worktree2").IsSelected(),
+ Contains("repo"),
+ )
+ },
+})