summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-05-21 12:31:17 +1000
committerJesse Duffield <jessedduffield@gmail.com>2023-05-21 13:54:06 +1000
commit7efe433f1c5a45297d2729e9fddedf41bbe7937c (patch)
treead99b699e0b19f4586f8dfb09f80f2ce51cbadc9
parent6f535d71c91df96eaa8e29d0b120ba1e281e27d9 (diff)
Mark commits which changed a file among the last X commitsmark-last-commit-to-change-file
See https://github.com/jesseduffield/lazygit/issues/2653
-rw-r--r--docs/Config.md2
-rw-r--r--pkg/commands/git_commands/commit.go17
-rw-r--r--pkg/config/user_config.go82
-rw-r--r--pkg/gui/context/local_commits_context.go43
-rw-r--r--pkg/gui/context/sub_commits_context.go15
-rw-r--r--pkg/gui/controllers/files_controller.go11
-rw-r--r--pkg/gui/gui.go10
-rw-r--r--pkg/gui/presentation/commits.go25
-rw-r--r--pkg/gui/types/common.go2
9 files changed, 145 insertions, 62 deletions
diff --git a/docs/Config.md b/docs/Config.md
index bc860156c..670994c9e 100644
--- a/docs/Config.md
+++ b/docs/Config.md
@@ -65,6 +65,8 @@ gui:
splitDiff: 'auto' # one of 'auto' | 'always'
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
border: 'single' # one of 'single' | 'double' | 'rounded' | 'hidden'
+ # For marking recent commits which changed the selected file
+ experimentalMarkCommitsWhichChangedFile: false
git:
paging:
colorArg: always
diff --git a/pkg/commands/git_commands/commit.go b/pkg/commands/git_commands/commit.go
index bca68c3ac..996ba3c3a 100644
--- a/pkg/commands/git_commands/commit.go
+++ b/pkg/commands/git_commands/commit.go
@@ -3,6 +3,7 @@ package git_commands
import (
"fmt"
"strings"
+ "time"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
@@ -250,3 +251,19 @@ func (self *CommitCommands) GetCommitMessageFromHistory(value int) (string, erro
}
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")
+}
diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go
index 9212a2de8..fc530dd5e 100644
--- a/pkg/config/user_config.go
+++ b/pkg/config/user_config.go
@@ -27,33 +27,34 @@ type RefresherConfig struct {
}
type GuiConfig struct {
- AuthorColors map[string]string `yaml:"authorColors"`
- BranchColors map[string]string `yaml:"branchColors"`
- ScrollHeight int `yaml:"scrollHeight"`
- ScrollPastBottom bool `yaml:"scrollPastBottom"`
- MouseEvents bool `yaml:"mouseEvents"`
- SkipUnstageLineWarning bool `yaml:"skipUnstageLineWarning"`
- SkipStashWarning bool `yaml:"skipStashWarning"`
- SidePanelWidth float64 `yaml:"sidePanelWidth"`
- ExpandFocusedSidePanel bool `yaml:"expandFocusedSidePanel"`
- MainPanelSplitMode string `yaml:"mainPanelSplitMode"`
- Language string `yaml:"language"`
- TimeFormat string `yaml:"timeFormat"`
- Theme ThemeConfig `yaml:"theme"`
- CommitLength CommitLengthConfig `yaml:"commitLength"`
- SkipNoStagedFilesWarning bool `yaml:"skipNoStagedFilesWarning"`
- ShowListFooter bool `yaml:"showListFooter"`
- ShowFileTree bool `yaml:"showFileTree"`
- ShowRandomTip bool `yaml:"showRandomTip"`
- ShowCommandLog bool `yaml:"showCommandLog"`
- ShowBottomLine bool `yaml:"showBottomLine"`
- ShowIcons bool `yaml:"showIcons"`
- ExperimentalShowBranchHeads bool `yaml:"experimentalShowBranchHeads"`
- CommandLogSize int `yaml:"commandLogSize"`
- SplitDiff string `yaml:"splitDiff"`
- SkipRewordInEditorWarning bool `yaml:"skipRewordInEditorWarning"`
- WindowSize string `yaml:"windowSize"`
- Border string `yaml:"border"`
+ AuthorColors map[string]string `yaml:"authorColors"`
+ BranchColors map[string]string `yaml:"branchColors"`
+ ScrollHeight int `yaml:"scrollHeight"`
+ ScrollPastBottom bool `yaml:"scrollPastBottom"`
+ MouseEvents bool `yaml:"mouseEvents"`
+ SkipUnstageLineWarning bool `yaml:"skipUnstageLineWarning"`
+ SkipStashWarning bool `yaml:"skipStashWarning"`
+ SidePanelWidth float64 `yaml:"sidePanelWidth"`
+ ExpandFocusedSidePanel bool `yaml:"expandFocusedSidePanel"`
+ MainPanelSplitMode string `yaml:"mainPanelSplitMode"`
+ Language string `yaml:"language"`
+ TimeFormat string `yaml:"timeFormat"`
+ Theme ThemeConfig `yaml:"theme"`
+ CommitLength CommitLengthConfig `yaml:"commitLength"`
+ SkipNoStagedFilesWarning bool `yaml:"skipNoStagedFilesWarning"`
+ ShowListFooter bool `yaml:"showListFooter"`
+ ShowFileTree bool `yaml:"showFileTree"`
+ ShowRandomTip bool `yaml:"showRandomTip"`
+ ShowCommandLog bool `yaml:"showCommandLog"`
+ ShowBottomLine bool `yaml:"showBottomLine"`
+ ShowIcons bool `yaml:"showIcons"`
+ ExperimentalShowBranchHeads bool `yaml:"experimentalShowBranchHeads"`
+ CommandLogSize int `yaml:"commandLogSize"`
+ SplitDiff string `yaml:"splitDiff"`
+ SkipRewordInEditorWarning bool `yaml:"skipRewordInEditorWarning"`
+ WindowSize string `yaml:"windowSize"`
+ Border string `yaml:"border"`
+ ExperimentalMarkCommitsWhichChangedFile bool `yaml:"experimentalMarkCommitsWhichChangedFile"`
}
type ThemeConfig struct {
@@ -410,19 +411,20 @@ func GetDefaultConfig() *UserConfig {
UnstagedChangesColor: []string{"red"},
DefaultFgColor: []string{"default"},
},
- CommitLength: CommitLengthConfig{Show: true},
- SkipNoStagedFilesWarning: false,
- ShowListFooter: true,
- ShowCommandLog: true,
- ShowBottomLine: true,
- ShowFileTree: true,
- ShowRandomTip: true,
- ShowIcons: false,
- ExperimentalShowBranchHeads: false,
- CommandLogSize: 8,
- SplitDiff: "auto",
- SkipRewordInEditorWarning: false,
- Border: "single",
+ CommitLength: CommitLengthConfig{Show: true},
+ SkipNoStagedFilesWarning: false,
+ ShowListFooter: true,
+ ShowCommandLog: true,
+ ShowBottomLine: true,
+ ShowFileTree: true,
+ ShowRandomTip: true,
+ ShowIcons: false,
+ ExperimentalShowBranchHeads: false,
+ CommandLogSize: 8,
+ SplitDiff: "auto",
+ SkipRewordInEditorWarning: false,
+ Border: "single",
+ ExperimentalMarkCommitsWhichChangedFile: false,
},
Git: GitConfig{
Paging: PagingConfig{
diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go
index e8ae0b6c5..bdbb81eb2 100644
--- a/pkg/gui/context/local_commits_context.go
+++ b/pkg/gui/context/local_commits_context.go
@@ -3,6 +3,7 @@ package context
import (
"log"
+ "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -37,20 +38,14 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == enums.REBASE_MODE_REBASING
- return presentation.GetCommitListDisplayStrings(
- c.Common,
+ return getCommitsDisplayStrings(
+ c,
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,
length,
- shouldShowGraph(c),
- c.Model().BisectInfo,
+ selectedCommitSha,
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)
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,
+ )
+}
diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go
index 16712f982..3c196fefd 100644
--- a/pkg/gui/context/sub_commits_context.go
+++ b/pkg/gui/context/sub_commits_context.go
@@ -5,7 +5,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"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/utils"
)
@@ -40,20 +39,14 @@ func NewSubCommitsContext(
selectedCommitSha = selectedCommit.Sha
}
}
- return presentation.GetCommitListDisplayStrings(
- c.Common,
+ return getCommitsDisplayStrings(
+ c,
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,
length,
- shouldShowGraph(c),
- git_commands.NewNullBisectInfo(),
+ selectedCommitSha,
false,
+ git_commands.NewNullBisectInfo(),
)
}
diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go
index 2876f97fb..b35015cae 100644
--- a/pkg/gui/controllers/files_controller.go
+++ b/pkg/gui/controllers/files_controller.go
@@ -9,6 +9,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/types"
+ "github.com/jesseduffield/lazygit/pkg/utils"
)
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()
pair := self.c.MainViewPairs().Normal
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index b429bda27..e1c5b81e8 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -220,6 +220,8 @@ type GuiRepoState struct {
ScreenMode types.WindowMaximisation
CurrentPopupOpts *types.CreatePopupPanelOpts
+
+ RecentCommitsWhichChangedFile []string
}
var _ types.IRepoStateAccessor = new(GuiRepoState)
@@ -268,6 +270,14 @@ func (self *GuiRepoState) GetSplitMainPanel() bool {
return self.SplitMainPanel
}
+func (self *GuiRepoState) SetRecentCommitsWhichChangedFile(value []string) {
+ self.RecentCommitsWhichChangedFile = value
+}
+
+func (self *GuiRepoState) GetRecentCommitsWhichChangedFile() []string {
+ return self.RecentCommitsWhichChangedFile
+}
+
type searchingState struct {
view *gocui.View
isSearching bool
diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go
index 6b83456b9..0cace9b09 100644
--- a/pkg/gui/presentation/commits.go
+++ b/pkg/gui/presentation/commits.go
@@ -16,6 +16,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/kyokomi/emoji/v2"
+ "github.com/samber/lo"
"github.com/sasha-s/go-deadlock"
)
@@ -48,6 +49,8 @@ func GetCommitListDisplayStrings(
showGraph bool,
bisectInfo *git_commands.BisectInfo,
showYouAreHereLabel bool,
+ recentCommitsWhichChangedFile []string,
+ markRecentFileChanges bool,
) [][]string {
mutex.Lock()
defer mutex.Unlock()
@@ -113,6 +116,8 @@ func GetCommitListDisplayStrings(
bisectStatus,
bisectInfo,
isYouAreHereCommit,
+ recentCommitsWhichChangedFile,
+ markRecentFileChanges,
))
}
return lines
@@ -259,6 +264,8 @@ func displayCommit(
bisectStatus BisectStatus,
bisectInfo *git_commands.BisectInfo,
isYouAreHereCommit bool,
+ recentCommitsWhichChangedFile []string,
+ markRecentFileChanges bool,
) []string {
shaColor := getShaColor(commit, diffName, cherryPickedCommitShaSet, bisectStatus, bisectInfo)
bisectString := getBisectStatusText(bisectStatus, bisectInfo)
@@ -299,7 +306,23 @@ func displayCommit(
cols := make([]string, 0, 7)
if icons.IsIconEnabled() {
- cols = append(cols, shaColor.Sprint(icons.IconForCommit(commit)))
+ 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)))
+ }
+ } 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, bisectString)
diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go
index 3709d3c7b..b2766ada3 100644
--- a/pkg/gui/types/common.go
+++ b/pkg/gui/types/common.go
@@ -254,6 +254,8 @@ type IRepoStateAccessor interface {
IsSearching() bool
SetSplitMainPanel(bool)
GetSplitMainPanel() bool
+ SetRecentCommitsWhichChangedFile([]string)
+ GetRecentCommitsWhichChangedFile() []string
}
// startup stages so we don't need to load everything at once