mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 19:11:25 +01:00
137 lines
4.6 KiB
Go
137 lines
4.6 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package services
|
|
|
|
import (
|
|
"context"
|
|
|
|
gitea "gitea.dev/sdk"
|
|
)
|
|
|
|
// RepositoryListOptions selects a repository collection and page.
|
|
type RepositoryListOptions struct {
|
|
Owner, Kind string
|
|
Starred, Watched bool
|
|
Limit, Page int
|
|
}
|
|
|
|
// RepositorySearchOptions supplies explicit repository search filters.
|
|
type RepositorySearchOptions struct {
|
|
Query, Owner, Kind, Sort, Order string
|
|
Topic bool
|
|
Private, Archived *bool
|
|
Limit, Page int
|
|
}
|
|
|
|
func (s Repositories) ownerID(ctx context.Context, owner string) (int64, bool, error) {
|
|
if id, isOrg, err := organization(ctx, s.Client, owner); err != nil || isOrg {
|
|
return id, isOrg, err
|
|
}
|
|
user, _, err := call(ctx, s.Client, func(ctx context.Context, c *gitea.Client) (*gitea.User, *gitea.Response, error) {
|
|
return c.Users.GetUserInfo(ctx, owner)
|
|
})
|
|
if err != nil {
|
|
return 0, false, err
|
|
}
|
|
return user.ID, false, nil
|
|
}
|
|
|
|
func repositoryKind(item Repository, kind string) bool {
|
|
switch kind {
|
|
case "fork":
|
|
return item.Fork
|
|
case "mirror":
|
|
return item.Mirror
|
|
case "source":
|
|
return !item.Fork && !item.Mirror
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
// List returns repositories accessible to the account, or its selected collection.
|
|
// It reports whether more repositories follow the selected page.
|
|
func (s Repositories) List(ctx context.Context, opts RepositoryListOptions) ([]Repository, bool, error) {
|
|
page, err := s.ListPage(ctx, opts)
|
|
return page.Items, page.More, err
|
|
}
|
|
|
|
// ListPage is List that also reports the size of the collection when the server counts it.
|
|
// A kind filter applies to the page, so the collection is not counted then.
|
|
func (s Repositories) ListPage(ctx context.Context, opts RepositoryListOptions) (Page[Repository], error) {
|
|
isOrg := false
|
|
var err error
|
|
if opts.Owner != "" {
|
|
if _, isOrg, err = s.ownerID(ctx, opts.Owner); err != nil {
|
|
return Page[Repository]{}, err
|
|
}
|
|
}
|
|
var window Page[*gitea.Repository]
|
|
if opts.Owner == "" && (opts.Starred || opts.Watched) {
|
|
// TODO(sdk): GetMyStarredRepos and GetMyWatchedRepos accept no ListOptions.
|
|
endpoint := "user/subscriptions"
|
|
if opts.Starred {
|
|
endpoint = "user/starred"
|
|
}
|
|
window, err = rawPage[*gitea.Repository](ctx, s.Client, endpoint, nil, opts.Limit, opts.Page)
|
|
} else {
|
|
window, err = callPage(ctx, s.Client, opts.Limit, opts.Page, func(ctx context.Context, c *gitea.Client, list gitea.ListOptions) ([]*gitea.Repository, *gitea.Response, error) {
|
|
switch {
|
|
case isOrg:
|
|
return c.Repositories.ListOrgRepos(ctx, opts.Owner, gitea.ListOrgReposOptions{ListOptions: list})
|
|
case opts.Owner != "":
|
|
return c.Repositories.ListUserRepos(ctx, opts.Owner, gitea.ListReposOptions{ListOptions: list})
|
|
default:
|
|
return c.Repositories.ListMyRepos(ctx, gitea.ListReposOptions{ListOptions: list})
|
|
}
|
|
})
|
|
}
|
|
if err != nil {
|
|
return Page[Repository]{}, err
|
|
}
|
|
result := Page[Repository]{Items: make([]Repository, 0, len(window.Items)), More: window.More, Total: window.Total, Counted: window.Counted && opts.Kind == ""}
|
|
for _, item := range window.Items {
|
|
if repo := repositoryFrom(item); repositoryKind(repo, opts.Kind) {
|
|
result.Items = append(result.Items, repo)
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// Search searches repository names, descriptions or topics within one instance.
|
|
func (s Repositories) Search(ctx context.Context, opts RepositorySearchOptions) (Page[Repository], error) {
|
|
options := gitea.SearchRepoOptions{
|
|
Keyword: opts.Query, KeywordIsTopic: opts.Topic, KeywordInDescription: true,
|
|
IsPrivate: opts.Private, IsArchived: opts.Archived, Type: gitea.RepoType(opts.Kind),
|
|
}
|
|
if opts.Sort != "" {
|
|
options.Sort, options.Order = opts.Sort, opts.Order
|
|
}
|
|
if opts.Owner != "" {
|
|
id, _, err := s.ownerID(ctx, opts.Owner)
|
|
if err != nil {
|
|
return Page[Repository]{}, err
|
|
}
|
|
options.OwnerID = id
|
|
}
|
|
account, _, err := call(ctx, s.Client, func(ctx context.Context, c *gitea.Client) (*gitea.User, *gitea.Response, error) {
|
|
return c.Users.GetMyUserInfo(ctx)
|
|
})
|
|
if err != nil {
|
|
return Page[Repository]{}, err
|
|
}
|
|
// Gitea groups results by owner ahead of the requested sort, so an explicit sort cannot keep it.
|
|
if opts.Sort == "" {
|
|
options.PrioritizedByOwnerID = account.ID
|
|
}
|
|
window, err := callPage(ctx, s.Client, opts.Limit, opts.Page, func(ctx context.Context, c *gitea.Client, list gitea.ListOptions) ([]*gitea.Repository, *gitea.Response, error) {
|
|
options.ListOptions = list
|
|
return c.Repositories.SearchRepos(ctx, options)
|
|
})
|
|
if err != nil {
|
|
return Page[Repository]{}, err
|
|
}
|
|
return convertPage(window, repositoryFrom), nil
|
|
}
|