mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-21 12:16:54 +02:00
This will make it possible to change the configured main branches at runtime. We'll support this in the next commit.
124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
package git_commands
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
"github.com/jesseduffield/lazygit/pkg/common"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
"github.com/samber/lo"
|
|
"github.com/sasha-s/go-deadlock"
|
|
)
|
|
|
|
type MainBranches struct {
|
|
c *common.Common
|
|
// Which of the configured main branches actually exist in the repository. Full
|
|
// ref names, and it could be either "refs/heads/..." or "refs/remotes/origin/..."
|
|
// depending on which one exists for a given bare name.
|
|
existingMainBranches []string
|
|
|
|
cmd oscommands.ICmdObjBuilder
|
|
mutex *deadlock.Mutex
|
|
}
|
|
|
|
func NewMainBranches(
|
|
cmn *common.Common,
|
|
cmd oscommands.ICmdObjBuilder,
|
|
) *MainBranches {
|
|
return &MainBranches{
|
|
c: cmn,
|
|
existingMainBranches: nil,
|
|
cmd: cmd,
|
|
mutex: &deadlock.Mutex{},
|
|
}
|
|
}
|
|
|
|
// Get the list of main branches that exist in the repository. This is a list of
|
|
// full ref names.
|
|
func (self *MainBranches) Get() []string {
|
|
self.mutex.Lock()
|
|
defer self.mutex.Unlock()
|
|
|
|
if self.existingMainBranches == nil {
|
|
self.existingMainBranches = self.determineMainBranches()
|
|
}
|
|
|
|
return self.existingMainBranches
|
|
}
|
|
|
|
// Return the merge base of the given refName with the closest main branch.
|
|
func (self *MainBranches) GetMergeBase(refName string) string {
|
|
mainBranches := self.Get()
|
|
if len(mainBranches) == 0 {
|
|
return ""
|
|
}
|
|
|
|
// We pass all existing main branches to the merge-base call; git will
|
|
// return the base commit for the closest one.
|
|
|
|
// We ignore errors from this call, since we can't distinguish whether the
|
|
// error is because one of the main branches has been deleted since the last
|
|
// call to determineMainBranches, or because the refName has no common
|
|
// history with any of the main branches. Since the former should happen
|
|
// very rarely, users must quit and restart lazygit to fix it; the latter is
|
|
// also not very common, but can totally happen and is not an error.
|
|
|
|
output, _ := self.cmd.New(
|
|
NewGitCmd("merge-base").Arg(refName).Arg(mainBranches...).
|
|
ToArgv(),
|
|
).DontLog().RunWithOutput()
|
|
return ignoringWarnings(output)
|
|
}
|
|
|
|
func (self *MainBranches) determineMainBranches() []string {
|
|
var existingBranches []string
|
|
var wg sync.WaitGroup
|
|
|
|
configuredMainBranches := self.c.UserConfig().Git.MainBranches
|
|
existingBranches = make([]string, len(configuredMainBranches))
|
|
|
|
for i, branchName := range configuredMainBranches {
|
|
wg.Add(1)
|
|
go utils.Safe(func() {
|
|
defer wg.Done()
|
|
|
|
// Try to determine upstream of local main branch
|
|
if ref, err := self.cmd.New(
|
|
NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(),
|
|
).DontLog().RunWithOutput(); err == nil {
|
|
existingBranches[i] = strings.TrimSpace(ref)
|
|
return
|
|
}
|
|
|
|
// If this failed, a local branch for this main branch doesn't exist or it
|
|
// has no upstream configured. Try looking for one in the "origin" remote.
|
|
ref := "refs/remotes/origin/" + branchName
|
|
if err := self.cmd.New(
|
|
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
|
).DontLog().Run(); err == nil {
|
|
existingBranches[i] = ref
|
|
return
|
|
}
|
|
|
|
// If this failed as well, try if we have the main branch as a local
|
|
// branch. This covers the case where somebody is using git locally
|
|
// for something, but never pushing anywhere.
|
|
ref = "refs/heads/" + branchName
|
|
if err := self.cmd.New(
|
|
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
|
).DontLog().Run(); err == nil {
|
|
existingBranches[i] = ref
|
|
}
|
|
})
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
existingBranches = lo.Filter(existingBranches, func(branch string, _ int) bool {
|
|
return branch != ""
|
|
})
|
|
|
|
return existingBranches
|
|
}
|