1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-11-05 23:50:39 +03:00

Make moving todo commits more robust

This commit is contained in:
Stefan Haller
2023-04-04 10:23:50 +02:00
parent 120dd1530a
commit dc4e88f8a4
6 changed files with 415 additions and 27 deletions

View File

@@ -1,11 +1,18 @@
package utils
import (
"fmt"
"os"
"strings"
"github.com/fsmiamoto/git-todo-parser/todo"
"github.com/samber/lo"
)
func equalShas(a, b string) bool {
return strings.HasPrefix(a, b) || strings.HasPrefix(b, a)
}
func ReadRebaseTodoFile(fileName string) ([]todo.Todo, error) {
f, err := os.Open(fileName)
if err != nil {
@@ -32,3 +39,70 @@ func WriteRebaseTodoFile(fileName string, todos []todo.Todo) error {
}
return err
}
func MoveTodoDown(fileName string, sha string, action todo.TodoCommand) error {
todos, err := ReadRebaseTodoFile(fileName)
if err != nil {
return err
}
rearrangedTodos, err := moveTodoDown(todos, sha, action)
if err != nil {
return err
}
return WriteRebaseTodoFile(fileName, rearrangedTodos)
}
func MoveTodoUp(fileName string, sha string, action todo.TodoCommand) error {
todos, err := ReadRebaseTodoFile(fileName)
if err != nil {
return err
}
rearrangedTodos, err := moveTodoUp(todos, sha, action)
if err != nil {
return err
}
return WriteRebaseTodoFile(fileName, rearrangedTodos)
}
func moveTodoDown(todos []todo.Todo, sha string, action todo.TodoCommand) ([]todo.Todo, error) {
rearrangedTodos, err := moveTodoUp(lo.Reverse(todos), sha, action)
return lo.Reverse(rearrangedTodos), err
}
func moveTodoUp(todos []todo.Todo, sha string, action todo.TodoCommand) ([]todo.Todo, error) {
_, sourceIdx, ok := lo.FindIndexOf(todos, func(t todo.Todo) bool {
// Comparing just the sha is not enough; we need to compare both the
// action and the sha, as the sha could appear multiple times (e.g. in a
// pick and later in a merge)
return t.Command == action && equalShas(t.Commit, sha)
})
if !ok {
// Should never happen
return []todo.Todo{}, fmt.Errorf("Todo %s not found in git-rebase-todo", sha)
}
// The todos are ordered backwards compared to our model commits, so
// actually move the commit _down_ in the todos slice (i.e. towards
// the end of the slice)
// Find the next todo that we show in lazygit's commits view (skipping the rest)
_, skip, ok := lo.FindIndexOf(todos[sourceIdx+1:], isRenderedTodo)
if !ok {
// We expect callers to guard against this
return []todo.Todo{}, fmt.Errorf("Destination position for moving todo is out of range")
}
destinationIdx := sourceIdx + 1 + skip
rearrangedTodos := MoveElement(todos, sourceIdx, destinationIdx)
return rearrangedTodos, nil
}
// We render a todo in the commits view if it's a commit or if it's an
// update-ref. We don't render label, reset, or comment lines.
func isRenderedTodo(t todo.Todo) bool {
return t.Commit != "" || t.Command == todo.UpdateRef
}