mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-17 00:18:05 +02:00
Optimize number of early calls to GetRepoPaths
This change reduces the number of calls during application startup to one, calling GetRepoPaths() earlier than previously and plumbing the repoPaths struct around to achieve this end.
This commit is contained in:
@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
|
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
@ -119,7 +118,14 @@ func NewApp(config config.AppConfigurer, test integrationTypes.IntegrationTest,
|
|||||||
return app, err
|
return app, err
|
||||||
}
|
}
|
||||||
|
|
||||||
showRecentRepos, err := app.setupRepo()
|
// If we're not in a repo, repoPaths will be nil. The error is moot for us
|
||||||
|
// at this stage, since we'll try to init a new repo in setupRepo(), below
|
||||||
|
repoPaths, err := git_commands.GetRepoPaths(app.OSCommand.Cmd, gitVersion)
|
||||||
|
if err != nil {
|
||||||
|
return app, err
|
||||||
|
}
|
||||||
|
|
||||||
|
showRecentRepos, err := app.setupRepo(repoPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return app, err
|
return app, err
|
||||||
}
|
}
|
||||||
@ -168,14 +174,16 @@ func openRecentRepo(app *App) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) setupRepo() (bool, error) {
|
func (app *App) setupRepo(
|
||||||
|
repoPaths *git_commands.RepoPaths,
|
||||||
|
) (bool, error) {
|
||||||
if env.GetGitDirEnv() != "" {
|
if env.GetGitDirEnv() != "" {
|
||||||
// we've been given the git dir directly. We'll verify this dir when initializing our Git object
|
// we've been given the git dir directly. Skip setup
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are not in a git repo, we ask if we want to `git init`
|
// if we are not in a git repo, we ask if we want to `git init`
|
||||||
if err := commands.VerifyInGitRepo(app.OSCommand); err != nil {
|
if repoPaths == nil {
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -221,6 +229,7 @@ func (app *App) setupRepo() (bool, error) {
|
|||||||
if err := app.OSCommand.Cmd.New(args).Run(); err != nil {
|
if err := app.OSCommand.Cmd.New(args).Run(); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,10 +247,7 @@ func (app *App) setupRepo() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run this afterward so that the previous repo creation steps can run without this interfering
|
// Run this afterward so that the previous repo creation steps can run without this interfering
|
||||||
if isBare, err := git_commands.IsBareRepo(app.OSCommand); isBare {
|
if repoPaths.IsBareRepo() {
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Print(app.Tr.BareRepo)
|
fmt.Print(app.Tr.BareRepo)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package git_commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ioFs "io/fs"
|
ioFs "io/fs"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -18,6 +19,7 @@ type RepoPaths struct {
|
|||||||
repoPath string
|
repoPath string
|
||||||
repoGitDirPath string
|
repoGitDirPath string
|
||||||
repoName string
|
repoName string
|
||||||
|
isBareRepo bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var gitPathFormatVersion GitVersion = GitVersion{2, 31, 0, ""}
|
var gitPathFormatVersion GitVersion = GitVersion{2, 31, 0, ""}
|
||||||
@ -54,6 +56,10 @@ func (self *RepoPaths) RepoName() string {
|
|||||||
return self.repoName
|
return self.repoName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RepoPaths) IsBareRepo() bool {
|
||||||
|
return self.isBareRepo
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the repo paths for a typical repo
|
// Returns the repo paths for a typical repo
|
||||||
func MockRepoPaths(currentPath string) *RepoPaths {
|
func MockRepoPaths(currentPath string) *RepoPaths {
|
||||||
return &RepoPaths{
|
return &RepoPaths{
|
||||||
@ -62,6 +68,7 @@ func MockRepoPaths(currentPath string) *RepoPaths {
|
|||||||
repoPath: currentPath,
|
repoPath: currentPath,
|
||||||
repoGitDirPath: path.Join(currentPath, ".git"),
|
repoGitDirPath: path.Join(currentPath, ".git"),
|
||||||
repoName: "lazygit",
|
repoName: "lazygit",
|
||||||
|
isBareRepo: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +76,19 @@ func GetRepoPaths(
|
|||||||
cmd oscommands.ICmdObjBuilder,
|
cmd oscommands.ICmdObjBuilder,
|
||||||
version *GitVersion,
|
version *GitVersion,
|
||||||
) (*RepoPaths, error) {
|
) (*RepoPaths, error) {
|
||||||
gitDirOutput, err := callGitRevParse(cmd, version, "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree")
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return GetRepoPathsForDir(cwd, cmd, version)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRepoPathsForDir(
|
||||||
|
dir string,
|
||||||
|
cmd oscommands.ICmdObjBuilder,
|
||||||
|
version *GitVersion,
|
||||||
|
) (*RepoPaths, error) {
|
||||||
|
gitDirOutput, err := callGitRevParseWithDir(cmd, version, dir, "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -84,13 +103,14 @@ func GetRepoPaths(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isBareRepo := gitDirResults[3] == "true"
|
||||||
|
|
||||||
// If we're in a submodule, --show-superproject-working-tree will return
|
// If we're in a submodule, --show-superproject-working-tree will return
|
||||||
// a value, meaning gitDirResults will be length 4. In that case
|
// a value, meaning gitDirResults will be length 5. In that case
|
||||||
// return the worktree path as the repoPath. Otherwise we're in a
|
// return the worktree path as the repoPath. Otherwise we're in a
|
||||||
// normal repo or a worktree so return the parent of the git common
|
// normal repo or a worktree so return the parent of the git common
|
||||||
// dir (repoGitDirPath)
|
// dir (repoGitDirPath)
|
||||||
isSubmodule := len(gitDirResults) == 4
|
isSubmodule := len(gitDirResults) == 5
|
||||||
|
|
||||||
var repoPath string
|
var repoPath string
|
||||||
if isSubmodule {
|
if isSubmodule {
|
||||||
@ -106,17 +126,10 @@ func GetRepoPaths(
|
|||||||
repoPath: repoPath,
|
repoPath: repoPath,
|
||||||
repoGitDirPath: repoGitDirPath,
|
repoGitDirPath: repoGitDirPath,
|
||||||
repoName: repoName,
|
repoName: repoName,
|
||||||
|
isBareRepo: isBareRepo,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func callGitRevParse(
|
|
||||||
cmd oscommands.ICmdObjBuilder,
|
|
||||||
version *GitVersion,
|
|
||||||
gitRevArgs ...string,
|
|
||||||
) (string, error) {
|
|
||||||
return callGitRevParseWithDir(cmd, version, "", gitRevArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func callGitRevParseWithDir(
|
func callGitRevParseWithDir(
|
||||||
cmd oscommands.ICmdObjBuilder,
|
cmd oscommands.ICmdObjBuilder,
|
||||||
version *GitVersion,
|
version *GitVersion,
|
||||||
|
@ -36,10 +36,12 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
"/path/to/repo/.git",
|
"/path/to/repo/.git",
|
||||||
// --git-common-dir
|
// --git-common-dir
|
||||||
"/path/to/repo/.git",
|
"/path/to/repo/.git",
|
||||||
|
// --is-bare-repository
|
||||||
|
"false",
|
||||||
// --show-superproject-working-tree
|
// --show-superproject-working-tree
|
||||||
}
|
}
|
||||||
runner.ExpectGitArgs(
|
runner.ExpectGitArgs(
|
||||||
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||||
strings.Join(expectedOutput, "\n"),
|
strings.Join(expectedOutput, "\n"),
|
||||||
nil)
|
nil)
|
||||||
},
|
},
|
||||||
@ -50,6 +52,38 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
repoPath: "/path/to/repo",
|
repoPath: "/path/to/repo",
|
||||||
repoGitDirPath: "/path/to/repo/.git",
|
repoGitDirPath: "/path/to/repo/.git",
|
||||||
repoName: "repo",
|
repoName: "repo",
|
||||||
|
isBareRepo: false,
|
||||||
|
},
|
||||||
|
Err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "bare repo",
|
||||||
|
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||||
|
// setup for main worktree
|
||||||
|
expectedOutput := []string{
|
||||||
|
// --show-toplevel
|
||||||
|
"/path/to/repo",
|
||||||
|
// --git-dir
|
||||||
|
"/path/to/bare_repo/bare.git",
|
||||||
|
// --git-common-dir
|
||||||
|
"/path/to/bare_repo/bare.git",
|
||||||
|
// --is-bare-repository
|
||||||
|
"true",
|
||||||
|
// --show-superproject-working-tree
|
||||||
|
}
|
||||||
|
runner.ExpectGitArgs(
|
||||||
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||||
|
strings.Join(expectedOutput, "\n"),
|
||||||
|
nil)
|
||||||
|
},
|
||||||
|
Path: "/path/to/repo",
|
||||||
|
Expected: &RepoPaths{
|
||||||
|
worktreePath: "/path/to/repo",
|
||||||
|
worktreeGitDirPath: "/path/to/bare_repo/bare.git",
|
||||||
|
repoPath: "/path/to/bare_repo",
|
||||||
|
repoGitDirPath: "/path/to/bare_repo/bare.git",
|
||||||
|
repoName: "bare_repo",
|
||||||
|
isBareRepo: true,
|
||||||
},
|
},
|
||||||
Err: nil,
|
Err: nil,
|
||||||
},
|
},
|
||||||
@ -63,11 +97,13 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
"/path/to/repo/.git/modules/submodule1",
|
"/path/to/repo/.git/modules/submodule1",
|
||||||
// --git-common-dir
|
// --git-common-dir
|
||||||
"/path/to/repo/.git/modules/submodule1",
|
"/path/to/repo/.git/modules/submodule1",
|
||||||
|
// --is-bare-repository
|
||||||
|
"false",
|
||||||
// --show-superproject-working-tree
|
// --show-superproject-working-tree
|
||||||
"/path/to/repo",
|
"/path/to/repo",
|
||||||
}
|
}
|
||||||
runner.ExpectGitArgs(
|
runner.ExpectGitArgs(
|
||||||
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||||
strings.Join(expectedOutput, "\n"),
|
strings.Join(expectedOutput, "\n"),
|
||||||
nil)
|
nil)
|
||||||
},
|
},
|
||||||
@ -78,6 +114,7 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
repoPath: "/path/to/repo/submodule1",
|
repoPath: "/path/to/repo/submodule1",
|
||||||
repoGitDirPath: "/path/to/repo/.git/modules/submodule1",
|
repoGitDirPath: "/path/to/repo/.git/modules/submodule1",
|
||||||
repoName: "submodule1",
|
repoName: "submodule1",
|
||||||
|
isBareRepo: false,
|
||||||
},
|
},
|
||||||
Err: nil,
|
Err: nil,
|
||||||
},
|
},
|
||||||
@ -85,7 +122,7 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
Name: "git rev-parse returns an error",
|
Name: "git rev-parse returns an error",
|
||||||
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||||
runner.ExpectGitArgs(
|
runner.ExpectGitArgs(
|
||||||
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree"),
|
||||||
"",
|
"",
|
||||||
errors.New("fatal: invalid gitfile format: /path/to/repo/worktree2/.git"))
|
errors.New("fatal: invalid gitfile format: /path/to/repo/worktree2/.git"))
|
||||||
},
|
},
|
||||||
@ -94,7 +131,7 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
Err: func(getRevParseArgs argFn) error {
|
Err: func(getRevParseArgs argFn) error {
|
||||||
args := strings.Join(getRevParseArgs(), " ")
|
args := strings.Join(getRevParseArgs(), " ")
|
||||||
return errors.New(
|
return errors.New(
|
||||||
fmt.Sprintf("'git %v --show-toplevel --absolute-git-dir --git-common-dir --show-superproject-working-tree' failed: fatal: invalid gitfile format: /path/to/repo/worktree2/.git", args),
|
fmt.Sprintf("'git %v --show-toplevel --absolute-git-dir --git-common-dir --is-bare-repository --show-superproject-working-tree' failed: fatal: invalid gitfile format: /path/to/repo/worktree2/.git", args),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -120,7 +157,7 @@ func TestGetRepoPaths(t *testing.T) {
|
|||||||
// prepare the filesystem for the scenario
|
// prepare the filesystem for the scenario
|
||||||
s.BeforeFunc(runner, getRevParseArgs)
|
s.BeforeFunc(runner, getRevParseArgs)
|
||||||
|
|
||||||
repoPaths, err := GetRepoPaths(cmd, version)
|
repoPaths, err := GetRepoPathsForDir("", cmd, version)
|
||||||
|
|
||||||
// check the error and the paths
|
// check the error and the paths
|
||||||
if s.Err != nil {
|
if s.Err != nil {
|
||||||
|
@ -3,10 +3,8 @@ package git_commands
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,20 +47,8 @@ func (self *StatusCommands) WorkingTreeState() enums.RebaseMode {
|
|||||||
return enums.REBASE_MODE_NONE
|
return enums.REBASE_MODE_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StatusCommands) IsBareRepo() (bool, error) {
|
func (self *StatusCommands) IsBareRepo() bool {
|
||||||
return IsBareRepo(self.os)
|
return self.repoPaths.isBareRepo
|
||||||
}
|
|
||||||
|
|
||||||
func IsBareRepo(osCommand *oscommands.OSCommand) (bool, error) {
|
|
||||||
res, err := osCommand.Cmd.New(
|
|
||||||
NewGitCmd("rev-parse").Arg("--is-bare-repository").ToArgv(),
|
|
||||||
).DontLog().RunWithOutput()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// The command returns output with a newline, so we need to strip
|
|
||||||
return strconv.ParseBool(strings.TrimSpace(res))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StatusCommands) IsInNormalRebase() (bool, error) {
|
func (self *StatusCommands) IsInNormalRebase() (bool, error) {
|
||||||
|
@ -17,6 +17,6 @@ func NewDummyUpdater() *updates.Updater {
|
|||||||
// NewDummyGui creates a new dummy GUI for testing
|
// NewDummyGui creates a new dummy GUI for testing
|
||||||
func NewDummyGui() *Gui {
|
func NewDummyGui() *Gui {
|
||||||
newAppConfig := config.NewDummyAppConfig()
|
newAppConfig := config.NewDummyAppConfig()
|
||||||
dummyGui, _ := NewGui(utils.NewDummyCommon(), newAppConfig, &git_commands.GitVersion{}, NewDummyUpdater(), false, "", nil)
|
dummyGui, _ := NewGui(utils.NewDummyCommon(), newAppConfig, &git_commands.GitVersion{Major: 2, Minor: 0, Patch: 0}, NewDummyUpdater(), false, "", nil)
|
||||||
return dummyGui
|
return dummyGui
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,7 @@ import (
|
|||||||
// updateRecentRepoList registers the fact that we opened lazygit in this repo,
|
// updateRecentRepoList registers the fact that we opened lazygit in this repo,
|
||||||
// so that we can open the same repo via the 'recent repos' menu
|
// so that we can open the same repo via the 'recent repos' menu
|
||||||
func (gui *Gui) updateRecentRepoList() error {
|
func (gui *Gui) updateRecentRepoList() error {
|
||||||
isBareRepo, err := gui.git.Status.IsBareRepo()
|
if gui.git.Status.IsBareRepo() {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isBareRepo {
|
|
||||||
// we could totally do this but it would require storing both the git-dir and the
|
// we could totally do this but it would require storing both the git-dir and the
|
||||||
// worktree in our recent repos list, which is a change that would need to be
|
// worktree in our recent repos list, which is a change that would need to be
|
||||||
// backwards compatible
|
// backwards compatible
|
||||||
|
Reference in New Issue
Block a user