Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142package knotfeed
import ( "cmp" "encoding/json" "fmt" "log/slog" "strings"
"github.com/bluesky-social/indigo/atproto/syntax" "github.com/samber/lo" "tangled.org/core/api/tangled" "tangled.org/core/tapc")
const ( legacyRefUpdateNSID syntax.NSID = tangled.GitRefUpdateNSID legacyCollaboratorUpdateNSID syntax.NSID = "sh.tangled.repo.collaboratorUpdate"
collaboratorInviteCollection syntax.NSID = tangled.RepoCollaboratorInviteNSID)
type legacyAclOp string
const ( legacyAclOpAdd legacyAclOp = "add" legacyAclOpRemove legacyAclOp = "remove")
func (op legacyAclOp) action() tapc.RecordAction { return lo.Ternary(strings.EqualFold(string(op), string(legacyAclOpRemove)), tapc.RecordDeleteAction, tapc.RecordCreateAction)}
type legacyFrame struct { Nsid syntax.NSID `json:"nsid"` Created int64 `json:"created"` Event json.RawMessage `json:"event"`}
type legacyRefUpdate struct { Repo syntax.DID `json:"repo"` LegacyRepo syntax.DID `json:"repoDid"` // knots older than 1.14 name the repo this way Ref string `json:"ref"` OldSha string `json:"oldSha"` NewSha string `json:"newSha"` CommitterDid string `json:"committerDid"` PushOptions []string `json:"pushOptions"`}
type legacyAclUpdate struct { Op legacyAclOp `json:"op"` Repo syntax.DID `json:"repo"` Subject syntax.DID `json:"subject"`}
var legacyOps = map[syntax.NSID]func(json.RawMessage, *Commit) error{ legacyRefUpdateNSID: legacyRefOp, legacyCollaboratorUpdateNSID: legacyCollaboratorOp,}
func decodeLegacy(data []byte, _ *slog.Logger) (Message, error) { var frame legacyFrame if err := json.Unmarshal(data, &frame); err != nil { return Message{}, fmt.Errorf("legacy frame: %w", err) } if frame.Created <= 0 { return Message{}, fmt.Errorf("legacy %s frame lacks its created stamp: %d", frame.Nsid, frame.Created) }
commit := &Commit{Seq: frame.Created} if op, known := legacyOps[frame.Nsid]; known { if err := op(frame.Event, commit); err != nil { return Message{}, err } } return Message{Type: TypeCommit, Commit: commit}, nil}
func legacyRefOp(payload json.RawMessage, commit *Commit) error { var event legacyRefUpdate if err := json.Unmarshal(payload, &event); err != nil { return fmt.Errorf("legacy ref update: %w", err) } rkey, short := EscapeRefname(event.Ref) newSha, isObject := ParseObjectID(event.NewSha) // pre-1.13 knots put the owner's did in repoDid, so this can miss on lookup; // the event still has to flow through so the host's cursor keeps moving repo := cmp.Or(event.Repo, event.LegacyRepo) if event.Ref == "" || repo == "" || !short || !isObject { return nil } op := RecordOp{ Action: tapc.RecordDeleteAction, Collection: GitRefCollection, Rkey: rkey, Prior: ParsePriorSha(event.OldSha), } if !newSha.IsZero() { // old knots leave committerDid empty; attribute those pushes to the repo itself editor, err := syntax.ParseDID(event.CommitterDid) if err != nil { editor = repo } record, err := encodeRefRecord(RefRecord{ Sha: newSha, Editor: editor, PushOptions: event.PushOptions, }) if err != nil { return fmt.Errorf("re-encoding legacy ref update: %w", err) } op.Action, op.Bytes = tapc.RecordCreateAction, record }
commit.Repo = repo commit.Records = []RecordOp{op} return nil}
func legacyCollaboratorOp(payload json.RawMessage, commit *Commit) error { var event legacyAclUpdate if err := json.Unmarshal(payload, &event); err != nil { return fmt.Errorf("legacy collaborator update: %w", err) } if event.Repo == "" || event.Subject == "" { return nil }
rkey, err := syntax.ParseRecordKey(event.Subject.String()) if err != nil { return fmt.Errorf("legacy collaborator update names subject %q: %w", event.Subject, err) } commit.Repo = event.Repo commit.Records = []RecordOp{{ Action: event.Op.action(), Collection: collaboratorInviteCollection, Rkey: rkey, }} return nil}