summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-04-15 17:16:11 +1000
committerGitHub <noreply@github.com>2023-04-15 17:16:11 +1000
commit46718e25ca442a694cdd9efeb87fc585971ba3f4 (patch)
treed00d7786582818ec580d729693831dca1bcdb6ea
parent981ba4c66c3a5e108746e743a58dc90face6aba5 (diff)
parentd675eb65077fee840d2ed7b13a0ee038611664b6 (diff)
Merge pull request #2547 from stefanhaller/more-robust-todo-rewriting
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--pkg/commands/git_commands/commit_loader.go40
-rw-r--r--pkg/commands/git_commands/commit_loader_test.go32
-rw-r--r--pkg/commands/git_commands/rebase.go61
-rw-r--r--pkg/commands/git_commands/reflog_commit_loader.go2
-rw-r--r--pkg/commands/git_commands/reflog_commit_loader_test.go18
-rw-r--r--pkg/commands/git_commands/version.go6
-rw-r--r--pkg/commands/models/commit.go25
-rw-r--r--pkg/gui/commits_panel.go8
-rw-r--r--pkg/gui/controllers/local_commits_controller.go49
-rw-r--r--pkg/gui/presentation/commits.go33
-rw-r--r--pkg/gui/presentation/commits_test.go27
-rw-r--r--pkg/i18n/english.go4
-rw-r--r--pkg/integration/components/runner.go24
-rw-r--r--pkg/integration/components/shell.go6
-rw-r--r--pkg/integration/components/test.go58
-rw-r--r--pkg/integration/components/test_test.go63
-rw-r--r--pkg/integration/tests/interactive_rebase/drop_todo_commit_with_update_ref.go69
-rw-r--r--pkg/integration/tests/test_list.go1
-rw-r--r--pkg/utils/rebaseTodo.go108
-rw-r--r--pkg/utils/rebaseTodo_test.go230
-rw-r--r--pkg/utils/slice.go21
-rw-r--r--pkg/utils/slice_test.go82
-rw-r--r--vendor/github.com/fsmiamoto/git-todo-parser/LICENSE7
-rw-r--r--vendor/github.com/fsmiamoto/git-todo-parser/todo/parse.go15
-rw-r--r--vendor/github.com/fsmiamoto/git-todo-parser/todo/todo.go35
-rw-r--r--vendor/github.com/fsmiamoto/git-todo-parser/todo/write.go92
-rw-r--r--vendor/modules.txt2
29 files changed, 974 insertions, 150 deletions
diff --git a/go.mod b/go.mod
index c710eee99..0a6a3871c 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
index 194b5f494..46f3c08e0 100644
--- a/go.sum
+++ b/go.sum
@@ -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