Browse Source

Count only visible repos on profile (#25928)

Fixes #25914
tags/v1.21.0-rc0
JakobDev 10 months ago
parent
commit
f3fbb7c67d
No account linked to committer's email address

+ 5
- 0
models/repo/repo_list.go View File

@@ -522,6 +522,11 @@ func SearchRepository(ctx context.Context, opts *SearchRepoOptions) (RepositoryL
return SearchRepositoryByCondition(ctx, opts, cond, true)
}

// CountRepository counts repositories based on search options,
func CountRepository(ctx context.Context, opts *SearchRepoOptions) (int64, error) {
return db.GetEngine(ctx).Where(SearchRepositoryCondition(opts)).Count(new(Repository))
}

// SearchRepositoryByCondition search repositories by condition
func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
sess, count, err := searchRepositoryByCondition(ctx, opts, cond)

+ 127
- 102
models/repo/repo_list_test.go View File

@@ -15,108 +15,11 @@ import (
"github.com/stretchr/testify/assert"
)

func TestSearchRepository(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

// test search public repository on explore page
repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "repo_12",
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
if assert.Len(t, repos, 1) {
assert.Equal(t, "test_repo_12", repos[0].Name)
}
assert.Equal(t, int64(1), count)

repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "test_repo",
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
assert.Equal(t, int64(2), count)
assert.Len(t, repos, 2)

// test search private repository on explore page
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "repo_13",
Private: true,
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
if assert.Len(t, repos, 1) {
assert.Equal(t, "test_repo_13", repos[0].Name)
}
assert.Equal(t, int64(1), count)

repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "test_repo",
Private: true,
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
assert.Equal(t, int64(3), count)
assert.Len(t, repos, 3)

// Test non existing owner
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID})

assert.NoError(t, err)
assert.Empty(t, repos)
assert.Equal(t, int64(0), count)

// Test search within description
repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "description_14",
Collaborate: util.OptionalBoolFalse,
IncludeDescription: true,
})

assert.NoError(t, err)
if assert.Len(t, repos, 1) {
assert.Equal(t, "test_repo_14", repos[0].Name)
}
assert.Equal(t, int64(1), count)

// Test NOT search within description
repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "description_14",
Collaborate: util.OptionalBoolFalse,
IncludeDescription: false,
})

assert.NoError(t, err)
assert.Empty(t, repos)
assert.Equal(t, int64(0), count)

func getTestCases() []struct {
name string
opts *repo_model.SearchRepoOptions
count int
} {
testCases := []struct {
name string
opts *repo_model.SearchRepoOptions
@@ -274,6 +177,113 @@ func TestSearchRepository(t *testing.T) {
},
}

return testCases
}

func TestSearchRepository(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

// test search public repository on explore page
repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "repo_12",
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
if assert.Len(t, repos, 1) {
assert.Equal(t, "test_repo_12", repos[0].Name)
}
assert.Equal(t, int64(1), count)

repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "test_repo",
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
assert.Equal(t, int64(2), count)
assert.Len(t, repos, 2)

// test search private repository on explore page
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "repo_13",
Private: true,
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
if assert.Len(t, repos, 1) {
assert.Equal(t, "test_repo_13", repos[0].Name)
}
assert.Equal(t, int64(1), count)

repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "test_repo",
Private: true,
Collaborate: util.OptionalBoolFalse,
})

assert.NoError(t, err)
assert.Equal(t, int64(3), count)
assert.Len(t, repos, 3)

// Test non existing owner
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID})

assert.NoError(t, err)
assert.Empty(t, repos)
assert.Equal(t, int64(0), count)

// Test search within description
repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "description_14",
Collaborate: util.OptionalBoolFalse,
IncludeDescription: true,
})

assert.NoError(t, err)
if assert.Len(t, repos, 1) {
assert.Equal(t, "test_repo_14", repos[0].Name)
}
assert.Equal(t, int64(1), count)

// Test NOT search within description
repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
},
Keyword: "description_14",
Collaborate: util.OptionalBoolFalse,
IncludeDescription: false,
})

assert.NoError(t, err)
assert.Empty(t, repos)
assert.Equal(t, int64(0), count)

testCases := getTestCases()

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts)
@@ -349,6 +359,21 @@ func TestSearchRepository(t *testing.T) {
}
}

func TestCountRepository(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

testCases := getTestCases()

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
count, err := repo_model.CountRepository(db.DefaultContext, testCase.opts)

assert.NoError(t, err)
assert.Equal(t, int64(testCase.count), count)
})
}
}

func TestSearchRepositoryByTopicName(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())


+ 7
- 0
routers/web/org/home.go View File

@@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
)

const (
@@ -158,6 +159,12 @@ func Home(ctx *context.Context) {
ctx.Data["PageIsViewRepositories"] = true
ctx.Data["IsFollowing"] = isFollowing

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

pager := context.NewPagination(int(count), setting.UI.User.RepoPagingNum, page, 5)
pager.SetDefaultParams(ctx)
pager.AddParam(ctx, "language", "Language")

+ 25
- 0
routers/web/org/projects.go View File

@@ -101,6 +101,12 @@ func Projects(ctx *context.Context) {
project.RenderedContent = project.Description
}

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

numPages := 0
if total > 0 {
numPages = (int(total) - 1/setting.UI.IssuePagingNum)
@@ -135,6 +141,13 @@ func RenderNewProject(ctx *context.Context) {
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
ctx.Data["CancelLink"] = ctx.ContextUser.HomeLink() + "/-/projects"
shared_user.RenderUserHeader(ctx)

err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

ctx.HTML(http.StatusOK, tplProjectsNew)
}

@@ -270,6 +283,12 @@ func EditProjectPost(ctx *context.Context) {

shared_user.RenderUserHeader(ctx)

err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

if ctx.HasError() {
ctx.HTML(http.StatusOK, tplProjectsNew)
return
@@ -379,6 +398,12 @@ func ViewProject(ctx *context.Context) {
ctx.Data["Boards"] = boards
shared_user.RenderUserHeader(ctx)

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

ctx.HTML(http.StatusOK, tplProjectsView)
}


+ 19
- 0
routers/web/shared/user/header.go View File

@@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)

// prepareContextForCommonProfile store some common data into context data for user's profile related pages (including the nav menu)
@@ -110,3 +111,21 @@ func RenderUserHeader(ctx *context.Context) {
defer profileClose()
ctx.Data["HasProfileReadme"] = profileReadmeBlob != nil
}

func LoadHeaderCount(ctx *context.Context) error {
prepareContextForCommonProfile(ctx)

repoCount, err := repo_model.CountRepository(ctx, &repo_model.SearchRepoOptions{
Actor: ctx.Doer,
OwnerID: ctx.ContextUser.ID,
Private: ctx.IsSigned,
Collaborate: util.OptionalBoolFalse,
IncludeDescription: setting.UI.SearchRepoDescription,
})
if err != nil {
return err
}
ctx.Data["RepoCount"] = repoCount

return nil
}

+ 18
- 0
routers/web/user/package.go View File

@@ -101,6 +101,12 @@ func ListPackages(ctx *context.Context) {
ctx.Data["Total"] = total
ctx.Data["RepositoryAccessMap"] = repositoryAccessMap

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

// TODO: context/org -> HandleOrgAssignment() can not be used
if ctx.ContextUser.IsOrganization() {
org := org_model.OrgFromUser(ctx.ContextUser)
@@ -255,6 +261,12 @@ func ViewPackageVersion(ctx *context.Context) {
}
ctx.Data["HasRepositoryAccess"] = hasRepositoryAccess

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

ctx.HTML(http.StatusOK, tplPackagesView)
}

@@ -346,6 +358,12 @@ func ListPackageVersions(ctx *context.Context) {

ctx.Data["Total"] = total

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
for k, v := range pagerParams {
pager.AddParamString(k, v)

+ 6
- 0
routers/web/user/profile.go View File

@@ -269,6 +269,12 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileGi
ctx.Data["Repos"] = repos
ctx.Data["Total"] = total

err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}

pager := context.NewPagination(total, pagingNum, page, 5)
pager.SetDefaultParams(ctx)
pager.AddParam(ctx, "tab", "TabName")

+ 2
- 2
templates/org/menu.tmpl View File

@@ -2,8 +2,8 @@
<div class="ui secondary stackable pointing menu">
<a class="{{if .PageIsViewRepositories}}active {{end}}item" href="{{$.Org.HomeLink}}">
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
{{if .ContextUser.NumRepos}}
<div class="ui small label">{{.ContextUser.NumRepos}}</div>
{{if .RepoCount}}
<div class="ui small label">{{.RepoCount}}</div>
{{end}}
</a>
{{if .CanReadProjects}}

+ 2
- 2
templates/user/overview/header.tmpl View File

@@ -6,8 +6,8 @@
{{end}}
<a class="{{if eq .TabName "repositories"}}active {{end}} item" href="{{.ContextUser.HomeLink}}?tab=repositories">
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
{{if .ContextUser.NumRepos}}
<div class="ui small label">{{.ContextUser.NumRepos}}</div>
{{if .RepoCount}}
<div class="ui small label">{{.RepoCount}}</div>
{{end}}
</a>
{{if or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadProjects)}}

Loading…
Cancel
Save