Monorepo for Tangled tangled.org
859
fork

Configure Feed

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

knotserver: create a fork PR link #341

open opened by willdot.net targeting master from willdot.net/tangled-fork: fork-pr-command

This should allow the PR link when pushing, to cater for forks.

Full disclosure, I haven't tested this because I can't get my local knot setup to work properly 🫠

Signed-off-by: Will Andrews did:plc:dadhhalkfcq3gucaq25hjqon

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:dadhhalkfcq3gucaq25hjqon/sh.tangled.repo.pull/3ml7kaijyha22
+148 -7
Diff #4
+22
knotserver/git/git.go
··· 13 13 "time" 14 14 15 15 "github.com/go-git/go-git/v5" 16 + gogit "github.com/go-git/go-git/v5" 16 17 "github.com/go-git/go-git/v5/config" 17 18 "github.com/go-git/go-git/v5/plumbing" 18 19 "github.com/go-git/go-git/v5/plumbing/object" ··· 281 282 return strings.TrimSpace(string(output)), nil 282 283 } 283 284 285 + func (g *GitRepo) Remote() (string, error) { 286 + remote, err := g.r.Remote("origin") 287 + if errors.Is(err, gogit.ErrRemoteNotFound) { 288 + return "", nil 289 + } 290 + if err != nil { 291 + return "", err 292 + } 293 + 294 + if remote == nil { 295 + return "", nil 296 + } 297 + 298 + urls := remote.Config().URLs 299 + if len(urls) == 0 { 300 + return "", nil 301 + } 302 + 303 + return urls[0], nil 304 + } 305 + 284 306 // WriteTar writes itself from a tree into a binary tar file format. 285 307 // prefix is root folder to be appended. 286 308 func (g *GitRepo) WriteTar(w io.Writer, prefix string) error {
+67 -7
knotserver/internal.go
··· 8 8 "net/http" 9 9 "net/url" 10 10 "os" 11 + "path" 11 12 "path/filepath" 12 13 "strings" 13 14 ··· 453 454 return err 454 455 } 455 456 457 + remote, err := gr.Remote() 458 + if err != nil { 459 + return fmt.Errorf("checking for upstream remote: %w", err) 460 + } 461 + 456 462 defaultBranch, err := gr.FindMainBranch() 457 463 if err != nil { 458 464 return err ··· 471 477 user = userIdent.Handle.String() 472 478 } 473 479 474 - query := url.Values{} 475 - query.Set("source", "branch") 476 - query.Set("sourceBranch", pushedBranch) 477 - query.Set("targetBranch", defaultBranch) 478 - 479 - basePath, err := url.JoinPath(h.c.AppViewEndpoint, user, repoName, "pulls", "new") 480 + pullURL, err := h.createPullURL(h.c.AppViewEndpoint, remote, user, ownerDid, repoName, pushedBranch, defaultBranch) 480 481 if err != nil { 481 482 return err 482 483 } 483 - pullURL := basePath + "?" + query.Encode() 484 484 485 485 ZWS := "\u200B" 486 486 *clientMsgs = append(*clientMsgs, ZWS) ··· 490 490 return nil 491 491 } 492 492 493 + func (h *InternalHandle) createPullURL(appviewURL, remote, user, ownerDID, repoName, pushedBranch, defaultBranch string) (string, error) { 494 + if remote != "" { 495 + return h.createForkPullURL(appviewURL, remote, ownerDID, repoName, pushedBranch, defaultBranch) 496 + } 497 + 498 + query := url.Values{} 499 + 500 + query.Set("source", "branch") 501 + query.Set("sourceBranch", pushedBranch) 502 + query.Set("targetBranch", defaultBranch) 503 + 504 + basePath, err := url.JoinPath(appviewURL, user, repoName, "pulls", "new") 505 + if err != nil { 506 + return "", err 507 + } 508 + pullURL := basePath + "?" + query.Encode() 509 + return pullURL, nil 510 + } 511 + 512 + func (h *InternalHandle) createForkPullURL(appviewURL, remote, ownerDID, repoName, pushedBranch, defaultBranch string) (string, error) { 513 + query := url.Values{} 514 + 515 + query.Set("fork", fmt.Sprintf("%s/%s", ownerDID, repoName)) 516 + query.Set("source", "fork") 517 + query.Set("sourceBranch", pushedBranch) 518 + query.Set("targetBranch", defaultBranch) 519 + 520 + repoPath, err := h.getRemoteOwnerRepoNamePath(remote) 521 + if err != nil { 522 + return "", err 523 + } 524 + 525 + basePath, err := url.JoinPath(appviewURL, repoPath, "pulls", "new") 526 + if err != nil { 527 + return "", err 528 + } 529 + pullURL := basePath + "?" + query.Encode() 530 + return pullURL, nil 531 + } 532 + 533 + func (h *InternalHandle) getRemoteOwnerRepoNamePath(remote string) (string, error) { 534 + u, err := url.Parse(remote) 535 + if err != nil { 536 + return "", fmt.Errorf("invalid remote: %w", err) 537 + } 538 + 539 + if u.Scheme != "file" { 540 + return u.Path, nil 541 + } 542 + 543 + repoDid := path.Base(u.String()) 544 + 545 + owner, name, err := h.db.GetRepoKeyOwner(repoDid) 546 + if err != nil { 547 + return "", err 548 + } 549 + 550 + return fmt.Sprintf("%s/%s", owner, name), nil 551 + } 552 + 493 553 func Internal(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, n *notifier.Notifier, res *idresolver.Resolver) http.Handler { 494 554 r := chi.NewRouter() 495 555 l := log.FromContext(ctx)
+59
knotserver/internal_test.go
··· 1 + package knotserver 2 + 3 + import ( 4 + "testing" 5 + 6 + "github.com/alecthomas/assert/v2" 7 + "github.com/stretchr/testify/require" 8 + "tangled.org/core/knotserver/db" 9 + ) 10 + 11 + const ( 12 + appviewURL = "https://tangled.org/" 13 + user = "willdot.net" 14 + userDID = "did:plc:dadhhalkfcq3gucaq25hjqon" 15 + pushedBranch = "feature-abc" 16 + defaultBranch = "main" 17 + ) 18 + 19 + func TestCreatePullURL(t *testing.T) { 20 + 21 + tt := map[string]struct { 22 + repoName string 23 + remote string 24 + expectedURL string 25 + }{ 26 + "not a fork": { 27 + repoName: "knot-testing", 28 + remote: "", 29 + expectedURL: "https://tangled.org/willdot.net/knot-testing/pulls/new?source=branch&sourceBranch=feature-abc&targetBranch=main", 30 + }, 31 + "is fork": { 32 + repoName: "knot-testing-fork", 33 + remote: "https://knot1.tangled.sh/did:plc:dadhhalkfcq3gucaq25hjqon/knot-testing", 34 + expectedURL: "https://tangled.org/did:plc:dadhhalkfcq3gucaq25hjqon/knot-testing/pulls/new?fork=did%3Aplc%3Adadhhalkfcq3gucaq25hjqon%2Fknot-testing-fork&source=fork&sourceBranch=feature-abc&targetBranch=main", 35 + }, 36 + "is fork on same knot": { 37 + repoName: "knot-testing-fork", 38 + remote: "file:///home/git/repositories/did:plc:ixran6dpypl5lslliiqceshs", 39 + expectedURL: "https://tangled.org/did:plc:dadhhalkfcq3gucaq25hjqon/knot-testing/pulls/new?fork=did%3Aplc%3Adadhhalkfcq3gucaq25hjqon%2Fknot-testing-fork&source=fork&sourceBranch=feature-abc&targetBranch=main", 40 + }, 41 + } 42 + 43 + for name, tc := range tt { 44 + t.Run(name, func(t *testing.T) { 45 + database, err := db.Setup(t.Context(), ":memory:") 46 + require.NoError(t, err) 47 + err = database.StoreRepoKey("did:plc:ixran6dpypl5lslliiqceshs", []byte{}, "did:plc:dadhhalkfcq3gucaq25hjqon", "knot-testing", "at://uri") 48 + require.NoError(t, err) 49 + 50 + h := InternalHandle{ 51 + db: database, 52 + } 53 + res, err := h.createPullURL(appviewURL, tc.remote, user, userDID, tc.repoName, pushedBranch, defaultBranch) 54 + require.NoError(t, err) 55 + 56 + assert.Equal(t, tc.expectedURL, res) 57 + }) 58 + } 59 + }

History

5 rounds 0 comments
sign up or login to add to the discussion
1 commit
expand
knotserver: create a fork PR link
no conflicts, ready to merge
expand 0 comments
1 commit
expand
knotserver: create a fork PR link
expand 0 comments
1 commit
expand
knotserver: create a fork PR link
expand 0 comments
1 commit
expand
knotserver: create a fork PR link
expand 0 comments
1 commit
expand
knotserver: create a fork PR link
expand 0 comments