diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /services/f3/driver/pullrequest.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to '')
-rw-r--r-- | services/f3/driver/pullrequest.go | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/services/f3/driver/pullrequest.go b/services/f3/driver/pullrequest.go new file mode 100644 index 0000000..466b4bd --- /dev/null +++ b/services/f3/driver/pullrequest.go @@ -0,0 +1,320 @@ +// Copyright Earl Warren <contact@earl-warren.org> +// Copyright Loïc Dachary <loic@dachary.org> +// SPDX-License-Identifier: MIT + +package driver + +import ( + "context" + "fmt" + "time" + + "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/timeutil" + issue_service "code.gitea.io/gitea/services/issue" + + "code.forgejo.org/f3/gof3/v3/f3" + f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3" + "code.forgejo.org/f3/gof3/v3/tree/generic" + f3_util "code.forgejo.org/f3/gof3/v3/util" +) + +var _ f3_tree.ForgeDriverInterface = &pullRequest{} + +type pullRequest struct { + common + + forgejoPullRequest *issues_model.Issue + headRepository *f3.Reference + baseRepository *f3.Reference + fetchFunc f3.PullRequestFetchFunc +} + +func (o *pullRequest) SetNative(pullRequest any) { + o.forgejoPullRequest = pullRequest.(*issues_model.Issue) +} + +func (o *pullRequest) GetNativeID() string { + return fmt.Sprintf("%d", o.forgejoPullRequest.Index) +} + +func (o *pullRequest) NewFormat() f3.Interface { + node := o.GetNode() + return node.GetTree().(f3_tree.TreeInterface).NewFormat(node.GetKind()) +} + +func (o *pullRequest) repositoryToReference(ctx context.Context, repository *repo_model.Repository) *f3.Reference { + if repository == nil { + panic("unexpected nil repository") + } + forge := o.getTree().GetRoot().GetChild(generic.NewNodeID(f3_tree.KindForge)).GetDriver().(*forge) + owners := forge.getOwnersPath(ctx, fmt.Sprintf("%d", repository.OwnerID)) + return f3_tree.NewRepositoryReference(owners.String(), repository.OwnerID, repository.ID) +} + +func (o *pullRequest) referenceToRepository(reference *f3.Reference) int64 { + var project int64 + if reference.Get() == "../../repository/vcs" { + project = f3_tree.GetProjectID(o.GetNode()) + } else { + p := f3_tree.ToPath(generic.PathAbsolute(o.GetNode().GetCurrentPath().String(), reference.Get())) + o.Trace("%v %v", o.GetNode().GetCurrentPath().String(), p) + _, project = p.OwnerAndProjectID() + } + return project +} + +func (o *pullRequest) ToFormat() f3.Interface { + if o.forgejoPullRequest == nil { + return o.NewFormat() + } + + var milestone *f3.Reference + if o.forgejoPullRequest.Milestone != nil { + milestone = f3_tree.NewIssueMilestoneReference(o.forgejoPullRequest.Milestone.ID) + } + + var mergedTime *time.Time + if o.forgejoPullRequest.PullRequest.HasMerged { + mergedTime = o.forgejoPullRequest.PullRequest.MergedUnix.AsTimePtr() + } + + var closedTime *time.Time + if o.forgejoPullRequest.IsClosed { + closedTime = o.forgejoPullRequest.ClosedUnix.AsTimePtr() + } + + makePullRequestBranch := func(repo *repo_model.Repository, branch string) f3.PullRequestBranch { + r, err := git.OpenRepository(context.Background(), repo.RepoPath()) + if err != nil { + panic(err) + } + defer r.Close() + + b, err := r.GetBranch(branch) + if err != nil { + panic(err) + } + + c, err := b.GetCommit() + if err != nil { + panic(err) + } + + return f3.PullRequestBranch{ + Ref: branch, + SHA: c.ID.String(), + } + } + if err := o.forgejoPullRequest.PullRequest.LoadHeadRepo(db.DefaultContext); err != nil { + panic(err) + } + head := makePullRequestBranch(o.forgejoPullRequest.PullRequest.HeadRepo, o.forgejoPullRequest.PullRequest.HeadBranch) + head.Repository = o.headRepository + if err := o.forgejoPullRequest.PullRequest.LoadBaseRepo(db.DefaultContext); err != nil { + panic(err) + } + base := makePullRequestBranch(o.forgejoPullRequest.PullRequest.BaseRepo, o.forgejoPullRequest.PullRequest.BaseBranch) + base.Repository = o.baseRepository + + return &f3.PullRequest{ + Common: f3.NewCommon(o.GetNativeID()), + PosterID: f3_tree.NewUserReference(o.forgejoPullRequest.Poster.ID), + Title: o.forgejoPullRequest.Title, + Content: o.forgejoPullRequest.Content, + Milestone: milestone, + State: string(o.forgejoPullRequest.State()), + IsLocked: o.forgejoPullRequest.IsLocked, + Created: o.forgejoPullRequest.CreatedUnix.AsTime(), + Updated: o.forgejoPullRequest.UpdatedUnix.AsTime(), + Closed: closedTime, + Merged: o.forgejoPullRequest.PullRequest.HasMerged, + MergedTime: mergedTime, + MergeCommitSHA: o.forgejoPullRequest.PullRequest.MergedCommitID, + Head: head, + Base: base, + FetchFunc: o.fetchFunc, + } +} + +func (o *pullRequest) FromFormat(content f3.Interface) { + pullRequest := content.(*f3.PullRequest) + var milestone *issues_model.Milestone + if pullRequest.Milestone != nil { + milestone = &issues_model.Milestone{ + ID: pullRequest.Milestone.GetIDAsInt(), + } + } + + o.headRepository = pullRequest.Head.Repository + o.baseRepository = pullRequest.Base.Repository + pr := issues_model.PullRequest{ + HeadBranch: pullRequest.Head.Ref, + HeadRepoID: o.referenceToRepository(o.headRepository), + BaseBranch: pullRequest.Base.Ref, + BaseRepoID: o.referenceToRepository(o.baseRepository), + + MergeBase: pullRequest.Base.SHA, + Index: f3_util.ParseInt(pullRequest.GetID()), + HasMerged: pullRequest.Merged, + } + + o.forgejoPullRequest = &issues_model.Issue{ + Index: f3_util.ParseInt(pullRequest.GetID()), + PosterID: pullRequest.PosterID.GetIDAsInt(), + Poster: &user_model.User{ + ID: pullRequest.PosterID.GetIDAsInt(), + }, + Title: pullRequest.Title, + Content: pullRequest.Content, + Milestone: milestone, + IsClosed: pullRequest.State == f3.PullRequestStateClosed, + CreatedUnix: timeutil.TimeStamp(pullRequest.Created.Unix()), + UpdatedUnix: timeutil.TimeStamp(pullRequest.Updated.Unix()), + IsLocked: pullRequest.IsLocked, + PullRequest: &pr, + IsPull: true, + } + + if pullRequest.Closed != nil { + o.forgejoPullRequest.ClosedUnix = timeutil.TimeStamp(pullRequest.Closed.Unix()) + } +} + +func (o *pullRequest) Get(ctx context.Context) bool { + node := o.GetNode() + o.Trace("%s", node.GetID()) + + project := f3_tree.GetProjectID(o.GetNode()) + id := node.GetID().Int64() + + issue, err := issues_model.GetIssueByIndex(ctx, project, id) + if issues_model.IsErrIssueNotExist(err) { + return false + } + if err != nil { + panic(fmt.Errorf("issue %v %w", id, err)) + } + if err := issue.LoadAttributes(ctx); err != nil { + panic(err) + } + if err := issue.PullRequest.LoadHeadRepo(ctx); err != nil { + panic(err) + } + o.headRepository = o.repositoryToReference(ctx, issue.PullRequest.HeadRepo) + if err := issue.PullRequest.LoadBaseRepo(ctx); err != nil { + panic(err) + } + o.baseRepository = o.repositoryToReference(ctx, issue.PullRequest.BaseRepo) + + o.forgejoPullRequest = issue + o.Trace("ID = %s", o.forgejoPullRequest.ID) + return true +} + +func (o *pullRequest) Patch(ctx context.Context) { + node := o.GetNode() + project := f3_tree.GetProjectID(o.GetNode()) + id := node.GetID().Int64() + o.Trace("repo_id = %d, index = %d", project, id) + if _, err := db.GetEngine(ctx).Where("`repo_id` = ? AND `index` = ?", project, id).Cols("name", "content").Update(o.forgejoPullRequest); err != nil { + panic(fmt.Errorf("%v %v", o.forgejoPullRequest, err)) + } +} + +func (o *pullRequest) GetPullRequestPushRefs() []string { + return []string{ + fmt.Sprintf("refs/f3/%s/head", o.GetNativeID()), + fmt.Sprintf("refs/pull/%s/head", o.GetNativeID()), + } +} + +func (o *pullRequest) GetPullRequestRef() string { + return fmt.Sprintf("refs/pull/%s/head", o.GetNativeID()) +} + +func (o *pullRequest) Put(ctx context.Context) generic.NodeID { + node := o.GetNode() + o.Trace("%s", node.GetID()) + + o.forgejoPullRequest.RepoID = f3_tree.GetProjectID(o.GetNode()) + + ctx, committer, err := db.TxContext(ctx) + if err != nil { + panic(err) + } + defer committer.Close() + + idx, err := db.GetNextResourceIndex(ctx, "issue_index", o.forgejoPullRequest.RepoID) + if err != nil { + panic(fmt.Errorf("generate issue index failed: %w", err)) + } + o.forgejoPullRequest.Index = idx + + sess := db.GetEngine(ctx) + + if _, err = sess.NoAutoTime().Insert(o.forgejoPullRequest); err != nil { + panic(err) + } + + pr := o.forgejoPullRequest.PullRequest + pr.Index = o.forgejoPullRequest.Index + pr.IssueID = o.forgejoPullRequest.ID + pr.HeadRepoID = o.referenceToRepository(o.headRepository) + if pr.HeadRepoID == 0 { + panic(fmt.Errorf("HeadRepoID == 0 in %v", pr)) + } + pr.BaseRepoID = o.referenceToRepository(o.baseRepository) + if pr.BaseRepoID == 0 { + panic(fmt.Errorf("BaseRepoID == 0 in %v", pr)) + } + + if _, err = sess.NoAutoTime().Insert(pr); err != nil { + panic(err) + } + + if err = committer.Commit(); err != nil { + panic(fmt.Errorf("Commit: %w", err)) + } + + if err := pr.LoadBaseRepo(ctx); err != nil { + panic(err) + } + if err := pr.LoadHeadRepo(ctx); err != nil { + panic(err) + } + + o.Trace("pullRequest created %d/%d", o.forgejoPullRequest.ID, o.forgejoPullRequest.Index) + return generic.NewNodeID(o.forgejoPullRequest.Index) +} + +func (o *pullRequest) Delete(ctx context.Context) { + node := o.GetNode() + o.Trace("%s", node.GetID()) + + owner := f3_tree.GetOwnerName(o.GetNode()) + project := f3_tree.GetProjectName(o.GetNode()) + repoPath := repo_model.RepoPath(owner, project) + gitRepo, err := git.OpenRepository(ctx, repoPath) + if err != nil { + panic(err) + } + defer gitRepo.Close() + + doer, err := user_model.GetAdminUser(ctx) + if err != nil { + panic(fmt.Errorf("GetAdminUser %w", err)) + } + + if err := issue_service.DeleteIssue(ctx, doer, gitRepo, o.forgejoPullRequest); err != nil { + panic(err) + } +} + +func newPullRequest() generic.NodeDriverInterface { + return &pullRequest{} +} |