summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-04-16 15:43:54 +1000
committerStefan Haller <stefan@haller-berlin.de>2023-04-29 07:28:33 +0200
commit185bbf0c75f9ea0d645fb0df6893169f7ae07340 (patch)
treed089088fa22629bd9cedab483eb1ec3c18641598
parenta8586ba57e15c1d069448044a1e7d5859547ea7d (diff)
Refactor to tighten interface to lazygit daemon
-rw-r--r--pkg/app/daemon/daemon.go290
-rw-r--r--pkg/app/daemon/rebase.go64
-rw-r--r--pkg/commands/git_commands/patch.go13
-rw-r--r--pkg/commands/git_commands/rebase.go160
-rw-r--r--pkg/commands/git_commands/rebase_test.go3
5 files changed, 319 insertions, 211 deletions
diff --git a/pkg/app/daemon/daemon.go b/pkg/app/daemon/daemon.go
index 7053a8032..d8f32e608 100644
--- a/pkg/app/daemon/daemon.go
+++ b/pkg/app/daemon/daemon.go
@@ -2,15 +2,16 @@ package daemon
import (
"encoding/json"
+ "fmt"
"log"
"os"
- "path/filepath"
- "strings"
+ "strconv"
"github.com/fsmiamoto/git-todo-parser/todo"
+ "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/common"
- "github.com/jesseduffield/lazygit/pkg/env"
"github.com/jesseduffield/lazygit/pkg/utils"
+ "github.com/samber/lo"
)
// Sometimes lazygit will be invoked in daemon mode from a parent lazygit process.
@@ -18,58 +19,56 @@ import (
// For example, if we want to ensure that a git command doesn't hang due to
// waiting for an editor to save a commit message, we can tell git to invoke lazygit
// as the editor via 'GIT_EDITOR=lazygit', and use the env var
-// 'LAZYGIT_DAEMON_KIND=EXIT_IMMEDIATELY' to specify that we want to run lazygit
-// as a daemon which simply exits immediately. Any additional arguments we want
-// to pass to a daemon can be done via other env vars.
+// 'LAZYGIT_DAEMON_KIND=1' (exit immediately) to specify that we want to run lazygit
+// as a daemon which simply exits immediately.
+//
+// 'Daemon' is not the best name for this, because it's not a persistent background
+// process, but it's close enough.
-type DaemonKind string
+type DaemonKind int
const (
- InteractiveRebase DaemonKind = "INTERACTIVE_REBASE"
- ExitImmediately DaemonKind = "EXIT_IMMEDIATELY"
+ // for when we fail to parse the daemon kind
+ DaemonKindUnknown DaemonKind = iota
+
+ DaemonKindExitImmediately
+ DaemonKindCherryPick
+ DaemonKindMoveTodoUp
+ DaemonKindMoveTodoDown
+ DaemonKindInsertBreak
+ DaemonKindChangeTodoActions
)
const (
DaemonKindEnvKey string = "LAZYGIT_DAEMON_KIND"
- // Contains a json-encoded instance of the InteractiveRebaseInstructions struct
- InteractiveRebaseInstructionsEnvKey string = "LAZYGIT_DAEMON_INSTRUCTIONS"
+ // Contains json-encoded arguments to the daemon
+ DaemonInstructionEnvKey string = "LAZYGIT_DAEMON_INSTRUCTION"
)
-// Exactly one of the fields in this struct is expected to be non-empty
-type InteractiveRebaseInstructions struct {
- // If this is non-empty, this string is prepended to the git-rebase-todo
- // file. The string is expected to have newlines at the end of each line.
- LinesToPrependToRebaseTODO string
+func getInstruction() Instruction {
+ jsonData := os.Getenv(DaemonInstructionEnvKey)
- // If this is non-empty, it tells lazygit to read the original todo file, and
- // change the action for one or more entries in it.
- // The existing action of the todo to be changed is expected to be "pick".
- ChangeTodoActions []ChangeTodoAction
-
- // Can be set to the sha of a "pick" todo that will be moved down by one.
- ShaToMoveDown string
-
- // Can be set to the sha of a "pick" todo that will be moved up by one.
- ShaToMoveUp string
-}
-
-type ChangeTodoAction struct {
- Sha string
- NewAction todo.TodoCommand
-}
+ mapping := map[DaemonKind]func(string) Instruction{
+ DaemonKindExitImmediately: deserializeInstruction[*ExitImmediatelyInstruction],
+ DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
+ DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
+ DaemonKindMoveTodoUp: deserializeInstruction[*MoveTodoUpInstruction],
+ DaemonKindMoveTodoDown: deserializeInstruction[*MoveTodoDownInstruction],
+ DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
+ }
-type Daemon interface {
- Run() error
+ return mapping[getDaemonKind()](jsonData)
}
func Handle(common *common.Common) {
- d := getDaemon(common)
- if d == nil {
+ if !InDaemonMode() {
return
}
- if err := d.Run(); err != nil {
+ instruction := getInstruction()
+
+ if err := instruction.run(common); err != nil {
log.Fatal(err)
}
@@ -77,89 +76,200 @@ func Handle(common *common.Common) {
}
func InDaemonMode() bool {
- return getDaemonKind() != ""
+ return getDaemonKind() != DaemonKindUnknown
}
-func getDaemon(common *common.Common) Daemon {
- switch getDaemonKind() {
- case InteractiveRebase:
- return &rebaseDaemon{c: common}
- case ExitImmediately:
- return &exitImmediatelyDaemon{c: common}
+func getDaemonKind() DaemonKind {
+ intValue, err := strconv.Atoi(os.Getenv(DaemonKindEnvKey))
+ if err != nil {
+ return DaemonKindUnknown
}
- return nil
+ return DaemonKind(intValue)
}
-func getDaemonKind() DaemonKind {
- return DaemonKind(os.Getenv(DaemonKindEnvKey))
+// An Instruction is a command to be run by lazygit in daemon mode.
+// It is serialized to json and passed to lazygit via environment variables
+type Instruction interface {
+ Kind() DaemonKind
+ SerializedInstructions() string
+
+ // runs the instruction
+ run(common *common.Common) error
}
-type rebaseDaemon struct {
- c *common.Common
+func serializeInstruction[T any](instruction T) string {
+ jsonData, err := json.Marshal(instruction)
+ if err != nil {
+ // this should never happen
+ panic(err)
+ }
+
+ return string(jsonData)
}
-func (self *rebaseDaemon) Run() error {
- self.c.Log.Info("Lazygit invoked as interactive rebase demon")
- self.c.Log.Info("args: ", os.Args)
- path := os.Args[1]
+func deserializeInstruction[T Instruction](jsonData string) Instruction {
+ var instruction T
+ err := json.Unmarshal([]byte(jsonData), &instruction)
+ if err != nil {
+ panic(err)
+ }
+
+ return instruction
+}
- if strings.HasSuffix(path, "git-rebase-todo") {
- return self.writeTodoFile(path)
- } else if strings.HasSuffix(path, filepath.Join(gitDir(), "COMMIT_EDITMSG")) { // TODO: test
- // if we are rebasing and squashing, we'll see a COMMIT_EDITMSG
- // but in this case we don't need to edit it, so we'll just return
- } else {
- self.c.Log.Info("Lazygit demon did not match on any use cases")
+func ToEnvVars(instruction Instruction) []string {
+ return []string{
+ fmt.Sprintf("%s=%d", DaemonKindEnvKey, instruction.Kind()),
+ fmt.Sprintf("%s=%s", DaemonInstructionEnvKey, instruction.SerializedInstructions()),
}
+}
+
+type ExitImmediatelyInstruction struct{}
+
+func (self *ExitImmediatelyInstruction) Kind() DaemonKind {
+ return DaemonKindExitImmediately
+}
+func (self *ExitImmediatelyInstruction) SerializedInstructions() string {
+ return serializeInstruction(self)
+}
+
+func (self *ExitImmediatelyInstruction) run(common *common.Common) error {
return nil
}
-func (self *rebaseDaemon) writeTodoFile(path string) error {
- jsonData := os.Getenv(InteractiveRebaseInstructionsEnvKey)
- instructions := InteractiveRebaseInstructions{}
- err := json.Unmarshal([]byte(jsonData), &instructions)
- if err != nil {
- return err
+func NewExitImmediatelyInstruction() Instruction {
+ return &ExitImmediatelyInstruction{}
+}
+
+type CherryPickCommitsInstruction struct {
+ Todo string
+}
+
+func NewCherryPickCommitsInstruction(commits []*models.Commit) Instruction {
+ todoLines := lo.Map(commits, func(commit *models.Commit, _ int) TodoLine {
+ return TodoLine{
+ Action: "pick",
+ Commit: commit,
+ }
+ })
+
+ todo := TodoLinesToString(todoLines)
+
+ return &CherryPickCommitsInstruction{
+ Todo: todo,
}
+}
+
+func (self *CherryPickCommitsInstruction) Kind() DaemonKind {
+ return DaemonKindCherryPick
+}
- if instructions.LinesToPrependToRebaseTODO != "" {
- return utils.PrependStrToTodoFile(path, []byte(instructions.LinesToPrependToRebaseTODO))
- } else if len(instructions.ChangeTodoActions) != 0 {
- return self.changeTodoAction(path, instructions.ChangeTodoActions)
- } else if instructions.ShaToMoveDown != "" {
- return utils.MoveTodoDown(path, instructions.ShaToMoveDown, todo.Pick)
- } else if instructions.ShaToMoveUp != "" {
- return utils.MoveTodoUp(path, instructions.ShaToMoveUp, todo.Pick)
+func (self *CherryPickCommitsInstruction) SerializedInstructions() string {
+ return serializeInstruction(self)
+}
+
+func (self *CherryPickCommitsInstruction) run(common *common.Common) error {
+ return handleInteractiveRebase(common, func(path string) error {
+ return utils.PrependStrToTodoFile(path, []byte(self.Todo))
+ })
+}
+
+type ChangeTodoActionsInstruction struct {
+ Changes []ChangeTodoAction
+}
+
+func NewChangeTodoActionsInstruction(changes []ChangeTodoAction) Instruction {
+ return &ChangeTodoActionsInstruction{
+ Changes: changes,
}
+}
- self.c.Log.Error("No instructions were given to daemon")
- return nil
+func (self *ChangeTodoActionsInstruction) Kind() DaemonKind {
+ return DaemonKindChangeTodoActions
+}
+
+func (self *ChangeTodoActionsInstruction) SerializedInstructions() string {
+ return serializeInstruction(self)
}
-func (self *rebaseDaemon) changeTodoAction(path string, changeTodoActions []ChangeTodoAction) error {
- for _, c := range changeTodoActions {
- if err := utils.EditRebaseTodo(path, c.Sha, todo.Pick, c.NewAction); err != nil {
- return err
+func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
+ return handleInteractiveRebase(common, func(path string) error {
+ for _, c := range self.Changes {
+ if err := utils.EditRebaseTodo(path, c.Sha, todo.Pick, c.NewAction); err != nil {
+ return err
+ }
}
+
+ return nil
+ })
+}
+
+type MoveTodoUpInstruction struct {
+ Sha string
+}
+
+func NewMoveTodoUpInstruction(sha string) Instruction {
+ return &MoveTodoUpInstruction{
+ Sha: sha,
}
+}
- return nil
+func (self *MoveTodoUpInstruction) Kind() DaemonKind {
+ return DaemonKindMoveTodoUp
}
-func gitDir() string {
- dir := env.GetGitDirEnv()
- if dir == "" {
- return ".git"
+func (self *MoveTodoUpInstruction) SerializedInstructions() string {
+ return serializeInstruction(self)
+}
+
+func (self *MoveTodoUpInstruction) run(common *common.Common) error {
+ return handleInteractiveRebase(common, func(path string) error {
+ return utils.MoveTodoUp(path, self.Sha, todo.Pick)
+ })
+}
+
+type MoveTodoDownInstruction struct {
+ Sha string
+}
+
+func NewMoveTodoDownInstruction(sha string) Instruction {
+ return &MoveTodoDownInstruction{
+ Sha: sha,
}
- return dir
}
-type exitImmediatelyDaemon struct {
- c *common.Common
+func (self *MoveTodoDownInstruction) Kind() DaemonKind {
+ return DaemonKindMoveTodoDown
}
-func (self *exitImmediatelyDaemon) Run() error {
- return nil
+func (self *MoveTodoDownInstruction) SerializedInstructions() string {
+ return serializeInstruction(self)
+}
+
+func (self *MoveTodoDownInstruction) run(common *common.Common) error {
+ return handleInteractiveRebase(common, func(path string) error {
+ return utils.MoveTodoDown(path, self.Sha, todo.Pick)
+ })
+}
+
+type InsertBreakInstruction struct{}
+
+func NewInsertBreakInstruction() Instruction {
+ return &InsertBreakInstruction{}
+}
+
+func (self *InsertBreakInstruction) Kind() DaemonKind {
+ return DaemonKindInsertBreak
+}
+
+func (self *InsertBreakInstruction) SerializedInstructions() string {
+ return serializeInstruction(self)
+}
+
+func (self *InsertBreakInstruction) run(common *common.Common) error {
+ return handleInteractiveRebase(common, func(path string) error {
+ return utils.PrependStrToTodoFile(path, []byte("break\n"))
+ })
}
diff --git a/pkg/app/daemon/rebase.go b/pkg/app/daemon/rebase.go
new file mode 100644
index 000000000..8702f0f69
--- /dev/null
+++ b/pkg/app/daemon/rebase.go
@@ -0,0 +1,64 @@
+package daemon
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/fsmiamoto/git-todo-parser/todo"
+ "github.com/jesseduffield/generics/slices"
+ "github.com/jesseduffield/lazygit/pkg/commands/models"
+ "github.com/jesseduffield/lazygit/pkg/common"
+ "github.com/jesseduffield/lazygit/pkg/env"
+)
+
+type TodoLine struct {
+ Action string
+ Commit *models.Commit
+}
+
+func (self *TodoLine) ToString() string {
+ if self.Action == "break" {
+ return self.Action + "\n"
+ } else {
+ return self.Action + " " + self.Commit.Sha + " " + self.Commit.Name + "\n"
+ }
+}
+
+func TodoLinesToString(todoLines []TodoLine) string {
+ lines := slices.Map(todoLines, func(todoLine TodoLine) string {
+ return todoLine.ToString()
+ })
+
+ return strings.Join(slices.Reverse(lines), "")
+}
+
+type ChangeTodoAction struct {
+ Sha string
+ NewAction todo.TodoCommand
+}
+
+func handleInteractiveRebase(common *common.Common, f func(path string) error) error {
+ common.Log.Info("Lazygit invoked as interactive rebase demon")
+ common.Log.Info("args: ", os.Args)
+ path := os.Args[1]
+
+ if strings.HasSuffix(path, "git-rebase-todo") {
+ return f(path)
+ } else if strings.HasSuffix(path, filepath.Join(gitDir(), "COMMIT_EDITMSG")) { // TODO: test
+ // if we are rebasing and squashing, we'll see a COMMIT_EDITMSG
+ // but in this case we don't need to edit it, so we'll just return
+ } else {
+ common.Log.Info("Lazygit demon did not match on any use cases")
+ }
+
+ return nil
+}
+
+func gitDir() string {
+ dir := env.GetGitDirEnv()
+ if dir == "" {
+ return ".git"
+ }
+ return dir
+}
diff --git a/pkg/commands/git_commands/patch.go b/pkg/commands/git_commands/patch.go
index 0f8bfed9d..06e5e0f67 100644
--- a/pkg/commands/git_commands/patch.go
+++ b/pkg/commands/git_commands/patch.go
@@ -105,15 +105,16 @@ func (self *PatchCommands) MovePatchToSelectedCommit(commits []*models.Commit, s
baseIndex := sourceCommitIdx + 1
+ changes := []daemon.ChangeTodoAction{
+ {Sha: commits[sourceCommitIdx].Sha, NewAction: todo.Edit},
+ {Sha: commits[destinationCommitIdx].Sha, NewAction: todo.Edit},
+ }
+ self.os.LogCommand(logTodoChanges(changes), false)
+
err := self.rebase.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: commits[baseIndex].Sha,
overrideEditor: true,
- instruction: ChangeTodoActionsInstruction{
- actions: []daemon.ChangeTodoAction{
- {Sha: commits[sourceCommitIdx].Sha, NewAction: todo.Edit},
- {Sha: commits[destinationCommitIdx].Sha, NewAction: todo.Edit},
- },
- },
+ instruction: daemon.NewChangeTodoActionsInstruction(changes),
}).Run()
if err != nil {
return err
diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go
index ead8da27a..be5384773 100644
--- a/pkg/commands/git_commands/rebase.go
+++ b/pkg/commands/git_commands/rebase.go
@@ -1,7 +1,6 @@
package git_commands
import (
- "encoding/json"
"fmt"
"path/filepath"
"strings"
@@ -13,6 +12,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/utils"
+ "github.com/samber/lo"
)
type RebaseCommands struct {
@@ -56,14 +56,15 @@ func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, me
}
func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index int) (oscommands.ICmdObj, error) {
+ changes := []daemon.ChangeTodoAction{{
+ Sha: commits[index].Sha,
+ NewAction: todo.Reword,
+ }}
+ self.os.LogCommand(logTodoChanges(changes), false)
+
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: getBaseShaOrRoot(commits, index+1),
- instruction: ChangeTodoActionsInstruction{
- actions: []daemon.ChangeTodoAction{{
- Sha: commits[index].Sha,
- NewAction: todo.Reword,
- }},
- },
+ instruction: daemon.NewChangeTodoActionsInstruction(changes),
}), nil
}
@@ -102,9 +103,13 @@ func (self *RebaseCommands) GenericAmend(commits []*models.Commit, index int, f
func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int) error {
baseShaOrRoot := getBaseShaOrRoot(commits, index+2)
+ sha := commits[index].Sha
+
+ self.os.LogCommand(fmt.Sprintf("Moving TODO down: %s", utils.ShortSha(sha)), false)
+
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: baseShaOrRoot,
- instruction: MoveDownInstruction{sha: commits[index].Sha},
+ instruction: daemon.NewMoveTodoDownInstruction(sha),
overrideEditor: true,
}).Run()
}
@@ -112,9 +117,13 @@ func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int)
func (self *RebaseCommands) MoveCommitUp(commits []*models.Commit, index int) error {
baseShaOrRoot := getBaseShaOrRoot(commits, index+1)
+ sha := commits[index].Sha
+
+ self.os.LogCommand(fmt.Sprintf("Moving TODO up: %s", utils.ShortSha(sha)), false)
+
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: baseShaOrRoot,
- instruction: MoveUpInstruction{sha: commits[index].Sha},
+ instruction: daemon.NewMoveTodoUpInstruction(sha),
overrideEditor: true,
}).Run()
}
@@ -127,74 +136,37 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index in
baseShaOrRoot := getBaseShaOrRoot(commits, baseIndex)
+ changes := []daemon.ChangeTodoAction{{
+ Sha: commits[index].Sha,
+ NewAction: action,
+ }}
+ self.os.LogCommand(logTodoChanges(changes), false)
+
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
- baseShaOrRoot: baseShaOrRoot,
- instruction: ChangeTodoActionsInstruction{
- actions: []daemon.ChangeTodoAction{{
- Sha: commits[index].Sha,
- NewAction: action,
- }},
- },
+ baseShaOrRoot: baseShaOrRoot,
overrideEditor: true,
+ instruction: daemon.NewChangeTodoActionsInstruction(changes),
}).Run()
}
func (self *RebaseCommands) EditRebase(branchRef string) error {
- commands := []TodoLine{{Action: "break"}}
+ self.os.LogCommand(fmt.Sprintf("Beginning interactive rebase at '%s'", branchRef), false)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: branchRef,
- instruction: PrependLinesInstruction{todoLines: commands},
+ instruction: daemon.NewInsertBreakInstruction(),
}).Run()
}
-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 {
+func logTodoChanges(changes []daemon.ChangeTodoAction) string {
+ changeTodoStr := strings.Join(slices.Map(changes, 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
- instruction InteractiveRebaseInstruction
+ instruction daemon.Instruction
overrideEditor bool
}
@@ -222,22 +194,12 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
gitSequenceEditor := ex
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)
- }
+ cmdObj.AddEnvVars(daemon.ToEnvVars(opts.instruction)...)
} else {
gitSequenceEditor = "true"
}
cmdObj.AddEnvVars(
- daemon.DaemonKindEnvKey+"="+string(daemon.InteractiveRebase),
"DEBUG="+debug,
"LANG=en_US.UTF-8", // Force using EN as language
"LC_ALL=en_US.UTF-8", // Force using EN as language
@@ -309,15 +271,16 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(commits []*models.Co
return errors.New(self.Tr.DisabledForGPG)
}
+ changes := []daemon.ChangeTodoAction{{
+ Sha: commits[commitIndex].Sha,
+ NewAction: todo.Edit,
+ }}
+ self.os.LogCommand(logTodoChanges(changes), false)
+
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: getBaseShaOrRoot(commits, commitIndex+1),
overrideEditor: true,
- instruction: ChangeTodoActionsInstruction{
- actions: []daemon.ChangeTodoAction{{
- Sha: commits[commitIndex].Sha,
- NewAction: todo.Edit,
- }},
- },
+ instruction: daemon.NewChangeTodoActionsInstruction(changes),
}).Run()
}
@@ -364,15 +327,16 @@ func (self *RebaseCommands) GenericMergeOrRebaseAction(commandType string, comma
}
func (self *RebaseCommands) runSkipEditorCommand(cmdObj oscommands.ICmdObj) error {
+ instruction := daemon.NewExitImmediatelyInstruction()
lazyGitPath := oscommands.GetLazygitPath()
return cmdObj.
AddEnvVars(
- daemon.DaemonKindEnvKey+"="+string(daemon.ExitImmediately),
"GIT_EDITOR="+lazyGitPath,
"GIT_SEQUENCE_EDITOR="+lazyGitPath,
"EDITOR="+lazyGitPath,
"VISUAL="+lazyGitPath,
).
+ AddEnvVars(daemon.ToEnvVars(instruction)...).
Run()
}
@@ -406,49 +370,17 @@ 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 {
- todoLines := self.BuildTodoLinesSingleAction(commits, "pick")
+ commitLines := lo.Map(commits, func(commit *models.Commit, _ int) string {
+ return fmt.Sprintf("%s %s", utils.ShortSha(commit.Sha), commit.Name)
+ })
+ self.os.LogCommand(fmt.Sprintf("Cherry-picking commits:\n%s", strings.Join(commitLines, "\n")), false)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: "HEAD",
- instruction: PrependLinesInstruction{
- todoLines: todoLines,
- },
+ instruction: daemon.NewCherryPickCommitsInstruction(commits),
}).Run()
}
-func TodoLinesToString(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
-}
-
-func (self *TodoLine) ToString() string {
- if self.Action == "break" {
- return self.Action + "\n"
- } else {
- return self.Action + " " + self.Commit.Sha + " " + self.Commit.Name + "\n"
- }
-}
-
// we can't start an interactive rebase from the first commit without passing the
// '--root' arg
func getBaseShaOrRoot(commits []*models.Commit, index int) string {
diff --git a/pkg/commands/git_commands/rebase_test.go b/pkg/commands/git_commands/rebase_test.go
index b2cd88323..1ef22ff5d 100644
--- a/pkg/commands/git_commands/rebase_test.go
+++ b/pkg/commands/git_commands/rebase_test.go
@@ -2,6 +2,7 @@ package git_commands
import (
"regexp"
+ "strconv"
"testing"
"github.com/go-errors/errors"
@@ -63,7 +64,7 @@ func TestRebaseSkipEditorCommand(t *testing.T) {
`^EDITOR=.*$`,
`^GIT_EDITOR=.*$`,
`^GIT_SEQUENCE_EDITOR=.*$`,
- "^" + daemon.DaemonKindEnvKey + "=" + string(daemon.ExitImmediately) + "$",
+ "^" + daemon.DaemonKindEnvKey + "=" + strconv.Itoa(int(daemon.DaemonKindExitImmediately)) + "$",
} {
regexStr := regexStr
foundMatch := lo.ContainsBy(envVars, func(envVar string) bool {