1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2026-06-20 01:19:23 +02:00

Show commit merged/push statuses against branches

When viewing branches in an enlargened window, we now colour the commit shas based on
whether the branch has been merged to a main branch and whether it's been pushed to
the upstream.

This isn't using the exact same code as we use for commits, so it's possible we'll get
a colour mismatch when the user checks out a branch and views the commits in the commits
view, but if we come across that situation we'll just need to fix it.
This commit is contained in:
Jesse Duffield
2023-10-05 19:25:58 +11:00
parent 16369dc3c2
commit 017367f940
8 changed files with 143 additions and 41 deletions
+3
View File
@@ -47,6 +47,7 @@ type GitCommand struct {
type Loaders struct {
BranchLoader *git_commands.BranchLoader
MergedBranchLoader *git_commands.MergedBranchLoader
CommitFileLoader *git_commands.CommitFileLoader
CommitLoader *git_commands.CommitLoader
FileLoader *git_commands.FileLoader
@@ -162,6 +163,7 @@ func NewGitCommandAux(
worktreeCommands := git_commands.NewWorktreeCommands(gitCommon)
branchLoader := git_commands.NewBranchLoader(cmn, cmd, branchCommands.CurrentBranchInfo, configCommands)
mergedBranchLoader := git_commands.NewMergedBranchLoader(gitCommon)
commitFileLoader := git_commands.NewCommitFileLoader(cmn, cmd)
commitLoader := git_commands.NewCommitLoader(cmn, cmd, statusCommands.RebaseMode, gitCommon)
reflogCommitLoader := git_commands.NewReflogCommitLoader(cmn, cmd)
@@ -200,6 +202,7 @@ func NewGitCommandAux(
Worktrees: worktreeLoader,
StashLoader: stashLoader,
TagLoader: tagLoader,
MergedBranchLoader: mergedBranchLoader,
},
RepoPaths: repoPaths,
}
@@ -0,0 +1,59 @@
package git_commands
import (
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/lazygit/pkg/utils"
)
// Returns a set of branch names which are merged into a main branch.
// This
type MergedBranchLoader struct {
c *GitCommon
}
func NewMergedBranchLoader(c *GitCommon) *MergedBranchLoader {
return &MergedBranchLoader{c: c}
}
// TODO: check against upstreams, and share code with commit loader that determines main branches
func (self *MergedBranchLoader) Load() *set.Set[string] {
set := set.New[string]()
mainBranches := self.c.UserConfig.Git.MainBranches
results := utils.ConcurrentMap(mainBranches, func(mainBranch string) []string {
mergedBranches, err := self.GetMergedBranches(mainBranch)
if err != nil {
self.c.Log.Warnf("Failed to get merged branches for %s: %s", mainBranch, err)
return nil
}
return mergedBranches
})
for i := 0; i < len(mainBranches); i++ {
for _, mergedBranch := range results[i] {
set.Add(mergedBranch)
}
}
return set
}
func (self *MergedBranchLoader) GetMergedBranches(mainBranch string) ([]string, error) {
// git for-each-ref --merged master --format '%(refname)' refs/heads/
cmdArgs := NewGitCmd("for-each-ref").Arg(
"--merged",
mainBranch,
"--format",
"%(refname)",
"refs/heads/",
).ToArgv()
output, err := self.c.cmd.New(cmdArgs).DontLog().RunWithOutput()
if err != nil {
return nil, err
}
branches := utils.SplitLines(output)
return branches, nil
}
+1
View File
@@ -33,6 +33,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
c.Tr,
c.UserConfig,
c.Model().Worktrees,
c.Model().MergedBranches,
)
}
+34 -16
View File
@@ -429,25 +429,43 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool) {
self.c.Mutexes().RefreshingBranchesMutex.Lock()
defer self.c.Mutexes().RefreshingBranchesMutex.Unlock()
reflogCommits := self.c.Model().FilteredReflogCommits
if self.c.Modes().Filtering.Active() {
// in filter mode we filter our reflog commits to just those containing the path
// however we need all the reflog entries to populate the recencies of our branches
// which allows us to order them correctly. So if we're filtering we'll just
// manually load all the reflog commits here
var err error
reflogCommits, _, err = self.c.Git().Loaders.ReflogCommitLoader.GetReflogCommits(nil, "")
if err != nil {
self.c.Log.Error(err)
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
reflogCommits := self.c.Model().FilteredReflogCommits
if self.c.Modes().Filtering.Active() {
// in filter mode we filter our reflog commits to just those containing the path
// however we need all the reflog entries to populate the recencies of our branches
// which allows us to order them correctly. So if we're filtering we'll just
// manually load all the reflog commits here
var err error
reflogCommits, _, err = self.c.Git().Loaders.ReflogCommitLoader.GetReflogCommits(nil, "")
if err != nil {
self.c.Log.Error(err)
}
}
}
branches, err := self.c.Git().Loaders.BranchLoader.Load(reflogCommits)
if err != nil {
_ = self.c.Error(err)
}
branches, err := self.c.Git().Loaders.BranchLoader.Load(reflogCommits)
if err != nil {
_ = self.c.Error(err)
}
self.c.Model().Branches = branches
self.c.Model().Branches = branches
}()
go func() {
defer wg.Done()
mergedBranches := self.c.Git().Loaders.MergedBranchLoader.Load()
self.c.Model().MergedBranches = mergedBranches
}()
wg.Wait()
if refreshWorktrees {
self.loadWorktrees()
+2
View File
@@ -8,6 +8,7 @@ import (
"strings"
"sync"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazycore/pkg/boxlayout"
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
@@ -384,6 +385,7 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
BisectInfo: git_commands.NewNullBisectInfo(),
FilesTrie: patricia.NewTrie(),
Authors: map[string]*models.Author{},
MergedBranches: set.New[string](),
},
Modes: &types.Modes{
Filtering: filtering.New(startArgs.FilterPath),
+13 -2
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"strings"
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/config"
@@ -26,10 +27,11 @@ func GetBranchListDisplayStrings(
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
worktrees []*models.Worktree,
mergedBranches *set.Set[string],
) [][]string {
return lo.Map(branches, func(branch *models.Branch, _ int) []string {
diffed := branch.Name == diffName
return getBranchDisplayStrings(branch, getItemOperation(branch), fullDescription, diffed, tr, userConfig, worktrees)
return getBranchDisplayStrings(branch, getItemOperation(branch), fullDescription, diffed, tr, userConfig, worktrees, mergedBranches)
})
}
@@ -42,6 +44,7 @@ func getBranchDisplayStrings(
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
worktrees []*models.Worktree,
mergedBranches *set.Set[string],
) []string {
displayName := b.Name
if b.DisplayName != "" {
@@ -74,7 +77,15 @@ func getBranchDisplayStrings(
}
if fullDescription || userConfig.Gui.ShowBranchCommitHash {
res = append(res, utils.ShortSha(b.CommitHash))
var commitStyle style.TextStyle
if b.HasCommitsToPush() {
commitStyle = getShaStyleFromStatus(models.StatusUnpushed)
} else if mergedBranches.Includes(b.FullRefName()) {
commitStyle = getShaStyleFromStatus(models.StatusMerged)
} else {
commitStyle = getShaStyleFromStatus(models.StatusPushed)
}
res = append(res, commitStyle.Sprint(utils.ShortSha(b.CommitHash)))
}
res = append(res, coloredName)
+19 -14
View File
@@ -413,20 +413,8 @@ func getShaColor(
}
diffed := commit.Sha != "" && commit.Sha == diffName
shaColor := theme.DefaultTextColor
switch commit.Status {
case models.StatusUnpushed:
shaColor = style.FgRed
case models.StatusPushed:
shaColor = style.FgYellow
case models.StatusMerged:
shaColor = style.FgGreen
case models.StatusRebasing:
shaColor = style.FgBlue
case models.StatusReflog:
shaColor = style.FgBlue
default:
}
shaColor := getShaStyleFromStatus(commit.Status)
if diffed {
shaColor = theme.DiffTerminalColor
@@ -439,6 +427,23 @@ func getShaColor(
return shaColor
}
func getShaStyleFromStatus(status models.CommitStatus) style.TextStyle {
switch status {
case models.StatusUnpushed:
return style.FgRed
case models.StatusPushed:
return style.FgYellow
case models.StatusMerged:
return style.FgGreen
case models.StatusRebasing:
return style.FgBlue
case models.StatusReflog:
return style.FgBlue
default:
return theme.DefaultTextColor
}
}
func actionColorMap(action todo.TodoCommand) style.TextStyle {
switch action {
case todo.Pick:
+12 -9
View File
@@ -1,6 +1,7 @@
package types
import (
"github.com/jesseduffield/generics/set"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
@@ -223,15 +224,17 @@ type MenuItem struct {
}
type Model struct {
CommitFiles []*models.CommitFile
Files []*models.File
Submodules []*models.SubmoduleConfig
Branches []*models.Branch
Commits []*models.Commit
StashEntries []*models.StashEntry
SubCommits []*models.Commit
Remotes []*models.Remote
Worktrees []*models.Worktree
CommitFiles []*models.CommitFile
Files []*models.File
Submodules []*models.SubmoduleConfig
Branches []*models.Branch
// set of branch names of the form 'refs/heads/mybranch'
MergedBranches *set.Set[string]
Commits []*models.Commit
StashEntries []*models.StashEntry
SubCommits []*models.Commit
Remotes []*models.Remote
Worktrees []*models.Worktree
// FilteredReflogCommits are the ones that appear in the reflog panel.
// when in filtering mode we only include the ones that match the given path