diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 68a0ea742..d290192e4 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -115,7 +115,6 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [ { Key: opts.GetKey(editCommitKey), Handler: self.withItems(self.edit), - // TODO: have disabled reason ensure that if we're not rebasing, we only select one commit GetDisabledReason: self.require( self.itemRangeSelected(self.midRebaseCommandEnabled), ), @@ -457,15 +456,7 @@ func (self *LocalCommitsController) edit(selectedCommits []*models.Commit) error return self.updateTodos(todo.Edit, selectedCommits) } - // TODO: support range select here (start a rebase and set the selected commits - // to 'edit' in the todo file) - if len(selectedCommits) > 1 { - return self.c.ErrorMsg(self.c.Tr.RangeSelectNotSupported) - } - - selectedCommit := selectedCommits[0] - - return self.startInteractiveRebaseWithEdit(selectedCommit) + return self.startInteractiveRebaseWithEdit(selectedCommits) } func (self *LocalCommitsController) quickStartInteractiveRebase() error { @@ -474,11 +465,11 @@ func (self *LocalCommitsController) quickStartInteractiveRebase() error { return self.c.Error(err) } - return self.startInteractiveRebaseWithEdit(commitToEdit) + return self.startInteractiveRebaseWithEdit([]*models.Commit{commitToEdit}) } func (self *LocalCommitsController) startInteractiveRebaseWithEdit( - commitToEdit *models.Commit, + commitsToEdit []*models.Commit, ) error { return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { self.c.LogAction(self.c.Tr.Actions.EditCommit) @@ -486,10 +477,24 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit( commits := self.c.Model().Commits selectedSha := commits[selectedIdx].Sha rangeStartSha := commits[rangeStartIdx].Sha - err := self.c.Git().Rebase.EditRebase(commitToEdit.Sha) + err := self.c.Git().Rebase.EditRebase(commitsToEdit[len(commitsToEdit)-1].Sha) return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions( err, types.RefreshOptions{Mode: types.BLOCK_UI, Then: func() { + todos := make([]*models.Commit, 0, len(commitsToEdit)-1) + for _, c := range commitsToEdit[:len(commitsToEdit)-1] { + // Merge commits can't be set to "edit", so just skip them + if !c.IsMerge() { + todos = append(todos, &models.Commit{Sha: c.Sha, Action: todo.Pick}) + } + } + if len(todos) > 0 { + err := self.updateTodos(todo.Edit, todos) + if err != nil { + _ = self.c.Error(err) + } + } + // We need to select the same commit range again because after starting a rebase, // new lines can be added for update-ref commands in the TODO file, due to // stacked branches. So the selected commits may be in different positions in the list. diff --git a/pkg/integration/tests/interactive_rebase/edit_range_select_outside_rebase.go b/pkg/integration/tests/interactive_rebase/edit_range_select_outside_rebase.go new file mode 100644 index 000000000..4ff2a8c83 --- /dev/null +++ b/pkg/integration/tests/interactive_rebase/edit_range_select_outside_rebase.go @@ -0,0 +1,51 @@ +package interactive_rebase + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" + "github.com/jesseduffield/lazygit/pkg/integration/tests/shared" +) + +var EditRangeSelectOutsideRebase = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Select a range of commits to edit outside of a rebase", + ExtraCmdArgs: []string{}, + Skip: false, + GitVersion: AtLeast("2.22.0"), // first version that supports the --rebase-merges option + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shared.CreateMergeCommit(shell) + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + TopLines( + Contains("Merge branch 'second-change-branch' into first-change-branch").IsSelected(), + ). + Press(keys.Universal.RangeSelectDown). + Press(keys.Universal.RangeSelectDown). + Press(keys.Universal.RangeSelectDown). + Press(keys.Universal.RangeSelectDown). + Press(keys.Universal.RangeSelectDown). + Lines( + Contains("CI ⏣─╮ Merge branch 'second-change-branch' into first-change-branch").IsSelected(), + Contains("CI │ ◯ * second-change-branch unrelated change").IsSelected(), + Contains("CI │ ◯ second change").IsSelected(), + Contains("CI ◯ │ first change").IsSelected(), + Contains("CI ◯─╯ * original").IsSelected(), + Contains("CI ◯ three").IsSelected(), + Contains("CI ◯ two"), + Contains("CI ◯ one"), + ). + Press(keys.Universal.Edit). + Lines( + Contains("merge CI Merge branch 'second-change-branch' into first-change-branch").IsSelected(), + Contains("edit CI first change").IsSelected(), + Contains("edit CI * second-change-branch unrelated change").IsSelected(), + Contains("edit CI second change").IsSelected(), + Contains("edit CI * original").IsSelected(), + Contains(" CI ◯ <-- YOU ARE HERE --- three").IsSelected(), + Contains(" CI ◯ two"), + Contains(" CI ◯ one"), + ) + }, +}) diff --git a/pkg/integration/tests/interactive_rebase/mid_rebase_range_select.go b/pkg/integration/tests/interactive_rebase/mid_rebase_range_select.go index 6dcb12ea6..c94b63295 100644 --- a/pkg/integration/tests/interactive_rebase/mid_rebase_range_select.go +++ b/pkg/integration/tests/interactive_rebase/mid_rebase_range_select.go @@ -20,27 +20,6 @@ var MidRebaseRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ TopLines( Contains("commit 10").IsSelected(), ). - NavigateToLine(Contains("commit 07")). - Press(keys.Universal.RangeSelectDown). - TopLines( - Contains("commit 10"), - Contains("commit 09"), - Contains("commit 08"), - Contains("commit 07").IsSelected(), - Contains("commit 06").IsSelected(), - Contains("commit 05"), - Contains("commit 04"), - ). - // Verify we can't perform an edit on multiple commits (it's not supported - // yet) - Press(keys.Universal.Edit). - Tap(func() { - // This ought to be a toast but I'm too lazy to implement that right now. - t.ExpectPopup().Alert(). - Title(Equals("Error")). - Content(Contains("Action does not support range selection, please select a single item")). - Confirm() - }). NavigateToLine(Contains("commit 05")). // Start a rebase Press(keys.Universal.Edit). diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 531fce5d9..d0525fa59 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -167,6 +167,7 @@ var tests = []*components.IntegrationTest{ interactive_rebase.DropWithCustomCommentChar, interactive_rebase.EditFirstCommit, interactive_rebase.EditNonTodoCommitDuringRebase, + interactive_rebase.EditRangeSelectOutsideRebase, interactive_rebase.EditTheConflCommit, interactive_rebase.FixupFirstCommit, interactive_rebase.FixupSecondCommit,