mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-25 12:24:47 +02:00
Fix deleting update ref todos (#3439)
- **PR Description** Deleting an update-ref todo in an interactive rebase now behaves as expected (i.e. it leaves the branch referenced by the update-ref untouched). Previously it would have deleted the branch referenced by the update-ref todo when the rebase was continued. See #3418 for more details. Fixes #3418.
This commit is contained in:
commit
e295ccefab
@ -39,6 +39,7 @@ const (
|
||||
DaemonKindInsertBreak
|
||||
DaemonKindChangeTodoActions
|
||||
DaemonKindMoveFixupCommitDown
|
||||
DaemonKindWriteRebaseTodo
|
||||
)
|
||||
|
||||
const (
|
||||
@ -59,6 +60,7 @@ func getInstruction() Instruction {
|
||||
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
|
||||
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
|
||||
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
||||
DaemonKindWriteRebaseTodo: deserializeInstruction[*WriteRebaseTodoInstruction],
|
||||
}
|
||||
|
||||
return mapping[getDaemonKind()](jsonData)
|
||||
@ -330,3 +332,27 @@ func (self *InsertBreakInstruction) run(common *common.Common) error {
|
||||
return utils.PrependStrToTodoFile(path, []byte("break\n"))
|
||||
})
|
||||
}
|
||||
|
||||
type WriteRebaseTodoInstruction struct {
|
||||
TodosFileContent []byte
|
||||
}
|
||||
|
||||
func NewWriteRebaseTodoInstruction(todosFileContent []byte) Instruction {
|
||||
return &WriteRebaseTodoInstruction{
|
||||
TodosFileContent: todosFileContent,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *WriteRebaseTodoInstruction) Kind() DaemonKind {
|
||||
return DaemonKindWriteRebaseTodo
|
||||
}
|
||||
|
||||
func (self *WriteRebaseTodoInstruction) SerializedInstructions() string {
|
||||
return serializeInstruction(self)
|
||||
}
|
||||
|
||||
func (self *WriteRebaseTodoInstruction) run(common *common.Common) error {
|
||||
return handleInteractiveRebase(common, func(path string) error {
|
||||
return os.WriteFile(path, self.TodosFileContent, 0o644)
|
||||
})
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ type PrepareInteractiveRebaseCommandOpts struct {
|
||||
|
||||
// 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
|
||||
// lazygit instructions what to do with the todo file
|
||||
func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteractiveRebaseCommandOpts) oscommands.ICmdObj {
|
||||
ex := oscommands.GetLazygitPath()
|
||||
|
||||
@ -250,6 +250,36 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
|
||||
return cmdObj
|
||||
}
|
||||
|
||||
// GitRebaseEditTodo runs "git rebase --edit-todo", saving the given todosFileContent to the file
|
||||
func (self *RebaseCommands) GitRebaseEditTodo(todosFileContent []byte) error {
|
||||
ex := oscommands.GetLazygitPath()
|
||||
|
||||
cmdArgs := NewGitCmd("rebase").
|
||||
Arg("--edit-todo").
|
||||
ToArgv()
|
||||
|
||||
debug := "FALSE"
|
||||
if self.Debug {
|
||||
debug = "TRUE"
|
||||
}
|
||||
|
||||
self.Log.WithField("command", cmdArgs).Debug("RunCommand")
|
||||
|
||||
cmdObj := self.cmd.New(cmdArgs)
|
||||
|
||||
cmdObj.AddEnvVars(daemon.ToEnvVars(daemon.NewWriteRebaseTodoInstruction(todosFileContent))...)
|
||||
|
||||
cmdObj.AddEnvVars(
|
||||
"DEBUG="+debug,
|
||||
"LANG=en_US.UTF-8", // Force using EN as language
|
||||
"LC_ALL=en_US.UTF-8", // Force using EN as language
|
||||
"GIT_EDITOR="+ex,
|
||||
"GIT_SEQUENCE_EDITOR="+ex,
|
||||
)
|
||||
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
// AmendTo amends the given commit with whatever files are staged
|
||||
func (self *RebaseCommands) AmendTo(commits []*models.Commit, commitIndex int) error {
|
||||
commit := commits[commitIndex]
|
||||
@ -302,11 +332,16 @@ func (self *RebaseCommands) DeleteUpdateRefTodos(commits []*models.Commit) error
|
||||
return todoFromCommit(commit)
|
||||
})
|
||||
|
||||
return utils.DeleteTodos(
|
||||
todosFileContent, err := utils.DeleteTodos(
|
||||
filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"),
|
||||
todosToDelete,
|
||||
self.config.GetCoreCommentChar(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.GitRebaseEditTodo(todosFileContent)
|
||||
}
|
||||
|
||||
func (self *RebaseCommands) MoveTodosDown(commits []*models.Commit) error {
|
||||
|
@ -50,6 +50,8 @@ var DeleteUpdateRefTodo = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("pick").Contains("CI commit 02"),
|
||||
Contains("CI ◯ <-- YOU ARE HERE --- commit 01"),
|
||||
).
|
||||
NavigateToLine(Contains("commit 02")).
|
||||
Press(keys.Universal.Remove).
|
||||
Tap(func() {
|
||||
t.Common().ContinueRebase()
|
||||
}).
|
||||
@ -57,9 +59,14 @@ var DeleteUpdateRefTodo = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("CI ◯ commit 06"),
|
||||
Contains("CI ◯ commit 05"),
|
||||
Contains("CI ◯ commit 04"),
|
||||
Contains("CI ◯ commit 03"), // No start on this commit, so there's no branch head here
|
||||
Contains("CI ◯ commit 02"),
|
||||
Contains("CI ◯ commit 03"), // No star on this commit, so there's no branch head here
|
||||
Contains("CI ◯ commit 01"),
|
||||
)
|
||||
|
||||
t.Views().Branches().
|
||||
Lines(
|
||||
Contains("branch2"),
|
||||
Contains("branch1"),
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@ -96,6 +97,12 @@ func WriteRebaseTodoFile(fileName string, todos []todo.Todo, commentChar byte) e
|
||||
return err
|
||||
}
|
||||
|
||||
func todosToString(todos []todo.Todo, commentChar byte) ([]byte, error) {
|
||||
buffer := bytes.Buffer{}
|
||||
err := todo.Write(&buffer, todos, commentChar)
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
|
||||
func PrependStrToTodoFile(filePath string, linesToPrepend []byte) error {
|
||||
existingContent, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
@ -106,16 +113,21 @@ func PrependStrToTodoFile(filePath string, linesToPrepend []byte) error {
|
||||
return os.WriteFile(filePath, linesToPrepend, 0o644)
|
||||
}
|
||||
|
||||
func DeleteTodos(fileName string, todosToDelete []Todo, commentChar byte) error {
|
||||
// Unlike the other functions in this file, which write the changed todos file
|
||||
// back to disk, this one returns the new content as a byte slice. This is
|
||||
// because when deleting update-ref todos, we must perform a "git rebase
|
||||
// --edit-todo" command to pass the changed todos to git so that it can do some
|
||||
// housekeeping around the deleted todos. This can only be done by our caller.
|
||||
func DeleteTodos(fileName string, todosToDelete []Todo, commentChar byte) ([]byte, error) {
|
||||
todos, err := ReadRebaseTodoFile(fileName, commentChar)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
rearrangedTodos, err := deleteTodos(todos, todosToDelete)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return WriteRebaseTodoFile(fileName, rearrangedTodos, commentChar)
|
||||
return todosToString(rearrangedTodos, commentChar)
|
||||
}
|
||||
|
||||
func deleteTodos(todos []todo.Todo, todosToDelete []Todo) ([]todo.Todo, error) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user