summaryrefslogtreecommitdiffstats
path: root/pkg/commands
diff options
context:
space:
mode:
authorStefan Haller <stefan@haller-berlin.de>2023-04-06 11:13:42 +0200
committerStefan Haller <stefan@haller-berlin.de>2023-04-29 07:28:33 +0200
commita8586ba57e15c1d069448044a1e7d5859547ea7d (patch)
treee9602e23ac227400a7e4fbd35ff576f318bcfb08 /pkg/commands
parentdad7a70bf8c58d63a57a7846c91d2fca82160e4d (diff)
Refactor: simplify PrepareInteractiveRebaseCommand API
Instead of passing a bunch of different options in PrepareInteractiveRebaseCommandOpts, where it was unclear how they interact if several are set, have only a single field "instruction" which can be set to one of various different instructions. The functionality of replacing the entire todo file with our own is no longer available; it is only possible to prepend todos to the existing file. Also, instead of using different env vars for the various rebase operations that we want to tell the daemon to do, use a single one that contains a json-encoded struct with all available instructions. This makes the protocol much clearer, and makes it easier to extend in the future.
Diffstat (limited to 'pkg/commands')
-rw-r--r--pkg/commands/git_commands/patch.go9
-rw-r--r--pkg/commands/git_commands/rebase.go149
2 files changed, 90 insertions, 68 deletions
diff --git a/pkg/commands/git_commands/patch.go b/pkg/commands/git_commands/patch.go
index a09f9bce6..0f8bfed9d 100644
--- a/pkg/commands/git_commands/patch.go
+++ b/pkg/commands/git_commands/patch.go
@@ -5,6 +5,7 @@ import (
"github.com/fsmiamoto/git-todo-parser/todo"
"github.com/go-errors/errors"
+ "github.com/jesseduffield/lazygit/pkg/app/daemon"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
@@ -107,9 +108,11 @@ func (self *PatchCommands) MovePatchToSelectedCommit(commits []*models.Commit, s
err := self.rebase.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: commits[baseIndex].Sha,
overrideEditor: true,
- changeTodoActions: []ChangeTodoAction{
- {sha: commits[sourceCommitIdx].Sha, newAction: todo.Edit},
- {sha: commits[destinationCommitIdx].Sha, newAction: todo.Edit},
+ instruction: ChangeTodoActionsInstruction{
+ actions: []daemon.ChangeTodoAction{
+ {Sha: commits[sourceCommitIdx].Sha, NewAction: todo.Edit},
+ {Sha: commits[destinationCommitIdx].Sha, NewAction: todo.Edit},
+ },
},
}).Run()
if err != nil {
diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go
index 13c978a92..ead8da27a 100644
--- a/pkg/commands/git_commands/rebase.go
+++ b/pkg/commands/git_commands/rebase.go
@@ -1,6 +1,7 @@
package git_commands
import (
+ "encoding/json"
"fmt"
"path/filepath"
"strings"
@@ -57,11 +58,11 @@ func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, me
func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index int) (oscommands.ICmdObj, error) {
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: getBaseShaOrRoot(commits, index+1),
- changeTodoActions: []ChangeTodoAction{
- {
- sha: commits[index].Sha,
- newAction: todo.Reword,
- },
+ instruction: ChangeTodoActionsInstruction{
+ actions: []daemon.ChangeTodoAction{{
+ Sha: commits[index].Sha,
+ NewAction: todo.Reword,
+ }},
},
}), nil
}
@@ -103,8 +104,8 @@ func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: baseShaOrRoot,
+ instruction: MoveDownInstruction{sha: commits[index].Sha},
overrideEditor: true,
- moveDown: commits[index].Sha,
}).Run()
}
@@ -113,8 +114,8 @@ func (self *RebaseCommands) MoveCommitUp(commits []*models.Commit, index int) er
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: baseShaOrRoot,
+ instruction: MoveUpInstruction{sha: commits[index].Sha},
overrideEditor: true,
- moveUp: commits[index].Sha,
}).Run()
}
@@ -127,12 +128,14 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index in
baseShaOrRoot := getBaseShaOrRoot(commits, baseIndex)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
- baseShaOrRoot: baseShaOrRoot,
+ baseShaOrRoot: baseShaOrRoot,
+ instruction: ChangeTodoActionsInstruction{
+ actions: []daemon.ChangeTodoAction{{
+ Sha: commits[index].Sha,
+ NewAction: action,
+ }},
+ },
overrideEditor: true,
- changeTodoActions: []ChangeTodoAction{{
- sha: commits[index].Sha,
- newAction: action,
- }},
}).Run()
}
@@ -140,59 +143,72 @@ func (self *RebaseCommands) EditRebase(branchRef string) error {
commands := []TodoLine{{Action: "break"}}
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: branchRef,
- todoLines: commands,
- prepend: true,
+ instruction: PrependLinesInstruction{todoLines: commands},
}).Run()
}
-type ChangeTodoAction struct {
- sha string
- newAction todo.TodoCommand
+type InteractiveRebaseInstruction interface {
+ // Add our data to the instructions struct, and return a log string
+ serialize(instructions *daemon.InteractiveRebaseInstructions) string
+}
+
+type PrependLinesInstruction struct {
+ todoLines []TodoLine
+}
+
+func (self PrependLinesInstruction) serialize(instructions *daemon.InteractiveRebaseInstructions) string {
+ todoStr := TodoLinesToString(self.todoLines)
+ instructions.LinesToPrependToRebaseTODO = todoStr
+ return fmt.Sprintf("Creating TODO file for interactive rebase: \n\n%s", todoStr)
+}
+
+type ChangeTodoActionsInstruction struct {
+ actions []daemon.ChangeTodoAction
+}
+
+func (self ChangeTodoActionsInstruction) serialize(instructions *daemon.InteractiveRebaseInstructions) string {
+ instructions.ChangeTodoActions = self.actions
+ changeTodoStr := strings.Join(slices.Map(self.actions, func(c daemon.ChangeTodoAction) string {
+ return fmt.Sprintf("%s:%s", c.Sha, c.NewAction)
+ }), "\n")
+ return fmt.Sprintf("Changing TODO actions: %s", changeTodoStr)
+}
+
+type MoveDownInstruction struct {
+ sha string
+}
+
+func (self MoveDownInstruction) serialize(instructions *daemon.InteractiveRebaseInstructions) string {
+ instructions.ShaToMoveDown = self.sha
+ return fmt.Sprintf("Moving TODO down: %s", self.sha)
+}
+
+type MoveUpInstruction struct {
+ sha string
+}
+
+func (self MoveUpInstruction) serialize(instructions *daemon.InteractiveRebaseInstructions) string {
+ instructions.ShaToMoveUp = self.sha
+ return fmt.Sprintf("Moving TODO up: %s", self.sha)
}
type PrepareInteractiveRebaseCommandOpts struct {
- baseShaOrRoot string
- todoLines []TodoLine
- overrideEditor bool
- prepend bool
- changeTodoActions []ChangeTodoAction
- moveDown string
- moveUp string
+ baseShaOrRoot string
+ instruction InteractiveRebaseInstruction
+ overrideEditor bool
}
// 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(opts PrepareInteractiveRebaseCommandOpts) oscommands.ICmdObj {
- todo := self.buildTodo(opts.todoLines)
ex := oscommands.GetLazygitPath()
- prependLines := ""
- if opts.prepend {
- prependLines = "TRUE"
- }
debug := "FALSE"
if self.Debug {
debug = "TRUE"
}
- changeTodoValue := strings.Join(slices.Map(opts.changeTodoActions, func(c ChangeTodoAction) string {
- return fmt.Sprintf("%s:%s", c.sha, c.newAction)
- }), "\n")
-
- moveDownValue := ""
- if opts.moveDown != "" {
- moveDownValue = opts.moveDown
- }
- moveUpValue := ""
- if opts.moveUp != "" {
- moveUpValue = opts.moveUp
- }
-
- if todo != "" && changeTodoValue != "" {
- panic("It's not allowed to pass both todoLines and changeActionOpts")
- }
-
rebaseMergesArg := " --rebase-merges"
if self.version.IsOlderThan(2, 22, 0) {
rebaseMergesArg = ""
@@ -204,25 +220,24 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
cmdObj := self.cmd.New(cmdStr)
gitSequenceEditor := ex
- if todo != "" {
- self.os.LogCommand(fmt.Sprintf("Creating TODO file for interactive rebase: \n\n%s", todo), false)
- } else if changeTodoValue != "" {
- self.os.LogCommand(fmt.Sprintf("Changing TODO action: %s", changeTodoValue), false)
- } else if moveDownValue != "" {
- self.os.LogCommand(fmt.Sprintf("Moving TODO down: %s", moveDownValue), false)
- } else if moveUpValue != "" {
- self.os.LogCommand(fmt.Sprintf("Moving TODO up: %s", moveUpValue), false)
+
+ if opts.instruction != nil {
+ instructions := daemon.InteractiveRebaseInstructions{}
+ logStr := opts.instruction.serialize(&instructions)
+ jsonData, err := json.Marshal(instructions)
+ if err == nil {
+ envVar := fmt.Sprintf("%s=%s", daemon.InteractiveRebaseInstructionsEnvKey, jsonData)
+ cmdObj.AddEnvVars(envVar)
+ self.os.LogCommand(logStr, false)
+ } else {
+ self.Log.Error(err)
+ }
} else {
gitSequenceEditor = "true"
}
cmdObj.AddEnvVars(
daemon.DaemonKindEnvKey+"="+string(daemon.InteractiveRebase),
- daemon.RebaseTODOEnvKey+"="+todo,
- daemon.PrependLinesEnvKey+"="+prependLines,
- daemon.ChangeTodoActionEnvKey+"="+changeTodoValue,
- daemon.MoveTodoDownEnvKey+"="+moveDownValue,
- daemon.MoveTodoUpEnvKey+"="+moveUpValue,
"DEBUG="+debug,
"LANG=en_US.UTF-8", // Force using EN as language
"LC_ALL=en_US.UTF-8", // Force using EN as language
@@ -297,10 +312,12 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(commits []*models.Co
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: getBaseShaOrRoot(commits, commitIndex+1),
overrideEditor: true,
- changeTodoActions: []ChangeTodoAction{{
- sha: commits[commitIndex].Sha,
- newAction: todo.Edit,
- }},
+ instruction: ChangeTodoActionsInstruction{
+ actions: []daemon.ChangeTodoAction{{
+ Sha: commits[commitIndex].Sha,
+ NewAction: todo.Edit,
+ }},
+ },
}).Run()
}
@@ -393,11 +410,13 @@ func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error {
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: "HEAD",
- todoLines: todoLines,
+ instruction: PrependLinesInstruction{
+ todoLines: todoLines,
+ },
}).Run()
}
-func (self *RebaseCommands) buildTodo(todoLines []TodoLine) string {
+func TodoLinesToString(todoLines []TodoLine) string {
lines := slices.Map(todoLines, func(todoLine TodoLine) string {
return todoLine.ToString()
})