summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/app/daemon/daemon.go104
-rw-r--r--pkg/commands/git_commands/patch.go9
-rw-r--r--pkg/commands/git_commands/rebase.go149
-rw-r--r--pkg/utils/rebase_todo.go10
4 files changed, 140 insertions, 132 deletions
diff --git a/pkg/app/daemon/daemon.go b/pkg/app/daemon/daemon.go
index 0bd457099..7053a8032 100644
--- a/pkg/app/daemon/daemon.go
+++ b/pkg/app/daemon/daemon.go
@@ -1,8 +1,7 @@
package daemon
import (
- "fmt"
- "io"
+ "encoding/json"
"log"
"os"
"path/filepath"
@@ -32,39 +31,39 @@ const (
const (
DaemonKindEnvKey string = "LAZYGIT_DAEMON_KIND"
- RebaseTODOEnvKey string = "LAZYGIT_REBASE_TODO"
- // The `PrependLinesEnvKey` env variable is set to `true` to tell our daemon
- // to prepend the content of `RebaseTODOEnvKey` to the default `git-rebase-todo`
- // file instead of using it as a replacement.
- PrependLinesEnvKey string = "LAZYGIT_PREPEND_LINES"
+ // Contains a json-encoded instance of the InteractiveRebaseInstructions struct
+ InteractiveRebaseInstructionsEnvKey string = "LAZYGIT_DAEMON_INSTRUCTIONS"
+)
+
+// 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
- // If this is set, it tells lazygit to read the original todo file, and
- // change the action for one or more entries in it. The value of the variable
- // will have one or more lines of the form "Sha1:newAction", e.g.
- // a02b54e1b7e7e8dd8bc1958c11ef4ee4df459ea4:edit
+ // 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".
- //
- // If this is used, the value of RebaseTODOEnvKey must be empty.
- ChangeTodoActionEnvKey string = "LAZYGIT_CHANGE_TODO_ACTION"
+ ChangeTodoActions []ChangeTodoAction
// Can be set to the sha of a "pick" todo that will be moved down by one.
- MoveTodoDownEnvKey string = "LAZYGIT_MOVE_COMMIT_DOWN"
+ ShaToMoveDown string
// Can be set to the sha of a "pick" todo that will be moved up by one.
- MoveTodoUpEnvKey string = "LAZYGIT_MOVE_COMMIT_UP"
-)
+ ShaToMoveUp string
+}
+
+type ChangeTodoAction struct {
+ Sha string
+ NewAction todo.TodoCommand
+}
type Daemon interface {
Run() error
}
-var logFile io.StringWriter
-
func Handle(common *common.Common) {
- logFile, _ = os.Create("/tmp/daemon-log.txt")
- _, _ = logFile.WriteString("Hello Daemon\n")
-
d := getDaemon(common)
if d == nil {
return
@@ -118,58 +117,35 @@ func (self *rebaseDaemon) Run() error {
}
func (self *rebaseDaemon) writeTodoFile(path string) error {
- if changeTodoActionEnvValue := os.Getenv(ChangeTodoActionEnvKey); changeTodoActionEnvValue != "" {
- return self.changeTodoAction(path, changeTodoActionEnvValue)
- } else if shaToMoveDown := os.Getenv(MoveTodoDownEnvKey); shaToMoveDown != "" {
- _, _ = logFile.WriteString(fmt.Sprintf("Moving commit down: %s\n", shaToMoveDown))
- return utils.MoveTodoDown(path, shaToMoveDown, todo.Pick)
- } else if shaToMoveUp := os.Getenv(MoveTodoUpEnvKey); shaToMoveUp != "" {
- _, _ = logFile.WriteString(fmt.Sprintf("Moving commit up: %s\n", shaToMoveUp))
- return utils.MoveTodoUp(path, shaToMoveUp, todo.Pick)
- } else {
- todoContent := []byte(os.Getenv(RebaseTODOEnvKey))
-
- prependLines := os.Getenv(PrependLinesEnvKey) != ""
- if prependLines {
- existingContent, err := os.ReadFile(path)
- if err != nil {
- return err
- }
-
- todoContent = append(todoContent, existingContent...)
- }
-
- return os.WriteFile(path, todoContent, 0o644)
+ jsonData := os.Getenv(InteractiveRebaseInstructionsEnvKey)
+ instructions := InteractiveRebaseInstructions{}
+ err := json.Unmarshal([]byte(jsonData), &instructions)
+ if err != nil {
+ return err
}
-}
-func (self *rebaseDaemon) changeTodoAction(path string, changeTodoActionEnvValue string) error {
- lines := strings.Split(changeTodoActionEnvValue, "\n")
- for _, line := range lines {
- fields := strings.Split(line, ":")
- if len(fields) != 2 {
- return fmt.Errorf("Unexpected value for %s: %s", ChangeTodoActionEnvKey, changeTodoActionEnvValue)
- }
- sha, newAction := fields[0], self.actionFromString(fields[1])
- if int(newAction) == 0 {
- return fmt.Errorf("Unknown action in %s", changeTodoActionEnvValue)
- }
- if err := utils.EditRebaseTodo(path, sha, todo.Pick, newAction); err != nil {
- return err
- }
+ 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)
}
+ self.c.Log.Error("No instructions were given to daemon")
return nil
}
-func (self *rebaseDaemon) actionFromString(actionString string) todo.TodoCommand {
- for t := todo.Pick; t < todo.Comment; t++ {
- if t.String() == actionString {
- return t
+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
}
}
- return 0
+ return nil
}
func gitDir() string {
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()
})
diff --git a/pkg/utils/rebase_todo.go b/pkg/utils/rebase_todo.go
index a61d4c36c..f34e11774 100644
--- a/pkg/utils/rebase_todo.go
+++ b/pkg/utils/rebase_todo.go
@@ -63,6 +63,16 @@ func WriteRebaseTodoFile(fileName string, todos []todo.Todo) error {
return err
}
+func PrependStrToTodoFile(filePath string, linesToPrepend []byte) error {
+ existingContent, err := os.ReadFile(filePath)
+ if err != nil {
+ return err
+ }
+
+ linesToPrepend = append(linesToPrepend, existingContent...)
+ return os.WriteFile(filePath, linesToPrepend, 0o644)
+}
+
func MoveTodoDown(fileName string, sha string, action todo.TodoCommand) error {
todos, err := ReadRebaseTodoFile(fileName)
if err != nil {