forgejo/modules/migration/pullrequest.go
Gusted 5e79b39654 fix(migrations): transfer PR flow information (#7421)
- When migrating a pull requests from a Gitea or Forgejo instance, check if the pull request was created via the AGit flow and transfer that bit of information to the migrated pull request.
- Expose this bit of information as the `flow` field for the pull request.
- We have to do a horrible Go hack with Gitea's [go-sdk](gitea.com/gitea/go-sdk) to list all pull requests while being able to decode it to a struct that contains the new `Flow` field. The library does not allow you to do this out of the box, so we have to use `go:linkname` to access the private method that allows us to do this. This in turn means we have to do some boilerplate code that the library otherwise would do for us. The better option would be forking, but that would be a hassle of keeping the library in sync.
- Resolves forgejo/forgejo#5848
- Unit test added.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7421
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2025-04-03 06:47:37 +00:00

76 lines
2.6 KiB
Go

// Copyright 2019 The Gitea Authors. All rights reserved.
// Copyright 2018 Jonas Franz. All rights reserved.
// SPDX-License-Identifier: MIT
package migration
import (
"fmt"
"time"
"forgejo.org/modules/git"
)
// PullRequest defines a standard pull request information
type PullRequest struct {
Number int64
Title string
PosterName string `yaml:"poster_name"`
PosterID int64 `yaml:"poster_id"`
PosterEmail string `yaml:"poster_email"`
Content string
Milestone string
State string
Created time.Time
Updated time.Time
Closed *time.Time
Labels []*Label
PatchURL string `yaml:"patch_url"` // SECURITY: This must be safe to download directly from
Merged bool
MergedTime *time.Time `yaml:"merged_time"`
MergeCommitSHA string `yaml:"merge_commit_sha"`
Head PullRequestBranch
Base PullRequestBranch
Assignees []string
IsLocked bool `yaml:"is_locked"`
Reactions []*Reaction
Flow int64
ForeignIndex int64
Context DownloaderContext `yaml:"-"`
EnsuredSafe bool `yaml:"ensured_safe"`
IsDraft bool `yaml:"is_draft"`
}
func (p *PullRequest) GetLocalIndex() int64 { return p.Number }
func (p *PullRequest) GetForeignIndex() int64 { return p.ForeignIndex }
func (p *PullRequest) GetContext() DownloaderContext { return p.Context }
// IsForkPullRequest returns true if the pull request from a forked repository but not the same repository
func (p *PullRequest) IsForkPullRequest() bool {
return p.Head.RepoFullName() != p.Base.RepoFullName()
}
// GetGitRefName returns pull request relative path to head
func (p PullRequest) GetGitRefName() string {
return fmt.Sprintf("%s%d/head", git.PullPrefix, p.Number)
}
// PullRequestBranch represents a pull request branch
type PullRequestBranch struct {
CloneURL string `yaml:"clone_url"` // SECURITY: This must be safe to download from
Ref string // SECURITY: this must be a git.IsValidRefPattern
SHA string // SECURITY: this must be a git.IsValidSHAPattern
RepoName string `yaml:"repo_name"`
OwnerName string `yaml:"owner_name"`
}
// RepoFullName returns pull request repo full name
func (p PullRequestBranch) RepoFullName() string {
return fmt.Sprintf("%s/%s", p.OwnerName, p.RepoName)
}
// GetExternalName ExternalUserMigrated interface
func (p *PullRequest) GetExternalName() string { return p.PosterName }
// ExternalID ExternalUserMigrated interface
func (p *PullRequest) GetExternalID() int64 { return p.PosterID }