diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2022-03-20 16:19:27 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2022-03-24 20:14:41 +1100 |
commit | 43d3f2bcb6094293156841f6670577720bab2314 (patch) | |
tree | f5a7bfdb3b9d475044e1d10fa6373b306d1e6fd3 /pkg/commands | |
parent | 99e55725fb0783bc3280498ec6047350368c25d7 (diff) |
refactor todo file generation
Diffstat (limited to 'pkg/commands')
-rw-r--r-- | pkg/commands/git_commands/patch.go | 14 | ||||
-rw-r--r-- | pkg/commands/git_commands/rebase.go | 79 |
2 files changed, 59 insertions, 34 deletions
diff --git a/pkg/commands/git_commands/patch.go b/pkg/commands/git_commands/patch.go index 8f9ce5784..a805c7f21 100644 --- a/pkg/commands/git_commands/patch.go +++ b/pkg/commands/git_commands/patch.go @@ -105,16 +105,16 @@ func (self *PatchCommands) MovePatchToSelectedCommit(commits []*models.Commit, s } baseIndex := sourceCommitIdx + 1 - todo := "" - for i, commit := range commits[0:baseIndex] { - a := "pick" + + todoLines := self.rebase.BuildTodoLines(commits[0:baseIndex], func(commit *models.Commit, i int) string { if i == sourceCommitIdx || i == destinationCommitIdx { - a = "edit" + return "edit" + } else { + return "pick" } - todo = a + " " + commit.Sha + " " + commit.Name + "\n" + todo - } + }) - err := self.rebase.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todo, true).Run() + err := self.rebase.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todoLines, true).Run() if err != nil { return err } diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index 71c8b0e63..ab7963c44 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/go-errors/errors" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" ) @@ -52,7 +53,7 @@ func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, me } func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index int) (oscommands.ICmdObj, error) { - todo, sha, err := self.GenerateGenericRebaseTodo(commits, index, "reword") + todo, sha, err := self.BuildSingleActionTodo(commits, index, "reword") if err != nil { return nil, err } @@ -67,17 +68,15 @@ func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int) return errors.New(self.Tr.NoRoom) } - todo := "" orderedCommits := append(commits[0:index], commits[index+1], commits[index]) - for _, commit := range orderedCommits { - todo = "pick " + commit.Sha + " " + commit.Name + "\n" + todo - } - return self.PrepareInteractiveRebaseCommand(commits[index+2].Sha, todo, true).Run() + todoLines := self.BuildTodoLinesSingleAction(orderedCommits, "pick") + + return self.PrepareInteractiveRebaseCommand(commits[index+2].Sha, todoLines, true).Run() } func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index int, action string) error { - todo, sha, err := self.GenerateGenericRebaseTodo(commits, index, action) + todo, sha, err := self.BuildSingleActionTodo(commits, index, action) if err != nil { return err } @@ -88,7 +87,8 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index in // PrepareInteractiveRebaseCommand returns the cmd for an interactive rebase // we tell git to run lazygit to edit the todo list, and we pass the client // lazygit a todo string to write to the todo file -func (self *RebaseCommands) PrepareInteractiveRebaseCommand(baseSha string, todo string, overrideEditor bool) oscommands.ICmdObj { +func (self *RebaseCommands) PrepareInteractiveRebaseCommand(baseSha string, todoLines []TodoLine, overrideEditor bool) oscommands.ICmdObj { + todo := self.buildTodo(todoLines) ex := oscommands.GetLazygitPath() debug := "FALSE" @@ -124,38 +124,37 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(baseSha string, todo return cmdObj } -func (self *RebaseCommands) GenerateGenericRebaseTodo(commits []*models.Commit, actionIndex int, action string) (string, string, error) { +// produces TodoLines where every commit is picked (or dropped for merge commits) except for the commit at the given index, which +// will have the given action applied to it. +func (self *RebaseCommands) BuildSingleActionTodo(commits []*models.Commit, actionIndex int, action string) ([]TodoLine, string, error) { baseIndex := actionIndex + 1 if len(commits) <= baseIndex { - return "", "", errors.New(self.Tr.CannotRebaseOntoFirstCommit) + return nil, "", errors.New(self.Tr.CannotRebaseOntoFirstCommit) } if action == "squash" || action == "fixup" { baseIndex++ if len(commits) <= baseIndex { - return "", "", errors.New(self.Tr.CannotSquashOntoSecondCommit) + return nil, "", errors.New(self.Tr.CannotSquashOntoSecondCommit) } } - todo := "" - for i, commit := range commits[0:baseIndex] { - var commitAction string + todoLines := self.BuildTodoLines(commits[0:baseIndex], func(commit *models.Commit, i int) string { if i == actionIndex { - commitAction = action + return action } else if commit.IsMerge() { // your typical interactive rebase will actually drop merge commits by default. Damn git CLI, you scary! // doing this means we don't need to worry about rebasing over merges which always causes problems. // you typically shouldn't be doing rebases that pass over merge commits anyway. - commitAction = "drop" + return "drop" } else { - commitAction = "pick" + return "pick" } - todo = commitAction + " " + commit.Sha + " " + commit.Name + "\n" + todo - } + }) - return todo, commits[baseIndex].Sha, nil + return todoLines, commits[baseIndex].Sha, nil } // AmendTo amends the given commit with whatever files are staged @@ -244,7 +243,7 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(commits []*models.Co return errors.New(self.Tr.DisabledForGPG) } - todo, sha, err := self.GenerateGenericRebaseTodo(commits, commitIndex, "edit") + todo, sha, err := self.BuildSingleActionTodo(commits, commitIndex, "edit") if err != nil { return err } @@ -254,7 +253,7 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(commits []*models.Co // RebaseBranch interactive rebases onto a branch func (self *RebaseCommands) RebaseBranch(branchName string) error { - return self.PrepareInteractiveRebaseCommand(branchName, "", false).Run() + return self.PrepareInteractiveRebaseCommand(branchName, nil, false).Run() } func (self *RebaseCommands) GenericMergeOrRebaseActionCmdObj(commandType string, command string) oscommands.ICmdObj { @@ -336,10 +335,36 @@ func (self *RebaseCommands) DiscardOldFileChanges(commits []*models.Commit, comm // CherryPickCommits begins an interactive rebase with the given shas being cherry picked onto HEAD func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error { - todo := "" - for _, commit := range commits { - todo = "pick " + commit.Sha + " " + commit.Name + "\n" + todo - } + todoLines := self.BuildTodoLinesSingleAction(commits, "pick") + + return self.PrepareInteractiveRebaseCommand("HEAD", todoLines, false).Run() +} + +func (self *RebaseCommands) buildTodo(todoLines []TodoLine) string { + lines := slices.Map(todoLines, func(todoLine TodoLine) string { + return todoLine.ToString() + }) + + return strings.Join(slices.Reverse(lines), "") +} + +func (self *RebaseCommands) BuildTodoLines(commits []*models.Commit, f func(*models.Commit, int) string) []TodoLine { + return slices.MapWithIndex(commits, func(commit *models.Commit, i int) TodoLine { + return TodoLine{Action: f(commit, i), Commit: commit} + }) +} + +func (self *RebaseCommands) BuildTodoLinesSingleAction(commits []*models.Commit, action string) []TodoLine { + return self.BuildTodoLines(commits, func(commit *models.Commit, i int) string { + return action + }) +} + +type TodoLine struct { + Action string + Commit *models.Commit +} - return self.PrepareInteractiveRebaseCommand("HEAD", todo, false).Run() +func (self *TodoLine) ToString() string { + return self.Action + " " + self.Commit.Sha + " " + self.Commit.Name + "\n" } |