diff --git a/pkg/app/daemon/daemon.go b/pkg/app/daemon/daemon.go index adc287309..cf10e9a18 100644 --- a/pkg/app/daemon/daemon.go +++ b/pkg/app/daemon/daemon.go @@ -10,6 +10,7 @@ import ( "github.com/fsmiamoto/git-todo-parser/todo" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/common" + "github.com/jesseduffield/lazygit/pkg/secureexec" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/samber/lo" ) @@ -90,6 +91,15 @@ func getDaemonKind() DaemonKind { return DaemonKind(intValue) } +func getCommentChar() byte { + cmd := secureexec.Command("git", "config", "--get", "--null", "core.commentChar") + if output, err := cmd.Output(); err == nil && len(output) == 2 { + return output[0] + } + + return '#' +} + // An Instruction is a command to be run by lazygit in daemon mode. // It is serialized to json and passed to lazygit via environment variables type Instruction interface { @@ -199,7 +209,7 @@ func (self *ChangeTodoActionsInstruction) SerializedInstructions() string { func (self *ChangeTodoActionsInstruction) run(common *common.Common) error { return handleInteractiveRebase(common, func(path string) error { for _, c := range self.Changes { - if err := utils.EditRebaseTodo(path, c.Sha, todo.Pick, c.NewAction); err != nil { + if err := utils.EditRebaseTodo(path, c.Sha, todo.Pick, c.NewAction, getCommentChar()); err != nil { return err } } @@ -233,7 +243,7 @@ func (self *MoveFixupCommitDownInstruction) SerializedInstructions() string { func (self *MoveFixupCommitDownInstruction) run(common *common.Common) error { return handleInteractiveRebase(common, func(path string) error { - return utils.MoveFixupCommitDown(path, self.OriginalSha, self.FixupSha) + return utils.MoveFixupCommitDown(path, self.OriginalSha, self.FixupSha, getCommentChar()) }) } @@ -257,7 +267,7 @@ func (self *MoveTodoUpInstruction) SerializedInstructions() string { func (self *MoveTodoUpInstruction) run(common *common.Common) error { return handleInteractiveRebase(common, func(path string) error { - return utils.MoveTodoUp(path, self.Sha, todo.Pick) + return utils.MoveTodoUp(path, self.Sha, todo.Pick, getCommentChar()) }) } @@ -281,7 +291,7 @@ func (self *MoveTodoDownInstruction) SerializedInstructions() string { func (self *MoveTodoDownInstruction) run(common *common.Common) error { return handleInteractiveRebase(common, func(path string) error { - return utils.MoveTodoDown(path, self.Sha, todo.Pick) + return utils.MoveTodoDown(path, self.Sha, todo.Pick, getCommentChar()) }) } diff --git a/pkg/commands/git.go b/pkg/commands/git.go index d09ff88b0..3a2349fd5 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -130,7 +130,7 @@ func NewGitCommandAux( branchLoader := git_commands.NewBranchLoader(cmn, cmd, branchCommands.CurrentBranchInfo, configCommands) commitFileLoader := git_commands.NewCommitFileLoader(cmn, cmd) - commitLoader := git_commands.NewCommitLoader(cmn, cmd, dotGitDir, statusCommands.RebaseMode) + commitLoader := git_commands.NewCommitLoader(cmn, cmd, dotGitDir, statusCommands.RebaseMode, gitCommon) reflogCommitLoader := git_commands.NewReflogCommitLoader(cmn, cmd) remoteLoader := git_commands.NewRemoteLoader(cmn, cmd, repo.Remotes) stashLoader := git_commands.NewStashLoader(cmn, cmd) diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index 4e868ccdc..148c96776 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -38,6 +38,7 @@ type CommitLoader struct { // When nil, we're yet to obtain the list of existing main branches. // When an empty slice, we've obtained the list and it's empty. mainBranches []string + *GitCommon } // making our dependencies explicit for the sake of easier testing @@ -46,6 +47,7 @@ func NewCommitLoader( cmd oscommands.ICmdObjBuilder, dotGitDir string, getRebaseMode func() (enums.RebaseMode, error), + gitCommon *GitCommon, ) *CommitLoader { return &CommitLoader{ Common: cmn, @@ -55,6 +57,7 @@ func NewCommitLoader( walkFiles: filepath.Walk, dotGitDir: dotGitDir, mainBranches: nil, + GitCommon: gitCommon, } } @@ -304,7 +307,7 @@ func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, err commits := []*models.Commit{} - todos, err := todo.Parse(bytes.NewBuffer(bytesContent), '#') + todos, err := todo.Parse(bytes.NewBuffer(bytesContent), self.config.GetCoreCommentChar()) if err != nil { self.Log.Error(fmt.Sprintf("error occurred while parsing git-rebase-todo file: %s", err.Error())) return nil, nil @@ -346,7 +349,7 @@ func (self *CommitLoader) getConflictedCommit(todos []todo.Todo) string { return "" } - doneTodos, err := todo.Parse(bytes.NewBuffer(bytesContent), '#') + doneTodos, err := todo.Parse(bytes.NewBuffer(bytesContent), self.config.GetCoreCommentChar()) if err != nil { self.Log.Error(fmt.Sprintf("error occurred while parsing rebase-merge/done file: %s", err.Error())) return "" diff --git a/pkg/commands/git_commands/config.go b/pkg/commands/git_commands/config.go index e22333541..46a00f9db 100644 --- a/pkg/commands/git_commands/config.go +++ b/pkg/commands/git_commands/config.go @@ -99,3 +99,11 @@ func (self *ConfigCommands) Branches() (map[string]*config.Branch, error) { func (self *ConfigCommands) GetGitFlowPrefixes() string { return self.gitConfig.GetGeneral("--local --get-regexp gitflow.prefix") } + +func (self *ConfigCommands) GetCoreCommentChar() byte { + if commentCharStr := self.gitConfig.Get("core.commentChar"); len(commentCharStr) == 1 { + return commentCharStr[0] + } + + return '#' +} diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index 48bf706e6..5067c167c 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -243,19 +243,19 @@ func (self *RebaseCommands) AmendTo(commits []*models.Commit, commitIndex int) e // EditRebaseTodo sets the action for a given rebase commit in the git-rebase-todo file func (self *RebaseCommands) EditRebaseTodo(commit *models.Commit, action todo.TodoCommand) error { return utils.EditRebaseTodo( - filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo"), commit.Sha, commit.Action, action) + filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo"), commit.Sha, commit.Action, action, self.config.GetCoreCommentChar()) } // MoveTodoDown moves a rebase todo item down by one position func (self *RebaseCommands) MoveTodoDown(commit *models.Commit) error { fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo") - return utils.MoveTodoDown(fileName, commit.Sha, commit.Action) + return utils.MoveTodoDown(fileName, commit.Sha, commit.Action, self.config.GetCoreCommentChar()) } // MoveTodoDown moves a rebase todo item down by one position func (self *RebaseCommands) MoveTodoUp(commit *models.Commit) error { fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo") - return utils.MoveTodoUp(fileName, commit.Sha, commit.Action) + return utils.MoveTodoUp(fileName, commit.Sha, commit.Action, self.config.GetCoreCommentChar()) } // SquashAllAboveFixupCommits squashes all fixup! commits above the given one diff --git a/pkg/integration/tests/interactive_rebase/drop_with_custom_comment_char.go b/pkg/integration/tests/interactive_rebase/drop_with_custom_comment_char.go index 6e93b6faa..dbaa77b90 100644 --- a/pkg/integration/tests/interactive_rebase/drop_with_custom_comment_char.go +++ b/pkg/integration/tests/interactive_rebase/drop_with_custom_comment_char.go @@ -27,16 +27,8 @@ var DropWithCustomCommentChar = NewIntegrationTest(NewIntegrationTestArgs{ Content(Equals("Are you sure you want to delete this commit?")). Confirm() }). - // The following behavior requires correction: - Tap(func() { - t.ExpectPopup().Alert(). - Title(Equals("Error")). - Content(Contains("failed to parse line")). - Confirm() - }). Lines( - Contains("commit 02").IsSelected(), - Contains("commit 01"), + Contains("commit 01").IsSelected(), ) }, }) diff --git a/pkg/integration/tests/interactive_rebase/move_with_custom_comment_char.go b/pkg/integration/tests/interactive_rebase/move_with_custom_comment_char.go index 0ff03169d..eefbcea33 100644 --- a/pkg/integration/tests/interactive_rebase/move_with_custom_comment_char.go +++ b/pkg/integration/tests/interactive_rebase/move_with_custom_comment_char.go @@ -21,13 +21,11 @@ var MoveWithCustomCommentChar = NewIntegrationTest(NewIntegrationTestArgs{ Contains("commit 01"), ). Press(keys.Commits.MoveDownCommit). - // The following behavior requires correction: - Tap(func() { - t.ExpectPopup().Alert(). - Title(Equals("Error")). - Content(Contains("failed to parse line")). - Confirm() - }). + Lines( + Contains("commit 01"), + Contains("commit 02").IsSelected(), + ). + Press(keys.Commits.MoveUpCommit). Lines( Contains("commit 02").IsSelected(), Contains("commit 01"), diff --git a/pkg/utils/rebase_todo.go b/pkg/utils/rebase_todo.go index d0bd92b82..08a9ca872 100644 --- a/pkg/utils/rebase_todo.go +++ b/pkg/utils/rebase_todo.go @@ -11,8 +11,8 @@ import ( // Read a git-rebase-todo file, change the action for the given sha to // newAction, and write it back -func EditRebaseTodo(filePath string, sha string, oldAction todo.TodoCommand, newAction todo.TodoCommand) error { - todos, err := ReadRebaseTodoFile(filePath) +func EditRebaseTodo(filePath string, sha string, oldAction todo.TodoCommand, newAction todo.TodoCommand, commentChar byte) error { + todos, err := ReadRebaseTodoFile(filePath, commentChar) if err != nil { return err } @@ -24,7 +24,7 @@ func EditRebaseTodo(filePath string, sha string, oldAction todo.TodoCommand, new // pick and later in a merge) if t.Command == oldAction && equalShas(t.Commit, sha) { t.Command = newAction - return WriteRebaseTodoFile(filePath, todos) + return WriteRebaseTodoFile(filePath, todos, commentChar) } } @@ -36,13 +36,13 @@ func equalShas(a, b string) bool { return strings.HasPrefix(a, b) || strings.HasPrefix(b, a) } -func ReadRebaseTodoFile(fileName string) ([]todo.Todo, error) { +func ReadRebaseTodoFile(fileName string, commentChar byte) ([]todo.Todo, error) { f, err := os.Open(fileName) if err != nil { return nil, err } - todos, err := todo.Parse(f, '#') + todos, err := todo.Parse(f, commentChar) err2 := f.Close() if err == nil { err = err2 @@ -50,12 +50,12 @@ func ReadRebaseTodoFile(fileName string) ([]todo.Todo, error) { return todos, err } -func WriteRebaseTodoFile(fileName string, todos []todo.Todo) error { +func WriteRebaseTodoFile(fileName string, todos []todo.Todo, commentChar byte) error { f, err := os.Create(fileName) if err != nil { return err } - err = todo.Write(f, todos, '#') + err = todo.Write(f, todos, commentChar) err2 := f.Close() if err == nil { err = err2 @@ -73,8 +73,8 @@ func PrependStrToTodoFile(filePath string, linesToPrepend []byte) error { return os.WriteFile(filePath, linesToPrepend, 0o644) } -func MoveTodoDown(fileName string, sha string, action todo.TodoCommand) error { - todos, err := ReadRebaseTodoFile(fileName) +func MoveTodoDown(fileName string, sha string, action todo.TodoCommand, commentChar byte) error { + todos, err := ReadRebaseTodoFile(fileName, commentChar) if err != nil { return err } @@ -82,11 +82,11 @@ func MoveTodoDown(fileName string, sha string, action todo.TodoCommand) error { if err != nil { return err } - return WriteRebaseTodoFile(fileName, rearrangedTodos) + return WriteRebaseTodoFile(fileName, rearrangedTodos, commentChar) } -func MoveTodoUp(fileName string, sha string, action todo.TodoCommand) error { - todos, err := ReadRebaseTodoFile(fileName) +func MoveTodoUp(fileName string, sha string, action todo.TodoCommand, commentChar byte) error { + todos, err := ReadRebaseTodoFile(fileName, commentChar) if err != nil { return err } @@ -94,7 +94,7 @@ func MoveTodoUp(fileName string, sha string, action todo.TodoCommand) error { if err != nil { return err } - return WriteRebaseTodoFile(fileName, rearrangedTodos) + return WriteRebaseTodoFile(fileName, rearrangedTodos, commentChar) } func moveTodoDown(todos []todo.Todo, sha string, action todo.TodoCommand) ([]todo.Todo, error) { @@ -134,8 +134,8 @@ func moveTodoUp(todos []todo.Todo, sha string, action todo.TodoCommand) ([]todo. return rearrangedTodos, nil } -func MoveFixupCommitDown(fileName string, originalSha string, fixupSha string) error { - todos, err := ReadRebaseTodoFile(fileName) +func MoveFixupCommitDown(fileName string, originalSha string, fixupSha string, commentChar byte) error { + todos, err := ReadRebaseTodoFile(fileName, commentChar) if err != nil { return err } @@ -145,7 +145,7 @@ func MoveFixupCommitDown(fileName string, originalSha string, fixupSha string) e return err } - return WriteRebaseTodoFile(fileName, newTodos) + return WriteRebaseTodoFile(fileName, newTodos, commentChar) } func moveFixupCommitDown(todos []todo.Todo, originalSha string, fixupSha string) ([]todo.Todo, error) {