diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2023-06-11 08:08:55 +0200 |
---|---|---|
committer | Stefan Haller <stefan@haller-berlin.de> | 2023-07-31 08:41:41 +0200 |
commit | 66de981e9108c83ddb1d778eb92e948050c85311 (patch) | |
tree | fcc5c35ee5909cd71157c331ef10beb200fe05ee /pkg/gui | |
parent | 375451785c2f72da368e0cafaff9dc2e9f40a5b4 (diff) |
Add a "Mark commit as base commit for rebase" command
This allows to do the equivalent of "git rebase --onto <target> <base>", by
first marking the <base> commit with the new command, and then selecting the
target branch and invoking the usual rebase command there.
Diffstat (limited to 'pkg/gui')
-rw-r--r-- | pkg/gui/context/local_commits_context.go | 1 | ||||
-rw-r--r-- | pkg/gui/context/sub_commits_context.go | 1 | ||||
-rw-r--r-- | pkg/gui/controllers/helpers/merge_and_rebase_helper.go | 32 | ||||
-rw-r--r-- | pkg/gui/controllers/helpers/mode_helper.go | 10 | ||||
-rw-r--r-- | pkg/gui/controllers/local_commits_controller.go | 16 | ||||
-rw-r--r-- | pkg/gui/gui.go | 8 | ||||
-rw-r--r-- | pkg/gui/modes/marked_base_commit/marked_base_commit.go | 25 | ||||
-rw-r--r-- | pkg/gui/presentation/commits.go | 16 | ||||
-rw-r--r-- | pkg/gui/presentation/commits_test.go | 2 | ||||
-rw-r--r-- | pkg/gui/types/modes.go | 8 |
10 files changed, 109 insertions, 10 deletions
diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go index 417a4f30a..f8f7848f2 100644 --- a/pkg/gui/context/local_commits_context.go +++ b/pkg/gui/context/local_commits_context.go @@ -49,6 +49,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext { c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL, c.Modes().CherryPicking.SelectedShaSet(), c.Modes().Diffing.Ref, + c.Modes().MarkedBaseCommit.GetSha(), c.UserConfig.Gui.TimeFormat, c.UserConfig.Gui.ShortTimeFormat, time.Now(), diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go index ba2f5e3f6..2643d294b 100644 --- a/pkg/gui/context/sub_commits_context.go +++ b/pkg/gui/context/sub_commits_context.go @@ -65,6 +65,7 @@ func NewSubCommitsContext( c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL, c.Modes().CherryPicking.SelectedShaSet(), c.Modes().Diffing.Ref, + "", c.UserConfig.Gui.TimeFormat, c.UserConfig.Gui.ShortTimeFormat, time.Now(), diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index e9140e102..03c3abb4b 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -224,8 +224,18 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error { Key: 's', OnPress: func() error { self.c.LogAction(self.c.Tr.Actions.RebaseBranch) - err := self.c.Git().Rebase.RebaseBranch(ref) - return self.CheckMergeOrRebase(err) + baseCommit := self.c.Modes().MarkedBaseCommit.GetSha() + var err error + if baseCommit != "" { + err = self.c.Git().Rebase.RebaseBranchFromBaseCommit(ref, baseCommit) + } else { + err = self.c.Git().Rebase.RebaseBranch(ref) + } + err = self.CheckMergeOrRebase(err) + if err == nil { + self.c.Modes().MarkedBaseCommit.Reset() + } + return err }, }, { @@ -234,17 +244,26 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error { Tooltip: self.c.Tr.InteractiveRebaseTooltip, OnPress: func() error { self.c.LogAction(self.c.Tr.Actions.RebaseBranch) - err := self.c.Git().Rebase.EditRebase(ref) + baseCommit := self.c.Modes().MarkedBaseCommit.GetSha() + var err error + if baseCommit != "" { + err = self.c.Git().Rebase.EditRebaseFromBaseCommit(ref, baseCommit) + } else { + err = self.c.Git().Rebase.EditRebase(ref) + } if err = self.CheckMergeOrRebase(err); err != nil { return err } + self.c.Modes().MarkedBaseCommit.Reset() return self.c.PushContext(self.c.Contexts().LocalCommits) }, }, } title := utils.ResolvePlaceholderString( - self.c.Tr.RebasingTitle, + lo.Ternary(self.c.Modes().MarkedBaseCommit.GetSha() != "", + self.c.Tr.RebasingFromBaseCommitTitle, + self.c.Tr.RebasingTitle), map[string]string{ "checkedOutBranch": checkedOutBranch, "ref": ref, @@ -283,3 +302,8 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e }, }) } + +func (self *MergeAndRebaseHelper) ResetMarkedBaseCommit() error { + self.c.Modes().MarkedBaseCommit.Reset() + return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits) +} diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go index f5f3c738c..b3d9549a4 100644 --- a/pkg/gui/controllers/helpers/mode_helper.go +++ b/pkg/gui/controllers/helpers/mode_helper.go @@ -83,6 +83,16 @@ func (self *ModeHelper) Statuses() []ModeStatus { Reset: self.ExitFilterMode, }, { + IsActive: self.c.Modes().MarkedBaseCommit.Active, + Description: func() string { + return self.withResetButton( + self.c.Tr.MarkedBaseCommitStatus, + style.FgCyan, + ) + }, + Reset: self.mergeAndRebaseHelper.ResetMarkedBaseCommit, + }, + { IsActive: self.c.Modes().CherryPicking.Active, Description: func() string { copiedCount := len(self.c.Modes().CherryPicking.CherryPickedCommits) diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index a8df8811c..49f664a29 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -103,6 +103,12 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [ Handler: self.paste, Description: self.c.Tr.PasteCommits, }, + { + Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase), + Handler: self.checkSelected(self.markAsBaseCommit), + Description: self.c.Tr.MarkAsBaseCommit, + Tooltip: self.c.Tr.MarkAsBaseCommitTooltip, + }, // overriding these navigation keybindings because we might need to load // more commits on demand { @@ -840,6 +846,16 @@ func (self *LocalCommitsController) paste() error { return self.c.Helpers().CherryPick.Paste() } +func (self *LocalCommitsController) markAsBaseCommit(commit *models.Commit) error { + if commit.Sha == self.c.Modes().MarkedBaseCommit.GetSha() { + // Reset when invoking it again on the marked commit + self.c.Modes().MarkedBaseCommit.SetSha("") + } else { + self.c.Modes().MarkedBaseCommit.SetSha(commit.Sha) + } + return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits) +} + func (self *LocalCommitsController) isHeadCommit() bool { return models.IsHeadCommit(self.c.Model().Commits, self.context().GetSelectedLineIdx()) } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 8db98238c..4da5d5e96 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -24,6 +24,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking" "github.com/jesseduffield/lazygit/pkg/gui/modes/diffing" "github.com/jesseduffield/lazygit/pkg/gui/modes/filtering" + "github.com/jesseduffield/lazygit/pkg/gui/modes/marked_base_commit" "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation/authors" @@ -362,9 +363,10 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context { Authors: map[string]*models.Author{}, }, Modes: &types.Modes{ - Filtering: filtering.New(startArgs.FilterPath), - CherryPicking: cherrypicking.New(), - Diffing: diffing.New(), + Filtering: filtering.New(startArgs.FilterPath), + CherryPicking: cherrypicking.New(), + Diffing: diffing.New(), + MarkedBaseCommit: marked_base_commit.New(), }, ScreenMode: initialScreenMode, // TODO: only use contexts from context manager diff --git a/pkg/gui/modes/marked_base_commit/marked_base_commit.go b/pkg/gui/modes/marked_base_commit/marked_base_commit.go new file mode 100644 index 000000000..516dd0f2f --- /dev/null +++ b/pkg/gui/modes/marked_base_commit/marked_base_commit.go @@ -0,0 +1,25 @@ +package marked_base_commit + +type MarkedBaseCommit struct { + sha string // the sha of the commit used as a rebase base commit; empty string when unset +} + +func New() MarkedBaseCommit { + return MarkedBaseCommit{} +} + +func (m *MarkedBaseCommit) Active() bool { + return m.sha != "" +} + +func (m *MarkedBaseCommit) Reset() { + m.sha = "" +} + +func (m *MarkedBaseCommit) SetSha(sha string) { + m.sha = sha +} + +func (m *MarkedBaseCommit) GetSha() string { + return m.sha +} diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go index c00564e9d..f5915a7ee 100644 --- a/pkg/gui/presentation/commits.go +++ b/pkg/gui/presentation/commits.go @@ -45,6 +45,7 @@ func GetCommitListDisplayStrings( fullDescription bool, cherryPickedCommitShaSet *set.Set[string], diffName string, + markedBaseCommit string, timeFormat string, shortTimeFormat string, now time.Time, @@ -128,6 +129,7 @@ func GetCommitListDisplayStrings( lines := make([][]string, 0, len(filteredCommits)) var bisectStatus BisectStatus + willBeRebased := markedBaseCommit == "" for i, commit := range filteredCommits { unfilteredIdx := i + startIdx bisectStatus = getBisectStatus(unfilteredIdx, commit.Sha, bisectInfo, bisectBounds) @@ -136,11 +138,17 @@ func GetCommitListDisplayStrings( isYouAreHereCommit = true showYouAreHereLabel = false } + isMarkedBaseCommit := commit.Sha != "" && commit.Sha == markedBaseCommit + if isMarkedBaseCommit { + willBeRebased = true + } lines = append(lines, displayCommit( common, commit, branchHeadsToVisualize, cherryPickedCommitShaSet, + isMarkedBaseCommit, + willBeRebased, diffName, timeFormat, shortTimeFormat, @@ -290,6 +298,8 @@ func displayCommit( commit *models.Commit, branchHeadsToVisualize *set.Set[string], cherryPickedCommitShaSet *set.Set[string], + isMarkedBaseCommit bool, + willBeRebased bool, diffName string, timeFormat string, shortTimeFormat string, @@ -335,6 +345,12 @@ func displayCommit( color := lo.Ternary(commit.Action == models.ActionConflict, style.FgRed, style.FgYellow) youAreHere := color.Sprintf("<-- %s ---", common.Tr.YouAreHere) name = fmt.Sprintf("%s %s", youAreHere, name) + } else if isMarkedBaseCommit { + rebaseFromHere := style.FgYellow.Sprint(common.Tr.MarkedCommitMarker) + name = fmt.Sprintf("%s %s", rebaseFromHere, name) + } else if !willBeRebased { + willBeRebased := style.FgYellow.Sprint("✓") + name = fmt.Sprintf("%s %s", willBeRebased, name) } authorFunc := authors.ShortAuthor diff --git a/pkg/gui/presentation/commits_test.go b/pkg/gui/presentation/commits_test.go index 4bf4c09af..65122961e 100644 --- a/pkg/gui/presentation/commits_test.go +++ b/pkg/gui/presentation/commits_test.go @@ -33,6 +33,7 @@ func TestGetCommitListDisplayStrings(t *testing.T) { hasUpdateRefConfig bool fullDescription bool cherryPickedCommitShaSet *set.Set[string] + markedBaseCommit string diffName string timeFormat string shortTimeFormat string @@ -408,6 +409,7 @@ func TestGetCommitListDisplayStrings(t *testing.T) { s.fullDescription, s.cherryPickedCommitShaSet, s.diffName, + s.markedBaseCommit, s.timeFormat, s.shortTimeFormat, s.now, diff --git a/pkg/gui/types/modes.go b/pkg/gui/types/modes.go index ba135de63..a11ed0081 100644 --- a/pkg/gui/types/modes.go +++ b/pkg/gui/types/modes.go @@ -4,10 +4,12 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking" "github.com/jesseduffield/lazygit/pkg/gui/modes/diffing" "github.com/jesseduffield/lazygit/pkg/gui/modes/filtering" + "github.com/jesseduffield/lazygit/pkg/gui/modes/marked_base_commit" ) type Modes struct { - Filtering filtering.Filtering - CherryPicking *cherrypicking.CherryPicking - Diffing diffing.Diffing + Filtering filtering.Filtering + CherryPicking *cherrypicking.CherryPicking + Diffing diffing.Diffing + MarkedBaseCommit marked_base_commit.MarkedBaseCommit } |