From 368f9c8cb3d1f86d2a854cdfc20a8c87221e4087 Mon Sep 17 00:00:00 2001 From: AzraelSec Date: Wed, 29 Mar 2023 00:49:19 +0200 Subject: [PATCH] feat: let interactive rebase prepend commands to the default todo file --- pkg/app/daemon/daemon.go | 26 ++++++++++++++++++++++---- pkg/commands/git_commands/patch.go | 2 +- pkg/commands/git_commands/rebase.go | 21 +++++++++++++-------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/pkg/app/daemon/daemon.go b/pkg/app/daemon/daemon.go index 182807b02..5490a25e5 100644 --- a/pkg/app/daemon/daemon.go +++ b/pkg/app/daemon/daemon.go @@ -29,6 +29,11 @@ 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" ) type Daemon interface { @@ -74,12 +79,25 @@ type rebaseDaemon struct { func (self *rebaseDaemon) Run() error { self.c.Log.Info("Lazygit invoked as interactive rebase demon") self.c.Log.Info("args: ", os.Args) + filePath := os.Args[1] - if strings.HasSuffix(os.Args[1], "git-rebase-todo") { - if err := os.WriteFile(os.Args[1], []byte(os.Getenv(RebaseTODOEnvKey)), 0o644); err != nil { - return err + if strings.HasSuffix(filePath, "git-rebase-todo") { + todoEnvKey := os.Getenv(RebaseTODOEnvKey) + + var todoContent []byte + if v := os.Getenv(PrependLinesEnvKey); v != "" { + existingContent, err := os.ReadFile(filePath) + if err != nil { + return err + } + + todoContent = append([]byte(todoEnvKey), existingContent...) + } else { + todoContent = []byte(todoEnvKey) } - } else if strings.HasSuffix(os.Args[1], filepath.Join(gitDir(), "COMMIT_EDITMSG")) { // TODO: test + + return os.WriteFile(filePath, todoContent, 0o644) + } else if strings.HasSuffix(filePath, 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 { diff --git a/pkg/commands/git_commands/patch.go b/pkg/commands/git_commands/patch.go index 7511d1a5b..b5d7bf313 100644 --- a/pkg/commands/git_commands/patch.go +++ b/pkg/commands/git_commands/patch.go @@ -111,7 +111,7 @@ func (self *PatchCommands) MovePatchToSelectedCommit(commits []*models.Commit, s } }) - err := self.rebase.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todoLines, true).Run() + err := self.rebase.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todoLines, true, false).Run() if err != nil { return err } diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index e4c20426f..4e4892d8d 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -60,7 +60,7 @@ func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index return nil, err } - return self.PrepareInteractiveRebaseCommand(sha, todo, false), nil + return self.PrepareInteractiveRebaseCommand(sha, todo, false, false), nil } func (self *RebaseCommands) ResetCommitAuthor(commits []*models.Commit, index int) error { @@ -104,7 +104,7 @@ func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int) baseShaOrRoot := getBaseShaOrRoot(commits, index+2) - return self.PrepareInteractiveRebaseCommand(baseShaOrRoot, todoLines, true).Run() + return self.PrepareInteractiveRebaseCommand(baseShaOrRoot, todoLines, true, false).Run() } func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index int, action string) error { @@ -113,7 +113,7 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index in return err } - return self.PrepareInteractiveRebaseCommand(sha, todo, true).Run() + return self.PrepareInteractiveRebaseCommand(sha, todo, true, false).Run() } func (self *RebaseCommands) InteractiveRebaseBreakAfter(commits []*models.Commit, index int) error { @@ -123,15 +123,19 @@ func (self *RebaseCommands) InteractiveRebaseBreakAfter(commits []*models.Commit } todo = append(todo, TodoLine{Action: "break", Commit: nil}) - return self.PrepareInteractiveRebaseCommand(sha, todo, true).Run() + return self.PrepareInteractiveRebaseCommand(sha, todo, true, false).Run() } // 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(baseShaOrRoot string, todoLines []TodoLine, overrideEditor bool) oscommands.ICmdObj { +func (self *RebaseCommands) PrepareInteractiveRebaseCommand(baseShaOrRoot string, todoLines []TodoLine, overrideEditor bool, prepend bool) oscommands.ICmdObj { todo := self.buildTodo(todoLines) ex := oscommands.GetLazygitPath() + prependLines := "" + if prepend { + prependLines = "TRUE" + } debug := "FALSE" if self.Debug { @@ -153,6 +157,7 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(baseShaOrRoot string cmdObj.AddEnvVars( daemon.DaemonKindEnvKey+"="+string(daemon.InteractiveRebase), daemon.RebaseTODOEnvKey+"="+todo, + daemon.PrependLinesEnvKey+"="+prependLines, "DEBUG="+debug, "LANG=en_US.UTF-8", // Force using EN as language "LC_ALL=en_US.UTF-8", // Force using EN as language @@ -273,12 +278,12 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(commits []*models.Co return err } - return self.PrepareInteractiveRebaseCommand(sha, todo, true).Run() + return self.PrepareInteractiveRebaseCommand(sha, todo, true, false).Run() } // RebaseBranch interactive rebases onto a branch func (self *RebaseCommands) RebaseBranch(branchName string) error { - return self.PrepareInteractiveRebaseCommand(branchName, nil, false).Run() + return self.PrepareInteractiveRebaseCommand(branchName, nil, false, false).Run() } func (self *RebaseCommands) GenericMergeOrRebaseActionCmdObj(commandType string, command string) oscommands.ICmdObj { @@ -363,7 +368,7 @@ func (self *RebaseCommands) DiscardOldFileChanges(commits []*models.Commit, comm func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error { todoLines := self.BuildTodoLinesSingleAction(commits, "pick") - return self.PrepareInteractiveRebaseCommand("HEAD", todoLines, false).Run() + return self.PrepareInteractiveRebaseCommand("HEAD", todoLines, false, false).Run() } func (self *RebaseCommands) buildTodo(todoLines []TodoLine) string {