mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-02-09 13:47:11 +02:00
WIP
This commit is contained in:
parent
192a548c99
commit
43a4fa970d
@ -151,7 +151,7 @@ func NewApp(config config.AppConfigurer, filterPath string) (*App, error) {
|
||||
}
|
||||
|
||||
func (app *App) validateGitVersion() error {
|
||||
output, err := app.OSCommand.RunWithOutput(app.OSCommand.NewCmdObj("git --version"))
|
||||
output, err := app.OSCommand.Cmd.New("git --version").RunWithOutput()
|
||||
// if we get an error anywhere here we'll show the same status
|
||||
minVersionError := errors.New(app.Tr.MinGitVersionError)
|
||||
if err != nil {
|
||||
@ -236,7 +236,7 @@ func (app *App) setupRepo() (bool, error) {
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := app.OSCommand.Run(app.OSCommand.NewCmdObj("git init")); err != nil {
|
||||
if err := app.OSCommand.Cmd.New("git init").Run(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
@ -11,19 +11,19 @@ import (
|
||||
|
||||
// NewBranch create new branch
|
||||
func (c *GitCommand) NewBranch(name string, base string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git checkout -b %s %s", c.OSCommand.Quote(name), c.OSCommand.Quote(base))))
|
||||
return c.Cmd.New(fmt.Sprintf("git checkout -b %s %s", c.OSCommand.Quote(name), c.OSCommand.Quote(base))).Run()
|
||||
}
|
||||
|
||||
// CurrentBranchName get the current branch name and displayname.
|
||||
// the first returned string is the name and the second is the displayname
|
||||
// e.g. name is 123asdf and displayname is '(HEAD detached at 123asdf)'
|
||||
func (c *GitCommand) CurrentBranchName() (string, string, error) {
|
||||
branchName, err := c.RunWithOutput(c.NewCmdObj("git symbolic-ref --short HEAD"))
|
||||
branchName, err := c.Cmd.New("git symbolic-ref --short HEAD").RunWithOutput()
|
||||
if err == nil && branchName != "HEAD\n" {
|
||||
trimmedBranchName := strings.TrimSpace(branchName)
|
||||
return trimmedBranchName, trimmedBranchName, nil
|
||||
}
|
||||
output, err := c.RunWithOutput(c.NewCmdObj("git branch --contains"))
|
||||
output, err := c.Cmd.New("git branch --contains").RunWithOutput()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
@ -47,7 +47,7 @@ func (c *GitCommand) DeleteBranch(branch string, force bool) error {
|
||||
command = "git branch -D"
|
||||
}
|
||||
|
||||
return c.OSCommand.Run(c.OSCommand.NewCmdObj(fmt.Sprintf("%s %s", command, c.OSCommand.Quote(branch))))
|
||||
return c.Cmd.New(fmt.Sprintf("%s %s", command, c.OSCommand.Quote(branch))).Run()
|
||||
}
|
||||
|
||||
// Checkout checks out a branch (or commit), with --force if you set the force arg to true
|
||||
@ -62,24 +62,23 @@ func (c *GitCommand) Checkout(branch string, options CheckoutOptions) error {
|
||||
forceArg = " --force"
|
||||
}
|
||||
|
||||
cmdObj := c.NewCmdObj(fmt.Sprintf("git checkout%s %s", forceArg, c.OSCommand.Quote(branch))).
|
||||
return c.Cmd.New(fmt.Sprintf("git checkout%s %s", forceArg, c.OSCommand.Quote(branch))).
|
||||
// prevents git from prompting us for input which would freeze the program
|
||||
// TODO: see if this is actually needed here
|
||||
AddEnvVars("GIT_TERMINAL_PROMPT=0").
|
||||
AddEnvVars(options.EnvVars...)
|
||||
|
||||
return c.OSCommand.Run(cmdObj)
|
||||
AddEnvVars(options.EnvVars...).
|
||||
Run()
|
||||
}
|
||||
|
||||
// GetBranchGraph gets the color-formatted graph of the log for the given branch
|
||||
// Currently it limits the result to 100 commits, but when we get async stuff
|
||||
// working we can do lazy loading
|
||||
func (c *GitCommand) GetBranchGraph(branchName string) (string, error) {
|
||||
return c.OSCommand.RunWithOutput(c.GetBranchGraphCmdObj(branchName))
|
||||
return c.GetBranchGraphCmdObj(branchName).RunWithOutput()
|
||||
}
|
||||
|
||||
func (c *GitCommand) GetUpstreamForBranch(branchName string) (string, error) {
|
||||
output, err := c.RunWithOutput(c.NewCmdObj(fmt.Sprintf("git rev-parse --abbrev-ref --symbolic-full-name %s@{u}", c.OSCommand.Quote(branchName))))
|
||||
output, err := c.Cmd.New(fmt.Sprintf("git rev-parse --abbrev-ref --symbolic-full-name %s@{u}", c.OSCommand.Quote(branchName))).RunWithOutput()
|
||||
return strings.TrimSpace(output), err
|
||||
}
|
||||
|
||||
@ -88,15 +87,15 @@ func (c *GitCommand) GetBranchGraphCmdObj(branchName string) oscommands.ICmdObj
|
||||
templateValues := map[string]string{
|
||||
"branchName": c.OSCommand.Quote(branchName),
|
||||
}
|
||||
return c.NewCmdObj(utils.ResolvePlaceholderString(branchLogCmdTemplate, templateValues))
|
||||
return c.Cmd.New(utils.ResolvePlaceholderString(branchLogCmdTemplate, templateValues))
|
||||
}
|
||||
|
||||
func (c *GitCommand) SetUpstreamBranch(upstream string) error {
|
||||
return c.Run(c.NewCmdObj("git branch -u " + c.OSCommand.Quote(upstream)))
|
||||
return c.Cmd.New("git branch -u " + c.OSCommand.Quote(upstream)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SetBranchUpstream(remoteName string, remoteBranchName string, branchName string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git branch --set-upstream-to=%s/%s %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(remoteBranchName), c.OSCommand.Quote(branchName))))
|
||||
return c.Cmd.New(fmt.Sprintf("git branch --set-upstream-to=%s/%s %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(remoteBranchName), c.OSCommand.Quote(branchName))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) GetCurrentBranchUpstreamDifferenceCount() (string, string) {
|
||||
@ -111,11 +110,11 @@ func (c *GitCommand) GetBranchUpstreamDifferenceCount(branchName string) (string
|
||||
// current branch
|
||||
func (c *GitCommand) GetCommitDifferences(from, to string) (string, string) {
|
||||
command := "git rev-list %s..%s --count"
|
||||
pushableCount, err := c.RunWithOutput(c.NewCmdObj(fmt.Sprintf(command, to, from)))
|
||||
pushableCount, err := c.Cmd.New(fmt.Sprintf(command, to, from)).RunWithOutput()
|
||||
if err != nil {
|
||||
return "?", "?"
|
||||
}
|
||||
pullableCount, err := c.RunWithOutput(c.NewCmdObj(fmt.Sprintf(command, from, to)))
|
||||
pullableCount, err := c.Cmd.New(fmt.Sprintf(command, from, to)).RunWithOutput()
|
||||
if err != nil {
|
||||
return "?", "?"
|
||||
}
|
||||
@ -135,37 +134,37 @@ func (c *GitCommand) Merge(branchName string, opts MergeOpts) error {
|
||||
command = fmt.Sprintf("%s --ff-only", command)
|
||||
}
|
||||
|
||||
return c.OSCommand.Run(c.OSCommand.NewCmdObj(command))
|
||||
return c.OSCommand.Cmd.New(command).Run()
|
||||
}
|
||||
|
||||
// AbortMerge abort merge
|
||||
func (c *GitCommand) AbortMerge() error {
|
||||
return c.Run(c.NewCmdObj("git merge --abort"))
|
||||
return c.Cmd.New("git merge --abort").Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) IsHeadDetached() bool {
|
||||
err := c.Run(c.NewCmdObj("git symbolic-ref -q HEAD"))
|
||||
err := c.Cmd.New("git symbolic-ref -q HEAD").Run()
|
||||
return err != nil
|
||||
}
|
||||
|
||||
// ResetHardHead runs `git reset --hard`
|
||||
func (c *GitCommand) ResetHard(ref string) error {
|
||||
return c.Run(c.NewCmdObj("git reset --hard " + c.OSCommand.Quote(ref)))
|
||||
return c.Cmd.New("git reset --hard " + c.OSCommand.Quote(ref)).Run()
|
||||
}
|
||||
|
||||
// ResetSoft runs `git reset --soft HEAD`
|
||||
func (c *GitCommand) ResetSoft(ref string) error {
|
||||
return c.Run(c.NewCmdObj("git reset --soft " + c.OSCommand.Quote(ref)))
|
||||
return c.Cmd.New("git reset --soft " + c.OSCommand.Quote(ref)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) ResetMixed(ref string) error {
|
||||
return c.Run(c.NewCmdObj("git reset --mixed " + c.OSCommand.Quote(ref)))
|
||||
return c.Cmd.New("git reset --mixed " + c.OSCommand.Quote(ref)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) RenameBranch(oldName string, newName string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git branch --move %s %s", c.OSCommand.Quote(oldName), c.OSCommand.Quote(newName))))
|
||||
return c.Cmd.New(fmt.Sprintf("git branch --move %s %s", c.OSCommand.Quote(oldName), c.OSCommand.Quote(newName))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) GetRawBranches() (string, error) {
|
||||
return c.RunWithOutput(c.NewCmdObj(`git for-each-ref --sort=-committerdate --format="%(HEAD)|%(refname:short)|%(upstream:short)|%(upstream:track)" refs/heads`))
|
||||
return c.Cmd.New(`git for-each-ref --sort=-committerdate --format="%(HEAD)|%(refname:short)|%(upstream:short)|%(upstream:track)" refs/heads`).RunWithOutput()
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ func TestGitCommandGetAllBranchGraph(t *testing.T) {
|
||||
return secureexec.Command("echo")
|
||||
}
|
||||
cmdStr := gitCmd.UserConfig.Git.AllBranchesLogCmd
|
||||
_, err := gitCmd.OSCommand.RunWithOutput(gitCmd.NewCmdObj(cmdStr))
|
||||
_, err := gitCmd.Cmd.New(cmdStr).RunWithOutput()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -10,18 +10,17 @@ import (
|
||||
|
||||
// RenameCommit renames the topmost commit with the given name
|
||||
func (c *GitCommand) RenameCommit(name string) error {
|
||||
return c.Run(c.NewCmdObj("git commit --allow-empty --amend --only -m " + c.OSCommand.Quote(name)))
|
||||
return c.Cmd.New("git commit --allow-empty --amend --only -m " + c.OSCommand.Quote(name)).Run()
|
||||
}
|
||||
|
||||
// ResetToCommit reset to commit
|
||||
func (c *GitCommand) ResetToCommit(sha string, strength string, envVars []string) error {
|
||||
cmdObj := c.NewCmdObj(fmt.Sprintf("git reset --%s %s", strength, sha)).
|
||||
return c.Cmd.New(fmt.Sprintf("git reset --%s %s", strength, sha)).
|
||||
// prevents git from prompting us for input which would freeze the program
|
||||
// TODO: see if this is actually needed here
|
||||
AddEnvVars("GIT_TERMINAL_PROMPT=0").
|
||||
AddEnvVars(envVars...)
|
||||
|
||||
return c.OSCommand.Run(cmdObj)
|
||||
AddEnvVars(envVars...).
|
||||
Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) CommitCmdObj(message string, flags string) oscommands.ICmdObj {
|
||||
@ -36,33 +35,33 @@ func (c *GitCommand) CommitCmdObj(message string, flags string) oscommands.ICmdO
|
||||
flagsStr = fmt.Sprintf(" %s", flags)
|
||||
}
|
||||
|
||||
return c.NewCmdObj(fmt.Sprintf("git commit%s%s", flagsStr, lineArgs))
|
||||
return c.Cmd.New(fmt.Sprintf("git commit%s%s", flagsStr, lineArgs))
|
||||
}
|
||||
|
||||
// Get the subject of the HEAD commit
|
||||
func (c *GitCommand) GetHeadCommitMessage() (string, error) {
|
||||
message, err := c.RunWithOutput(c.NewCmdObj("git log -1 --pretty=%s"))
|
||||
message, err := c.Cmd.New("git log -1 --pretty=%s").RunWithOutput()
|
||||
return strings.TrimSpace(message), err
|
||||
}
|
||||
|
||||
func (c *GitCommand) GetCommitMessage(commitSha string) (string, error) {
|
||||
cmdStr := "git rev-list --format=%B --max-count=1 " + commitSha
|
||||
messageWithHeader, err := c.RunWithOutput(c.NewCmdObj(cmdStr))
|
||||
messageWithHeader, err := c.Cmd.New(cmdStr).RunWithOutput()
|
||||
message := strings.Join(strings.SplitAfter(messageWithHeader, "\n")[1:], "\n")
|
||||
return strings.TrimSpace(message), err
|
||||
}
|
||||
|
||||
func (c *GitCommand) GetCommitMessageFirstLine(sha string) (string, error) {
|
||||
return c.RunWithOutput(c.NewCmdObj(fmt.Sprintf("git show --no-patch --pretty=format:%%s %s", sha)))
|
||||
return c.Cmd.New(fmt.Sprintf("git show --no-patch --pretty=format:%%s %s", sha)).RunWithOutput()
|
||||
}
|
||||
|
||||
// AmendHead amends HEAD with whatever is staged in your working tree
|
||||
func (c *GitCommand) AmendHead() error {
|
||||
return c.OSCommand.Run(c.AmendHeadCmdObj())
|
||||
return c.AmendHeadCmdObj().Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) AmendHeadCmdObj() oscommands.ICmdObj {
|
||||
return c.NewCmdObj("git commit --amend --no-edit --allow-empty")
|
||||
return c.Cmd.New("git commit --amend --no-edit --allow-empty")
|
||||
}
|
||||
|
||||
func (c *GitCommand) ShowCmdObj(sha string, filterPath string) oscommands.ICmdObj {
|
||||
@ -73,16 +72,16 @@ func (c *GitCommand) ShowCmdObj(sha string, filterPath string) oscommands.ICmdOb
|
||||
}
|
||||
|
||||
cmdStr := fmt.Sprintf("git show --submodule --color=%s --unified=%d --no-renames --stat -p %s %s", c.colorArg(), contextSize, sha, filterPathArg)
|
||||
return c.NewCmdObj(cmdStr)
|
||||
return c.Cmd.New(cmdStr)
|
||||
}
|
||||
|
||||
// Revert reverts the selected commit by sha
|
||||
func (c *GitCommand) Revert(sha string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git revert %s", sha)))
|
||||
return c.Cmd.New(fmt.Sprintf("git revert %s", sha)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) RevertMerge(sha string, parentNumber int) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git revert %s -m %d", sha, parentNumber)))
|
||||
return c.Cmd.New(fmt.Sprintf("git revert %s -m %d", sha, parentNumber)).Run()
|
||||
}
|
||||
|
||||
// CherryPickCommits begins an interactive rebase with the given shas being cherry picked onto HEAD
|
||||
@ -92,15 +91,15 @@ func (c *GitCommand) CherryPickCommits(commits []*models.Commit) error {
|
||||
todo = "pick " + commit.Sha + " " + commit.Name + "\n" + todo
|
||||
}
|
||||
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand("HEAD", todo, false)
|
||||
cmdObj, err := c.PrepareInteractiveRebaseCommand("HEAD", todo, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.OSCommand.Run(cmd)
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
// CreateFixupCommit creates a commit that fixes up a previous commit
|
||||
func (c *GitCommand) CreateFixupCommit(sha string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git commit --fixup=%s", sha)))
|
||||
return c.Cmd.New(fmt.Sprintf("git commit --fixup=%s", sha)).Run()
|
||||
}
|
||||
|
@ -25,26 +25,26 @@ func (c *GitCommand) CatFile(fileName string) (string, error) {
|
||||
}
|
||||
|
||||
func (c *GitCommand) OpenMergeToolCmdObj() oscommands.ICmdObj {
|
||||
return c.NewCmdObj("git mergetool")
|
||||
return c.Cmd.New("git mergetool")
|
||||
}
|
||||
|
||||
func (c *GitCommand) OpenMergeTool() error {
|
||||
return c.Run(c.OpenMergeToolCmdObj())
|
||||
return c.OpenMergeToolCmdObj().Run()
|
||||
}
|
||||
|
||||
// StageFile stages a file
|
||||
func (c *GitCommand) StageFile(fileName string) error {
|
||||
return c.Run(c.NewCmdObj("git add -- " + c.OSCommand.Quote(fileName)))
|
||||
return c.Cmd.New("git add -- " + c.OSCommand.Quote(fileName)).Run()
|
||||
}
|
||||
|
||||
// StageAll stages all files
|
||||
func (c *GitCommand) StageAll() error {
|
||||
return c.Run(c.NewCmdObj("git add -A"))
|
||||
return c.Cmd.New("git add -A").Run()
|
||||
}
|
||||
|
||||
// UnstageAll unstages all files
|
||||
func (c *GitCommand) UnstageAll() error {
|
||||
return c.Run(c.NewCmdObj("git reset"))
|
||||
return c.Cmd.New("git reset").Run()
|
||||
}
|
||||
|
||||
// UnStageFile unstages a file
|
||||
@ -57,8 +57,8 @@ func (c *GitCommand) UnStageFile(fileNames []string, reset bool) error {
|
||||
}
|
||||
|
||||
for _, name := range fileNames {
|
||||
cmdObj := c.NewCmdObj(fmt.Sprintf(command, c.OSCommand.Quote(name)))
|
||||
if err := c.Run(cmdObj); err != nil {
|
||||
err := c.Cmd.New(fmt.Sprintf(command, c.OSCommand.Quote(name))).Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -122,22 +122,22 @@ func (c *GitCommand) DiscardAllFileChanges(file *models.File) error {
|
||||
quotedFileName := c.OSCommand.Quote(file.Name)
|
||||
|
||||
if file.ShortStatus == "AA" {
|
||||
if err := c.Run(c.NewCmdObj("git checkout --ours -- " + quotedFileName)); err != nil {
|
||||
if err := c.Cmd.New("git checkout --ours -- " + quotedFileName).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.Run(c.NewCmdObj("git add -- " + quotedFileName)); err != nil {
|
||||
if err := c.Cmd.New("git add -- " + quotedFileName).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if file.ShortStatus == "DU" {
|
||||
return c.Run(c.NewCmdObj("git rm -- " + quotedFileName))
|
||||
return c.Cmd.New("git rm -- " + quotedFileName).Run()
|
||||
}
|
||||
|
||||
// if the file isn't tracked, we assume you want to delete it
|
||||
if file.HasStagedChanges || file.HasMergeConflicts {
|
||||
if err := c.Run(c.NewCmdObj("git reset -- " + quotedFileName)); err != nil {
|
||||
if err := c.Cmd.New("git reset -- " + quotedFileName).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ func (c *GitCommand) DiscardUnstagedDirChanges(node *filetree.FileNode) error {
|
||||
}
|
||||
|
||||
quotedPath := c.OSCommand.Quote(node.GetPath())
|
||||
if err := c.Run(c.NewCmdObj("git checkout -- " + quotedPath)); err != nil {
|
||||
if err := c.Cmd.New("git checkout -- " + quotedPath).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ func (c *GitCommand) RemoveUntrackedDirFiles(node *filetree.FileNode) error {
|
||||
// DiscardUnstagedFileChanges directly
|
||||
func (c *GitCommand) DiscardUnstagedFileChanges(file *models.File) error {
|
||||
quotedFileName := c.OSCommand.Quote(file.Name)
|
||||
return c.Run(c.NewCmdObj("git checkout -- " + quotedFileName))
|
||||
return c.Cmd.New("git checkout -- " + quotedFileName).Run()
|
||||
}
|
||||
|
||||
// Ignore adds a file to the gitignore for the repo
|
||||
@ -199,7 +199,7 @@ func (c *GitCommand) Ignore(filename string) error {
|
||||
// WorktreeFileDiff returns the diff of a file
|
||||
func (c *GitCommand) WorktreeFileDiff(file *models.File, plain bool, cached bool, ignoreWhitespace bool) string {
|
||||
// for now we assume an error means the file was deleted
|
||||
s, _ := c.OSCommand.RunWithOutput(c.WorktreeFileDiffCmdObj(file, plain, cached, ignoreWhitespace))
|
||||
s, _ := c.WorktreeFileDiffCmdObj(file, plain, cached, ignoreWhitespace).RunWithOutput()
|
||||
return s
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ func (c *GitCommand) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cache
|
||||
|
||||
cmdStr := fmt.Sprintf("git diff --submodule --no-ext-diff --unified=%d --color=%s %s %s %s %s", contextSize, colorArg, ignoreWhitespaceArg, cachedArg, trackedArg, quotedPath)
|
||||
|
||||
return c.NewCmdObj(cmdStr)
|
||||
return c.Cmd.New(cmdStr)
|
||||
}
|
||||
|
||||
func (c *GitCommand) ApplyPatch(patch string, flags ...string) error {
|
||||
@ -240,14 +240,13 @@ func (c *GitCommand) ApplyPatch(patch string, flags ...string) error {
|
||||
flagStr += " --" + flag
|
||||
}
|
||||
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git apply %s %s", flagStr, c.OSCommand.Quote(filepath))))
|
||||
return c.Cmd.New(fmt.Sprintf("git apply %s %s", flagStr, c.OSCommand.Quote(filepath))).Run()
|
||||
}
|
||||
|
||||
// ShowFileDiff get the diff of specified from and to. Typically this will be used for a single commit so it'll be 123abc^..123abc
|
||||
// but when we're in diff mode it could be any 'from' to any 'to'. The reverse flag is also here thanks to diff mode.
|
||||
func (c *GitCommand) ShowFileDiff(from string, to string, reverse bool, fileName string, plain bool) (string, error) {
|
||||
cmdObj := c.ShowFileDiffCmdObj(from, to, reverse, fileName, plain)
|
||||
return c.RunWithOutput(cmdObj)
|
||||
return c.ShowFileDiffCmdObj(from, to, reverse, fileName, plain).RunWithOutput()
|
||||
}
|
||||
|
||||
func (c *GitCommand) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) oscommands.ICmdObj {
|
||||
@ -262,12 +261,12 @@ func (c *GitCommand) ShowFileDiffCmdObj(from string, to string, reverse bool, fi
|
||||
reverseFlag = " -R "
|
||||
}
|
||||
|
||||
return c.NewCmdObj(fmt.Sprintf("git diff --submodule --no-ext-diff --unified=%d --no-renames --color=%s %s %s %s -- %s", contextSize, colorArg, from, to, reverseFlag, c.OSCommand.Quote(fileName)))
|
||||
return c.Cmd.New(fmt.Sprintf("git diff --submodule --no-ext-diff --unified=%d --no-renames --color=%s %s %s %s -- %s", contextSize, colorArg, from, to, reverseFlag, c.OSCommand.Quote(fileName)))
|
||||
}
|
||||
|
||||
// CheckoutFile checks out the file for the given commit
|
||||
func (c *GitCommand) CheckoutFile(commitSha, fileName string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git checkout %s -- %s", commitSha, c.OSCommand.Quote(fileName))))
|
||||
return c.Cmd.New(fmt.Sprintf("git checkout %s -- %s", commitSha, c.OSCommand.Quote(fileName))).Run()
|
||||
}
|
||||
|
||||
// DiscardOldFileChanges discards changes to a file from an old commit
|
||||
@ -277,7 +276,7 @@ func (c *GitCommand) DiscardOldFileChanges(commits []*models.Commit, commitIndex
|
||||
}
|
||||
|
||||
// check if file exists in previous commit (this command returns an error if the file doesn't exist)
|
||||
if err := c.Run(c.NewCmdObj("git cat-file -e HEAD^:" + c.OSCommand.Quote(fileName))); err != nil {
|
||||
if err := c.Cmd.New("git cat-file -e HEAD^:" + c.OSCommand.Quote(fileName)).Run(); err != nil {
|
||||
if err := c.OSCommand.Remove(fileName); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -300,17 +299,17 @@ func (c *GitCommand) DiscardOldFileChanges(commits []*models.Commit, commitIndex
|
||||
|
||||
// DiscardAnyUnstagedFileChanges discards any unstages file changes via `git checkout -- .`
|
||||
func (c *GitCommand) DiscardAnyUnstagedFileChanges() error {
|
||||
return c.Run(c.NewCmdObj("git checkout -- ."))
|
||||
return c.Cmd.New("git checkout -- .").Run()
|
||||
}
|
||||
|
||||
// RemoveTrackedFiles will delete the given file(s) even if they are currently tracked
|
||||
func (c *GitCommand) RemoveTrackedFiles(name string) error {
|
||||
return c.Run(c.NewCmdObj("git rm -r --cached -- " + c.OSCommand.Quote(name)))
|
||||
return c.Cmd.New("git rm -r --cached -- " + c.OSCommand.Quote(name)).Run()
|
||||
}
|
||||
|
||||
// RemoveUntrackedFiles runs `git clean -fd`
|
||||
func (c *GitCommand) RemoveUntrackedFiles() error {
|
||||
return c.Run(c.NewCmdObj("git clean -fd"))
|
||||
return c.Cmd.New("git clean -fd").Run()
|
||||
}
|
||||
|
||||
// ResetAndClean removes all unstaged changes and removes all untracked files
|
||||
@ -350,7 +349,7 @@ func (c *GitCommand) EditFileCmdStr(filename string, lineNumber int) (string, er
|
||||
editor = c.OSCommand.Getenv("EDITOR")
|
||||
}
|
||||
if editor == "" {
|
||||
if err := c.OSCommand.Run(c.NewCmdObj("which vi")); err == nil {
|
||||
if err := c.OSCommand.Cmd.New("which vi").Run(); err == nil {
|
||||
editor = "vi"
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
|
||||
@ -42,6 +41,8 @@ type GitCommand struct {
|
||||
// Coincidentally at the moment it's the same view that OnRunCommand logs to
|
||||
// but that need not always be the case.
|
||||
GetCmdWriter func() io.Writer
|
||||
|
||||
Cmd oscommands.ICmdObjBuilder
|
||||
}
|
||||
|
||||
// NewGitCommand it runs git commands
|
||||
@ -68,6 +69,8 @@ func NewGitCommand(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := NewGitCmdObjBuilder(cmn.Log, osCommand.Cmd)
|
||||
|
||||
gitCommand := &GitCommand{
|
||||
Common: cmn,
|
||||
OSCommand: osCommand,
|
||||
@ -76,6 +79,7 @@ func NewGitCommand(
|
||||
PushToCurrent: pushToCurrent,
|
||||
GitConfig: gitConfig,
|
||||
GetCmdWriter: func() io.Writer { return ioutil.Discard },
|
||||
Cmd: cmd,
|
||||
}
|
||||
|
||||
gitCommand.PatchManager = patch.NewPatchManager(gitCommand.Log, gitCommand.ApplyPatch, gitCommand.ShowFileDiff)
|
||||
@ -215,44 +219,5 @@ func findDotGitDir(stat func(string) (os.FileInfo, error), readFile func(filenam
|
||||
}
|
||||
|
||||
func VerifyInGitRepo(osCommand *oscommands.OSCommand) error {
|
||||
return osCommand.Run(osCommand.NewCmdObj("git rev-parse --git-dir"))
|
||||
}
|
||||
|
||||
func (c *GitCommand) Run(cmdObj oscommands.ICmdObj) error {
|
||||
_, err := c.RunWithOutput(cmdObj)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *GitCommand) RunWithOutput(cmdObj oscommands.ICmdObj) (string, error) {
|
||||
// TODO: have this retry logic in other places we run the command
|
||||
waitTime := 50 * time.Millisecond
|
||||
retryCount := 5
|
||||
attempt := 0
|
||||
|
||||
for {
|
||||
output, err := c.OSCommand.RunWithOutput(cmdObj)
|
||||
if err != nil {
|
||||
// if we have an error based on the index lock, we should wait a bit and then retry
|
||||
if strings.Contains(output, ".git/index.lock") {
|
||||
c.Log.Error(output)
|
||||
c.Log.Info("index.lock prevented command from running. Retrying command after a small wait")
|
||||
attempt++
|
||||
time.Sleep(waitTime)
|
||||
if attempt < retryCount {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return output, err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *GitCommand) NewCmdObj(cmdStr string) oscommands.ICmdObj {
|
||||
return c.OSCommand.NewCmdObj(cmdStr).AddEnvVars("GIT_OPTIONAL_LOCKS=0")
|
||||
}
|
||||
|
||||
func (c *GitCommand) NewCmdObjWithLog(cmdStr string) oscommands.ICmdObj {
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
c.OSCommand.LogCmdObj(cmdObj)
|
||||
return cmdObj
|
||||
return osCommand.Cmd.New("git rev-parse --git-dir").Run()
|
||||
}
|
||||
|
47
pkg/commands/git_cmd_obj_builder.go
Normal file
47
pkg/commands/git_cmd_obj_builder.go
Normal file
@ -0,0 +1,47 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// all we're doing here is wrapping the default command object builder with
|
||||
// some git-specific stuff: e.g. adding a git-specific env var
|
||||
|
||||
type gitCmdObjBuilder struct {
|
||||
innerBuilder *oscommands.CmdObjBuilder
|
||||
}
|
||||
|
||||
var _ oscommands.ICmdObjBuilder = &gitCmdObjBuilder{}
|
||||
|
||||
func NewGitCmdObjBuilder(log *logrus.Entry, innerBuilder *oscommands.CmdObjBuilder) *gitCmdObjBuilder {
|
||||
// the price of having a convenient interface where we can say .New(...).Run() is that our builder now depends on our runner, so when we want to wrap the default builder/runner in new functionality we need to jump through some hoops. We could avoid the use of a decorator function here by just exporting the runner field on the default builder but that would be misleading because we don't want anybody using that to run commands (i.e. we want there to be a single API used across the codebase)
|
||||
updatedBuilder := innerBuilder.CloneWithNewRunner(func(runner oscommands.ICmdObjRunner) oscommands.ICmdObjRunner {
|
||||
return &gitCmdObjRunner{
|
||||
log: log,
|
||||
innerRunner: runner,
|
||||
}
|
||||
})
|
||||
|
||||
return &gitCmdObjBuilder{
|
||||
innerBuilder: updatedBuilder,
|
||||
}
|
||||
}
|
||||
|
||||
var defaultEnvVar = "GIT_OPTIONAL_LOCKS=0"
|
||||
|
||||
func (self *gitCmdObjBuilder) New(cmdStr string) oscommands.ICmdObj {
|
||||
return self.innerBuilder.New(cmdStr).AddEnvVars(defaultEnvVar)
|
||||
}
|
||||
|
||||
func (self *gitCmdObjBuilder) NewFromArgs(args []string) oscommands.ICmdObj {
|
||||
return self.innerBuilder.NewFromArgs(args).AddEnvVars(defaultEnvVar)
|
||||
}
|
||||
|
||||
func (self *gitCmdObjBuilder) NewShell(cmdStr string) oscommands.ICmdObj {
|
||||
return self.innerBuilder.NewShell(cmdStr).AddEnvVars(defaultEnvVar)
|
||||
}
|
||||
|
||||
func (self *gitCmdObjBuilder) Quote(str string) string {
|
||||
return self.innerBuilder.Quote(str)
|
||||
}
|
49
pkg/commands/git_cmd_obj_runner.go
Normal file
49
pkg/commands/git_cmd_obj_runner.go
Normal file
@ -0,0 +1,49 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// here we're wrapping the default command runner in some git-specific stuff e.g. retry logic if we get an error due to the presence of .git/index.lock
|
||||
|
||||
type gitCmdObjRunner struct {
|
||||
log *logrus.Entry
|
||||
innerRunner oscommands.ICmdObjRunner
|
||||
}
|
||||
|
||||
func (self *gitCmdObjRunner) Run(cmdObj oscommands.ICmdObj) error {
|
||||
_, err := self.RunWithOutput(cmdObj)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *gitCmdObjRunner) RunWithOutput(cmdObj oscommands.ICmdObj) (string, error) {
|
||||
// TODO: have this retry logic in other places we run the command
|
||||
waitTime := 50 * time.Millisecond
|
||||
retryCount := 5
|
||||
attempt := 0
|
||||
|
||||
for {
|
||||
output, err := self.innerRunner.RunWithOutput(cmdObj)
|
||||
if err != nil {
|
||||
// if we have an error based on the index lock, we should wait a bit and then retry
|
||||
if strings.Contains(output, ".git/index.lock") {
|
||||
self.log.Error(output)
|
||||
self.log.Info("index.lock prevented command from running. Retrying command after a small wait")
|
||||
attempt++
|
||||
time.Sleep(waitTime)
|
||||
if attempt < retryCount {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return output, err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *gitCmdObjRunner) RunLineOutputCmd(cmdObj oscommands.ICmdObj, onLine func(line string) (bool, error)) error {
|
||||
return self.innerRunner.RunLineOutputCmd(cmdObj, onLine)
|
||||
}
|
@ -42,6 +42,51 @@ func NewBranchListBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
// Build the list of branches for the current repo
|
||||
func (b *BranchListBuilder) Build() []*models.Branch {
|
||||
branches := b.obtainBranches()
|
||||
|
||||
reflogBranches := b.obtainReflogBranches()
|
||||
|
||||
// loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches
|
||||
branchesWithRecency := make([]*models.Branch, 0)
|
||||
outer:
|
||||
for _, reflogBranch := range reflogBranches {
|
||||
for j, branch := range branches {
|
||||
if branch.Head {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(reflogBranch.Name, branch.Name) {
|
||||
branch.Recency = reflogBranch.Recency
|
||||
branchesWithRecency = append(branchesWithRecency, branch)
|
||||
branches = append(branches[0:j], branches[j+1:]...)
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
branches = append(branchesWithRecency, branches...)
|
||||
|
||||
foundHead := false
|
||||
for i, branch := range branches {
|
||||
if branch.Head {
|
||||
foundHead = true
|
||||
branch.Recency = " *"
|
||||
branches = append(branches[0:i], branches[i+1:]...)
|
||||
branches = append([]*models.Branch{branch}, branches...)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundHead {
|
||||
currentBranchName, currentBranchDisplayName, err := b.getCurrentBranchName()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
branches = append([]*models.Branch{{Name: currentBranchName, DisplayName: currentBranchDisplayName, Head: true, Recency: " *"}}, branches...)
|
||||
}
|
||||
return branches
|
||||
}
|
||||
|
||||
func (b *BranchListBuilder) obtainBranches() []*models.Branch {
|
||||
output, err := b.getRawBranches()
|
||||
if err != nil {
|
||||
@ -103,51 +148,6 @@ func (b *BranchListBuilder) obtainBranches() []*models.Branch {
|
||||
return branches
|
||||
}
|
||||
|
||||
// Build the list of branches for the current repo
|
||||
func (b *BranchListBuilder) Build() []*models.Branch {
|
||||
branches := b.obtainBranches()
|
||||
|
||||
reflogBranches := b.obtainReflogBranches()
|
||||
|
||||
// loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches
|
||||
branchesWithRecency := make([]*models.Branch, 0)
|
||||
outer:
|
||||
for _, reflogBranch := range reflogBranches {
|
||||
for j, branch := range branches {
|
||||
if branch.Head {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(reflogBranch.Name, branch.Name) {
|
||||
branch.Recency = reflogBranch.Recency
|
||||
branchesWithRecency = append(branchesWithRecency, branch)
|
||||
branches = append(branches[0:j], branches[j+1:]...)
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
branches = append(branchesWithRecency, branches...)
|
||||
|
||||
foundHead := false
|
||||
for i, branch := range branches {
|
||||
if branch.Head {
|
||||
foundHead = true
|
||||
branch.Recency = " *"
|
||||
branches = append(branches[0:i], branches[i+1:]...)
|
||||
branches = append([]*models.Branch{branch}, branches...)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundHead {
|
||||
currentBranchName, currentBranchDisplayName, err := b.getCurrentBranchName()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
branches = append([]*models.Branch{{Name: currentBranchName, DisplayName: currentBranchDisplayName, Head: true, Recency: " *"}}, branches...)
|
||||
}
|
||||
return branches
|
||||
}
|
||||
|
||||
// TODO: only look at the new reflog commits, and otherwise store the recencies in
|
||||
// int form against the branch to recalculate the time ago
|
||||
func (b *BranchListBuilder) obtainReflogBranches() []*models.Branch {
|
||||
|
@ -14,7 +14,7 @@ func (c *GitCommand) GetFilesInDiff(from string, to string, reverse bool) ([]*mo
|
||||
reverseFlag = " -R "
|
||||
}
|
||||
|
||||
filenames, err := c.RunWithOutput(c.NewCmdObj(fmt.Sprintf("git diff --submodule --no-ext-diff --name-status -z --no-renames %s %s %s", reverseFlag, from, to)))
|
||||
filenames, err := c.Cmd.New(fmt.Sprintf("git diff --submodule --no-ext-diff --name-status -z --no-renames %s %s %s", reverseFlag, from, to)).RunWithOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -11,9 +11,8 @@ import (
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// context:
|
||||
@ -29,24 +28,28 @@ const SEPARATION_CHAR = "|"
|
||||
|
||||
// CommitListBuilder returns a list of Branch objects for the current repo
|
||||
type CommitListBuilder struct {
|
||||
Log *logrus.Entry
|
||||
GitCommand *GitCommand
|
||||
OSCommand *oscommands.OSCommand
|
||||
Tr *i18n.TranslationSet
|
||||
*common.Common
|
||||
cmd oscommands.ICmdObjBuilder
|
||||
|
||||
getCurrentBranchName func() (string, string, error)
|
||||
getRebaseMode func() (string, error)
|
||||
readFile func(filename string) ([]byte, error)
|
||||
dotGitDir string
|
||||
}
|
||||
|
||||
// NewCommitListBuilder builds a new commit list builder
|
||||
func NewCommitListBuilder(
|
||||
log *logrus.Entry,
|
||||
cmn *common.Common,
|
||||
gitCommand *GitCommand,
|
||||
osCommand *oscommands.OSCommand,
|
||||
tr *i18n.TranslationSet,
|
||||
) *CommitListBuilder {
|
||||
return &CommitListBuilder{
|
||||
Log: log,
|
||||
GitCommand: gitCommand,
|
||||
OSCommand: osCommand,
|
||||
Tr: tr,
|
||||
Common: cmn,
|
||||
cmd: gitCommand.Cmd,
|
||||
getCurrentBranchName: gitCommand.CurrentBranchName,
|
||||
getRebaseMode: gitCommand.RebaseMode,
|
||||
dotGitDir: gitCommand.DotGitDir,
|
||||
readFile: ioutil.ReadFile,
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +109,7 @@ func (c *CommitListBuilder) MergeRebasingCommits(commits []*models.Commit) ([]*m
|
||||
}
|
||||
}
|
||||
|
||||
rebaseMode, err := c.GitCommand.RebaseMode()
|
||||
rebaseMode, err := c.getRebaseMode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -131,7 +134,7 @@ func (c *CommitListBuilder) MergeRebasingCommits(commits []*models.Commit) ([]*m
|
||||
func (c *CommitListBuilder) GetCommits(opts GetCommitsOptions) ([]*models.Commit, error) {
|
||||
commits := []*models.Commit{}
|
||||
var rebasingCommits []*models.Commit
|
||||
rebaseMode, err := c.GitCommand.RebaseMode()
|
||||
rebaseMode, err := c.getRebaseMode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -152,9 +155,7 @@ func (c *CommitListBuilder) GetCommits(opts GetCommitsOptions) ([]*models.Commit
|
||||
passedFirstPushedCommit = true
|
||||
}
|
||||
|
||||
cmdObj := c.getLogCmd(opts)
|
||||
|
||||
err = c.OSCommand.RunLineOutputCmd(cmdObj, func(line string) (bool, error) {
|
||||
err = c.getLogCmd(opts).RunLineOutputCmd(func(line string) (bool, error) {
|
||||
if canExtractCommit(line) {
|
||||
commit := c.extractCommitFromLine(line)
|
||||
if commit.Sha == firstPushedCommit {
|
||||
@ -200,7 +201,7 @@ func (c *CommitListBuilder) getHydratedRebasingCommits(rebaseMode string) ([]*mo
|
||||
|
||||
// note that we're not filtering these as we do non-rebasing commits just because
|
||||
// I suspect that will cause some damage
|
||||
cmdObj := c.OSCommand.NewCmdObj(
|
||||
cmdObj := c.cmd.New(
|
||||
fmt.Sprintf(
|
||||
"git show %s --no-patch --oneline %s --abbrev=%d",
|
||||
strings.Join(commitShas, " "),
|
||||
@ -211,7 +212,7 @@ func (c *CommitListBuilder) getHydratedRebasingCommits(rebaseMode string) ([]*mo
|
||||
|
||||
hydratedCommits := make([]*models.Commit, 0, len(commits))
|
||||
i := 0
|
||||
err = c.OSCommand.RunLineOutputCmd(cmdObj, func(line string) (bool, error) {
|
||||
err = cmdObj.RunLineOutputCmd(func(line string) (bool, error) {
|
||||
if canExtractCommit(line) {
|
||||
commit := c.extractCommitFromLine(line)
|
||||
matchingCommit := commits[i]
|
||||
@ -242,7 +243,7 @@ func (c *CommitListBuilder) getRebasingCommits(rebaseMode string) ([]*models.Com
|
||||
|
||||
func (c *CommitListBuilder) getNormalRebasingCommits() ([]*models.Commit, error) {
|
||||
rewrittenCount := 0
|
||||
bytesContent, err := ioutil.ReadFile(filepath.Join(c.GitCommand.DotGitDir, "rebase-apply/rewritten"))
|
||||
bytesContent, err := c.readFile(filepath.Join(c.dotGitDir, "rebase-apply/rewritten"))
|
||||
if err == nil {
|
||||
content := string(bytesContent)
|
||||
rewrittenCount = len(strings.Split(content, "\n"))
|
||||
@ -250,7 +251,7 @@ func (c *CommitListBuilder) getNormalRebasingCommits() ([]*models.Commit, error)
|
||||
|
||||
// we know we're rebasing, so lets get all the files whose names have numbers
|
||||
commits := []*models.Commit{}
|
||||
err = filepath.Walk(filepath.Join(c.GitCommand.DotGitDir, "rebase-apply"), func(path string, f os.FileInfo, err error) error {
|
||||
err = filepath.Walk(filepath.Join(c.dotGitDir, "rebase-apply"), func(path string, f os.FileInfo, err error) error {
|
||||
if rewrittenCount > 0 {
|
||||
rewrittenCount--
|
||||
return nil
|
||||
@ -262,7 +263,7 @@ func (c *CommitListBuilder) getNormalRebasingCommits() ([]*models.Commit, error)
|
||||
if !re.MatchString(f.Name()) {
|
||||
return nil
|
||||
}
|
||||
bytesContent, err := ioutil.ReadFile(path)
|
||||
bytesContent, err := c.readFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -294,7 +295,7 @@ func (c *CommitListBuilder) getNormalRebasingCommits() ([]*models.Commit, error)
|
||||
// and extracts out the sha and names of commits that we still have to go
|
||||
// in the rebase:
|
||||
func (c *CommitListBuilder) getInteractiveRebasingCommits() ([]*models.Commit, error) {
|
||||
bytesContent, err := ioutil.ReadFile(filepath.Join(c.GitCommand.DotGitDir, "rebase-merge/git-rebase-todo"))
|
||||
bytesContent, err := c.readFile(filepath.Join(c.dotGitDir, "rebase-merge/git-rebase-todo"))
|
||||
if err != nil {
|
||||
c.Log.Error(fmt.Sprintf("error occurred reading git-rebase-todo: %s", err.Error()))
|
||||
// we assume an error means the file doesn't exist so we just return
|
||||
@ -362,7 +363,7 @@ func (c *CommitListBuilder) setCommitMergedStatuses(refName string, commits []*m
|
||||
}
|
||||
|
||||
func (c *CommitListBuilder) getMergeBase(refName string) (string, error) {
|
||||
currentBranch, _, err := c.GitCommand.CurrentBranchName()
|
||||
currentBranch, _, err := c.getCurrentBranchName()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -373,7 +374,7 @@ func (c *CommitListBuilder) getMergeBase(refName string) (string, error) {
|
||||
}
|
||||
|
||||
// swallowing error because it's not a big deal; probably because there are no commits yet
|
||||
output, _ := c.OSCommand.RunWithOutput(c.OSCommand.NewCmdObj(fmt.Sprintf("git merge-base %s %s", c.OSCommand.Quote(refName), c.OSCommand.Quote(baseBranch))))
|
||||
output, _ := c.cmd.New(fmt.Sprintf("git merge-base %s %s", c.cmd.Quote(refName), c.cmd.Quote(baseBranch))).RunWithOutput()
|
||||
return ignoringWarnings(output), nil
|
||||
}
|
||||
|
||||
@ -390,7 +391,7 @@ func ignoringWarnings(commandOutput string) string {
|
||||
// getFirstPushedCommit returns the first commit SHA which has been pushed to the ref's upstream.
|
||||
// all commits above this are deemed unpushed and marked as such.
|
||||
func (c *CommitListBuilder) getFirstPushedCommit(refName string) (string, error) {
|
||||
output, err := c.OSCommand.RunWithOutput(c.OSCommand.NewCmdObj(fmt.Sprintf("git merge-base %s %s@{u}", c.OSCommand.Quote(refName), c.OSCommand.Quote(refName))))
|
||||
output, err := c.cmd.New(fmt.Sprintf("git merge-base %s %s@{u}", c.cmd.Quote(refName), c.cmd.Quote(refName))).RunWithOutput()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -407,10 +408,10 @@ func (c *CommitListBuilder) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj
|
||||
|
||||
filterFlag := ""
|
||||
if opts.FilterPath != "" {
|
||||
filterFlag = fmt.Sprintf(" --follow -- %s", c.OSCommand.Quote(opts.FilterPath))
|
||||
filterFlag = fmt.Sprintf(" --follow -- %s", c.cmd.Quote(opts.FilterPath))
|
||||
}
|
||||
|
||||
config := c.GitCommand.UserConfig.Git.Log
|
||||
config := c.UserConfig.Git.Log
|
||||
|
||||
orderFlag := "--" + config.Order
|
||||
allFlag := ""
|
||||
@ -418,10 +419,10 @@ func (c *CommitListBuilder) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj
|
||||
allFlag = " --all"
|
||||
}
|
||||
|
||||
return c.OSCommand.NewCmdObj(
|
||||
return c.cmd.New(
|
||||
fmt.Sprintf(
|
||||
"git log %s %s %s --oneline %s %s --abbrev=%d %s",
|
||||
c.OSCommand.Quote(opts.RefName),
|
||||
c.cmd.Quote(opts.RefName),
|
||||
orderFlag,
|
||||
allFlag,
|
||||
prettyFormat,
|
||||
|
@ -80,7 +80,7 @@ func (c *GitCommand) GitStatus(opts GitStatusOptions) ([]FileStatus, error) {
|
||||
noRenamesFlag = "--no-renames"
|
||||
}
|
||||
|
||||
statusLines, err := c.RunWithOutput(c.NewCmdObj(fmt.Sprintf("git status %s --porcelain -z %s", opts.UntrackedFilesArg, noRenamesFlag)))
|
||||
statusLines, err := c.Cmd.New(fmt.Sprintf("git status %s --porcelain -z %s", opts.UntrackedFilesArg, noRenamesFlag)).RunWithOutput()
|
||||
if err != nil {
|
||||
return []FileStatus{}, err
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ func (c *GitCommand) GetReflogCommits(lastReflogCommit *models.Commit, filterPat
|
||||
filterPathArg = fmt.Sprintf(" --follow -- %s", c.OSCommand.Quote(filterPath))
|
||||
}
|
||||
|
||||
cmdObj := c.OSCommand.NewCmdObj(fmt.Sprintf(`git log -g --abbrev=20 --format="%%h %%ct %%gs" %s`, filterPathArg))
|
||||
cmdObj := c.OSCommand.Cmd.New(fmt.Sprintf(`git log -g --abbrev=20 --format="%%h %%ct %%gs" %s`, filterPathArg))
|
||||
onlyObtainedNewReflogCommits := false
|
||||
err := c.OSCommand.RunLineOutputCmd(cmdObj, func(line string) (bool, error) {
|
||||
err := cmdObj.RunLineOutputCmd(func(line string) (bool, error) {
|
||||
fields := strings.SplitN(line, " ", 3)
|
||||
if len(fields) <= 2 {
|
||||
return false, nil
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func (c *GitCommand) GetRemotes() ([]*models.Remote, error) {
|
||||
remoteBranchesStr, err := c.RunWithOutput(c.NewCmdObj("git branch -r"))
|
||||
remoteBranchesStr, err := c.Cmd.New("git branch -r").RunWithOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func (c *GitCommand) getUnfilteredStashEntries() []*models.StashEntry {
|
||||
rawString, _ := c.RunWithOutput(c.NewCmdObj("git stash list --pretty='%gs'"))
|
||||
rawString, _ := c.Cmd.New("git stash list --pretty='%gs'").RunWithOutput()
|
||||
stashEntries := []*models.StashEntry{}
|
||||
for i, line := range utils.SplitLines(rawString) {
|
||||
stashEntries = append(stashEntries, stashEntryFromLine(line, i))
|
||||
@ -24,7 +24,7 @@ func (c *GitCommand) GetStashEntries(filterPath string) []*models.StashEntry {
|
||||
return c.getUnfilteredStashEntries()
|
||||
}
|
||||
|
||||
rawString, err := c.RunWithOutput(c.NewCmdObj("git stash list --name-only"))
|
||||
rawString, err := c.Cmd.New("git stash list --name-only").RunWithOutput()
|
||||
if err != nil {
|
||||
return c.getUnfilteredStashEntries()
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
func (c *GitCommand) GetTags() ([]*models.Tag, error) {
|
||||
// get remote branches, sorted by creation date (descending)
|
||||
// see: https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---sortltkeygt
|
||||
remoteBranchesStr, err := c.OSCommand.RunWithOutput(c.NewCmdObj(`git tag --list --sort=-creatordate`))
|
||||
remoteBranchesStr, err := c.Cmd.New(`git tag --list --sort=-creatordate`).RunWithOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -5,18 +5,27 @@ import (
|
||||
)
|
||||
|
||||
// A command object is a general way to represent a command to be run on the
|
||||
// command line. If you want to log the command you'll use .ToString() and
|
||||
// if you want to run it you'll use .GetCmd()
|
||||
// command line.
|
||||
type ICmdObj interface {
|
||||
GetCmd() *exec.Cmd
|
||||
ToString() string
|
||||
AddEnvVars(...string) ICmdObj
|
||||
GetEnvVars() []string
|
||||
|
||||
Run() error
|
||||
RunWithOutput() (string, error)
|
||||
RunLineOutputCmd(onLine func(line string) (bool, error)) error
|
||||
|
||||
// logs command
|
||||
Log() ICmdObj
|
||||
}
|
||||
|
||||
type CmdObj struct {
|
||||
cmdStr string
|
||||
cmd *exec.Cmd
|
||||
|
||||
runner ICmdObjRunner
|
||||
logCommand func(ICmdObj)
|
||||
}
|
||||
|
||||
func (self *CmdObj) GetCmd() *exec.Cmd {
|
||||
@ -36,3 +45,21 @@ func (self *CmdObj) AddEnvVars(vars ...string) ICmdObj {
|
||||
func (self *CmdObj) GetEnvVars() []string {
|
||||
return self.cmd.Env
|
||||
}
|
||||
|
||||
func (self *CmdObj) Log() ICmdObj {
|
||||
self.logCommand(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *CmdObj) Run() error {
|
||||
return self.runner.Run(self)
|
||||
}
|
||||
|
||||
func (self *CmdObj) RunWithOutput() (string, error) {
|
||||
return self.runner.RunWithOutput(self)
|
||||
}
|
||||
|
||||
func (self *CmdObj) RunLineOutputCmd(onLine func(line string) (bool, error)) error {
|
||||
return self.runner.RunLineOutputCmd(self, onLine)
|
||||
}
|
||||
|
72
pkg/commands/oscommands/cmd_obj_builder.go
Normal file
72
pkg/commands/oscommands/cmd_obj_builder.go
Normal file
@ -0,0 +1,72 @@
|
||||
package oscommands
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/mgutz/str"
|
||||
)
|
||||
|
||||
type ICmdObjBuilder interface {
|
||||
// New returns a new command object based on the string provided
|
||||
New(cmdStr string) ICmdObj
|
||||
// NewShell takes a string like `git commit` and returns an executable shell command for it e.g. `sh -c 'git commit'`
|
||||
NewShell(commandStr string) ICmdObj
|
||||
// NewFromArgs takes a slice of strings like []string{"git", "commit"} and returns a new command object. This can be useful when you don't want to worry about whitespace and quoting and stuff.
|
||||
NewFromArgs(args []string) ICmdObj
|
||||
// Quote wraps a string in quotes with any necessary escaping applied. The reason for bundling this up with the other methods in this interface is that we basically always need to make use of this when creating new command objects.
|
||||
Quote(str string) string
|
||||
}
|
||||
|
||||
// poor man's version of explicitly saying that struct X implements interface Y
|
||||
var _ ICmdObjBuilder = &CmdObjBuilder{}
|
||||
|
||||
type CmdObjBuilder struct {
|
||||
runner ICmdObjRunner
|
||||
logCmdObj func(ICmdObj)
|
||||
// TODO: see if you can just remove this entirely and use secureexec.Command,
|
||||
// now that we're mocking out the runner itself.
|
||||
command func(string, ...string) *exec.Cmd
|
||||
platform *Platform
|
||||
}
|
||||
|
||||
func (self *CmdObjBuilder) New(cmdStr string) ICmdObj {
|
||||
args := str.ToArgv(cmdStr)
|
||||
cmd := self.command(args[0], args[1:]...)
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
return &CmdObj{
|
||||
cmdStr: cmdStr,
|
||||
cmd: cmd,
|
||||
runner: self.runner,
|
||||
logCommand: self.logCmdObj,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CmdObjBuilder) NewFromArgs(args []string) ICmdObj {
|
||||
cmd := self.command(args[0], args[1:]...)
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
return &CmdObj{
|
||||
cmdStr: strings.Join(args, " "),
|
||||
cmd: cmd,
|
||||
runner: self.runner,
|
||||
logCommand: self.logCmdObj,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CmdObjBuilder) NewShell(commandStr string) ICmdObj {
|
||||
return self.NewFromArgs([]string{self.platform.Shell, self.platform.ShellArg, commandStr})
|
||||
}
|
||||
|
||||
func (self *CmdObjBuilder) CloneWithNewRunner(decorate func(ICmdObjRunner) ICmdObjRunner) *CmdObjBuilder {
|
||||
decoratedRunner := decorate(self.runner)
|
||||
|
||||
return &CmdObjBuilder{
|
||||
runner: decoratedRunner,
|
||||
logCmdObj: self.logCmdObj,
|
||||
command: self.command,
|
||||
platform: self.platform,
|
||||
}
|
||||
}
|
79
pkg/commands/oscommands/cmd_obj_runner.go
Normal file
79
pkg/commands/oscommands/cmd_obj_runner.go
Normal file
@ -0,0 +1,79 @@
|
||||
package oscommands
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ICmdObjRunner interface {
|
||||
Run(cmdObj ICmdObj) error
|
||||
RunWithOutput(cmdObj ICmdObj) (string, error)
|
||||
RunLineOutputCmd(cmdObj ICmdObj, onLine func(line string) (bool, error)) error
|
||||
}
|
||||
|
||||
type RunExpectation func(ICmdObj) (string, error)
|
||||
|
||||
type RealRunner struct {
|
||||
log *logrus.Entry
|
||||
logCmdObj func(ICmdObj)
|
||||
}
|
||||
|
||||
func (self *RealRunner) Run(cmdObj ICmdObj) error {
|
||||
_, err := self.RunWithOutput(cmdObj)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *RealRunner) RunWithOutput(cmdObj ICmdObj) (string, error) {
|
||||
self.logCmdObj(cmdObj)
|
||||
output, err := sanitisedCommandOutput(cmdObj.GetCmd().CombinedOutput())
|
||||
if err != nil {
|
||||
self.log.WithField("command", cmdObj.ToString()).Error(output)
|
||||
}
|
||||
return output, err
|
||||
}
|
||||
|
||||
func (self *RealRunner) RunLineOutputCmd(cmdObj ICmdObj, onLine func(line string) (bool, error)) error {
|
||||
cmd := cmdObj.GetCmd()
|
||||
stdoutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(stdoutPipe)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
stop, err := onLine(line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stop {
|
||||
_ = cmd.Process.Kill()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
_ = cmd.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sanitisedCommandOutput(output []byte, err error) (string, error) {
|
||||
outputString := string(output)
|
||||
if err != nil {
|
||||
// errors like 'exit status 1' are not very useful so we'll create an error
|
||||
// from the combined output
|
||||
if outputString == "" {
|
||||
return "", utils.WrapError(err)
|
||||
}
|
||||
return outputString, errors.New(outputString)
|
||||
}
|
||||
return outputString, nil
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package oscommands
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -16,7 +15,6 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/secureexec"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/mgutz/str"
|
||||
)
|
||||
|
||||
// Platform stores the os state
|
||||
@ -55,7 +53,7 @@ type OSCommand struct {
|
||||
|
||||
removeFile func(string) error
|
||||
|
||||
IRunner
|
||||
Cmd *CmdObjBuilder
|
||||
}
|
||||
|
||||
// TODO: make these fields private
|
||||
@ -90,15 +88,20 @@ func NewCmdLogEntry(cmdStr string, span string, commandLine bool) CmdLogEntry {
|
||||
|
||||
// NewOSCommand os command runner
|
||||
func NewOSCommand(common *common.Common) *OSCommand {
|
||||
command := secureexec.Command
|
||||
platform := getPlatform()
|
||||
|
||||
c := &OSCommand{
|
||||
Common: common,
|
||||
Platform: getPlatform(),
|
||||
Command: secureexec.Command,
|
||||
Platform: platform,
|
||||
Command: command,
|
||||
Getenv: os.Getenv,
|
||||
removeFile: os.RemoveAll,
|
||||
}
|
||||
|
||||
c.IRunner = &RealRunner{c: c}
|
||||
runner := &RealRunner{log: common.Log, logCmdObj: c.LogCmdObj}
|
||||
c.Cmd = &CmdObjBuilder{runner: runner, command: command, logCmdObj: c.LogCmdObj, platform: platform}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
@ -162,8 +165,7 @@ func (c *OSCommand) OpenFile(filename string) error {
|
||||
"filename": c.Quote(filename),
|
||||
}
|
||||
command := utils.ResolvePlaceholderString(commandTemplate, templateValues)
|
||||
err := c.Run(c.NewShellCmdObjFromString(command))
|
||||
return err
|
||||
return c.Cmd.NewShell(command).Run()
|
||||
}
|
||||
|
||||
// OpenLink opens a file with the given
|
||||
@ -175,14 +177,17 @@ func (c *OSCommand) OpenLink(link string) error {
|
||||
}
|
||||
|
||||
command := utils.ResolvePlaceholderString(commandTemplate, templateValues)
|
||||
err := c.Run(c.NewShellCmdObjFromString(command))
|
||||
return err
|
||||
return c.Cmd.NewShell(command).Run()
|
||||
}
|
||||
|
||||
// Quote wraps a message in platform-specific quotation marks
|
||||
func (c *OSCommand) Quote(message string) string {
|
||||
return c.Cmd.Quote(message)
|
||||
}
|
||||
|
||||
func (self *CmdObjBuilder) Quote(message string) string {
|
||||
var quote string
|
||||
if c.Platform.OS == "windows" {
|
||||
if self.platform.OS == "windows" {
|
||||
quote = `\"`
|
||||
message = strings.NewReplacer(
|
||||
`"`, `"'"'"`,
|
||||
@ -289,7 +294,7 @@ func (c *OSCommand) PipeCommands(commandStrings ...string) error {
|
||||
logCmdStr += " | "
|
||||
}
|
||||
logCmdStr += str
|
||||
cmds[i] = c.NewCmdObj(str).GetCmd()
|
||||
cmds[i] = c.Cmd.New(str).GetCmd()
|
||||
}
|
||||
c.LogCommand(logCmdStr, true)
|
||||
|
||||
@ -365,127 +370,6 @@ func (c *OSCommand) RemoveFile(path string) error {
|
||||
return c.removeFile(path)
|
||||
}
|
||||
|
||||
// builders
|
||||
|
||||
func (c *OSCommand) NewCmdObj(cmdStr string) ICmdObj {
|
||||
args := str.ToArgv(cmdStr)
|
||||
cmd := c.Command(args[0], args[1:]...)
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
return &CmdObj{
|
||||
cmdStr: cmdStr,
|
||||
cmd: cmd,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *OSCommand) NewCmdObjFromArgs(args []string) ICmdObj {
|
||||
cmd := c.Command(args[0], args[1:]...)
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
return &CmdObj{
|
||||
cmdStr: strings.Join(args, " "),
|
||||
cmd: cmd,
|
||||
}
|
||||
}
|
||||
|
||||
// NewShellCmdObjFromString takes a string like `git commit` and returns an executable shell command for it
|
||||
func (c *OSCommand) NewShellCmdObjFromString(commandStr string) ICmdObj {
|
||||
quotedCommand := ""
|
||||
// Windows does not seem to like quotes around the command
|
||||
if c.Platform.OS == "windows" {
|
||||
quotedCommand = strings.NewReplacer(
|
||||
"^", "^^",
|
||||
"&", "^&",
|
||||
"|", "^|",
|
||||
"<", "^<",
|
||||
">", "^>",
|
||||
"%", "^%",
|
||||
).Replace(commandStr)
|
||||
} else {
|
||||
quotedCommand = c.Quote(commandStr)
|
||||
}
|
||||
|
||||
shellCommand := fmt.Sprintf("%s %s %s", c.Platform.Shell, c.Platform.ShellArg, quotedCommand)
|
||||
return c.NewCmdObj(shellCommand)
|
||||
}
|
||||
|
||||
// TODO: pick one of NewShellCmdObjFromString2 and ShellCommandFromString to use. I'm not sure
|
||||
// which one actually is better, but I suspect it's NewShellCmdObjFromString2
|
||||
func (c *OSCommand) NewShellCmdObjFromString2(command string) ICmdObj {
|
||||
return c.NewCmdObjFromArgs([]string{c.Platform.Shell, c.Platform.ShellArg, command})
|
||||
}
|
||||
|
||||
// runners
|
||||
|
||||
type IRunner interface {
|
||||
Run(cmdObj ICmdObj) error
|
||||
RunWithOutput(cmdObj ICmdObj) (string, error)
|
||||
RunLineOutputCmd(cmdObj ICmdObj, onLine func(line string) (bool, error)) error
|
||||
}
|
||||
|
||||
type RunExpectation func(ICmdObj) (string, error)
|
||||
|
||||
type RealRunner struct {
|
||||
c *OSCommand
|
||||
}
|
||||
|
||||
func (self *RealRunner) Run(cmdObj ICmdObj) error {
|
||||
_, err := self.RunWithOutput(cmdObj)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *RealRunner) RunWithOutput(cmdObj ICmdObj) (string, error) {
|
||||
self.c.LogCmdObj(cmdObj)
|
||||
output, err := sanitisedCommandOutput(cmdObj.GetCmd().CombinedOutput())
|
||||
if err != nil {
|
||||
self.c.Log.WithField("command", cmdObj.ToString()).Error(output)
|
||||
}
|
||||
return output, err
|
||||
}
|
||||
|
||||
func (self *RealRunner) RunLineOutputCmd(cmdObj ICmdObj, onLine func(line string) (bool, error)) error {
|
||||
cmd := cmdObj.GetCmd()
|
||||
stdoutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(stdoutPipe)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
stop, err := onLine(line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stop {
|
||||
_ = cmd.Process.Kill()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
_ = cmd.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sanitisedCommandOutput(output []byte, err error) (string, error) {
|
||||
outputString := string(output)
|
||||
if err != nil {
|
||||
// errors like 'exit status 1' are not very useful so we'll create an error
|
||||
// from the combined output
|
||||
if outputString == "" {
|
||||
return "", utils.WrapError(err)
|
||||
}
|
||||
return outputString, errors.New(outputString)
|
||||
}
|
||||
return outputString, nil
|
||||
}
|
||||
|
||||
func GetTempDir() string {
|
||||
return filepath.Join(os.TempDir(), "lazygit")
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func TestOSCommandRunWithOutput(t *testing.T) {
|
||||
|
||||
for _, s := range scenarios {
|
||||
c := NewDummyOSCommand()
|
||||
s.test(NewDummyOSCommand().RunWithOutput(c.NewCmdObj(s.command)))
|
||||
s.test(c.Cmd.New(s.command).RunWithOutput())
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ func TestOSCommandRun(t *testing.T) {
|
||||
|
||||
for _, s := range scenarios {
|
||||
c := NewDummyOSCommand()
|
||||
s.test(c.Run(c.NewCmdObj(s.command)))
|
||||
s.test(c.Cmd.New(s.command)).Run()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,12 +85,12 @@ func (c *GitCommand) MovePatchToSelectedCommit(commits []*models.Commit, sourceC
|
||||
todo = a + " " + commit.Sha + " " + commit.Name + "\n" + todo
|
||||
}
|
||||
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todo, true)
|
||||
cmdObj, err := c.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todo, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.OSCommand.Run(cmd); err != nil {
|
||||
if err := cmdObj.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ func (c *GitCommand) PullPatchIntoNewCommit(commits []*models.Commit, commitIdx
|
||||
|
||||
head_message, _ := c.GetHeadCommitMessage()
|
||||
new_message := fmt.Sprintf("Split from \"%s\"", head_message)
|
||||
err := c.OSCommand.Run(c.CommitCmdObj(new_message, ""))
|
||||
err := c.CommitCmdObj(new_message, "").Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -33,12 +33,12 @@ func (c *GitCommand) MoveCommitDown(commits []*models.Commit, index int) error {
|
||||
todo = "pick " + commit.Sha + " " + commit.Name + "\n" + todo
|
||||
}
|
||||
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand(commits[index+2].Sha, todo, true)
|
||||
cmdObj, err := c.PrepareInteractiveRebaseCommand(commits[index+2].Sha, todo, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.OSCommand.Run(cmd)
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) InteractiveRebase(commits []*models.Commit, index int, action string) error {
|
||||
@ -47,12 +47,12 @@ func (c *GitCommand) InteractiveRebase(commits []*models.Commit, index int, acti
|
||||
return err
|
||||
}
|
||||
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand(sha, todo, true)
|
||||
cmdObj, err := c.PrepareInteractiveRebaseCommand(sha, todo, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.OSCommand.Run(cmd)
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
// PrepareInteractiveRebaseCommand returns the cmd for an interactive rebase
|
||||
@ -69,7 +69,7 @@ func (c *GitCommand) PrepareInteractiveRebaseCommand(baseSha string, todo string
|
||||
cmdStr := fmt.Sprintf("git rebase --interactive --autostash --keep-empty %s", baseSha)
|
||||
c.Log.WithField("command", cmdStr).Info("RunCommand")
|
||||
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
cmdObj := c.Cmd.New(cmdStr)
|
||||
|
||||
gitSequenceEditor := ex
|
||||
if todo == "" {
|
||||
@ -217,26 +217,22 @@ func (c *GitCommand) BeginInteractiveRebaseForCommit(commits []*models.Commit, c
|
||||
return err
|
||||
}
|
||||
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand(sha, todo, true)
|
||||
cmdObj, err := c.PrepareInteractiveRebaseCommand(sha, todo, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.OSCommand.Run(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
// RebaseBranch interactive rebases onto a branch
|
||||
func (c *GitCommand) RebaseBranch(branchName string) error {
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand(branchName, "", false)
|
||||
cmdObj, err := c.PrepareInteractiveRebaseCommand(branchName, "", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.OSCommand.Run(cmd)
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
// GenericMerge takes a commandType of "merge" or "rebase" and a command of "abort", "skip" or "continue"
|
||||
@ -271,13 +267,14 @@ func (c *GitCommand) GenericMergeOrRebaseAction(commandType string, command stri
|
||||
}
|
||||
|
||||
func (c *GitCommand) runSkipEditorCommand(command string) error {
|
||||
cmdObj := c.OSCommand.NewCmdObj(command)
|
||||
cmdObj := c.OSCommand.Cmd.New(command)
|
||||
lazyGitPath := c.OSCommand.GetLazygitPath()
|
||||
cmdObj.AddEnvVars(
|
||||
"LAZYGIT_CLIENT_COMMAND=EXIT_IMMEDIATELY",
|
||||
"GIT_EDITOR="+lazyGitPath,
|
||||
"EDITOR="+lazyGitPath,
|
||||
"VISUAL="+lazyGitPath,
|
||||
)
|
||||
return c.OSCommand.Run(cmdObj)
|
||||
return cmdObj.
|
||||
AddEnvVars(
|
||||
"LAZYGIT_CLIENT_COMMAND=EXIT_IMMEDIATELY",
|
||||
"GIT_EDITOR="+lazyGitPath,
|
||||
"EDITOR="+lazyGitPath,
|
||||
"VISUAL="+lazyGitPath,
|
||||
).
|
||||
Run()
|
||||
}
|
||||
|
@ -7,24 +7,24 @@ import (
|
||||
)
|
||||
|
||||
func (c *GitCommand) AddRemote(name string, url string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git remote add %s %s", c.OSCommand.Quote(name), c.OSCommand.Quote(url))))
|
||||
return c.Cmd.New(fmt.Sprintf("git remote add %s %s", c.OSCommand.Quote(name), c.OSCommand.Quote(url))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) RemoveRemote(name string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git remote remove %s", c.OSCommand.Quote(name))))
|
||||
return c.Cmd.New(fmt.Sprintf("git remote remove %s", c.OSCommand.Quote(name))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) RenameRemote(oldRemoteName string, newRemoteName string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git remote rename %s %s", c.OSCommand.Quote(oldRemoteName), c.OSCommand.Quote(newRemoteName))))
|
||||
return c.Cmd.New(fmt.Sprintf("git remote rename %s %s", c.OSCommand.Quote(oldRemoteName), c.OSCommand.Quote(newRemoteName))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) UpdateRemoteUrl(remoteName string, updatedUrl string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git remote set-url %s %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(updatedUrl))))
|
||||
return c.Cmd.New(fmt.Sprintf("git remote set-url %s %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(updatedUrl))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) DeleteRemoteBranch(remoteName string, branchName string, promptUserForCredential func(string) string) error {
|
||||
command := fmt.Sprintf("git push %s --delete %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(branchName))
|
||||
cmdObj := c.NewCmdObj(command)
|
||||
cmdObj := c.Cmd.New(command)
|
||||
return c.DetectUnamePass(cmdObj, promptUserForCredential)
|
||||
}
|
||||
|
||||
@ -34,10 +34,10 @@ func (c *GitCommand) DetectUnamePass(cmdObj oscommands.ICmdObj, promptUserForCre
|
||||
|
||||
// CheckRemoteBranchExists Returns remote branch
|
||||
func (c *GitCommand) CheckRemoteBranchExists(branchName string) bool {
|
||||
_, err := c.RunWithOutput(c.NewCmdObj(
|
||||
_, err := c.Cmd.New(
|
||||
fmt.Sprintf("git show-ref --verify -- refs/remotes/origin/%s",
|
||||
c.OSCommand.Quote(branchName),
|
||||
)))
|
||||
)).RunWithOutput()
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ import "fmt"
|
||||
|
||||
// StashDo modify stash
|
||||
func (c *GitCommand) StashDo(index int, method string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git stash %s stash@{%d}", method, index)))
|
||||
return c.Cmd.New(fmt.Sprintf("git stash %s stash@{%d}", method, index)).Run()
|
||||
}
|
||||
|
||||
// StashSave save stash
|
||||
// TODO: before calling this, check if there is anything to save
|
||||
func (c *GitCommand) StashSave(message string) error {
|
||||
return c.Run(c.NewCmdObj("git stash save " + c.OSCommand.Quote(message)))
|
||||
return c.Cmd.New("git stash save " + c.OSCommand.Quote(message)).Run()
|
||||
}
|
||||
|
||||
// GetStashEntryDiff stash diff
|
||||
@ -22,7 +22,7 @@ func (c *GitCommand) ShowStashEntryCmdStr(index int) string {
|
||||
// shoutouts to Joe on https://stackoverflow.com/questions/14759748/stashing-only-staged-changes-in-git-is-it-possible
|
||||
func (c *GitCommand) StashSaveStagedChanges(message string) error {
|
||||
// wrap in 'writing', which uses a mutex
|
||||
if err := c.Run(c.NewCmdObj("git stash --keep-index")); err != nil {
|
||||
if err := c.Cmd.New("git stash --keep-index").Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ func (c *GitCommand) StashSaveStagedChanges(message string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.Run(c.NewCmdObj("git stash apply stash@{1}")); err != nil {
|
||||
if err := c.Cmd.New("git stash apply stash@{1}").Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ func (c *GitCommand) StashSaveStagedChanges(message string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.Run(c.NewCmdObj("git stash drop stash@{1}")); err != nil {
|
||||
if err := c.Cmd.New("git stash drop stash@{1}").Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -71,28 +71,28 @@ func (c *GitCommand) SubmoduleStash(submodule *models.SubmoduleConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.Run(c.NewCmdObj("git -C " + c.OSCommand.Quote(submodule.Path) + " stash --include-untracked"))
|
||||
return c.Cmd.New("git -C " + c.OSCommand.Quote(submodule.Path) + " stash --include-untracked").Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleReset(submodule *models.SubmoduleConfig) error {
|
||||
return c.Run(c.NewCmdObj("git submodule update --init --force -- " + c.OSCommand.Quote(submodule.Path)))
|
||||
return c.Cmd.New("git submodule update --init --force -- " + c.OSCommand.Quote(submodule.Path)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleUpdateAll() error {
|
||||
// not doing an --init here because the user probably doesn't want that
|
||||
return c.Run(c.NewCmdObj("git submodule update --force"))
|
||||
return c.Cmd.New("git submodule update --force").Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleDelete(submodule *models.SubmoduleConfig) error {
|
||||
// based on https://gist.github.com/myusuf3/7f645819ded92bda6677
|
||||
|
||||
if err := c.Run(c.NewCmdObj("git submodule deinit --force -- " + c.OSCommand.Quote(submodule.Path))); err != nil {
|
||||
if err := c.Cmd.New("git submodule deinit --force -- " + c.OSCommand.Quote(submodule.Path)).Run(); err != nil {
|
||||
if strings.Contains(err.Error(), "did not match any file(s) known to git") {
|
||||
if err := c.Run(c.NewCmdObj("git config --file .gitmodules --remove-section submodule." + c.OSCommand.Quote(submodule.Name))); err != nil {
|
||||
if err := c.Cmd.New("git config --file .gitmodules --remove-section submodule." + c.OSCommand.Quote(submodule.Name)).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.Run(c.NewCmdObj("git config --remove-section submodule." + c.OSCommand.Quote(submodule.Name))); err != nil {
|
||||
if err := c.Cmd.New("git config --remove-section submodule." + c.OSCommand.Quote(submodule.Name)).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ func (c *GitCommand) SubmoduleDelete(submodule *models.SubmoduleConfig) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.Run(c.NewCmdObj("git rm --force -r " + submodule.Path)); err != nil {
|
||||
if err := c.Cmd.New("git rm --force -r " + submodule.Path).Run(); err != nil {
|
||||
// if the directory isn't there then that's fine
|
||||
c.Log.Error(err)
|
||||
}
|
||||
@ -111,23 +111,24 @@ func (c *GitCommand) SubmoduleDelete(submodule *models.SubmoduleConfig) error {
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleAdd(name string, path string, url string) error {
|
||||
return c.OSCommand.Run(
|
||||
c.OSCommand.NewCmdObj(
|
||||
return c.Cmd.
|
||||
New(
|
||||
fmt.Sprintf(
|
||||
"git submodule add --force --name %s -- %s %s ",
|
||||
c.OSCommand.Quote(name),
|
||||
c.OSCommand.Quote(url),
|
||||
c.OSCommand.Quote(path),
|
||||
)))
|
||||
)).
|
||||
Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleUpdateUrl(name string, path string, newUrl string) error {
|
||||
// the set-url command is only for later git versions so we're doing it manually here
|
||||
if err := c.Run(c.NewCmdObj("git config --file .gitmodules submodule." + c.OSCommand.Quote(name) + ".url " + c.OSCommand.Quote(newUrl))); err != nil {
|
||||
if err := c.Cmd.New("git config --file .gitmodules submodule." + c.OSCommand.Quote(name) + ".url " + c.OSCommand.Quote(newUrl)).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.Run(c.NewCmdObj("git submodule sync -- " + c.OSCommand.Quote(path))); err != nil {
|
||||
if err := c.Cmd.New("git submodule sync -- " + c.OSCommand.Quote(path)).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -135,27 +136,27 @@ func (c *GitCommand) SubmoduleUpdateUrl(name string, path string, newUrl string)
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleInit(path string) error {
|
||||
return c.Run(c.NewCmdObj("git submodule init -- " + c.OSCommand.Quote(path)))
|
||||
return c.Cmd.New("git submodule init -- " + c.OSCommand.Quote(path)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleUpdate(path string) error {
|
||||
return c.Run(c.NewCmdObj("git submodule update --init -- " + c.OSCommand.Quote(path)))
|
||||
return c.Cmd.New("git submodule update --init -- " + c.OSCommand.Quote(path)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleBulkInitCmdObj() oscommands.ICmdObj {
|
||||
return c.NewCmdObj("git submodule init")
|
||||
return c.Cmd.New("git submodule init")
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleBulkUpdateCmdObj() oscommands.ICmdObj {
|
||||
return c.NewCmdObj("git submodule update")
|
||||
return c.Cmd.New("git submodule update")
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleForceBulkUpdateCmdObj() oscommands.ICmdObj {
|
||||
return c.NewCmdObj("git submodule update --force")
|
||||
return c.Cmd.New("git submodule update --force")
|
||||
}
|
||||
|
||||
func (c *GitCommand) SubmoduleBulkDeinitCmdObj() oscommands.ICmdObj {
|
||||
return c.NewCmdObj("git submodule deinit --all --force")
|
||||
return c.Cmd.New("git submodule deinit --all --force")
|
||||
}
|
||||
|
||||
func (c *GitCommand) ResetSubmodules(submodules []*models.SubmoduleConfig) error {
|
||||
|
@ -37,7 +37,7 @@ func (c *GitCommand) Push(opts PushOpts) error {
|
||||
cmdStr += " " + c.OSCommand.Quote(opts.UpstreamBranch)
|
||||
}
|
||||
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
cmdObj := c.Cmd.New(cmdStr)
|
||||
return c.DetectUnamePass(cmdObj, opts.PromptUserForCredential)
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ func (c *GitCommand) Fetch(opts FetchOptions) error {
|
||||
cmdStr = fmt.Sprintf("%s %s", cmdStr, c.OSCommand.Quote(opts.BranchName))
|
||||
}
|
||||
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
cmdObj := c.Cmd.New(cmdStr)
|
||||
return c.DetectUnamePass(cmdObj, func(question string) string {
|
||||
if opts.PromptUserForCredential != nil {
|
||||
return opts.PromptUserForCredential(question)
|
||||
@ -94,18 +94,18 @@ func (c *GitCommand) Pull(opts PullOptions) error {
|
||||
|
||||
// setting GIT_SEQUENCE_EDITOR to ':' as a way of skipping it, in case the user
|
||||
// has 'pull.rebase = interactive' configured.
|
||||
cmdObj := c.NewCmdObj(cmdStr).AddEnvVars("GIT_SEQUENCE_EDITOR=:")
|
||||
cmdObj := c.Cmd.New(cmdStr).AddEnvVars("GIT_SEQUENCE_EDITOR=:")
|
||||
return c.DetectUnamePass(cmdObj, opts.PromptUserForCredential)
|
||||
}
|
||||
|
||||
func (c *GitCommand) FastForward(branchName string, remoteName string, remoteBranchName string, promptUserForCredential func(string) string) error {
|
||||
cmdStr := fmt.Sprintf("git fetch %s %s:%s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(remoteBranchName), c.OSCommand.Quote(branchName))
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
cmdObj := c.Cmd.New(cmdStr)
|
||||
return c.DetectUnamePass(cmdObj, promptUserForCredential)
|
||||
}
|
||||
|
||||
func (c *GitCommand) FetchRemote(remoteName string, promptUserForCredential func(string) string) error {
|
||||
cmdStr := fmt.Sprintf("git fetch %s", c.OSCommand.Quote(remoteName))
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
cmdObj := c.Cmd.New(cmdStr)
|
||||
return c.DetectUnamePass(cmdObj, promptUserForCredential)
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
)
|
||||
|
||||
func (c *GitCommand) CreateLightweightTag(tagName string, commitSha string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git tag -- %s %s", c.OSCommand.Quote(tagName), commitSha)))
|
||||
return c.Cmd.New(fmt.Sprintf("git tag -- %s %s", c.OSCommand.Quote(tagName), commitSha)).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) CreateAnnotatedTag(tagName, commitSha, msg string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git tag %s %s -m %s", tagName, commitSha, c.OSCommand.Quote(msg))))
|
||||
return c.Cmd.New(fmt.Sprintf("git tag %s %s -m %s", tagName, commitSha, c.OSCommand.Quote(msg))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) DeleteTag(tagName string) error {
|
||||
return c.Run(c.NewCmdObj(fmt.Sprintf("git tag -d %s", c.OSCommand.Quote(tagName))))
|
||||
return c.Cmd.New(fmt.Sprintf("git tag -d %s", c.OSCommand.Quote(tagName))).Run()
|
||||
}
|
||||
|
||||
func (c *GitCommand) PushTag(remoteName string, tagName string, promptUserForCredential func(string) string) error {
|
||||
cmdStr := fmt.Sprintf("git push %s %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(tagName))
|
||||
cmdObj := c.NewCmdObj(cmdStr)
|
||||
cmdObj := c.Cmd.New(cmdStr)
|
||||
return c.DetectUnamePass(cmdObj, promptUserForCredential)
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ func (gui *Gui) refreshCommitsWithLimit() error {
|
||||
gui.Mutexes.BranchCommitsMutex.Lock()
|
||||
defer gui.Mutexes.BranchCommitsMutex.Unlock()
|
||||
|
||||
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
|
||||
builder := commands.NewCommitListBuilder(gui.Common, gui.GitCommand, gui.OSCommand)
|
||||
|
||||
commits, err := builder.GetCommits(
|
||||
commands.GetCommitsOptions{
|
||||
@ -142,7 +142,7 @@ func (gui *Gui) refreshRebaseCommits() error {
|
||||
gui.Mutexes.BranchCommitsMutex.Lock()
|
||||
defer gui.Mutexes.BranchCommitsMutex.Unlock()
|
||||
|
||||
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
|
||||
builder := commands.NewCommitListBuilder(gui.Common, gui.GitCommand, gui.OSCommand)
|
||||
|
||||
updatedCommits, err := builder.MergeRebasingCommits(gui.State.Commits)
|
||||
if err != nil {
|
||||
|
@ -203,7 +203,7 @@ func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptR
|
||||
}
|
||||
|
||||
// Run and save output
|
||||
message, err := gui.GitCommand.RunWithOutput(gui.GitCommand.NewCmdObj(cmdStr))
|
||||
message, err := gui.GitCommand.Cmd.New(cmdStr).RunWithOutput()
|
||||
if err != nil {
|
||||
return gui.surfaceError(err)
|
||||
}
|
||||
@ -244,7 +244,7 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
|
||||
}
|
||||
|
||||
if customCommand.Subprocess {
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(gui.OSCommand.NewShellCmdObjFromString2(cmdStr))
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(gui.OSCommand.Cmd.NewShell(cmdStr))
|
||||
}
|
||||
|
||||
loadingText := customCommand.LoadingText
|
||||
@ -252,8 +252,8 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
|
||||
loadingText = gui.Tr.LcRunningCustomCommandStatus
|
||||
}
|
||||
return gui.WithWaitingStatus(loadingText, func() error {
|
||||
cmdObj := gui.OSCommand.NewShellCmdObjFromString(cmdStr)
|
||||
if err := gui.OSCommand.WithSpan(gui.Tr.Spans.CustomCommand).Run(cmdObj); err != nil {
|
||||
err := gui.OSCommand.WithSpan(gui.Tr.Spans.CustomCommand).Cmd.NewShell(cmdStr).Run()
|
||||
if err != nil {
|
||||
return gui.surfaceError(err)
|
||||
}
|
||||
return gui.refreshSidePanels(refreshOptions{})
|
||||
|
@ -13,7 +13,7 @@ func (gui *Gui) exitDiffMode() error {
|
||||
}
|
||||
|
||||
func (gui *Gui) renderDiff() error {
|
||||
cmdObj := gui.OSCommand.NewCmdObj(
|
||||
cmdObj := gui.OSCommand.Cmd.New(
|
||||
fmt.Sprintf("git diff --submodule --no-ext-diff --color %s", gui.diffStr()),
|
||||
)
|
||||
task := NewRunPtyTask(cmdObj.GetCmd())
|
||||
|
@ -465,7 +465,7 @@ func (gui *Gui) handleCommitEditorPress() error {
|
||||
cmdStr := "git " + strings.Join(args, " ")
|
||||
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(
|
||||
gui.GitCommand.WithSpan(gui.Tr.Spans.Commit).NewCmdObjWithLog(cmdStr),
|
||||
gui.GitCommand.WithSpan(gui.Tr.Spans.Commit).Cmd.New(cmdStr).Log(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -511,7 +511,7 @@ func (gui *Gui) editFileAtLine(filename string, lineNumber int) error {
|
||||
}
|
||||
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(
|
||||
gui.OSCommand.WithSpan(gui.Tr.Spans.EditFile).NewShellCmdObjFromString(cmdStr),
|
||||
gui.OSCommand.WithSpan(gui.Tr.Spans.EditFile).Cmd.NewShell(cmdStr),
|
||||
)
|
||||
}
|
||||
|
||||
@ -923,7 +923,7 @@ func (gui *Gui) handleCustomCommand() error {
|
||||
|
||||
gui.OnRunCommand(oscommands.NewCmdLogEntry(command, gui.Tr.Spans.CustomCommand, true))
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(
|
||||
gui.OSCommand.NewShellCmdObjFromString2(command),
|
||||
gui.OSCommand.Cmd.NewShell(command),
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -32,7 +32,7 @@ func (gui *Gui) gitFlowFinishBranch(gitFlowConfig string, branchName string) err
|
||||
}
|
||||
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(
|
||||
gui.GitCommand.WithSpan(gui.Tr.Spans.GitFlowFinish).NewCmdObjWithLog("git flow " + branchType + " finish " + suffix),
|
||||
gui.GitCommand.WithSpan(gui.Tr.Spans.GitFlowFinish).Cmd.New("git flow " + branchType + " finish " + suffix).Log(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ func (gui *Gui) handleCreateGitFlowMenu() error {
|
||||
}
|
||||
|
||||
// get config
|
||||
gitFlowConfig, err := gui.GitCommand.RunWithOutput(gui.GitCommand.NewCmdObj("git config --local --get-regexp gitflow"))
|
||||
gitFlowConfig, err := gui.GitCommand.Cmd.New("git config --local --get-regexp gitflow").RunWithOutput()
|
||||
if err != nil {
|
||||
return gui.createErrorPanel("You need to install git-flow and enable it in this repo to use git-flow features")
|
||||
}
|
||||
@ -56,7 +56,7 @@ func (gui *Gui) handleCreateGitFlowMenu() error {
|
||||
title: title,
|
||||
handleConfirm: func(name string) error {
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(
|
||||
gui.GitCommand.WithSpan(gui.Tr.Spans.GitFlowStart).NewCmdObjWithLog("git flow " + branchType + " start " + name),
|
||||
gui.GitCommand.WithSpan(gui.Tr.Spans.GitFlowStart).Cmd.New("git flow " + branchType + " start " + name).Log(),
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
func (gui *Gui) withGpgHandling(cmdObj oscommands.ICmdObj, waitingStatus string, onSuccess func() error) error {
|
||||
useSubprocess := gui.GitCommand.UsingGpg()
|
||||
if useSubprocess {
|
||||
success, err := gui.runSubprocessWithSuspense(gui.OSCommand.NewShellCmdObjFromString(cmdObj.ToString()))
|
||||
success, err := gui.runSubprocessWithSuspense(gui.OSCommand.Cmd.NewShell(cmdObj.ToString()))
|
||||
if success && onSuccess != nil {
|
||||
if err := onSuccess(); err != nil {
|
||||
return err
|
||||
@ -33,7 +33,7 @@ func (gui *Gui) withGpgHandling(cmdObj oscommands.ICmdObj, waitingStatus string,
|
||||
|
||||
func (gui *Gui) RunAndStream(cmdObj oscommands.ICmdObj, waitingStatus string, onSuccess func() error) error {
|
||||
return gui.WithWaitingStatus(waitingStatus, func() error {
|
||||
cmdObj := gui.OSCommand.NewShellCmdObjFromString(cmdObj.ToString())
|
||||
cmdObj := gui.OSCommand.Cmd.NewShell(cmdObj.ToString())
|
||||
cmdObj.AddEnvVars("TERM=dumb")
|
||||
cmdWriter := gui.getCmdWriter()
|
||||
cmd := cmdObj.GetCmd()
|
||||
|
@ -58,7 +58,7 @@ func (gui *Gui) genericMergeCommand(command string) error {
|
||||
|
||||
// it's impossible for a rebase to require a commit so we'll use a subprocess only if it's a merge
|
||||
if status == commands.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && gui.UserConfig.Git.Merging.ManualCommit {
|
||||
sub := gitCommand.NewCmdObj("git " + commandType + " --" + command)
|
||||
sub := gitCommand.Cmd.New("git " + commandType + " --" + command)
|
||||
if sub != nil {
|
||||
return gui.runSubprocessWithSuspenseAndRefresh(sub)
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ func (gui *Gui) handleCreateRecentReposMenu() error {
|
||||
}
|
||||
|
||||
func (gui *Gui) handleShowAllBranchLogs() error {
|
||||
cmdObj := gui.OSCommand.NewCmdObj(
|
||||
cmdObj := gui.OSCommand.Cmd.New(
|
||||
gui.UserConfig.Git.AllBranchesLogCmd,
|
||||
)
|
||||
task := NewRunPtyTask(cmdObj.GetCmd())
|
||||
|
@ -22,7 +22,7 @@ func (gui *Gui) stashRenderToMain() error {
|
||||
if stashEntry == nil {
|
||||
task = NewRenderStringTask(gui.Tr.NoStashEntries)
|
||||
} else {
|
||||
cmdObj := gui.OSCommand.NewCmdObj(
|
||||
cmdObj := gui.OSCommand.Cmd.New(
|
||||
gui.GitCommand.ShowStashEntryCmdStr(stashEntry.Index),
|
||||
)
|
||||
task = NewRunPtyTask(cmdObj.GetCmd())
|
||||
|
@ -75,7 +75,7 @@ func (gui *Gui) handleViewSubCommitFiles() error {
|
||||
|
||||
func (gui *Gui) switchToSubCommitsContext(refName string) error {
|
||||
// need to populate my sub commits
|
||||
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
|
||||
builder := commands.NewCommitListBuilder(gui.Common, gui.GitCommand, gui.OSCommand)
|
||||
|
||||
commits, err := builder.GetCommits(
|
||||
commands.GetCommitsOptions{
|
||||
|
@ -214,7 +214,8 @@ func (gui *Gui) handleBulkSubmoduleActionsMenu() error {
|
||||
displayStrings: []string{gui.Tr.LcBulkInitSubmodules, style.FgGreen.Sprint(gui.GitCommand.SubmoduleBulkInitCmdObj().ToString())},
|
||||
onPress: func() error {
|
||||
return gui.WithWaitingStatus(gui.Tr.LcRunningCommand, func() error {
|
||||
if err := gui.OSCommand.WithSpan(gui.Tr.Spans.BulkInitialiseSubmodules).Run(gui.GitCommand.SubmoduleBulkInitCmdObj()); err != nil {
|
||||
err := gui.GitCommand.WithSpan(gui.Tr.Spans.BulkInitialiseSubmodules).SubmoduleBulkInitCmdObj().Run()
|
||||
if err != nil {
|
||||
return gui.surfaceError(err)
|
||||
}
|
||||
|
||||
@ -226,7 +227,7 @@ func (gui *Gui) handleBulkSubmoduleActionsMenu() error {
|
||||
displayStrings: []string{gui.Tr.LcBulkUpdateSubmodules, style.FgYellow.Sprint(gui.GitCommand.SubmoduleBulkUpdateCmdObj().ToString())},
|
||||
onPress: func() error {
|
||||
return gui.WithWaitingStatus(gui.Tr.LcRunningCommand, func() error {
|
||||
if err := gui.OSCommand.WithSpan(gui.Tr.Spans.BulkUpdateSubmodules).Run(gui.GitCommand.SubmoduleBulkUpdateCmdObj()); err != nil {
|
||||
if err := gui.GitCommand.WithSpan(gui.Tr.Spans.BulkUpdateSubmodules).SubmoduleBulkUpdateCmdObj().Run(); err != nil {
|
||||
return gui.surfaceError(err)
|
||||
}
|
||||
|
||||
@ -250,7 +251,7 @@ func (gui *Gui) handleBulkSubmoduleActionsMenu() error {
|
||||
displayStrings: []string{gui.Tr.LcBulkDeinitSubmodules, style.FgRed.Sprint(gui.GitCommand.SubmoduleBulkDeinitCmdObj().ToString())},
|
||||
onPress: func() error {
|
||||
return gui.WithWaitingStatus(gui.Tr.LcRunningCommand, func() error {
|
||||
if err := gui.OSCommand.WithSpan(gui.Tr.Spans.BulkDeinitialiseSubmodules).Run(gui.GitCommand.SubmoduleBulkDeinitCmdObj()); err != nil {
|
||||
if err := gui.GitCommand.WithSpan(gui.Tr.Spans.BulkDeinitialiseSubmodules).SubmoduleBulkDeinitCmdObj().Run(); err != nil {
|
||||
return gui.surfaceError(err)
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ func RunTests(
|
||||
testDir := filepath.Join(rootDir, "test", "integration")
|
||||
|
||||
osCommand := oscommands.NewDummyOSCommand()
|
||||
err = osCommand.Run(osCommand.NewCmdObj("go build -o " + tempLazygitPath()))
|
||||
err = osCommand.Cmd.New("go build -o " + tempLazygitPath()).Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -319,7 +319,7 @@ func generateSnapshot(dir string) (string, error) {
|
||||
|
||||
for _, cmdStr := range cmdStrs {
|
||||
// ignoring error for now. If there's an error it could be that there are no results
|
||||
output, _ := osCommand.RunWithOutput(osCommand.NewCmdObj(cmdStr))
|
||||
output, _ := osCommand.Cmd.New(cmdStr).RunWithOutput()
|
||||
|
||||
snapshot += output + "\n"
|
||||
}
|
||||
@ -428,7 +428,7 @@ func getLazygitCommand(testPath string, rootDir string, record bool, speed float
|
||||
|
||||
cmdStr := fmt.Sprintf("%s -debug --use-config-dir=%s --path=%s %s", tempLazygitPath(), configDir, actualDir, extraCmdArgs)
|
||||
|
||||
cmdObj := osCommand.NewCmdObj(cmdStr)
|
||||
cmdObj := osCommand.Cmd.New(cmdStr)
|
||||
cmdObj.AddEnvVars(fmt.Sprintf("SPEED=%f", speed))
|
||||
|
||||
if record {
|
||||
|
@ -295,8 +295,8 @@ func (u *Updater) downloadAndInstall(rawUrl string) error {
|
||||
}
|
||||
|
||||
u.Log.Info("untarring tarball/unzipping zip file")
|
||||
cmdObj := u.OSCommand.NewCmdObj(fmt.Sprintf("tar -zxf %s %s", u.OSCommand.Quote(zipPath), "lazygit"))
|
||||
if err := u.OSCommand.Run(cmdObj); err != nil {
|
||||
err = u.OSCommand.Cmd.New(fmt.Sprintf("tar -zxf %s %s", u.OSCommand.Quote(zipPath), "lazygit")).Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user