diff --git a/pkg/commands/git_commands/ahead_behind.go b/pkg/commands/git_commands/ahead_behind.go index 8d7c92212..f142bf9f4 100644 --- a/pkg/commands/git_commands/ahead_behind.go +++ b/pkg/commands/git_commands/ahead_behind.go @@ -74,23 +74,25 @@ func selectBehindForBranch(aheadBehinds []aheadBehind) int { }).behind } -// The output format is: +// Builds a for-each-ref command that reports, for each ref matched by one of +// refPatterns, how far it is ahead and behind each of the bases. A base is a +// ref name or a commit hash. The output format is: // // \x00 \x00 ...\n // -// with one ahead-behind field per base, in the same order as mainBranchRefs. +// with one ahead-behind field per base, in the same order as bases. // // Requires git >= 2.41 (when %(ahead-behind:...) was added). -func buildAheadBehindForEachRefArgs(mainBranchRefs []string) []string { - formatParts := make([]string, 0, 1+len(mainBranchRefs)) +func buildAheadBehindForEachRefArgs(bases []string, refPatterns []string) []string { + formatParts := make([]string, 0, 1+len(bases)) formatParts = append(formatParts, "%(refname)") - for _, ref := range mainBranchRefs { - formatParts = append(formatParts, "%(ahead-behind:"+ref+")") + for _, base := range bases { + formatParts = append(formatParts, "%(ahead-behind:"+base+")") } format := strings.Join(formatParts, "%00") return NewGitCmd("for-each-ref"). Arg("--format=" + format). - Arg("refs/heads"). + Arg(refPatterns...). ToArgv() } diff --git a/pkg/commands/git_commands/ahead_behind_test.go b/pkg/commands/git_commands/ahead_behind_test.go index 2d9ed63d8..e963dc975 100644 --- a/pkg/commands/git_commands/ahead_behind_test.go +++ b/pkg/commands/git_commands/ahead_behind_test.go @@ -197,15 +197,17 @@ func TestSelectBehindForBranch(t *testing.T) { func TestBuildAheadBehindForEachRefArgs(t *testing.T) { type scenario struct { - testName string - mainBranchRefs []string - expected []string + testName string + bases []string + refPatterns []string + expected []string } scenarios := []scenario{ { - testName: "single base", - mainBranchRefs: []string{"refs/heads/master"}, + testName: "single base", + bases: []string{"refs/heads/master"}, + refPatterns: []string{"refs/heads"}, expected: []string{ "git", "for-each-ref", @@ -214,8 +216,9 @@ func TestBuildAheadBehindForEachRefArgs(t *testing.T) { }, }, { - testName: "two bases", - mainBranchRefs: []string{"refs/heads/master", "refs/remotes/origin/develop"}, + testName: "two bases", + bases: []string{"refs/heads/master", "refs/remotes/origin/develop"}, + refPatterns: []string{"refs/heads"}, expected: []string{ "git", "for-each-ref", @@ -224,8 +227,9 @@ func TestBuildAheadBehindForEachRefArgs(t *testing.T) { }, }, { - testName: "four bases", - mainBranchRefs: []string{"refs/heads/a", "refs/heads/b", "refs/heads/c", "refs/heads/d"}, + testName: "four bases", + bases: []string{"refs/heads/a", "refs/heads/b", "refs/heads/c", "refs/heads/d"}, + refPatterns: []string{"refs/heads"}, expected: []string{ "git", "for-each-ref", @@ -233,11 +237,23 @@ func TestBuildAheadBehindForEachRefArgs(t *testing.T) { "refs/heads", }, }, + { + testName: "commit hashes as bases, individual refs as patterns", + bases: []string{"1234567", "89abcde"}, + refPatterns: []string{"refs/heads/a", "refs/remotes/origin/b"}, + expected: []string{ + "git", + "for-each-ref", + "--format=%(refname)%00%(ahead-behind:1234567)%00%(ahead-behind:89abcde)", + "refs/heads/a", + "refs/remotes/origin/b", + }, + }, } for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - result := buildAheadBehindForEachRefArgs(s.mainBranchRefs) + result := buildAheadBehindForEachRefArgs(s.bases, s.refPatterns) assert.Equal(t, s.expected, result) }) } diff --git a/pkg/commands/git_commands/branch_loader.go b/pkg/commands/git_commands/branch_loader.go index 761ed9ce8..407ae6c10 100644 --- a/pkg/commands/git_commands/branch_loader.go +++ b/pkg/commands/git_commands/branch_loader.go @@ -214,7 +214,7 @@ func (self *BranchLoader) getBehindBaseBranchValuesFast( t := time.Now() output, err := self.cmd.New( - buildAheadBehindForEachRefArgs(mainBranchRefs), + buildAheadBehindForEachRefArgs(mainBranchRefs, []string{"refs/heads"}), ).DontLog().RunWithOutput() if err != nil { return err