Monorepo for Tangled tangled.org
2

Configure Feed

Select the types of activity you want to include in your feed.

appview: deal with fork PR opening by repoDID

Lewis: May this revision serve well! <lewis@tangled.org>

author
Lewis
committer
Tangled
date (May 15, 2026, 3:26 PM +0300) commit 9a56e207 parent 94765dfc change-id uvuwpxyl
+36 -75
+4 -50
appview/db/repos.go
··· 636 636 return repos, nil 637 637 } 638 638 639 - func GetForkByDid(e Execer, did string, rkey string) (*models.Repo, error) { 640 - var repo models.Repo 641 - var createdAt string 642 - var nullableDescription sql.NullString 643 - var nullableWebsite sql.NullString 644 - var nullableTopicStr sql.NullString 645 - var nullableSource sql.NullString 646 - var nullableRepoDid sql.NullString 647 - 648 - row := e.QueryRow( 649 - `select id, did, name, knot, rkey, description, website, topics, created, source, repo_did 650 - from repos 651 - where did = ? and rkey = ? and source is not null and source != ''`, 652 - did, rkey, 653 - ) 654 - 655 - err := row.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &nullableWebsite, &nullableTopicStr, &createdAt, &nullableSource, &nullableRepoDid) 656 - if err != nil { 657 - return nil, err 658 - } 659 - 660 - if nullableDescription.Valid { 661 - repo.Description = nullableDescription.String 662 - } 663 - 664 - if nullableWebsite.Valid { 665 - repo.Website = nullableWebsite.String 666 - } 667 - 668 - if nullableTopicStr.Valid { 669 - repo.Topics = strings.Fields(nullableTopicStr.String) 670 - } 671 - 672 - if nullableSource.Valid { 673 - repo.Source = nullableSource.String 674 - } 675 - if nullableRepoDid.Valid { 676 - repo.RepoDid = nullableRepoDid.String 677 - } 678 - 679 - createdAtTime, err := time.Parse(time.RFC3339, createdAt) 680 - if err != nil { 681 - repo.Created = time.Now() 682 - } else { 683 - repo.Created = createdAtTime 684 - } 685 - 686 - return &repo, nil 639 + func GetRepoByDid(e Execer, repoDid string) (*models.Repo, error) { 640 + return GetRepo(e, orm.FilterEq("repo_did", repoDid)) 687 641 } 688 642 689 - func GetRepoByDid(e Execer, repoDid string) (*models.Repo, error) { 690 - return GetRepo(e, orm.FilterEq("repo_did", repoDid)) 643 + func GetForkByRepoDid(e Execer, repoDid string) (*models.Repo, error) { 644 + return GetRepo(e, orm.FilterEq("repo_did", repoDid), orm.FilterNotEq("source", "")) 691 645 } 692 646 693 647 // TODO: just queue every legacy records regardless of target repo has a DID or not.
+1 -2
appview/pages/templates/repo/pulls/fragments/pullCompareForks.html
··· 15 15 > 16 16 <option disabled {{ if not $.Fork }}selected{{ end }}>Select a fork</option> 17 17 {{ range .Forks }} 18 - {{ $ident := printf "%s/%s" .Did .Name }} 19 - <option value="{{ $ident }}" {{ if eq $ident $.Fork }}selected{{ end }} class="py-1"> 18 + <option value="{{ .RepoDid }}" {{ if eq .RepoDid $.Fork }}selected{{ end }} class="py-1"> 20 19 {{ .Did | resolve }}/{{ .Name }} 21 20 </option> 22 21 {{ end }}
+19 -12
appview/pulls/compose.go
··· 2 2 3 3 import ( 4 4 "context" 5 + "database/sql" 5 6 "encoding/json" 6 7 "errors" 7 8 "fmt" ··· 19 20 "tangled.org/core/appview/pages/markup" 20 21 "tangled.org/core/appview/pages/repoinfo" 21 22 "tangled.org/core/appview/xrpcclient" 22 - "tangled.org/core/orm" 23 23 "tangled.org/core/patchutil" 24 24 "tangled.org/core/types" 25 25 ··· 222 222 l.Warn("failed to list user forks", "err", err, "user", user.Did) 223 223 } 224 224 } 225 + forks = slices.DeleteFunc(forks, func(f models.Repo) bool { 226 + return f.RepoDid == "" 227 + }) 225 228 226 229 repoInfo := s.repoResolver.GetRepoInfo(r, user) 227 230 source, ok := pages.ParseSource(r.FormValue("source")) ··· 238 241 patch := r.FormValue("patch") 239 242 240 243 if source == pages.SourceFork && fork == "" && len(forks) == 1 { 241 - fork = fmt.Sprintf("%s/%s", forks[0].Did, forks[0].Name) 244 + fork = forks[0].RepoDid 242 245 } 243 246 244 247 var forkBranches []types.Branch ··· 345 348 return result.Branches, nil 346 349 } 347 350 348 - func (s *Pulls) listForkBranches(ctx context.Context, forkIdent string) ([]types.Branch, error) { 349 - parts := strings.SplitN(forkIdent, "/", 2) 350 - if len(parts) != 2 { 351 - return nil, fmt.Errorf("invalid fork identifier: %s", forkIdent) 351 + func (s *Pulls) listForkBranches(ctx context.Context, forkRepoDid string) ([]types.Branch, error) { 352 + if forkRepoDid == "" { 353 + return nil, fmt.Errorf("fork not found") 354 + } 355 + forkRepo, err := db.GetForkByRepoDid(s.db, forkRepoDid) 356 + if errors.Is(err, sql.ErrNoRows) { 357 + return nil, fmt.Errorf("fork not found") 352 358 } 353 - forkRepo, err := db.GetRepo(s.db, orm.FilterEq("did", parts[0]), orm.FilterEq("name", parts[1])) 354 359 if err != nil { 355 360 return nil, err 356 361 } ··· 551 556 return &comparison, nil 552 557 } 553 558 554 - func (s *Pulls) fetchForkComparison(r *http.Request, forkIdent, targetBranch, sourceBranch string) (*types.RepoFormatPatchResponse, error) { 555 - parts := strings.SplitN(forkIdent, "/", 2) 556 - if len(parts) != 2 { 557 - return nil, fmt.Errorf("invalid fork identifier: %s", forkIdent) 559 + func (s *Pulls) fetchForkComparison(r *http.Request, forkRepoDid, targetBranch, sourceBranch string) (*types.RepoFormatPatchResponse, error) { 560 + if forkRepoDid == "" { 561 + return nil, fmt.Errorf("fork not found") 558 562 } 559 - fork, err := db.GetForkByDid(s.db, parts[0], parts[1]) 563 + fork, err := db.GetForkByRepoDid(s.db, forkRepoDid) 564 + if errors.Is(err, sql.ErrNoRows) { 565 + return nil, fmt.Errorf("fork not found") 566 + } 560 567 if err != nil { 561 568 return nil, err 562 569 }
+4 -4
appview/pulls/compose_helpers_test.go
··· 202 202 pages.RepoNewPullParams{ 203 203 RepoInfo: repo, 204 204 Source: pages.SourceFork, 205 - Fork: "did:plc:other/repo", 205 + Fork: "did:plc:limpet", 206 206 SourceBranch: "feature", 207 207 TargetBranch: "main", 208 208 }, 209 - "/did:plc:abc/demo/pulls/new?fork=did%3Aplc%3Aother%2Frepo&source=fork&sourceBranch=feature&targetBranch=main", 209 + "/did:plc:abc/demo/pulls/new?fork=did%3Aplc%3Alimpet&source=fork&sourceBranch=feature&targetBranch=main", 210 210 }, 211 211 { 212 212 "branch with selection drops source param", ··· 449 449 {"branch missing target", pages.SourceBranch, "", "", "feature"}, 450 450 {"branch missing source", pages.SourceBranch, "", "main", ""}, 451 451 {"fork missing fork", pages.SourceFork, "", "main", "feature"}, 452 - {"fork missing target", pages.SourceFork, "did/repo", "", "feature"}, 453 - {"fork missing source", pages.SourceFork, "did/repo", "main", ""}, 452 + {"fork missing target", pages.SourceFork, "did:plc:limpet", "", "feature"}, 453 + {"fork missing source", pages.SourceFork, "did:plc:limpet", "main", ""}, 454 454 {"unknown source", pages.Source("bogus"), "", "", ""}, 455 455 } 456 456 for _, c := range cases {
+8 -7
appview/pulls/create.go
··· 94 94 s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, "", "", nil, isStacked, stackTitles, stackBodies) 95 95 } 96 96 97 - func (s *Pulls) handleForkBasedPull(w http.ResponseWriter, r *http.Request, repo *models.Repo, userDid syntax.DID, forkRepo string, title, body, targetBranch, sourceBranch string, isStacked bool, stackTitles, stackBodies map[string]string) { 98 - l := s.logger.With("handler", "handleForkBasedPull", "user", userDid, "fork_repo", forkRepo, "target_branch", targetBranch, "source_branch", sourceBranch, "is_stacked", isStacked) 97 + func (s *Pulls) handleForkBasedPull(w http.ResponseWriter, r *http.Request, repo *models.Repo, userDid syntax.DID, forkRepoDid string, title, body, targetBranch, sourceBranch string, isStacked bool, stackTitles, stackBodies map[string]string) { 98 + l := s.logger.With("handler", "handleForkBasedPull", "user", userDid, "fork_repo_did", forkRepoDid, "target_branch", targetBranch, "source_branch", sourceBranch, "is_stacked", isStacked) 99 99 100 - repoString := strings.SplitN(forkRepo, "/", 2) 101 - forkOwnerDid := repoString[0] 102 - forkRkey := strings.ToLower(repoString[1]) 103 - fork, err := db.GetForkByDid(s.db, forkOwnerDid, forkRkey) 100 + if forkRepoDid == "" { 101 + s.pages.Notice(w, "pull", "No such fork.") 102 + return 103 + } 104 + fork, err := db.GetForkByRepoDid(s.db, forkRepoDid) 104 105 if errors.Is(err, sql.ErrNoRows) { 105 106 s.pages.Notice(w, "pull", "No such fork.") 106 107 return 107 108 } else if err != nil { 108 - l.Error("failed to fetch fork", "err", err, "fork_owner_did", forkOwnerDid, "fork_rkey", forkRkey) 109 + l.Error("failed to fetch fork", "err", err, "fork_repo_did", forkRepoDid) 109 110 s.pages.Notice(w, "pull", "Failed to fetch fork.") 110 111 return 111 112 }