mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Faster git.GetDivergingCommits (#24482)
Using `git rev-list --left-right` is almost 2x faster than calling `git rev-list` twice. Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
		| @@ -244,35 +244,28 @@ type DivergeObject struct { | |||||||
| 	Behind int | 	Behind int | ||||||
| } | } | ||||||
|  |  | ||||||
| func checkDivergence(ctx context.Context, repoPath, baseBranch, targetBranch string) (int, error) { | // GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch | ||||||
| 	branches := fmt.Sprintf("%s..%s", baseBranch, targetBranch) | func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) { | ||||||
| 	cmd := NewCommand(ctx, "rev-list", "--count").AddDynamicArguments(branches) | 	cmd := NewCommand(ctx, "rev-list", "--count", "--left-right"). | ||||||
|  | 		AddDynamicArguments(baseBranch + "..." + targetBranch) | ||||||
| 	stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}) | 	stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return -1, err | 		return do, err | ||||||
| 	} | 	} | ||||||
| 	outInteger, errInteger := strconv.Atoi(strings.Trim(stdout, "\n")) | 	left, right, found := strings.Cut(strings.Trim(stdout, "\n"), "\t") | ||||||
| 	if errInteger != nil { | 	if !found { | ||||||
| 		return -1, errInteger | 		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 |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// $(git rev-list --count feature..master) commits behind master | 	do.Behind, err = strconv.Atoi(left) | ||||||
| 	behind, errorBehind := checkDivergence(ctx, repoPath, targetBranch, baseBranch) | 	if err != nil { | ||||||
| 	if errorBehind != nil { | 		return do, err | ||||||
| 		return DivergeObject{}, errorBehind |  | ||||||
| 	} | 	} | ||||||
|  | 	do.Ahead, err = strconv.Atoi(right) | ||||||
| 	return DivergeObject{ahead, behind}, nil | 	if err != nil { | ||||||
|  | 		return do, err | ||||||
|  | 	} | ||||||
|  | 	return do, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // CreateBundle create bundle content to the target path | // CreateBundle create bundle content to the target path | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| package git | package git | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| @@ -29,3 +30,27 @@ func TestRepoIsEmpty(t *testing.T) { | |||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.True(t, isEmpty) | 	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) | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user