diff --git a/models/git/branch.go b/models/git/branch.go index bc6e2a1748..30d517a06d 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -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)) +} diff --git a/models/git/branch_test.go b/models/git/branch_test.go index 9e6148946d..b9b761fd5f 100644 --- a/models/git/branch_test.go +++ b/models/git/branch_test.go @@ -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) +} diff --git a/modules/structs/repo.go b/modules/structs/repo.go index a08cf36037..3507cc410a 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -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"` diff --git a/services/convert/repository.go b/services/convert/repository.go index 150c952b15..658d31d55c 100644 --- a/services/convert/repository.go +++ b/services/convert/repository.go @@ -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), diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 7b86cc3d45..212046f8e6 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -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"