diff --git a/pkg/commands/git_commands/branch.go b/pkg/commands/git_commands/branch.go index f6b084c9f..fd6994e01 100644 --- a/pkg/commands/git_commands/branch.go +++ b/pkg/commands/git_commands/branch.go @@ -142,7 +142,7 @@ func (self *BranchCommands) Rename(oldName string, newName string) error { } func (self *BranchCommands) GetRawBranches() (string, error) { - return self.cmd.New(`git for-each-ref --sort=-committerdate --format="%(HEAD)|%(refname:short)|%(upstream:short)|%(upstream:track)" refs/heads`).DontLog().RunWithOutput() + return self.cmd.New(`git for-each-ref --sort=-committerdate --format="%(HEAD)%00%(refname:short)%00%(upstream:short)%00%(upstream:track)" refs/heads`).DontLog().RunWithOutput() } type MergeOpts struct { diff --git a/pkg/commands/loaders/branches.go b/pkg/commands/loaders/branches.go index f9e5c052b..5a4502085 100644 --- a/pkg/commands/loaders/branches.go +++ b/pkg/commands/loaders/branches.go @@ -121,7 +121,7 @@ func (self *BranchLoader) obtainBranches() []*models.Branch { return nil, false } - split := strings.Split(line, SEPARATION_CHAR) + split := strings.Split(line, "\x00") if len(split) != 4 { // Ignore line if it isn't separated into 4 parts // This is probably a warning message, for more info see: diff --git a/pkg/commands/loaders/commits.go b/pkg/commands/loaders/commits.go index c370cc059..ae4455df5 100644 --- a/pkg/commands/loaders/commits.go +++ b/pkg/commands/loaders/commits.go @@ -23,8 +23,6 @@ import ( // be processed as part of a rebase (these won't appear in git log but we // grab them from the rebase-related files in the .git directory to show them -const SEPARATION_CHAR = "|" - // CommitLoader returns a list of Commit objects for the current repo type CommitLoader struct { *common.Common @@ -159,15 +157,15 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod // example input: // 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit { - split := strings.Split(line, SEPARATION_CHAR) + split := strings.SplitN(line, "\x00", 6) sha := split[0] unixTimestamp := split[1] author := split[2] extraInfo := strings.TrimSpace(split[3]) parentHashes := split[4] + message := split[5] - message := strings.Join(split[5:], SEPARATION_CHAR) tags := []string{} if extraInfo != "" { @@ -444,13 +442,15 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj { var prettyFormat = fmt.Sprintf( "--pretty=format:\"%%H%s%%at%s%%aN%s%%d%s%%p%s%%s\"", - SEPARATION_CHAR, - SEPARATION_CHAR, - SEPARATION_CHAR, - SEPARATION_CHAR, - SEPARATION_CHAR, + NULL_CODE, + NULL_CODE, + NULL_CODE, + NULL_CODE, + NULL_CODE, ) +const NULL_CODE = "%x00" + func canExtractCommit(line string) bool { return line != "" && strings.Split(line, " ")[0] != "gpg:" } diff --git a/pkg/commands/loaders/commits_test.go b/pkg/commands/loaders/commits_test.go index 6bb81c57d..5c1509287 100644 --- a/pkg/commands/loaders/commits_test.go +++ b/pkg/commands/loaders/commits_test.go @@ -2,6 +2,7 @@ package loaders import ( "path/filepath" + "strings" "testing" "github.com/jesseduffield/lazygit/pkg/commands/models" @@ -11,14 +12,14 @@ import ( "github.com/stretchr/testify/assert" ) -const commitsOutput = `0eea75e8c631fba6b58135697835d58ba4c18dbc|1640826609|Jesse Duffield| (HEAD -> better-tests)|b21997d6b4cbdf84b149|better typing for rebase mode +var commitsOutput = strings.Replace(`0eea75e8c631fba6b58135697835d58ba4c18dbc|1640826609|Jesse Duffield| (HEAD -> better-tests)|b21997d6b4cbdf84b149|better typing for rebase mode b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164|1640824515|Jesse Duffield| (origin/better-tests)|e94e8fc5b6fab4cb755f|fix logging e94e8fc5b6fab4cb755f29f1bdb3ee5e001df35c|1640823749|Jesse Duffield||d8084cd558925eb7c9c3|refactor d8084cd558925eb7c9c38afeed5725c21653ab90|1640821426|Jesse Duffield||65f910ebd85283b5cce9|WIP 65f910ebd85283b5cce9bf67d03d3f1a9ea3813a|1640821275|Jesse Duffield||26c07b1ab33860a1a759|WIP 26c07b1ab33860a1a7591a0638f9925ccf497ffa|1640750752|Jesse Duffield||3d4470a6c072208722e5|WIP 3d4470a6c072208722e5ae9a54bcb9634959a1c5|1640748818|Jesse Duffield||053a66a7be3da43aacdc|WIP -053a66a7be3da43aacdc7aa78e1fe757b82c4dd2|1640739815|Jesse Duffield||985fe482e806b172aea4|refactoring the config struct` +053a66a7be3da43aacdc7aa78e1fe757b82c4dd2|1640739815|Jesse Duffield||985fe482e806b172aea4|refactoring the config struct`, "|", "\x00", -1) func TestGetCommits(t *testing.T) { type scenario struct { @@ -39,7 +40,7 @@ func TestGetCommits(t *testing.T) { opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false}, runner: oscommands.NewFakeRunner(t). Expect(`git merge-base "HEAD" "HEAD"@{u}`, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). - Expect(`git log "HEAD" --topo-order --oneline --pretty=format:"%H|%at|%aN|%d|%p|%s" --abbrev=40`, "", nil), + Expect(`git log "HEAD" --topo-order --oneline --pretty=format:"%H%x00%at%x00%aN%x00%d%x00%p%x00%s" --abbrev=40`, "", nil), expectedCommits: []*models.Commit{}, expectedError: nil, @@ -53,7 +54,7 @@ func TestGetCommits(t *testing.T) { // here it's seeing which commits are yet to be pushed Expect(`git merge-base "HEAD" "HEAD"@{u}`, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). // here it's actually getting all the commits in a formatted form, one per line - Expect(`git log "HEAD" --topo-order --oneline --pretty=format:"%H|%at|%aN|%d|%p|%s" --abbrev=40`, commitsOutput, nil). + Expect(`git log "HEAD" --topo-order --oneline --pretty=format:"%H%x00%at%x00%aN%x00%d%x00%p%x00%s" --abbrev=40`, commitsOutput, nil). // here it's seeing where our branch diverged from the master branch so that we can mark that commit and parent commits as 'merged' Expect(`git merge-base "HEAD" "master"`, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil), diff --git a/pkg/commands/loaders/reflog_commits.go b/pkg/commands/loaders/reflog_commits.go index 849c96f50..56c1c71f9 100644 --- a/pkg/commands/loaders/reflog_commits.go +++ b/pkg/commands/loaders/reflog_commits.go @@ -32,10 +32,10 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit filterPathArg = fmt.Sprintf(" --follow -- %s", self.cmd.Quote(filterPath)) } - cmdObj := self.cmd.New(fmt.Sprintf(`git log -g --abbrev=40 --format="%%h %%ct %%gs"%s`, filterPathArg)).DontLog() + cmdObj := self.cmd.New(fmt.Sprintf(`git log -g --abbrev=40 --format="%s"%s`, "%h%x00%ct%x00%gs", filterPathArg)).DontLog() onlyObtainedNewReflogCommits := false err := cmdObj.RunAndProcessLines(func(line string) (bool, error) { - fields := strings.SplitN(line, " ", 3) + fields := strings.SplitN(line, "\x00", 3) if len(fields) <= 2 { return false, nil } diff --git a/pkg/commands/loaders/reflog_commits_test.go b/pkg/commands/loaders/reflog_commits_test.go index e3f1cbeb8..bb93caba5 100644 --- a/pkg/commands/loaders/reflog_commits_test.go +++ b/pkg/commands/loaders/reflog_commits_test.go @@ -2,6 +2,7 @@ package loaders import ( "errors" + "strings" "testing" "github.com/jesseduffield/lazygit/pkg/commands/models" @@ -11,12 +12,12 @@ import ( "github.com/stretchr/testify/assert" ) -const reflogOutput = `c3c4b66b64c97ffeecde 1643150483 checkout: moving from A to B -c3c4b66b64c97ffeecde 1643150483 checkout: moving from B to A -c3c4b66b64c97ffeecde 1643150483 checkout: moving from A to B -c3c4b66b64c97ffeecde 1643150483 checkout: moving from master to A -f4ddf2f0d4be4ccc7efa 1643149435 checkout: moving from A to master -` +var reflogOutput = strings.Replace(`c3c4b66b64c97ffeecde|1643150483|checkout: moving from A to B +c3c4b66b64c97ffeecde|1643150483|checkout: moving from B to A +c3c4b66b64c97ffeecde|1643150483|checkout: moving from A to B +c3c4b66b64c97ffeecde|1643150483|checkout: moving from master to A +f4ddf2f0d4be4ccc7efa|1643149435|checkout: moving from A to master +`, "|", "\x00", -1) func TestGetReflogCommits(t *testing.T) { type scenario struct { @@ -33,7 +34,7 @@ func TestGetReflogCommits(t *testing.T) { { testName: "no reflog entries", runner: oscommands.NewFakeRunner(t). - Expect(`git log -g --abbrev=40 --format="%h %ct %gs"`, "", nil), + Expect(`git log -g --abbrev=40 --format="%h%x00%ct%x00%gs"`, "", nil), lastReflogCommit: nil, expectedCommits: []*models.Commit{}, @@ -43,7 +44,7 @@ func TestGetReflogCommits(t *testing.T) { { testName: "some reflog entries", runner: oscommands.NewFakeRunner(t). - Expect(`git log -g --abbrev=40 --format="%h %ct %gs"`, reflogOutput, nil), + Expect(`git log -g --abbrev=40 --format="%h%x00%ct%x00%gs"`, reflogOutput, nil), lastReflogCommit: nil, expectedCommits: []*models.Commit{ @@ -84,7 +85,7 @@ func TestGetReflogCommits(t *testing.T) { { testName: "some reflog entries where last commit is given", runner: oscommands.NewFakeRunner(t). - Expect(`git log -g --abbrev=40 --format="%h %ct %gs"`, reflogOutput, nil), + Expect(`git log -g --abbrev=40 --format="%h%x00%ct%x00%gs"`, reflogOutput, nil), lastReflogCommit: &models.Commit{ Sha: "c3c4b66b64c97ffeecde", @@ -106,7 +107,7 @@ func TestGetReflogCommits(t *testing.T) { { testName: "when passing filterPath", runner: oscommands.NewFakeRunner(t). - Expect(`git log -g --abbrev=40 --format="%h %ct %gs" --follow -- "path"`, reflogOutput, nil), + Expect(`git log -g --abbrev=40 --format="%h%x00%ct%x00%gs" --follow -- "path"`, reflogOutput, nil), lastReflogCommit: &models.Commit{ Sha: "c3c4b66b64c97ffeecde", @@ -129,7 +130,7 @@ func TestGetReflogCommits(t *testing.T) { { testName: "when command returns error", runner: oscommands.NewFakeRunner(t). - Expect(`git log -g --abbrev=40 --format="%h %ct %gs"`, "", errors.New("haha")), + Expect(`git log -g --abbrev=40 --format="%h%x00%ct%x00%gs"`, "", errors.New("haha")), lastReflogCommit: nil, filterPath: "",