1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-14 11:23:09 +02:00
lazygit/pkg/commands/git_commands/branch.go

224 lines
6.1 KiB
Go
Raw Normal View History

2022-01-08 05:00:36 +02:00
package git_commands
2020-09-29 12:03:39 +02:00
import (
"fmt"
"strings"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/mgutz/str"
2020-09-29 12:03:39 +02:00
)
2022-01-02 01:34:33 +02:00
type BranchCommands struct {
*GitCommon
2022-01-02 01:34:33 +02:00
}
func NewBranchCommands(gitCommon *GitCommon) *BranchCommands {
2022-01-02 01:34:33 +02:00
return &BranchCommands{
GitCommon: gitCommon,
2022-01-02 01:34:33 +02:00
}
}
// New creates a new branch
func (self *BranchCommands) New(name string, base string) error {
cmdArgs := NewGitCmd("checkout").
Arg("-b", name, base).
ToArgv()
return self.cmd.New(cmdArgs).Run()
2020-09-29 12:03:39 +02:00
}
// CurrentBranchInfo get the current branch information.
func (self *BranchCommands) CurrentBranchInfo() (BranchInfo, error) {
branchName, err := self.cmd.New(
NewGitCmd("symbolic-ref").
Arg("--short", "HEAD").
ToArgv(),
).DontLog().RunWithOutput()
2020-09-29 12:03:39 +02:00
if err == nil && branchName != "HEAD\n" {
trimmedBranchName := strings.TrimSpace(branchName)
return BranchInfo{
RefName: trimmedBranchName,
DisplayName: trimmedBranchName,
DetachedHead: false,
}, nil
2020-09-29 12:03:39 +02:00
}
output, err := self.cmd.New(
NewGitCmd("branch").
Arg("--points-at=HEAD", "--format=%(HEAD)%00%(objectname)%00%(refname)").
ToArgv(),
).DontLog().RunWithOutput()
2020-09-29 12:03:39 +02:00
if err != nil {
return BranchInfo{}, err
2020-09-29 12:03:39 +02:00
}
for _, line := range utils.SplitLines(output) {
split := strings.Split(strings.TrimRight(line, "\r\n"), "\x00")
if len(split) == 3 && split[0] == "*" {
sha := split[1]
displayName := split[2]
return BranchInfo{
RefName: sha,
DisplayName: displayName,
DetachedHead: true,
}, nil
2020-09-29 12:03:39 +02:00
}
}
return BranchInfo{
RefName: "HEAD",
DisplayName: "HEAD",
DetachedHead: true,
}, nil
2020-09-29 12:03:39 +02:00
}
2023-07-12 08:47:50 +02:00
// CurrentBranchName get name of current branch
func (self *BranchCommands) CurrentBranchName() (string, error) {
cmdArgs := NewGitCmd("rev-parse").
Arg("--abbrev-ref").
Arg("--verify").
Arg("HEAD").
ToArgv()
output, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
if err == nil {
return strings.TrimSpace(output), nil
}
return "", err
}
2022-01-02 01:34:33 +02:00
// Delete delete branch
func (self *BranchCommands) Delete(branch string, force bool) error {
cmdArgs := NewGitCmd("branch").
ArgIfElse(force, "-D", "-d").
Arg(branch).
ToArgv()
2020-09-29 12:03:39 +02:00
return self.cmd.New(cmdArgs).Run()
2020-09-29 12:03:39 +02:00
}
// Checkout checks out a branch (or commit), with --force if you set the force arg to true
type CheckoutOptions struct {
Force bool
EnvVars []string
}
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) Checkout(branch string, options CheckoutOptions) error {
cmdArgs := NewGitCmd("checkout").
ArgIf(options.Force, "--force").
Arg(branch).
ToArgv()
2021-12-07 12:59:36 +02:00
return self.cmd.New(cmdArgs).
2021-12-07 12:59:36 +02:00
// 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").
2021-12-29 05:33:38 +02:00
AddEnvVars(options.EnvVars...).
Run()
2020-09-29 12:03:39 +02:00
}
2022-01-02 01:34:33 +02:00
// GetGraph gets the color-formatted graph of the log for the given branch
2020-09-29 12:03:39 +02:00
// Currently it limits the result to 100 commits, but when we get async stuff
// working we can do lazy loading
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) GetGraph(branchName string) (string, error) {
return self.GetGraphCmdObj(branchName).DontLog().RunWithOutput()
2020-09-29 12:03:39 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) GetGraphCmdObj(branchName string) oscommands.ICmdObj {
branchLogCmdTemplate := self.UserConfig.Git.BranchLogCmd
2020-09-29 12:03:39 +02:00
templateValues := map[string]string{
2022-01-02 01:34:33 +02:00
"branchName": self.cmd.Quote(branchName),
2020-09-29 12:03:39 +02:00
}
resolvedTemplate := utils.ResolvePlaceholderString(branchLogCmdTemplate, templateValues)
return self.cmd.New(str.ToArgv(resolvedTemplate)).DontLog()
2020-09-29 12:03:39 +02:00
}
func (self *BranchCommands) SetCurrentBranchUpstream(remoteName string, remoteBranchName string) error {
cmdArgs := NewGitCmd("branch").
Arg(fmt.Sprintf("--set-upstream-to=%s/%s", remoteName, remoteBranchName)).
ToArgv()
return self.cmd.New(cmdArgs).Run()
2020-09-29 12:03:39 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) SetUpstream(remoteName string, remoteBranchName string, branchName string) error {
cmdArgs := NewGitCmd("branch").
Arg(fmt.Sprintf("--set-upstream-to=%s/%s", remoteName, remoteBranchName)).
Arg(branchName).
ToArgv()
return self.cmd.New(cmdArgs).Run()
2020-09-29 12:03:39 +02:00
}
func (self *BranchCommands) UnsetUpstream(branchName string) error {
cmdArgs := NewGitCmd("branch").Arg("--unset-upstream", branchName).
ToArgv()
return self.cmd.New(cmdArgs).Run()
}
2020-09-29 12:03:39 +02:00
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) GetCurrentBranchUpstreamDifferenceCount() (string, string) {
return self.GetCommitDifferences("HEAD", "HEAD@{u}")
}
func (self *BranchCommands) GetUpstreamDifferenceCount(branchName string) (string, string) {
return self.GetCommitDifferences(branchName, branchName+"@{u}")
2020-09-29 12:03:39 +02:00
}
// GetCommitDifferences checks how many pushables/pullables there are for the
// current branch
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) GetCommitDifferences(from, to string) (string, string) {
pushableCount, err := self.countDifferences(to, from)
2020-09-29 12:03:39 +02:00
if err != nil {
return "?", "?"
}
pullableCount, err := self.countDifferences(from, to)
2020-09-29 12:03:39 +02:00
if err != nil {
return "?", "?"
}
return strings.TrimSpace(pushableCount), strings.TrimSpace(pullableCount)
}
func (self *BranchCommands) countDifferences(from, to string) (string, error) {
cmdArgs := NewGitCmd("rev-list").
Arg(fmt.Sprintf("%s..%s", from, to)).
Arg("--count").
ToArgv()
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
}
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) IsHeadDetached() bool {
cmdArgs := NewGitCmd("symbolic-ref").Arg("-q", "HEAD").ToArgv()
err := self.cmd.New(cmdArgs).DontLog().Run()
2022-01-02 01:34:33 +02:00
return err != nil
}
func (self *BranchCommands) Rename(oldName string, newName string) error {
cmdArgs := NewGitCmd("branch").
Arg("--move", oldName, newName).
ToArgv()
return self.cmd.New(cmdArgs).Run()
2022-01-02 01:34:33 +02:00
}
2020-09-29 12:03:39 +02:00
type MergeOpts struct {
FastForwardOnly bool
}
2022-01-02 01:34:33 +02:00
func (self *BranchCommands) Merge(branchName string, opts MergeOpts) error {
cmdArgs := NewGitCmd("merge").
Arg("--no-edit").
ArgIf(self.UserConfig.Git.Merging.Args != "", self.UserConfig.Git.Merging.Args).
ArgIf(opts.FastForwardOnly, "--ff-only").
Arg(branchName).
ToArgv()
2020-09-29 12:03:39 +02:00
return self.cmd.New(cmdArgs).Run()
}
2022-01-08 04:22:29 +02:00
func (self *BranchCommands) AllBranchesLogCmdObj() oscommands.ICmdObj {
return self.cmd.New(str.ToArgv(self.UserConfig.Git.AllBranchesLogCmd)).DontLog()
2022-01-08 04:22:29 +02:00
}