Files
autogits/common/gitea_utils.go
Adam Majer 9f0909621b PR: fix timeline fetches
only fetch latest reviews from a user, not all
2025-07-15 11:06:17 +02:00

880 lines
24 KiB
Go

package common
/*
* This file is part of Autogits.
*
* Copyright © 2024 SUSE LLC
*
* Autogits is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* Autogits is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Foobar. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/url"
"os"
"path"
"path/filepath"
"slices"
"time"
transport "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
apiclient "src.opensuse.org/autogits/common/gitea-generated/client"
"src.opensuse.org/autogits/common/gitea-generated/client/issue"
"src.opensuse.org/autogits/common/gitea-generated/client/notification"
"src.opensuse.org/autogits/common/gitea-generated/client/organization"
"src.opensuse.org/autogits/common/gitea-generated/client/repository"
"src.opensuse.org/autogits/common/gitea-generated/client/user"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
//go:generate mockgen -source=gitea_utils.go -destination=mock/gitea_utils.go -typed
// maintainer list file in ProjectGit
const (
MaintainershipFile = "_maintainership.json"
MaintainershipDir = "maintainership"
)
const (
// from Gitea
// ReviewStateApproved pr is approved
ReviewStateApproved models.ReviewStateType = "APPROVED"
// ReviewStatePending pr state is pending
ReviewStatePending models.ReviewStateType = "PENDING"
// ReviewStateComment is a comment review
ReviewStateComment models.ReviewStateType = "COMMENT"
// ReviewStateRequestChanges changes for pr are requested
ReviewStateRequestChanges models.ReviewStateType = "REQUEST_CHANGES"
// ReviewStateRequestReview review is requested from user
ReviewStateRequestReview models.ReviewStateType = "REQUEST_REVIEW"
// ReviewStateUnknown state of pr is unknown
ReviewStateUnknown models.ReviewStateType = ""
)
type GiteaTimelineFetcher interface {
GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error)
}
type GiteaComment interface {
AddComment(pr *models.PullRequest, comment string) error
}
type GiteaSetRepoOptions interface {
SetRepoOptions(owner, repo string, manual_merge bool) (*models.Repository, error)
}
type GiteaMaintainershipReader interface {
FetchMaintainershipFile(org, prjGit, branch string) ([]byte, string, error)
FetchMaintainershipDirFile(org, prjGit, branch, pkg string) ([]byte, string, error)
}
type GiteaPRFetcher interface {
GetPullRequest(org, project string, num int64) (*models.PullRequest, error)
}
type GiteaPRUpdater interface {
UpdatePullRequest(org, repo string, num int64, options *models.EditPullRequestOption) (*models.PullRequest, error)
}
type GiteaPRTimelineFetcher interface {
GiteaPRFetcher
GiteaTimelineFetcher
}
type GiteaCommitFetcher interface {
GetCommit(org, repo, sha string) (*models.Commit, error)
}
type GiteaReviewFetcher interface {
GetPullRequestReviews(org, project string, PRnum int64) ([]*models.PullReview, error)
}
type GiteaCommentFetcher interface {
GetIssueComments(org, project string, issueNo int64) ([]*models.Comment, error)
}
type GiteaReviewTimelineFetcher interface {
GiteaReviewFetcher
GiteaTimelineFetcher
}
type GiteaPRChecker interface {
GiteaReviewTimelineFetcher
GiteaCommentFetcher
GiteaMaintainershipReader
}
type GiteaReviewFetcherAndRequester interface {
GiteaReviewTimelineFetcher
GiteaCommentFetcher
GiteaReviewRequester
}
type GiteaReviewRequester interface {
RequestReviews(pr *models.PullRequest, reviewer ...string) ([]*models.PullReview, error)
}
type GiteaReviewUnrequester interface {
UnrequestReview(org, repo string, id int64, reviwers ...string) error
}
type GiteaReviewer interface {
AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error)
}
type GiteaRepoFetcher interface {
GetRepository(org, repo string) (*models.Repository, error)
}
type GiteaFileContentReader interface {
GetRepositoryFileContent(org, repo, hash, path string) ([]byte, string, error)
}
const (
CommitStatus_Pending = "pending"
CommitStatus_Success = "success"
CommitStatus_Fail = "failure"
CommitStatus_Error = "error"
)
type GiteaCommitStatusSetter interface {
SetCommitStatus(org, repo, hash string, status *models.CommitStatus) (*models.CommitStatus, error)
}
type GiteaCommitStatusGetter interface {
GetCommitStatus(org, repo, hash string) ([]*models.CommitStatus, error)
}
type Gitea interface {
GiteaComment
GiteaRepoFetcher
GiteaReviewRequester
GiteaReviewUnrequester
GiteaReviewer
GiteaPRFetcher
GiteaPRUpdater
GiteaCommitFetcher
GiteaReviewFetcher
GiteaCommentFetcher
GiteaTimelineFetcher
GiteaMaintainershipReader
GiteaFileContentReader
GiteaCommitStatusGetter
GiteaCommitStatusSetter
GiteaSetRepoOptions
GiteaTimelineFetcher
GetNotifications(Type string, since *time.Time) ([]*models.NotificationThread, error)
GetDoneNotifications(Type string, page int64) ([]*models.NotificationThread, error)
SetNotificationRead(notificationId int64) error
GetOrganization(orgName string) (*models.Organization, error)
GetOrganizationRepositories(orgName string) ([]*models.Repository, error)
CreateRepositoryIfNotExist(git Git, org, repoName string) (*models.Repository, error)
CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error)
GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, string, error)
GetRecentPullRequests(org, repo, branch string) ([]*models.PullRequest, error)
GetRecentCommits(org, repo, branch string, commitNo int64) ([]*models.Commit, error)
GetPullRequests(org, project string) ([]*models.PullRequest, error)
GetCurrentUser() (*models.User, error)
}
type GiteaTransport struct {
transport *transport.Runtime
client *apiclient.GiteaAPI
}
func AllocateGiteaTransport(giteaUrl string) Gitea {
var r GiteaTransport
url, err := url.Parse(giteaUrl)
if err != nil {
log.Panicln("Failed to parse gitea url:", err)
}
r.transport = transport.New(url.Host, apiclient.DefaultBasePath, [](string){url.Scheme})
r.transport.DefaultAuthentication = transport.BearerToken(giteaToken)
r.client = apiclient.New(r.transport, nil)
return &r
}
func (gitea *GiteaTransport) FetchMaintainershipFile(org, repo, branch string) ([]byte, string, error) {
return gitea.GetRepositoryFileContent(org, repo, branch, MaintainershipFile)
}
func (gitea *GiteaTransport) FetchMaintainershipDirFile(org, repo, branch, pkg string) ([]byte, string, error) {
return gitea.GetRepositoryFileContent(org, repo, branch, path.Join(MaintainershipDir, pkg))
}
func (gitea *GiteaTransport) GetPullRequest(org, project string, num int64) (*models.PullRequest, error) {
pr, err := gitea.client.Repository.RepoGetPullRequest(
repository.NewRepoGetPullRequestParams().
WithDefaults().
WithOwner(org).
WithRepo(project).
WithIndex(num),
gitea.transport.DefaultAuthentication,
)
return pr.Payload, err
}
func (gitea *GiteaTransport) UpdatePullRequest(org, repo string, num int64, options *models.EditPullRequestOption) (*models.PullRequest, error) {
pr, err := gitea.client.Repository.RepoEditPullRequest(
repository.NewRepoEditPullRequestParams().
WithOwner(org).
WithRepo(repo).
WithIndex(num).
WithBody(options),
gitea.transport.DefaultAuthentication,
)
return pr.Payload, err
}
func (gitea *GiteaTransport) GetPullRequests(org, repo string) ([]*models.PullRequest, error) {
var page, limit int64
prs := make([]*models.PullRequest, 0)
limit = 20
state := "open"
for {
page++
req, err := gitea.client.Repository.RepoListPullRequests(
repository.
NewRepoListPullRequestsParams().
WithDefaults().
WithOwner(org).
WithRepo(repo).
WithState(&state).
WithPage(&page).
WithLimit(&limit),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, fmt.Errorf("cannot fetch PR list for %s / %s : %w", org, repo, err)
}
prs = slices.Concat(prs, req.Payload)
if len(req.Payload) < int(limit) {
break
}
}
return prs, nil
}
func (gitea *GiteaTransport) GetCommitStatus(org, repo, hash string) ([]*models.CommitStatus, error) {
page := int64(1)
limit := int64(10)
var res []*models.CommitStatus
for {
r, err := gitea.client.Repository.RepoListStatuses(
repository.NewRepoListStatusesParams().WithDefaults().WithOwner(org).WithRepo(repo).WithSha(hash).WithPage(&page).WithLimit(&limit),
gitea.transport.DefaultAuthentication)
if err != nil {
return res, err
}
res = append(res, r.Payload...)
if len(r.Payload) < int(limit) {
break
}
}
return res, nil
}
func (gitea *GiteaTransport) SetCommitStatus(org, repo, hash string, status *models.CommitStatus) (*models.CommitStatus, error) {
res, err := gitea.client.Repository.RepoCreateStatus(
repository.NewRepoCreateStatusParams().
WithDefaults().
WithOwner(org).
WithRepo(repo).
WithSha(hash).
WithBody(&models.CreateStatusOption{
TargetURL: status.TargetURL,
Description: status.Description,
Context: status.Context,
State: models.CommitStatusState(status.Status),
}),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, err
}
return res.Payload, err
}
func (gitea *GiteaTransport) GetRepository(org, pkg string) (*models.Repository, error) {
repo, err := gitea.client.Repository.RepoGet(repository.NewRepoGetParams().WithDefaults().WithOwner(org).WithRepo(pkg), gitea.transport.DefaultAuthentication)
if err != nil {
switch err.(type) {
case *repository.RepoGetNotFound:
return nil, nil
}
return nil, err
}
return repo.Payload, nil
}
func (gitea *GiteaTransport) GetPullRequestReviews(org, project string, PRnum int64) ([]*models.PullReview, error) {
limit := int64(20)
var page int64
var allReviews []*models.PullReview
for {
reviews, err := gitea.client.Repository.RepoListPullReviews(
repository.NewRepoListPullReviewsParams().
WithDefaults().
WithOwner(org).
WithRepo(project).
WithIndex(PRnum).
WithPage(&page).
WithLimit(&limit),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, err
}
allReviews = slices.Concat(allReviews, reviews.Payload)
if len(reviews.Payload) < int(limit) {
break
}
page++
}
return allReviews, nil
}
func (gitea *GiteaTransport) GetCommit(org, repo, sha string) (*models.Commit, error) {
f := false
r, err := gitea.client.Repository.RepoGetSingleCommit(
repository.NewRepoGetSingleCommitParams().
WithOwner(org).
WithRepo(repo).
WithSha(sha).
WithStat(&f).
WithFiles(&f).
WithVerification(&f),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return r.Payload, nil
}
func (gitea *GiteaTransport) GetIssueComments(org, project string, issueNo int64) ([]*models.Comment, error) {
// limit := int64(20)
// var page int64
// var allComments []*models.Comment
// for {
c, err := gitea.client.Issue.IssueGetComments(
issue.NewIssueGetCommentsParams().
WithDefaults().
WithOwner(org).
WithRepo(project).
WithIndex(issueNo),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return c.Payload, nil
// if len(c.Payload) < int(limit)
// }
}
func (gitea *GiteaTransport) SetRepoOptions(owner, repo string, manual_merge bool) (*models.Repository, error) {
ok, err := gitea.client.Repository.RepoEdit(repository.NewRepoEditParams().WithOwner(owner).WithRepo(repo).WithBody(
&models.EditRepoOption{
AllowManualMerge: manual_merge,
AutodetectManualMerge: manual_merge,
}), gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return ok.Payload, err
}
const (
GiteaNotificationType_Pull = "Pull"
)
func (gitea *GiteaTransport) GetNotifications(Type string, since *time.Time) ([]*models.NotificationThread, error) {
bigLimit := int64(20)
ret := make([]*models.NotificationThread, 0, 100)
for page := int64(1); ; page++ {
params := notification.NewNotifyGetListParams().
WithDefaults().
WithSubjectType([]string{Type}).
WithStatusTypes([]string{"unread"}).
WithLimit(&bigLimit).
WithPage(&page)
if since != nil {
s := strfmt.DateTime(*since)
params.SetSince(&s)
}
list, err := gitea.client.Notification.NotifyGetList(params, gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
ret = slices.Concat(ret, list.Payload)
if len(list.Payload) < int(bigLimit) {
break
}
}
return ret, nil
}
func (gitea *GiteaTransport) GetDoneNotifications(Type string, page int64) ([]*models.NotificationThread, error) {
limit := int64(20)
t := true
if page <= 0 {
return nil, fmt.Errorf("Page is 1-base positive int...")
}
list, err := gitea.client.Notification.NotifyGetList(
notification.NewNotifyGetListParams().
WithAll(&t).
WithSubjectType([]string{Type}).
WithStatusTypes([]string{"read"}).
WithLimit(&limit).
WithPage(&page),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
return list.Payload, nil
}
func (gitea *GiteaTransport) SetNotificationRead(notificationId int64) error {
_, err := gitea.client.Notification.NotifyReadThread(
notification.NewNotifyReadThreadParams().
WithDefaults().
WithID(fmt.Sprint(notificationId)),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return fmt.Errorf("Error setting notification: %d. Err: %w", notificationId, err)
}
return nil
}
func (gitea *GiteaTransport) GetOrganization(orgName string) (*models.Organization, error) {
org, err := gitea.client.Organization.OrgGet(
organization.NewOrgGetParams().WithOrg(orgName),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, fmt.Errorf("Error fetching org: '%s' data. Err: %w", orgName, err)
}
return org.Payload, nil
}
func (gitea *GiteaTransport) GetOrganizationRepositories(orgName string) ([]*models.Repository, error) {
var page int64
repos := make([]*models.Repository, 0, 100)
page = 1
for {
ret, err := gitea.client.Organization.OrgListRepos(
organization.NewOrgListReposParams().WithOrg(orgName).WithPage(&page),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, fmt.Errorf("Error retrieving repository list for org: '%s'. Err: %w", orgName, err)
}
if len(ret.Payload) == 0 {
break
}
repos = append(repos, ret.Payload...)
page++
}
return repos, nil
}
func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git Git, org, repoName string) (*models.Repository, error) {
log.Println(org, repoName)
repo, err := gitea.client.Repository.RepoGet(
repository.NewRepoGetParams().WithDefaults().WithOwner(org).WithRepo(repoName),
gitea.transport.DefaultAuthentication)
if err != nil {
switch err.(type) {
case *repository.RepoGetNotFound:
log.Println("not found", err)
repo, err := gitea.client.Organization.CreateOrgRepo(
organization.NewCreateOrgRepoParams().WithDefaults().WithBody(
&models.CreateRepoOption{
AutoInit: false,
Name: &repoName,
ObjectFormatName: models.CreateRepoOptionObjectFormatNameSha256,
},
).WithOrg(org),
nil,
)
if err != nil {
switch err.(type) {
case *organization.CreateOrgRepoCreated:
// weird, but ok, repo created
default:
return nil, fmt.Errorf("error creating repo '%s' under '%s'. Err: %w", repoName, org, err)
}
}
// initialize repository
if err = os.Mkdir(filepath.Join(git.GetPath(), DefaultGitPrj), 0700); err != nil {
return nil, err
}
if err = git.GitExec(DefaultGitPrj, "init", "--object-format="+repo.Payload.ObjectFormatName); err != nil {
return nil, err
}
if err = git.GitExec(DefaultGitPrj, "checkout", "-b", repo.Payload.DefaultBranch); err != nil {
return nil, err
}
readmeFilename := filepath.Join(git.GetPath(), DefaultGitPrj, "README.md")
{
file, _ := os.Create(readmeFilename)
defer file.Close()
io.WriteString(file, ReadmeBoilerplate)
}
if err = git.GitExec(DefaultGitPrj, "add", "README.md"); err != nil {
return nil, err
}
if err = git.GitExec(DefaultGitPrj, "commit", "-m", "Automatic devel project creation"); err != nil {
return nil, err
}
if err = git.GitExec(DefaultGitPrj, "remote", "add", "origin", repo.Payload.SSHURL); err != nil {
return nil, err
}
return repo.Payload, nil
default:
return nil, fmt.Errorf("cannot fetch repo data for %s/%s: %w", org, repoName, err)
}
}
return repo.Payload, nil
}
func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) {
prOptions := models.CreatePullRequestOption{
Base: targetId,
Head: srcId,
Title: title,
Body: body,
}
if pr, err := gitea.client.Repository.RepoGetPullRequestByBaseHead(
repository.NewRepoGetPullRequestByBaseHeadParams().WithOwner(repo.Owner.UserName).WithRepo(repo.Name).WithBase(targetId).WithHead(srcId),
gitea.transport.DefaultAuthentication,
); err == nil {
return pr.Payload, nil
}
pr, err := gitea.client.Repository.RepoCreatePullRequest(
repository.
NewRepoCreatePullRequestParams().
WithDefaults().
WithOwner(repo.Owner.UserName).
WithRepo(repo.Name).
WithBody(&prOptions),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, fmt.Errorf("Cannot create pull request. %w", err)
}
return pr.GetPayload(), nil
}
func (gitea *GiteaTransport) RequestReviews(pr *models.PullRequest, reviewers ...string) ([]*models.PullReview, error) {
reviewOptions := models.PullReviewRequestOptions{
Reviewers: reviewers,
}
review, err := gitea.client.Repository.RepoCreatePullReviewRequests(
repository.
NewRepoCreatePullReviewRequestsParams().
WithOwner(pr.Base.Repo.Owner.UserName).
WithRepo(pr.Base.Repo.Name).
WithIndex(pr.Index).
WithBody(&reviewOptions),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, fmt.Errorf("Cannot create pull request reviews: %w", err)
}
return review.GetPayload(), nil
}
func (gitea *GiteaTransport) UnrequestReview(org, repo string, id int64, reviwers ...string) error {
_, err := gitea.client.Repository.RepoDeletePullReviewRequests(
repository.NewRepoDeletePullReviewRequestsParams().WithOwner(org).WithRepo(repo).WithIndex(id).WithBody(&models.PullReviewRequestOptions{
Reviewers: reviwers,
}), gitea.transport.DefaultAuthentication)
return err
}
func (gitea *GiteaTransport) AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) {
c, err := gitea.client.Repository.RepoCreatePullReview(
repository.NewRepoCreatePullReviewParams().
WithDefaults().
WithOwner(pr.Base.Repo.Owner.UserName).
WithRepo(pr.Base.Repo.Name).
WithIndex(pr.Index).
WithBody(&models.CreatePullReviewOptions{
Event: state,
Body: comment,
}),
gitea.transport.DefaultAuthentication,
)
/*
c, err := client.Repository.RepoSubmitPullReview(
repository.NewRepoSubmitPullReviewParams().
WithDefaults().
WithOwner(pr.Base.Repo.Owner.UserName).
WithRepo(pr.Base.Repo.Name).
WithIndex(pr.Index).
WithID(review.ID).
WithBody(&models.SubmitPullReviewOptions{
Event: state,
Body: comment,
}),
transport.DefaultAuthentication,
)
*/
if err != nil {
return nil, err
}
return c.Payload, nil
}
func (gitea *GiteaTransport) AddComment(pr *models.PullRequest, comment string) error {
_, err := gitea.client.Issue.IssueCreateComment(
issue.NewIssueCreateCommentParams().
WithDefaults().
WithOwner(pr.Base.Repo.Owner.UserName).
WithRepo(pr.Base.Repo.Name).
WithIndex(pr.Index).
WithBody(&models.CreateIssueCommentOption{
Body: &comment,
}),
gitea.transport.DefaultAuthentication)
if err != nil {
return err
}
return nil
}
func (gitea *GiteaTransport) GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error) {
page := int64(1)
resCount := 1
retData := []*models.TimelineComment{}
for resCount > 0 {
res, err := gitea.client.Issue.IssueGetCommentsAndTimeline(
issue.NewIssueGetCommentsAndTimelineParams().
WithOwner(org).
WithRepo(repo).
WithIndex(idx).
WithPage(&page),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, err
}
resCount = len(res.Payload)
LogDebug("page:", page, "len:", resCount)
page++
retData = append(retData, res.Payload...)
}
LogDebug("total results:", len(retData))
slices.SortFunc(retData, func(a, b *models.TimelineComment) int {
return time.Time(b.Created).Compare(time.Time(a.Created))
})
return retData, nil
}
func (gitea *GiteaTransport) GetRepositoryFileContent(org, repo, hash, path string) ([]byte, string, error) {
params := repository.NewRepoGetContentsParams().WithOwner(org).WithRepo(repo).WithFilepath(path)
if len(hash) > 0 {
params = params.WithRef(&hash)
}
content, err := gitea.client.Repository.RepoGetContents(params,
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, "", err
}
if content.Payload.Encoding != "base64" {
return nil, "", fmt.Errorf("Unhandled content encoding: %s", content.Payload.Encoding)
}
if content.Payload.Size > 10000000 {
return nil, "", fmt.Errorf("Content length is too large for %s/%s/%s#%s - %d bytes", org, repo, path, hash, content.Payload.Size)
}
data := make([]byte, content.Payload.Size)
n, err := base64.StdEncoding.Decode(data, []byte(content.Payload.Content))
if err != nil {
log.Println(content.Payload.Content[239])
log.Println(len(content.Payload.Content))
log.Println(string(data))
log.Println(content.Payload.Encoding)
enc, _ := json.MarshalIndent(content.Payload, "", " ")
log.Println(string(enc))
return nil, "", fmt.Errorf("Error decoding file %s/%s/%s#%s : %w", org, repo, path, hash, err)
}
if n != int(content.Payload.Size) {
return nil, "", fmt.Errorf("Decoded length doesn't match expected for %s/%s/%s#%s - %d vs %d bytes", org, repo, path, hash, content.Payload.Size, n)
}
return data, content.Payload.SHA, nil
}
func (gitea *GiteaTransport) GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, string, error) {
return gitea.GetRepositoryFileContent(pr.Head.Repo.Owner.UserName, pr.Head.Repo.Name, pr.Head.Sha, path)
}
func (gitea *GiteaTransport) GetRecentPullRequests(org, repo, branch string) ([]*models.PullRequest, error) {
prs := make([]*models.PullRequest, 0, 10)
var page int64
page = 1
sort := "recentupdate"
endPrs:
for {
res, err := gitea.client.Repository.RepoListPullRequests(
repository.NewRepoListPullRequestsParams().
WithOwner(org).
WithRepo(repo).
WithPage(&page).
WithSort(&sort),
gitea.transport.DefaultAuthentication)
if err != nil {
return nil, err
}
if len(res.Payload) == 0 {
break
}
for _, pr := range res.Payload {
if pr.Base.Name != branch {
continue
}
// if pr is closed for more than a week, assume that we are done too
if pr.State == "closed" && time.Since(time.Time(pr.Updated)) > 7*24*time.Hour {
break endPrs
}
prs = append(prs, pr)
}
page++
}
return prs, nil
}
func (gitea *GiteaTransport) GetRecentCommits(org, repo, branch string, commitNo int64) ([]*models.Commit, error) {
not := false
var page int64 = 1
params := repository.NewRepoGetAllCommitsParams().
WithOwner(org).
WithRepo(repo).
WithPage(&page).
WithStat(&not).
WithFiles(&not).
WithVerification(&not).
WithLimit(&commitNo)
if len(branch) > 0 {
params = params.WithSha(&branch)
}
commits, err := gitea.client.Repository.RepoGetAllCommits(params, gitea.transport.DefaultAuthentication)
if err != nil {
switch err.(type) {
case *repository.RepoGetAllCommitsNotFound:
return nil, nil
}
return nil, err
}
return commits.Payload, nil
}
func (gitea *GiteaTransport) GetCurrentUser() (*models.User, error) {
user, err := gitea.client.User.UserGetCurrent(
user.NewUserGetCurrentParams(),
gitea.transport.DefaultAuthentication,
)
if err != nil {
return nil, err
}
return user.GetPayload(), nil
}