mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-12 04:45:47 +02:00
Mark commits which changed a file among the last X commits
See https://github.com/jesseduffield/lazygit/issues/2653
This commit is contained in:
parent
6f535d71c9
commit
7efe433f1c
9 changed files with 145 additions and 62 deletions
|
@ -65,6 +65,8 @@ gui:
|
||||||
splitDiff: 'auto' # one of 'auto' | 'always'
|
splitDiff: 'auto' # one of 'auto' | 'always'
|
||||||
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
|
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
|
||||||
border: 'single' # one of 'single' | 'double' | 'rounded' | 'hidden'
|
border: 'single' # one of 'single' | 'double' | 'rounded' | 'hidden'
|
||||||
|
# For marking recent commits which changed the selected file
|
||||||
|
experimentalMarkCommitsWhichChangedFile: false
|
||||||
git:
|
git:
|
||||||
paging:
|
paging:
|
||||||
colorArg: always
|
colorArg: always
|
||||||
|
|
|
@ -3,6 +3,7 @@ package git_commands
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
@ -250,3 +251,19 @@ func (self *CommitCommands) GetCommitMessageFromHistory(value int) (string, erro
|
||||||
}
|
}
|
||||||
return self.GetCommitMessage(formattedHash)
|
return self.GetCommitMessage(formattedHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns hashes of recent commits which changed the given file
|
||||||
|
// Note: This does not look for the last X commits to change a file, instead
|
||||||
|
// it looks among the last X commits and see which of them happened to have changed the file.
|
||||||
|
// This is more efficient.
|
||||||
|
func (self *CommitCommands) GetRecentCommitsWhichChangedFile(path string) []string {
|
||||||
|
t := time.Now()
|
||||||
|
// Checking last X commits. Funnily this seems to actually consider more than the last
|
||||||
|
// X, perhaps because of topological sorting.
|
||||||
|
cmdStr := NewGitCmd("log").Arg("HEAD~50..HEAD", "--pretty=%H", "--", self.cmd.Quote(path)).
|
||||||
|
ToString()
|
||||||
|
|
||||||
|
hashes, _ := self.cmd.New(cmdStr).DontLog().RunWithOutput()
|
||||||
|
self.Log.Warn(fmt.Sprintf("GetRecentCommitsWhichChangedFile took %s", time.Since(t)))
|
||||||
|
return strings.Split(strings.TrimSpace(hashes), "\n")
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ type GuiConfig struct {
|
||||||
SkipRewordInEditorWarning bool `yaml:"skipRewordInEditorWarning"`
|
SkipRewordInEditorWarning bool `yaml:"skipRewordInEditorWarning"`
|
||||||
WindowSize string `yaml:"windowSize"`
|
WindowSize string `yaml:"windowSize"`
|
||||||
Border string `yaml:"border"`
|
Border string `yaml:"border"`
|
||||||
|
ExperimentalMarkCommitsWhichChangedFile bool `yaml:"experimentalMarkCommitsWhichChangedFile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ThemeConfig struct {
|
type ThemeConfig struct {
|
||||||
|
@ -423,6 +424,7 @@ func GetDefaultConfig() *UserConfig {
|
||||||
SplitDiff: "auto",
|
SplitDiff: "auto",
|
||||||
SkipRewordInEditorWarning: false,
|
SkipRewordInEditorWarning: false,
|
||||||
Border: "single",
|
Border: "single",
|
||||||
|
ExperimentalMarkCommitsWhichChangedFile: false,
|
||||||
},
|
},
|
||||||
Git: GitConfig{
|
Git: GitConfig{
|
||||||
Paging: PagingConfig{
|
Paging: PagingConfig{
|
||||||
|
|
|
@ -3,6 +3,7 @@ package context
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||||
|
@ -37,20 +38,14 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
||||||
|
|
||||||
showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == enums.REBASE_MODE_REBASING
|
showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == enums.REBASE_MODE_REBASING
|
||||||
|
|
||||||
return presentation.GetCommitListDisplayStrings(
|
return getCommitsDisplayStrings(
|
||||||
c.Common,
|
c,
|
||||||
c.Model().Commits,
|
c.Model().Commits,
|
||||||
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
|
||||||
c.Modes().CherryPicking.SelectedShaSet(),
|
|
||||||
c.Modes().Diffing.Ref,
|
|
||||||
c.UserConfig.Gui.TimeFormat,
|
|
||||||
c.UserConfig.Git.ParseEmoji,
|
|
||||||
selectedCommitSha,
|
|
||||||
startIdx,
|
startIdx,
|
||||||
length,
|
length,
|
||||||
shouldShowGraph(c),
|
selectedCommitSha,
|
||||||
c.Model().BisectInfo,
|
|
||||||
showYouAreHereLabel,
|
showYouAreHereLabel,
|
||||||
|
c.Model().BisectInfo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,3 +154,31 @@ func shouldShowGraph(c *ContextCommon) bool {
|
||||||
log.Fatalf("Unknown value for git.log.showGraph: %s. Expected one of: 'always', 'never', 'when-maximised'", value)
|
log.Fatalf("Unknown value for git.log.showGraph: %s. Expected one of: 'always', 'never', 'when-maximised'", value)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getCommitsDisplayStrings(
|
||||||
|
c *ContextCommon,
|
||||||
|
commits []*models.Commit,
|
||||||
|
startIdx int,
|
||||||
|
length int,
|
||||||
|
selectedCommitSha string,
|
||||||
|
showYouAreHereLabel bool,
|
||||||
|
bisectInfo *git_commands.BisectInfo,
|
||||||
|
) [][]string {
|
||||||
|
return presentation.GetCommitListDisplayStrings(
|
||||||
|
c.Common,
|
||||||
|
commits,
|
||||||
|
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
||||||
|
c.Modes().CherryPicking.SelectedShaSet(),
|
||||||
|
c.Modes().Diffing.Ref,
|
||||||
|
c.UserConfig.Gui.TimeFormat,
|
||||||
|
c.UserConfig.Git.ParseEmoji,
|
||||||
|
selectedCommitSha,
|
||||||
|
startIdx,
|
||||||
|
length,
|
||||||
|
shouldShowGraph(c),
|
||||||
|
bisectInfo,
|
||||||
|
showYouAreHereLabel,
|
||||||
|
c.State().GetRepoState().GetRecentCommitsWhichChangedFile(),
|
||||||
|
c.UserConfig.Gui.ExperimentalMarkCommitsWhichChangedFile,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
@ -40,20 +39,14 @@ func NewSubCommitsContext(
|
||||||
selectedCommitSha = selectedCommit.Sha
|
selectedCommitSha = selectedCommit.Sha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return presentation.GetCommitListDisplayStrings(
|
return getCommitsDisplayStrings(
|
||||||
c.Common,
|
c,
|
||||||
c.Model().SubCommits,
|
c.Model().SubCommits,
|
||||||
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
|
||||||
c.Modes().CherryPicking.SelectedShaSet(),
|
|
||||||
c.Modes().Diffing.Ref,
|
|
||||||
c.UserConfig.Gui.TimeFormat,
|
|
||||||
c.UserConfig.Git.ParseEmoji,
|
|
||||||
selectedCommitSha,
|
|
||||||
startIdx,
|
startIdx,
|
||||||
length,
|
length,
|
||||||
shouldShowGraph(c),
|
selectedCommitSha,
|
||||||
git_commands.NewNullBisectInfo(),
|
|
||||||
false,
|
false,
|
||||||
|
git_commands.NewNullBisectInfo(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FilesController struct {
|
type FilesController struct {
|
||||||
|
@ -192,6 +193,16 @@ func (self *FilesController) GetOnRenderToMain() func() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.c.UserConfig.Gui.ExperimentalMarkCommitsWhichChangedFile {
|
||||||
|
go utils.Safe(func() {
|
||||||
|
recentCommitsWhichChangedFile := self.c.Git().Commit.GetRecentCommitsWhichChangedFile(node.GetPath())
|
||||||
|
self.c.OnUIThread(func() error {
|
||||||
|
self.c.State().GetRepoState().SetRecentCommitsWhichChangedFile(recentCommitsWhichChangedFile)
|
||||||
|
return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
self.c.Helpers().MergeConflicts.ResetMergeState()
|
self.c.Helpers().MergeConflicts.ResetMergeState()
|
||||||
|
|
||||||
pair := self.c.MainViewPairs().Normal
|
pair := self.c.MainViewPairs().Normal
|
||||||
|
|
|
@ -220,6 +220,8 @@ type GuiRepoState struct {
|
||||||
ScreenMode types.WindowMaximisation
|
ScreenMode types.WindowMaximisation
|
||||||
|
|
||||||
CurrentPopupOpts *types.CreatePopupPanelOpts
|
CurrentPopupOpts *types.CreatePopupPanelOpts
|
||||||
|
|
||||||
|
RecentCommitsWhichChangedFile []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IRepoStateAccessor = new(GuiRepoState)
|
var _ types.IRepoStateAccessor = new(GuiRepoState)
|
||||||
|
@ -268,6 +270,14 @@ func (self *GuiRepoState) GetSplitMainPanel() bool {
|
||||||
return self.SplitMainPanel
|
return self.SplitMainPanel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *GuiRepoState) SetRecentCommitsWhichChangedFile(value []string) {
|
||||||
|
self.RecentCommitsWhichChangedFile = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *GuiRepoState) GetRecentCommitsWhichChangedFile() []string {
|
||||||
|
return self.RecentCommitsWhichChangedFile
|
||||||
|
}
|
||||||
|
|
||||||
type searchingState struct {
|
type searchingState struct {
|
||||||
view *gocui.View
|
view *gocui.View
|
||||||
isSearching bool
|
isSearching bool
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/kyokomi/emoji/v2"
|
"github.com/kyokomi/emoji/v2"
|
||||||
|
"github.com/samber/lo"
|
||||||
"github.com/sasha-s/go-deadlock"
|
"github.com/sasha-s/go-deadlock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,6 +49,8 @@ func GetCommitListDisplayStrings(
|
||||||
showGraph bool,
|
showGraph bool,
|
||||||
bisectInfo *git_commands.BisectInfo,
|
bisectInfo *git_commands.BisectInfo,
|
||||||
showYouAreHereLabel bool,
|
showYouAreHereLabel bool,
|
||||||
|
recentCommitsWhichChangedFile []string,
|
||||||
|
markRecentFileChanges bool,
|
||||||
) [][]string {
|
) [][]string {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
|
@ -113,6 +116,8 @@ func GetCommitListDisplayStrings(
|
||||||
bisectStatus,
|
bisectStatus,
|
||||||
bisectInfo,
|
bisectInfo,
|
||||||
isYouAreHereCommit,
|
isYouAreHereCommit,
|
||||||
|
recentCommitsWhichChangedFile,
|
||||||
|
markRecentFileChanges,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
return lines
|
return lines
|
||||||
|
@ -259,6 +264,8 @@ func displayCommit(
|
||||||
bisectStatus BisectStatus,
|
bisectStatus BisectStatus,
|
||||||
bisectInfo *git_commands.BisectInfo,
|
bisectInfo *git_commands.BisectInfo,
|
||||||
isYouAreHereCommit bool,
|
isYouAreHereCommit bool,
|
||||||
|
recentCommitsWhichChangedFile []string,
|
||||||
|
markRecentFileChanges bool,
|
||||||
) []string {
|
) []string {
|
||||||
shaColor := getShaColor(commit, diffName, cherryPickedCommitShaSet, bisectStatus, bisectInfo)
|
shaColor := getShaColor(commit, diffName, cherryPickedCommitShaSet, bisectStatus, bisectInfo)
|
||||||
bisectString := getBisectStatusText(bisectStatus, bisectInfo)
|
bisectString := getBisectStatusText(bisectStatus, bisectInfo)
|
||||||
|
@ -299,8 +306,24 @@ func displayCommit(
|
||||||
|
|
||||||
cols := make([]string, 0, 7)
|
cols := make([]string, 0, 7)
|
||||||
if icons.IsIconEnabled() {
|
if icons.IsIconEnabled() {
|
||||||
|
if markRecentFileChanges && lo.SomeBy(recentCommitsWhichChangedFile, func(sha string) bool {
|
||||||
|
return utils.ShortSha(sha) == utils.ShortSha(commit.Sha)
|
||||||
|
}) {
|
||||||
|
cols = append(cols, style.FgDefault.Sprint(">"))
|
||||||
|
} else {
|
||||||
cols = append(cols, shaColor.Sprint(icons.IconForCommit(commit)))
|
cols = append(cols, shaColor.Sprint(icons.IconForCommit(commit)))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if markRecentFileChanges {
|
||||||
|
if lo.SomeBy(recentCommitsWhichChangedFile, func(sha string) bool {
|
||||||
|
return utils.ShortSha(sha) == utils.ShortSha(commit.Sha)
|
||||||
|
}) {
|
||||||
|
cols = append(cols, style.FgDefault.Sprint(">"))
|
||||||
|
} else {
|
||||||
|
cols = append(cols, " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
cols = append(cols, shaColor.Sprint(commit.ShortSha()))
|
cols = append(cols, shaColor.Sprint(commit.ShortSha()))
|
||||||
cols = append(cols, bisectString)
|
cols = append(cols, bisectString)
|
||||||
if fullDescription {
|
if fullDescription {
|
||||||
|
|
|
@ -254,6 +254,8 @@ type IRepoStateAccessor interface {
|
||||||
IsSearching() bool
|
IsSearching() bool
|
||||||
SetSplitMainPanel(bool)
|
SetSplitMainPanel(bool)
|
||||||
GetSplitMainPanel() bool
|
GetSplitMainPanel() bool
|
||||||
|
SetRecentCommitsWhichChangedFile([]string)
|
||||||
|
GetRecentCommitsWhichChangedFile() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// startup stages so we don't need to load everything at once
|
// startup stages so we don't need to load everything at once
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue