summaryrefslogtreecommitdiffstats
path: root/pkg/commands
diff options
context:
space:
mode:
authorStefan Haller <stefan@haller-berlin.de>2024-03-23 15:45:42 +0100
committerStefan Haller <stefan@haller-berlin.de>2024-03-26 22:29:56 +0100
commit1fdcc29277d48fddaa6d02cabba10552eac7ef14 (patch)
tree88f98ce03575e7dd3fd7fbb0373f21e0136ca75c /pkg/commands
parent6da9d55e47b54dabc226d9549ddb62ce7dc3c0d4 (diff)
Fix deleting update-ref todos
It is a bad idea to read a git-rebase-todo file, remove some update-ref todos, and write it back out behind git's back. This will cause git to actually remove the branches referenced by those update-ref todos when the rebase is continued. The reason is that git remembers the refs affected by update-ref todos at the beginning of the rebase, and remembers information about them in the file .git/rebase-merge/update-refs. Then, whenever the user performs a "git rebase --edit-todo" command, it updates that file based on whether update-ref todos were added or removed by that edit. If we rewrite the git-rebase-todo file behind git's back, this updating doesn't happen. Fix this by not updating the git-rebase-todo file directly in this case, but performing a "git rebase --edit-todo" command where we set ourselves as the editor and change the file in there. This makes git update the bookkeeping information properly. Ideally we would use this method for all cases where we change the git-rebase-todo file (e.g. moving todos up/down, or changing the type of a todo); this would be cleaner because we wouldn't mess with git's private implementation details. I tried this, but unfortunately it isn't fast enough. Right now, moving a todo up or down takes between 1 and 2ms on my machine; changing it to do a "git rebase --edit-todo" slows it down to over 100ms, which is unacceptable.
Diffstat (limited to 'pkg/commands')
-rw-r--r--pkg/commands/git_commands/rebase.go37
1 files changed, 36 insertions, 1 deletions
diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go
index 874cbd809..2d1de707f 100644
--- a/pkg/commands/git_commands/rebase.go
+++ b/pkg/commands/git_commands/rebase.go
@@ -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 {