diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2023-04-15 17:16:11 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-15 17:16:11 +1000 |
commit | 46718e25ca442a694cdd9efeb87fc585971ba3f4 (patch) | |
tree | d00d7786582818ec580d729693831dca1bcdb6ea | |
parent | 981ba4c66c3a5e108746e743a58dc90face6aba5 (diff) | |
parent | d675eb65077fee840d2ed7b13a0ee038611664b6 (diff) |
Merge pull request #2547 from stefanhaller/more-robust-todo-rewriting
29 files changed, 974 insertions, 150 deletions
@@ -9,7 +9,7 @@ require ( github.com/cli/safeexec v1.0.0 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/creack/pty v1.1.11 - github.com/fsmiamoto/git-todo-parser v0.0.2 + github.com/fsmiamoto/git-todo-parser v0.0.4-0.20230403011024-617a5a7ce980 github.com/fsnotify/fsnotify v1.4.7 github.com/gdamore/tcell/v2 v2.6.0 github.com/go-errors/errors v1.4.2 @@ -28,8 +28,8 @@ github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886/go.mod h1:Zm6kSWBoL9 github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/fsmiamoto/git-todo-parser v0.0.2 h1:l6Y+9q7jbM+yK/w6kASpHO7ejL9ARCErm3tCEqOT278= -github.com/fsmiamoto/git-todo-parser v0.0.2/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas= +github.com/fsmiamoto/git-todo-parser v0.0.4-0.20230403011024-617a5a7ce980 h1:ay9aM+Ay9I4LJttUVF4EFVmeNUkS9/snYVFK6lwieVQ= +github.com/fsmiamoto/git-todo-parser v0.0.4-0.20230403011024-617a5a7ce980/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index 119566f08..bce16de15 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -89,7 +89,7 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit, if commit.Sha == firstPushedCommit { passedFirstPushedCommit = true } - commit.Status = map[bool]string{true: "unpushed", false: "pushed"}[!passedFirstPushedCommit] + commit.Status = map[bool]models.CommitStatus{true: models.StatusUnpushed, false: models.StatusPushed}[!passedFirstPushedCommit] commits = append(commits, commit) return false, nil }) @@ -194,8 +194,8 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode return nil, nil } - commitShas := slices.Map(commits, func(commit *models.Commit) string { - return commit.Sha + commitShas := slices.FilterMap(commits, func(commit *models.Commit) (string, bool) { + return commit.Sha, commit.Sha != "" }) // note that we're not filtering these as we do non-rebasing commits just because @@ -209,20 +209,26 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode ), ).DontLog() - hydratedCommits := make([]*models.Commit, 0, len(commits)) - i := 0 + fullCommits := map[string]*models.Commit{} err = cmdObj.RunAndProcessLines(func(line string) (bool, error) { commit := self.extractCommitFromLine(line) - matchingCommit := commits[i] - commit.Action = matchingCommit.Action - commit.Status = matchingCommit.Status - hydratedCommits = append(hydratedCommits, commit) - i++ + fullCommits[commit.Sha] = commit return false, nil }) if err != nil { return nil, err } + + hydratedCommits := make([]*models.Commit, 0, len(commits)) + for _, rebasingCommit := range commits { + if rebasingCommit.Sha == "" { + hydratedCommits = append(hydratedCommits, rebasingCommit) + } else if commit := fullCommits[rebasingCommit.Sha]; commit != nil { + commit.Action = rebasingCommit.Action + commit.Status = rebasingCommit.Status + hydratedCommits = append(hydratedCommits, commit) + } + } return hydratedCommits, nil } @@ -305,15 +311,17 @@ func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, err } for _, t := range todos { - if t.Commit == "" { + if t.Command == todo.UpdateRef { + t.Msg = strings.TrimPrefix(t.Ref, "refs/heads/") + } else if t.Commit == "" { // Command does not have a commit associated, skip continue } commits = slices.Prepend(commits, &models.Commit{ Sha: t.Commit, Name: t.Msg, - Status: "rebasing", - Action: t.Command.String(), + Status: models.StatusRebasing, + Action: t.Command, }) } @@ -332,7 +340,7 @@ func (self *CommitLoader) commitFromPatch(content string) *models.Commit { return &models.Commit{ Sha: sha, Name: name, - Status: "rebasing", + Status: models.StatusRebasing, } } @@ -349,11 +357,11 @@ func (self *CommitLoader) setCommitMergedStatuses(refName string, commits []*mod if strings.HasPrefix(ancestor, commit.Sha) { passedAncestor = true } - if commit.Status != "pushed" { + if commit.Status != models.StatusPushed { continue } if passedAncestor { - commits[i].Status = "merged" + commits[i].Status = models.StatusMerged } } return commits, nil diff --git a/pkg/commands/git_commands/commit_loader_test.go b/pkg/commands/git_commands/commit_loader_test.go index 8ba3e6649..140541545 100644 --- a/pkg/commands/git_commands/commit_loader_test.go +++ b/pkg/commands/git_commands/commit_loader_test.go @@ -78,8 +78,8 @@ func TestGetCommits(t *testing.T) { { Sha: "0eea75e8c631fba6b58135697835d58ba4c18dbc", Name: "better typing for rebase mode", - Status: "unpushed", - Action: "", + Status: models.StatusUnpushed, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "(HEAD -> better-tests)", AuthorName: "Jesse Duffield", @@ -92,8 +92,8 @@ func TestGetCommits(t *testing.T) { { Sha: "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", Name: "fix logging", - Status: "pushed", - Action: "", + Status: models.StatusPushed, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "(origin/better-tests)", AuthorName: "Jesse Duffield", @@ -106,8 +106,8 @@ func TestGetCommits(t *testing.T) { { Sha: "e94e8fc5b6fab4cb755f29f1bdb3ee5e001df35c", Name: "refactor", - Status: "pushed", - Action: "", + Status: models.StatusPushed, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "", AuthorName: "Jesse Duffield", @@ -120,8 +120,8 @@ func TestGetCommits(t *testing.T) { { Sha: "d8084cd558925eb7c9c38afeed5725c21653ab90", Name: "WIP", - Status: "pushed", - Action: "", + Status: models.StatusPushed, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "", AuthorName: "Jesse Duffield", @@ -134,8 +134,8 @@ func TestGetCommits(t *testing.T) { { Sha: "65f910ebd85283b5cce9bf67d03d3f1a9ea3813a", Name: "WIP", - Status: "pushed", - Action: "", + Status: models.StatusPushed, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "", AuthorName: "Jesse Duffield", @@ -148,8 +148,8 @@ func TestGetCommits(t *testing.T) { { Sha: "26c07b1ab33860a1a7591a0638f9925ccf497ffa", Name: "WIP", - Status: "merged", - Action: "", + Status: models.StatusMerged, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "", AuthorName: "Jesse Duffield", @@ -162,8 +162,8 @@ func TestGetCommits(t *testing.T) { { Sha: "3d4470a6c072208722e5ae9a54bcb9634959a1c5", Name: "WIP", - Status: "merged", - Action: "", + Status: models.StatusMerged, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "", AuthorName: "Jesse Duffield", @@ -176,8 +176,8 @@ func TestGetCommits(t *testing.T) { { Sha: "053a66a7be3da43aacdc7aa78e1fe757b82c4dd2", Name: "refactoring the config struct", - Status: "merged", - Action: "", + Status: models.StatusMerged, + Action: models.ActionNone, Tags: []string{}, ExtraInfo: "", AuthorName: "Jesse Duffield", diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index 6af83a27f..e4c20426f 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -2,15 +2,16 @@ package git_commands import ( "fmt" - "os" "path/filepath" "strings" + "github.com/fsmiamoto/git-todo-parser/todo" "github.com/go-errors/errors" "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/app/daemon" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" + "github.com/jesseduffield/lazygit/pkg/utils" ) type RebaseCommands struct { @@ -201,55 +202,39 @@ func (self *RebaseCommands) AmendTo(commit *models.Commit) error { return self.SquashAllAboveFixupCommits(commit) } -// EditRebaseTodo sets the action at a given index in the git-rebase-todo file -func (self *RebaseCommands) EditRebaseTodo(index int, action string) error { +// EditRebaseTodo sets the action for a given rebase commit in the git-rebase-todo file +func (self *RebaseCommands) EditRebaseTodo(commit *models.Commit, action todo.TodoCommand) error { fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo") - bytes, err := os.ReadFile(fileName) + todos, err := utils.ReadRebaseTodoFile(fileName) if err != nil { return err } - content := strings.Split(string(bytes), "\n") - commitCount := self.getTodoCommitCount(content) - - // we have the most recent commit at the bottom whereas the todo file has - // it at the bottom, so we need to subtract our index from the commit count - contentIndex := commitCount - 1 - index - splitLine := strings.Split(content[contentIndex], " ") - content[contentIndex] = action + " " + strings.Join(splitLine[1:], " ") - result := strings.Join(content, "\n") - - return os.WriteFile(fileName, []byte(result), 0o644) -} - -func (self *RebaseCommands) getTodoCommitCount(content []string) int { - // count lines that are not blank and are not comments - commitCount := 0 - for _, line := range content { - if line != "" && !strings.HasPrefix(line, "#") { - commitCount++ + for i := range todos { + t := &todos[i] + // Comparing just the sha is not enough; we need to compare both the + // action and the sha, as the sha could appear multiple times (e.g. in a + // pick and later in a merge) + if t.Command == commit.Action && t.Commit == commit.Sha { + t.Command = action + return utils.WriteRebaseTodoFile(fileName, todos) } } - return commitCount + + // Should never get here + return fmt.Errorf("Todo %s not found in git-rebase-todo", commit.Sha) } // MoveTodoDown moves a rebase todo item down by one position -func (self *RebaseCommands) MoveTodoDown(index int) error { +func (self *RebaseCommands) MoveTodoDown(commit *models.Commit) error { fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo") - bytes, err := os.ReadFile(fileName) - if err != nil { - return err - } - - content := strings.Split(string(bytes), "\n") - commitCount := self.getTodoCommitCount(content) - contentIndex := commitCount - 1 - index - - rearrangedContent := append(content[0:contentIndex-1], content[contentIndex], content[contentIndex-1]) - rearrangedContent = append(rearrangedContent, content[contentIndex+1:]...) - result := strings.Join(rearrangedContent, "\n") + return utils.MoveTodoDown(fileName, commit.Sha, commit.Action) +} - return os.WriteFile(fileName, []byte(result), 0o644) +// MoveTodoDown moves a rebase todo item down by one position +func (self *RebaseCommands) MoveTodoUp(commit *models.Commit) error { + fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo") + return utils.MoveTodoUp(fileName, commit.Sha, commit.Action) } // SquashAllAboveFixupCommits squashes all fixup! commits above the given one diff --git a/pkg/commands/git_commands/reflog_commit_loader.go b/pkg/commands/git_commands/reflog_commit_loader.go index e2d3a7dad..c5c14fb72 100644 --- a/pkg/commands/git_commands/reflog_commit_loader.go +++ b/pkg/commands/git_commands/reflog_commit_loader.go @@ -52,7 +52,7 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit Sha: fields[0], Name: fields[2], UnixTimestamp: int64(unixTimestamp), - Status: "reflog", + Status: models.StatusReflog, Parents: parents, } diff --git a/pkg/commands/git_commands/reflog_commit_loader_test.go b/pkg/commands/git_commands/reflog_commit_loader_test.go index 7170196e9..a51a40e69 100644 --- a/pkg/commands/git_commands/reflog_commit_loader_test.go +++ b/pkg/commands/git_commands/reflog_commit_loader_test.go @@ -51,35 +51,35 @@ func TestGetReflogCommits(t *testing.T) { { Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from A to B", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, { Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from B to A", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, { Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from A to B", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, { Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from master to A", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, { Sha: "f4ddf2f0d4be4ccc7efa", Name: "checkout: moving from A to master", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643149435, Parents: []string{"51baa8c1"}, }, @@ -95,7 +95,7 @@ func TestGetReflogCommits(t *testing.T) { lastReflogCommit: &models.Commit{ Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from B to A", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, @@ -103,7 +103,7 @@ func TestGetReflogCommits(t *testing.T) { { Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from A to B", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, @@ -119,7 +119,7 @@ func TestGetReflogCommits(t *testing.T) { lastReflogCommit: &models.Commit{ Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from B to A", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, @@ -128,7 +128,7 @@ func TestGetReflogCommits(t *testing.T) { { Sha: "c3c4b66b64c97ffeecde", Name: "checkout: moving from A to B", - Status: "reflog", + Status: models.StatusReflog, UnixTimestamp: 1643150483, Parents: []string{"51baa8c1"}, }, diff --git a/pkg/commands/git_commands/version.go b/pkg/commands/git_commands/version.go index 0cf4b485c..1b1351df4 100644 --- a/pkg/commands/git_commands/version.go +++ b/pkg/commands/git_commands/version.go @@ -32,7 +32,7 @@ func ParseGitVersion(versionStr string) (*GitVersion, error) { // versionStr should be something like: // git version 2.39.0 // git version 2.37.1 (Apple Git-137.1) - re := regexp.MustCompile(`[^\d]+(\d+)(\.\d+)?(\.\d+)?(.*)`) + re := regexp.MustCompile(`[^\d]*(\d+)(\.\d+)?(\.\d+)?(.*)`) matches := re.FindStringSubmatch(versionStr) if len(matches) < 5 { @@ -65,3 +65,7 @@ func (v *GitVersion) IsOlderThan(major, minor, patch int) bool { required := major*1000*1000 + minor*1000 + patch return actual < required } + +func (v *GitVersion) IsOlderThanVersion(version *GitVersion) bool { + return v.IsOlderThan(version.Major, version.Minor, version.Patch) +} diff --git a/pkg/commands/models/commit.go b/pkg/commands/models/commit.go index b3a171934..e0ff875a0 100644 --- a/pkg/commands/models/commit.go +++ b/pkg/commands/models/commit.go @@ -3,18 +3,37 @@ package models import ( "fmt" + "github.com/fsmiamoto/git-todo-parser/todo" "github.com/jesseduffield/lazygit/pkg/utils" ) // Special commit hash for empty tree object const EmptyTreeCommitHash = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" +type CommitStatus int + +const ( + StatusNone CommitStatus = iota + StatusUnpushed + StatusPushed + StatusMerged + StatusRebasing + StatusSelected + StatusReflog +) + +const ( + // Conveniently for us, the todo package starts the enum at 1, and given + // that it doesn't have a "none" value, we're setting ours to 0 + ActionNone todo.TodoCommand = 0 +) + // Commit : A git commit type Commit struct { Sha string Name string - Status string // one of "unpushed", "pushed", "merged", "rebasing" or "selected" - Action string // one of "", "pick", "edit", "squash", "reword", "drop", "fixup" + Status CommitStatus + Action todo.TodoCommand Tags []string ExtraInfo string // something like 'HEAD -> master, tag: v0.15.2' AuthorName string // something like 'Jesse Duffield' @@ -63,7 +82,7 @@ func (c *Commit) IsMerge() bool { // returns true if this commit is not actually in the git log but instead // is from a TODO file for an interactive rebase. func (c *Commit) IsTODO() bool { - return c.Action != "" + return c.Action != ActionNone } func IsHeadCommit(commits []*Commit, index int) bool { diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index 8b8c74eec..2b75be4d0 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -1,6 +1,7 @@ package gui import ( + "github.com/fsmiamoto/git-todo-parser/todo" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" @@ -34,6 +35,13 @@ func (gui *Gui) branchCommitsRenderToMain() error { commit := gui.State.Contexts.LocalCommits.GetSelected() if commit == nil { task = types.NewRenderStringTask(gui.c.Tr.NoCommitsThisBranch) + } else if commit.Action == todo.UpdateRef { + task = types.NewRenderStringTask( + utils.ResolvePlaceholderString( + gui.c.Tr.UpdateRefHere, + map[string]string{ + "ref": commit.Name, + })) } else { cmdObj := gui.git.Commit.ShowCmdObj(commit.Sha, gui.State.Modes.Filtering.GetPath(), gui.IgnoreWhitespaceInDiffView) diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 284534ffa..4610aed12 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -3,11 +3,13 @@ package controllers import ( "fmt" + "github.com/fsmiamoto/git-todo-parser/todo" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/samber/lo" ) type ( @@ -153,7 +155,7 @@ func (self *LocalCommitsController) squashDown(commit *models.Commit) error { return self.c.ErrorMsg(self.c.Tr.CannotSquashOrFixupFirstCommit) } - applied, err := self.handleMidRebaseCommand("squash", commit) + applied, err := self.handleMidRebaseCommand(todo.Squash, commit) if err != nil { return err } @@ -178,7 +180,7 @@ func (self *LocalCommitsController) fixup(commit *models.Commit) error { return self.c.ErrorMsg(self.c.Tr.CannotSquashOrFixupFirstCommit) } - applied, err := self.handleMidRebaseCommand("fixup", commit) + applied, err := self.handleMidRebaseCommand(todo.Fixup, commit) if err != nil { return err } @@ -199,7 +201,7 @@ func (self *LocalCommitsController) fixup(commit *models.Commit) error { } func (self *LocalCommitsController) reword(commit *models.Commit) error { - applied, err := self.handleMidRebaseCommand("reword", commit) + applied, err := self.handleMidRebaseCommand(todo.Reword, commit) if err != nil { return err } @@ -248,7 +250,7 @@ func (self *LocalCommitsController) doRewordEditor() error { } func (self *LocalCommitsController) rewordEditor(commit *models.Commit) error { - midRebase, err := self.handleMidRebaseCommand("reword", commit) + midRebase, err := self.handleMidRebaseCommand(todo.Reword, commit) if err != nil { return err } @@ -268,7 +270,7 @@ func (self *LocalCommitsController) rewordEditor(commit *models.Commit) error { } func (self *LocalCommitsController) drop(commit *models.Commit) error { - applied, err := self.handleMidRebaseCommand("drop", commit) + applied, err := self.handleMidRebaseCommand(todo.Drop, commit) if err != nil { return err } @@ -289,7 +291,7 @@ func (self *LocalCommitsController) drop(commit *models.Commit) error { } func (self *LocalCommitsController) edit(commit *models.Commit) error { - applied, err := self.handleMidRebaseCommand("edit", commit) + applied, err := self.handleMidRebaseCommand(todo.Edit, commit) if err != nil { return err } @@ -305,7 +307,7 @@ func (self *LocalCommitsController) edit(commit *models.Commit) error { } func (self *LocalCommitsController) pick(commit *models.Commit) error { - applied, err := self.handleMidRebaseCommand("pick", commit) + applied, err := self.handleMidRebaseCommand(todo.Pick, commit) if err != nil { return err } @@ -326,12 +328,12 @@ func (self *LocalCommitsController) interactiveRebase(action string) error { // handleMidRebaseCommand sees if the selected commit is in fact a rebasing // commit meaning you are trying to edit the todo file rather than actually // begin a rebase. It then updates the todo file with that action -func (self *LocalCommitsController) handleMidRebaseCommand(action string, commit *models.Commit) (bool, error) { +func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoCommand, commit *models.Commit) (bool, error) { if !commit.IsTODO() { if self.git.Status.WorkingTreeState() != enums.REBASE_MODE_NONE { // If we are in a rebase, the only action that is allowed for // non-todo commits is rewording the current head commit - if !(action == "reword" && self.isHeadCommit()) { + if !(action == todo.Reword && self.isHeadCommit()) { return true, self.c.ErrorMsg(self.c.Tr.AlreadyRebasing) } } @@ -343,19 +345,21 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action string, commit // and that means we either unconditionally wait around for the subprocess to ask for // our input or we set a lazygit client as the EDITOR env variable and have it // request us to edit the commit message when prompted. - if action == "reword" { + if action == todo.Reword { return true, self.c.ErrorMsg(self.c.Tr.LcRewordNotSupported) } + if allowed := isChangeOfRebaseTodoAllowed(action); !allowed { + return true, self.c.ErrorMsg(self.c.Tr.LcChangingThisActionIsNotAllowed) + } + self.c.LogAction("Update rebase TODO") self.c.LogCommand( - fmt.Sprintf("Updating rebase action of commit %s to '%s'", commit.ShortSha(), action), + fmt.Sprintf("Updating rebase action of commit %s to '%s'", commit.ShortSha(), action.String()), false, ) - if err := self.git.Rebase.EditRebaseTodo( - self.context().GetSelectedLineIdx(), action, - ); err != nil { + if err := self.git.Rebase.EditRebaseTodo(commit, action); err != nil { return false, self.c.Error(err) } @@ -383,7 +387,7 @@ func (self *LocalCommitsController) moveDown(commit *models.Commit) error { self.c.LogAction(self.c.Tr.Actions.MoveCommitDown) self.c.LogCommand(fmt.Sprintf("Moving commit %s down", commit.ShortSha()), false) - if err := self.git.Rebase.MoveTodoDown(index); err != nil { + if err := self.git.Rebase.MoveTodoDown(commit); err != nil { return self.c.Error(err) } self.context().MoveSelectedLine(1) @@ -421,7 +425,7 @@ func (self *LocalCommitsController) moveUp(commit *models.Commit) error { false, ) - if err := self.git.Rebase.MoveTodoDown(index - 1); err != nil { + if err := self.git.Rebase.MoveTodoUp(self.model.Commits[index]); err != nil { return self.c.Error(err) } self.context().MoveSelectedLine(-1) @@ -760,3 +764,16 @@ func (self *LocalCommitsController) paste() error { func (self *LocalCommitsController) isHeadCommit() bool { return mode |