mirror of
https://github.com/go-gitea/gitea.git
synced 2026-02-28 09:31:05 +01:00
Description This PR adds a branch_count field to the repository API response. Currently, clients have to fetch all branches via /branches just to determine the total number of branches. This addition brings Gitea closer to parity with GitLab's API and improves efficiency for UI/CLI clients that need this metric. Linked Issue Fixes #35351 Changes API Structs: Added BranchCount field to Repository struct in modules/structs/repo.go. Database Logic: Implemented CountBranches in models/git/branch.go using XORM for efficient counting. Service Layer: Updated the ToRepo conversion logic in services/convert/repository.go to populate the new field during API serialisation. Tests: Added a new unit test TestCountBranches in models/git/branch_test.go to verify counts (including handling of deleted branches). Screenshots <img width="196" height="121" alt="Screenshot 2026-02-24 at 21 41 07" src="https://github.com/user-attachments/assets/cd023e92-f338-448b-9e49-0a5d54cc96c2" /> Testing Manually verified the output using curl against a local Gitea instance. Verified that adding a branch increments the count and deleting a branch (soft-delete) decrements it. Ran backend linting: make lint-backend (Passed). Ran specific unit test: go test -v -tags "sqlite sqlite_unlock_notify" ./models/git -run TestCountBranches (Passed). Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -583,3 +583,12 @@ func FindRecentlyPushedNewBranches(ctx context.Context, doer *user_model.User, o
|
||||
|
||||
return newBranches, nil
|
||||
}
|
||||
|
||||
// CountBranches returns the number of branches in the repository
|
||||
func CountBranches(ctx context.Context, repoID int64, includeDeleted bool) (int64, error) {
|
||||
sess := db.GetEngine(ctx).Where("repo_id=?", repoID)
|
||||
if !includeDeleted {
|
||||
sess.And("is_deleted=?", false)
|
||||
}
|
||||
return sess.Count(new(Branch))
|
||||
}
|
||||
|
||||
@@ -263,3 +263,25 @@ func TestOnlyGetDeletedBranchOnCorrectRepo(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, deletedBranch)
|
||||
}
|
||||
|
||||
func TestCountBranches(t *testing.T) {
|
||||
// 1. Setup - Exactly like TestAddDeletedBranch
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
|
||||
// 2. Execution - Using t.Context() to match the rest of the file
|
||||
initialCount, err := git_model.CountBranches(t.Context(), repo.ID, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 3. Database Action - Using t.Context()
|
||||
err = db.Insert(t.Context(), &git_model.Branch{
|
||||
RepoID: repo.ID,
|
||||
Name: "test-branch-for-counting",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 4. Verification
|
||||
newCount, err := git_model.CountBranches(t.Context(), repo.ID, false)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, initialCount+1, newCount)
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ type Repository struct {
|
||||
Stars int `json:"stars_count"`
|
||||
Forks int `json:"forks_count"`
|
||||
Watchers int `json:"watchers_count"`
|
||||
BranchCount int `json:"branch_count"`
|
||||
OpenIssues int `json:"open_issues_count"`
|
||||
OpenPulls int `json:"open_pr_counter"`
|
||||
Releases int `json:"release_counter"`
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@@ -144,6 +145,11 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
RepoID: repo.ID,
|
||||
})
|
||||
|
||||
branchCount, err := git_model.CountBranches(ctx, repo.ID, false)
|
||||
if err != nil {
|
||||
log.Error("CountBranches [%d]: %v", repo.ID, err)
|
||||
}
|
||||
|
||||
mirrorInterval := ""
|
||||
var mirrorUpdated time.Time
|
||||
if repo.IsMirror {
|
||||
@@ -205,6 +211,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
Stars: repo.NumStars,
|
||||
Forks: repo.NumForks,
|
||||
Watchers: repo.NumWatches,
|
||||
BranchCount: int(branchCount),
|
||||
OpenIssues: repo.NumOpenIssues,
|
||||
OpenPulls: repo.NumOpenPulls,
|
||||
Releases: int(numReleases),
|
||||
|
||||
5
templates/swagger/v1_json.tmpl
generated
5
templates/swagger/v1_json.tmpl
generated
@@ -28128,6 +28128,11 @@
|
||||
"type": "string",
|
||||
"x-go-name": "AvatarURL"
|
||||
},
|
||||
"branch_count": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "BranchCount"
|
||||
},
|
||||
"clone_url": {
|
||||
"type": "string",
|
||||
"x-go-name": "CloneURL"
|
||||
|
||||
Reference in New Issue
Block a user