Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Go
at test-pr-link
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349package models
import ( "fmt" "log" "slices" "strings" "time"
"github.com/bluesky-social/indigo/atproto/syntax" "tangled.org/core/api/tangled" "tangled.org/core/patchutil" "tangled.org/core/types")
type PullState int
const ( PullClosed PullState = iota PullOpen PullMerged PullDeleted)
func (p PullState) String() string { switch p { case PullOpen: return "open" case PullMerged: return "merged" case PullClosed: return "closed" case PullDeleted: return "deleted" default: return "closed" }}
func (p PullState) IsOpen() bool { return p == PullOpen}func (p PullState) IsMerged() bool { return p == PullMerged}func (p PullState) IsClosed() bool { return p == PullClosed}func (p PullState) IsDeleted() bool { return p == PullDeleted}
type Pull struct { // ids ID int PullId int
// at ids RepoAt syntax.ATURI OwnerDid string Rkey string
// content Title string Body string TargetBranch string State PullState Submissions []*PullSubmission
// stacking StackId string // nullable string ChangeId string // nullable string ParentChangeId string // nullable string
// meta Created time.Time PullSource *PullSource
// optionally, populate this when querying for reverse mappings Labels LabelState Repo *Repo}
func (p Pull) AsRecord() tangled.RepoPull { var source *tangled.RepoPull_Source if p.PullSource != nil { source = &tangled.RepoPull_Source{} source.Branch = p.PullSource.Branch source.Sha = p.LatestSha() if p.PullSource.RepoAt != nil { s := p.PullSource.Repo.RepoAt().String() source.Repo = &s } }
record := tangled.RepoPull{ Title: p.Title, Body: &p.Body, CreatedAt: p.Created.Format(time.RFC3339), Target: &tangled.RepoPull_Target{ Repo: p.RepoAt.String(), Branch: p.TargetBranch, }, Patch: p.LatestPatch(), Source: source, } return record}
type PullSource struct { Branch string RepoAt *syntax.ATURI
// optionally populate this for reverse mappings Repo *Repo}
type PullSubmission struct { // ids ID int
// at ids PullAt syntax.ATURI
// content RoundNumber int Patch string Comments []PullComment SourceRev string // include the rev that was used to create this submission: only for branch/fork PRs
// meta Created time.Time}
type PullComment struct { // ids ID int PullId int SubmissionId int
// at ids RepoAt string OwnerDid string CommentAt string
// content Body string
// meta Created time.Time}
func (p *Pull) LatestPatch() string { latestSubmission := p.Submissions[p.LastRoundNumber()] return latestSubmission.Patch}
func (p *Pull) LatestSha() string { latestSubmission := p.Submissions[p.LastRoundNumber()] return latestSubmission.SourceRev}
func (p *Pull) PullAt() syntax.ATURI { return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", p.OwnerDid, tangled.RepoPullNSID, p.Rkey))}
func (p *Pull) LastRoundNumber() int { return len(p.Submissions) - 1}
func (p *Pull) IsPatchBased() bool { return p.PullSource == nil}
func (p *Pull) IsBranchBased() bool { if p.PullSource != nil { if p.PullSource.RepoAt != nil { return p.PullSource.RepoAt == &p.RepoAt } else { // no repo specified return true } } return false}
func (p *Pull) IsForkBased() bool { if p.PullSource != nil { if p.PullSource.RepoAt != nil { // make sure repos are different return p.PullSource.RepoAt != &p.RepoAt } } return false}
func (p *Pull) IsStacked() bool { return p.StackId != ""}
func (p *Pull) Participants() []string { participantSet := make(map[string]struct{}) participants := []string{}
addParticipant := func(did string) { if _, exists := participantSet[did]; !exists { participantSet[did] = struct{}{} participants = append(participants, did) } }
addParticipant(p.OwnerDid)
for _, s := range p.Submissions { for _, sp := range s.Participants() { addParticipant(sp) } }
return participants}
func (s PullSubmission) IsFormatPatch() bool { return patchutil.IsFormatPatch(s.Patch)}
func (s PullSubmission) AsFormatPatch() []types.FormatPatch { patches, err := patchutil.ExtractPatches(s.Patch) if err != nil { log.Println("error extracting patches from submission:", err) return []types.FormatPatch{} }
return patches}
func (s *PullSubmission) Participants() []string { participantSet := make(map[string]struct{}) participants := []string{}
addParticipant := func(did string) { if _, exists := participantSet[did]; !exists { participantSet[did] = struct{}{} participants = append(participants, did) } }
addParticipant(s.PullAt.Authority().String())
for _, c := range s.Comments { addParticipant(c.OwnerDid) }
return participants}
type Stack []*Pull
// position of this pull in the stackfunc (stack Stack) Position(pull *Pull) int { return slices.IndexFunc(stack, func(p *Pull) bool { return p.ChangeId == pull.ChangeId })}
// all pulls below this pull (including self) in this stack//// nil if this pull does not belong to this stackfunc (stack Stack) Below(pull *Pull) Stack { position := stack.Position(pull)
if position < 0 { return nil }
return stack[position:]}
// all pulls below this pull (excluding self) in this stackfunc (stack Stack) StrictlyBelow(pull *Pull) Stack { below := stack.Below(pull)
if len(below) > 0 { return below[1:] }
return nil}
// all pulls above this pull (including self) in this stackfunc (stack Stack) Above(pull *Pull) Stack { position := stack.Position(pull)
if position < 0 { return nil }
return stack[:position+1]}
// all pulls below this pull (excluding self) in this stackfunc (stack Stack) StrictlyAbove(pull *Pull) Stack { above := stack.Above(pull)
if len(above) > 0 { return above[:len(above)-1] }
return nil}
// the combined format-patches of all the newest submissions in this stackfunc (stack Stack) CombinedPatch() string { // go in reverse order because the bottom of the stack is the last element in the slice var combined strings.Builder for idx := range stack { pull := stack[len(stack)-1-idx] combined.WriteString(pull.LatestPatch()) combined.WriteString("\n") } return combined.String()}
// filter out PRs that are "active"//// PRs that are still open are activefunc (stack Stack) Mergeable() Stack { var mergeable Stack
for _, p := range stack { // stop at the first merged PR if p.State == PullMerged || p.State == PullClosed { break }
// skip over deleted PRs if p.State != PullDeleted { mergeable = append(mergeable, p) } }
return mergeable}
type BranchDeleteStatus struct { Repo *Repo Branch string}