]> source.dussan.org Git - gitea.git/commitdiff
Faster git.GetDivergingCommits (#24482)
authoroliverpool <3864879+oliverpool@users.noreply.github.com>
Thu, 4 May 2023 05:08:41 +0000 (07:08 +0200)
committerGitHub <noreply@github.com>
Thu, 4 May 2023 05:08:41 +0000 (05:08 +0000)
Using `git rev-list --left-right` is almost 2x faster than calling `git
rev-list` twice.

Co-authored-by: silverwind <me@silverwind.io>
modules/git/repo.go
modules/git/repo_test.go

index 3637aa47c45895c57a9061442f8bcab912ee820a..61930ab31db9624b5b451f653dcb818e3ca8a0a0 100644 (file)
@@ -244,35 +244,28 @@ type DivergeObject struct {
        Behind int
 }
 
-func checkDivergence(ctx context.Context, repoPath, baseBranch, targetBranch string) (int, error) {
-       branches := fmt.Sprintf("%s..%s", baseBranch, targetBranch)
-       cmd := NewCommand(ctx, "rev-list", "--count").AddDynamicArguments(branches)
+// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
+func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) {
+       cmd := NewCommand(ctx, "rev-list", "--count", "--left-right").
+               AddDynamicArguments(baseBranch + "..." + targetBranch)
        stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
        if err != nil {
-               return -1, err
+               return do, err
        }
-       outInteger, errInteger := strconv.Atoi(strings.Trim(stdout, "\n"))
-       if errInteger != nil {
-               return -1, errInteger
+       left, right, found := strings.Cut(strings.Trim(stdout, "\n"), "\t")
+       if !found {
+               return do, fmt.Errorf("git rev-list output is missing a tab: %q", stdout)
        }
-       return outInteger, nil
-}
 
-// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
-func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (DivergeObject, error) {
-       // $(git rev-list --count master..feature) commits ahead of master
-       ahead, errorAhead := checkDivergence(ctx, repoPath, baseBranch, targetBranch)
-       if errorAhead != nil {
-               return DivergeObject{}, errorAhead
+       do.Behind, err = strconv.Atoi(left)
+       if err != nil {
+               return do, err
        }
-
-       // $(git rev-list --count feature..master) commits behind master
-       behind, errorBehind := checkDivergence(ctx, repoPath, targetBranch, baseBranch)
-       if errorBehind != nil {
-               return DivergeObject{}, errorBehind
+       do.Ahead, err = strconv.Atoi(right)
+       if err != nil {
+               return do, err
        }
-
-       return DivergeObject{ahead, behind}, nil
+       return do, nil
 }
 
 // CreateBundle create bundle content to the target path
index 044b9d406502ff0a57029466cd1965368ce4c887..9db78153a1027caffb91909bac453af3dfac050f 100644 (file)
@@ -4,6 +4,7 @@
 package git
 
 import (
+       "context"
        "path/filepath"
        "testing"
 
@@ -29,3 +30,27 @@ func TestRepoIsEmpty(t *testing.T) {
        assert.NoError(t, err)
        assert.True(t, isEmpty)
 }
+
+func TestRepoGetDivergingCommits(t *testing.T) {
+       bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
+       do, err := GetDivergingCommits(context.Background(), bareRepo1Path, "master", "branch2")
+       assert.NoError(t, err)
+       assert.Equal(t, DivergeObject{
+               Ahead:  1,
+               Behind: 5,
+       }, do)
+
+       do, err = GetDivergingCommits(context.Background(), bareRepo1Path, "master", "master")
+       assert.NoError(t, err)
+       assert.Equal(t, DivergeObject{
+               Ahead:  0,
+               Behind: 0,
+       }, do)
+
+       do, err = GetDivergingCommits(context.Background(), bareRepo1Path, "master", "test")
+       assert.NoError(t, err)
+       assert.Equal(t, DivergeObject{
+               Ahead:  0,
+               Behind: 2,
+       }, do)
+}