mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-03-05 15:15:49 +02:00
Support opening lazygit in a submodule
This commit is contained in:
parent
e38d9d5f22
commit
c61bfbdd4c
@ -25,13 +25,10 @@ func verifyInGitRepo(runCmd func(string) error) error {
|
||||
|
||||
func navigateToRepoRootDirectory(stat func(string) (os.FileInfo, error), chdir func(string) error) error {
|
||||
for {
|
||||
f, err := stat(".git")
|
||||
_, err := stat(".git")
|
||||
|
||||
if err == nil {
|
||||
if f.IsDir() {
|
||||
return nil
|
||||
}
|
||||
return errors.New("expected .git to be a directory")
|
||||
return nil
|
||||
}
|
||||
|
||||
if !os.IsNotExist(err) {
|
||||
@ -75,6 +72,7 @@ type GitCommand struct {
|
||||
getGlobalGitConfig func(string) (string, error)
|
||||
getLocalGitConfig func(string) (string, error)
|
||||
removeFile func(string) error
|
||||
DotGitDir string
|
||||
}
|
||||
|
||||
// NewGitCommand it runs git commands
|
||||
@ -102,6 +100,11 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer,
|
||||
}
|
||||
}
|
||||
|
||||
dotGitDir, err := findDotGitDir(os.Stat, ioutil.ReadFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GitCommand{
|
||||
Log: log,
|
||||
OSCommand: osCommand,
|
||||
@ -112,9 +115,31 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer,
|
||||
getGlobalGitConfig: gitconfig.Global,
|
||||
getLocalGitConfig: gitconfig.Local,
|
||||
removeFile: os.RemoveAll,
|
||||
DotGitDir: dotGitDir,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func findDotGitDir(stat func(string) (os.FileInfo, error), readFile func(filename string) ([]byte, error)) (string, error) {
|
||||
f, err := stat(".git")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if f.IsDir() {
|
||||
return ".git", nil
|
||||
}
|
||||
|
||||
fileBytes, err := readFile(".git")
|
||||
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 but the file's contents do not contain a gitdir pointing to the actual .git directory")
|
||||
}
|
||||
return strings.TrimSpace(strings.TrimPrefix(fileContent, "gitdir: ")), nil
|
||||
}
|
||||
|
||||
// GetStashEntries stash entryies
|
||||
func (c *GitCommand) GetStashEntries() []*StashEntry {
|
||||
rawString, _ := c.OSCommand.RunCommandWithOutput("git stash list --pretty='%gs'")
|
||||
@ -426,14 +451,14 @@ func (c *GitCommand) IsInMergeState() (bool, error) {
|
||||
// RebaseMode returns "" for non-rebase mode, "normal" for normal rebase
|
||||
// and "interactive" for interactive rebase
|
||||
func (c *GitCommand) RebaseMode() (string, error) {
|
||||
exists, err := c.OSCommand.FileExists(".git/rebase-apply")
|
||||
exists, err := c.OSCommand.FileExists(fmt.Sprintf("%s/rebase-apply", c.DotGitDir))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if exists {
|
||||
return "normal", nil
|
||||
}
|
||||
exists, err = c.OSCommand.FileExists(".git/rebase-merge")
|
||||
exists, err = c.OSCommand.FileExists(fmt.Sprintf("%s/rebase-merge", c.DotGitDir))
|
||||
if exists {
|
||||
return "interactive", err
|
||||
} else {
|
||||
@ -743,7 +768,7 @@ func (c *GitCommand) AmendTo(sha string) error {
|
||||
|
||||
// EditRebaseTodo sets the action at a given index in the git-rebase-todo file
|
||||
func (c *GitCommand) EditRebaseTodo(index int, action string) error {
|
||||
fileName := ".git/rebase-merge/git-rebase-todo"
|
||||
fileName := fmt.Sprintf("%s/rebase-merge/git-rebase-todo", c.DotGitDir)
|
||||
bytes, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -775,7 +800,7 @@ func (c *GitCommand) getTodoCommitCount(content []string) int {
|
||||
|
||||
// MoveTodoDown moves a rebase todo item down by one position
|
||||
func (c *GitCommand) MoveTodoDown(index int) error {
|
||||
fileName := ".git/rebase-merge/git-rebase-todo"
|
||||
fileName := fmt.Sprintf("%s/rebase-merge/git-rebase-todo", c.DotGitDir)
|
||||
bytes, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/jesseduffield/lazygit/pkg/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -2122,3 +2123,78 @@ func TestGitCommandCreateFixupCommit(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindDotGitDir(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
stat func(string) (os.FileInfo, error)
|
||||
readFile func(filename string) ([]byte, error)
|
||||
test func(string, error)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
".git is a directory",
|
||||
func(dotGit string) (os.FileInfo, error) {
|
||||
assert.Equal(t, ".git", dotGit)
|
||||
return os.Stat("testdata/a_dir")
|
||||
},
|
||||
func(dotGit string) ([]byte, error) {
|
||||
assert.Fail(t, "readFile should not be called if .git is a directory")
|
||||
return nil, nil
|
||||
},
|
||||
func(gitDir string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ".git", gitDir)
|
||||
},
|
||||
},
|
||||
{
|
||||
".git is a file",
|
||||
func(dotGit string) (os.FileInfo, error) {
|
||||
assert.Equal(t, ".git", dotGit)
|
||||
return os.Stat("testdata/a_file")
|
||||
},
|
||||
func(dotGit string) ([]byte, error) {
|
||||
assert.Equal(t, ".git", dotGit)
|
||||
return []byte("gitdir: blah\n"), nil
|
||||
},
|
||||
func(gitDir string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "blah", gitDir)
|
||||
},
|
||||
},
|
||||
{
|
||||
"os.Stat returns an error",
|
||||
func(dotGit string) (os.FileInfo, error) {
|
||||
assert.Equal(t, ".git", dotGit)
|
||||
return nil, errors.New("error")
|
||||
},
|
||||
func(dotGit string) ([]byte, error) {
|
||||
assert.Fail(t, "readFile should not be called os.Stat returns an error")
|
||||
return nil, nil
|
||||
},
|
||||
func(gitDir string, err error) {
|
||||
assert.Error(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
"readFile returns an error",
|
||||
func(dotGit string) (os.FileInfo, error) {
|
||||
assert.Equal(t, ".git", dotGit)
|
||||
return os.Stat("testdata/a_file")
|
||||
},
|
||||
func(dotGit string) ([]byte, error) {
|
||||
return nil, errors.New("error")
|
||||
},
|
||||
func(gitDir string, err error) {
|
||||
assert.Error(t, err)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
s.test(findDotGitDir(s.stat, s.readFile))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
0
pkg/commands/testdata/a_dir/file
vendored
Normal file
0
pkg/commands/testdata/a_dir/file
vendored
Normal file
0
pkg/commands/testdata/a_file
vendored
Normal file
0
pkg/commands/testdata/a_file
vendored
Normal file
@ -123,7 +123,7 @@ func (c *CommitListBuilder) getRebasingCommits(rebaseMode string) ([]*commands.C
|
||||
|
||||
func (c *CommitListBuilder) getNormalRebasingCommits() ([]*commands.Commit, error) {
|
||||
rewrittenCount := 0
|
||||
bytesContent, err := ioutil.ReadFile(".git/rebase-apply/rewritten")
|
||||
bytesContent, err := ioutil.ReadFile(fmt.Sprintf("%s/rebase-apply/rewritten", c.GitCommand.DotGitDir))
|
||||
if err == nil {
|
||||
content := string(bytesContent)
|
||||
rewrittenCount = len(strings.Split(content, "\n"))
|
||||
@ -131,7 +131,7 @@ func (c *CommitListBuilder) getNormalRebasingCommits() ([]*commands.Commit, erro
|
||||
|
||||
// we know we're rebasing, so lets get all the files whose names have numbers
|
||||
commits := []*commands.Commit{}
|
||||
err = filepath.Walk(".git/rebase-apply", func(path string, f os.FileInfo, err error) error {
|
||||
err = filepath.Walk(fmt.Sprintf("%s/rebase-apply", c.GitCommand.DotGitDir), func(path string, f os.FileInfo, err error) error {
|
||||
if rewrittenCount > 0 {
|
||||
rewrittenCount--
|
||||
return nil
|
||||
@ -175,7 +175,7 @@ func (c *CommitListBuilder) getNormalRebasingCommits() ([]*commands.Commit, erro
|
||||
// and extracts out the sha and names of commits that we still have to go
|
||||
// in the rebase:
|
||||
func (c *CommitListBuilder) getInteractiveRebasingCommits() ([]*commands.Commit, error) {
|
||||
bytesContent, err := ioutil.ReadFile(".git/rebase-merge/git-rebase-todo")
|
||||
bytesContent, err := ioutil.ReadFile(fmt.Sprintf("%s/rebase-merge/git-rebase-todo", c.GitCommand.DotGitDir))
|
||||
if err != nil {
|
||||
c.Log.Info(fmt.Sprintf("error occured reading git-rebase-todo: %s", err.Error()))
|
||||
// we assume an error means the file doesn't exist so we just return
|
||||
|
Loading…
x
Reference in New Issue
Block a user