diff --git a/appview/db/pulls.go b/appview/db/pulls.go index e4338390..f943f934 100644 --- a/appview/db/pulls.go +++ b/appview/db/pulls.go @@ -194,18 +194,16 @@ func createNewPull(tx *sql.Tx, pull *models.Pull) error { pull_at, round_number, patch, - combined, source_rev, patch_blob_ref, patch_blob_mime, patch_blob_size ) - values (?, ?, ?, ?, ?, ?, ?, ?) + values (?, ?, ?, ?, ?, ?, ?) `, pull.AtUri(), i, s.Patch, - s.Combined, s.SourceRev, s.Blob.Ref.String(), s.Blob.MimeType, @@ -255,18 +253,16 @@ func updatePull(tx *sql.Tx, pull *models.Pull, existingPull *models.Pull) error pull_at, round_number, patch, - combined, source_rev, patch_blob_ref, patch_blob_mime, patch_blob_size ) - values (?, ?, ?, ?, ?, ?, ?, ?) + values (?, ?, ?, ?, ?, ?, ?) `, pull.AtUri(), i, s.Patch, - s.Combined, s.SourceRev, s.Blob.Ref.String(), s.Blob.MimeType, @@ -505,7 +501,6 @@ func GetPullSubmissions(e Execer, filters ...orm.Filter) (map[syntax.ATURI][]*mo pull_at, round_number, patch, - combined, created, source_rev, patch_blob_ref, @@ -529,7 +524,7 @@ func GetPullSubmissions(e Execer, filters ...orm.Filter) (map[syntax.ATURI][]*mo for rows.Next() { var submission models.PullSubmission var submissionCreatedStr string - var submissionSourceRev, submissionCombined sql.Null[string] + var submissionSourceRev sql.Null[string] var patchBlobRef, patchBlobMime sql.Null[string] var patchBlobSize sql.Null[int64] err := rows.Scan( @@ -537,7 +532,6 @@ func GetPullSubmissions(e Execer, filters ...orm.Filter) (map[syntax.ATURI][]*mo &submission.PullAt, &submission.RoundNumber, &submission.Patch, - &submissionCombined, &submissionCreatedStr, &submissionSourceRev, &patchBlobRef, @@ -556,10 +550,6 @@ func GetPullSubmissions(e Execer, filters ...orm.Filter) (map[syntax.ATURI][]*mo submission.SourceRev = submissionSourceRev.V } - if submissionCombined.Valid { - submission.Combined = submissionCombined.V - } - if patchBlobRef.Valid { submission.Blob.Ref = lexutil.LexLink(cid.MustParse(patchBlobRef.V)) } @@ -845,7 +835,6 @@ func ResubmitPull( pullAt syntax.ATURI, newRoundNumber int, newPatch string, - combinedPatch string, newSourceRev string, blob *lexutil.LexBlob, ) error { @@ -854,14 +843,13 @@ func ResubmitPull( pull_at, round_number, patch, - combined, source_rev, patch_blob_ref, patch_blob_mime, patch_blob_size ) - values (?, ?, ?, ?, ?, ?, ?, ?) - `, pullAt, newRoundNumber, newPatch, combinedPatch, newSourceRev, blob.Ref.String(), blob.MimeType, blob.Size) + values (?, ?, ?, ?, ?, ?, ?) + `, pullAt, newRoundNumber, newPatch, newSourceRev, blob.Ref.String(), blob.MimeType, blob.Size) return err } diff --git a/appview/models/pull.go b/appview/models/pull.go index 5723b1fa..ce43e1de 100644 --- a/appview/models/pull.go +++ b/appview/models/pull.go @@ -298,7 +298,6 @@ type PullSubmission struct { RoundNumber int Blob lexutil.LexBlob Patch string - Combined string Comments []PullComment SourceRev string // include the rev that was used to create this submission: only for branch/fork PRs @@ -457,14 +456,6 @@ func (s *PullSubmission) Participants() []string { return participants } -func (s PullSubmission) CombinedPatch() string { - if s.Combined == "" { - return s.Patch - } - - return s.Combined -} - func (s *PullSubmission) GetBlob() *lexutil.LexBlob { if !s.Blob.Ref.Defined() { return nil diff --git a/appview/pulls/create.go b/appview/pulls/create.go index 4302fc2e..a6eed441 100644 --- a/appview/pulls/create.go +++ b/appview/pulls/create.go @@ -24,6 +24,7 @@ import ( comatproto "github.com/bluesky-social/indigo/api/atproto" "github.com/bluesky-social/indigo/atproto/syntax" lexutil "github.com/bluesky-social/indigo/lex/util" + indigoxrpc "github.com/bluesky-social/indigo/xrpc" ) func (s *Pulls) handleBranchBasedPull( @@ -40,35 +41,32 @@ func (s *Pulls) handleBranchBasedPull( ) { l := s.logger.With("handler", "handleBranchBasedPull", "user", userDid, "target_branch", targetBranch, "source_branch", sourceBranch, "is_stacked", isStacked) - xrpcc := s.knotClient(repo.Knot) + xrpcc := &indigoxrpc.Client{Host: s.config.KnotMirror.Url} - xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo.RepoIdentifier(), targetBranch, sourceBranch) + fpOut, err := tangled.GitTempFormatPatch(r.Context(), xrpcc, repo.RepoAt().String(), "", targetBranch, sourceBranch) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { - l.Error("failed to call XRPC repo.compare", "xrpcerr", xrpcerr, "err", err) + l.Error("failed to call XRPC git.formatPatch", "xrpcerr", xrpcerr, "err", err) s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - l.Error("failed to compare", "err", err) + l.Error("failed to run format-patch", "err", err) s.pages.Notice(w, "pull", err.Error()) return } - - var comparison types.RepoFormatPatchResponse - if err := json.Unmarshal(xrpcBytes, &comparison); err != nil { - l.Error("failed to decode XRPC compare response", "err", err) + if fpOut.Rev2 == nil { + l.Error("failed to parse git.formatPatch output", "err", "rev2 is missing") s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - if len(comparison.FormatPatch) == 0 { + if fpOut.Patch == "" { s.pages.Notice(w, "pull", "No commits between target and source.") return } - sourceRev := comparison.Rev2 - patch := comparison.FormatPatchRaw - combined := comparison.CombinedPatchRaw + sourceRev := *fpOut.Rev2 + patch := fpOut.Patch if err := s.validator.ValidatePatch(&patch); err != nil { s.logger.Error("failed to validate patch", "err", err) @@ -80,7 +78,7 @@ func (s *Pulls) handleBranchBasedPull( Branch: sourceBranch, } - s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, combined, sourceRev, pullSource, isStacked, stackTitles, stackBodies) + s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, sourceRev, pullSource, isStacked) } func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, repo *models.Repo, userDid syntax.DID, title, body, targetBranch, patch string, isStacked bool, stackTitles, stackBodies map[string]string) { @@ -90,7 +88,7 @@ func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, rep return } - s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, "", "", nil, isStacked, stackTitles, stackBodies) + s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, "", nil, isStacked, stackTitles, stackBodies) } 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) { @@ -109,72 +107,32 @@ func (s *Pulls) handleForkBasedPull(w http.ResponseWriter, r *http.Request, repo return } - client, err := s.oauth.ServiceClient( - r, - oauth.WithService(fork.Knot), - oauth.WithLxm(tangled.RepoHiddenRefNSID), - oauth.WithDev(s.config.Core.Dev), - ) - - resp, err := tangled.RepoHiddenRef( - r.Context(), - client, - &tangled.RepoHiddenRef_Input{ - ForkRef: sourceBranch, - RemoteRef: targetBranch, - Repo: fork.RepoAt().String(), - }, - ) - if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { - s.logger.Error("failed to set hidden ref", "xrpcerr", xrpcerr, "err", err) - s.pages.Notice(w, "pull", xrpcerr.Error()) - return - } - - if !resp.Success { - errorMsg := "Failed to create pull request" - if resp.Error != nil { - errorMsg = fmt.Sprintf("Failed to create pull request: %s", *resp.Error) - } - s.pages.Notice(w, "pull", errorMsg) - return - } + xrpcc := &indigoxrpc.Client{Host: s.config.KnotMirror.Url} - hiddenRef := fmt.Sprintf("hidden/%s/%s", sourceBranch, targetBranch) - // We're now comparing the sourceBranch (on the fork) against the hiddenRef which is tracking - // the targetBranch on the target repository. This code is a bit confusing, but here's an example: - // hiddenRef: hidden/feature-1/main (on repo-fork) - // targetBranch: main (on repo-1) - // sourceBranch: feature-1 (on repo-fork) - forkXrpcc := s.knotClient(fork.Knot) - - forkXrpcBytes, err := tangled.RepoCompare(r.Context(), forkXrpcc, fork.RepoIdentifier(), hiddenRef, sourceBranch) + fpOut, err := tangled.GitTempFormatPatch(r.Context(), xrpcc, repo.RepoAt().String(), fork.RepoAt().String(), targetBranch, sourceBranch) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { - l.Error("failed to call XRPC repo.compare for fork", "xrpcerr", xrpcerr, "err", err, "hidden_ref", hiddenRef) + l.Error("failed to call XRPC git.formatPatch", "xrpcerr", xrpcerr, "err", err) s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - l.Error("failed to compare across branches", "err", err, "hidden_ref", hiddenRef) + l.Error("failed to run format-patch", "err", err) s.pages.Notice(w, "pull", err.Error()) return } - - var comparison types.RepoFormatPatchResponse - if err := json.Unmarshal(forkXrpcBytes, &comparison); err != nil { - l.Error("failed to decode XRPC compare response for fork", "err", err) + if fpOut.Rev2 == nil { + l.Error("failed to parse git.formatPatch output", "err", "rev2 is missing") s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - if len(comparison.FormatPatch) == 0 { + if fpOut.Patch == "" { s.pages.Notice(w, "pull", "No commits between target and source.") return } - sourceRev := comparison.Rev2 - patch := comparison.FormatPatchRaw - combined := comparison.CombinedPatchRaw + sourceRev := *fpOut.Rev2 + patch := fpOut.Patch if err := s.validator.ValidatePatch(&patch); err != nil { s.logger.Error("failed to validate patch", "err", err) @@ -195,7 +153,7 @@ func (s *Pulls) handleForkBasedPull(w http.ResponseWriter, r *http.Request, repo RepoDid: forkDid, } - s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, combined, sourceRev, pullSource, isStacked, stackTitles, stackBodies) + s.createPullRequest(w, r, repo, userDid, title, body, targetBranch, patch, sourceRev, pullSource, isStacked, stackTitles, stackBodies) } func (s *Pulls) createPullRequest( @@ -205,7 +163,6 @@ func (s *Pulls) createPullRequest( userDid syntax.DID, title, body, targetBranch string, patch string, - combined string, sourceRev string, pullSource *models.PullSource, isStacked bool, @@ -291,7 +248,6 @@ func (s *Pulls) createPullRequest( Submissions: []*models.PullSubmission{ { Patch: patch, - Combined: combined, SourceRev: sourceRev, Blob: *blob.Blob, Created: now, @@ -509,7 +465,6 @@ func (s *Pulls) newStack( { Patch: fp.Raw, SourceRev: fp.SHA, - Combined: fp.Raw, Blob: *blobs[i], Created: now, }, diff --git a/appview/pulls/resubmit.go b/appview/pulls/resubmit.go index e8f2cde0..65346886 100644 --- a/appview/pulls/resubmit.go +++ b/appview/pulls/resubmit.go @@ -1,7 +1,6 @@ package pulls import ( - "encoding/json" "fmt" "net/http" "time" @@ -9,19 +8,18 @@ import ( "tangled.org/core/api/tangled" "tangled.org/core/appview/db" "tangled.org/core/appview/models" - "tangled.org/core/appview/oauth" "tangled.org/core/appview/pages" "tangled.org/core/appview/pages/repoinfo" "tangled.org/core/appview/reporesolver" "tangled.org/core/appview/xrpcclient" "tangled.org/core/orm" "tangled.org/core/patchutil" - "tangled.org/core/types" "tangled.org/core/xrpc" comatproto "github.com/bluesky-social/indigo/api/atproto" "github.com/bluesky-social/indigo/atproto/syntax" lexutil "github.com/bluesky-social/indigo/lex/util" + indigoxrpc "github.com/bluesky-social/indigo/xrpc" ) func (s *Pulls) ResubmitPull(w http.ResponseWriter, r *http.Request) { @@ -91,7 +89,7 @@ func (s *Pulls) resubmitPatch(w http.ResponseWriter, r *http.Request) { patch := r.FormValue("patch") - s.resubmitPullHelper(w, r, f, syntax.DID(user.Did), pull, patch, "", "") + s.resubmitPullHelper(w, r, f, syntax.DID(user.Did), pull, patch, "") } func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) { @@ -129,32 +127,30 @@ func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) { return } - xrpcc := s.knotClient(f.Knot) + xrpcc := &indigoxrpc.Client{Host: s.config.KnotMirror.Url} - xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, f.RepoIdentifier(), pull.TargetBranch, pull.PullSource.Branch) + fpOut, err := tangled.GitTempFormatPatch(r.Context(), xrpcc, f.RepoAt().String(), "", pull.TargetBranch, pull.PullSource.Branch) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { - l.Error("failed to call XRPC repo.compare", "xrpcerr", xrpcerr, "err", err, "source_branch", pull.PullSource.Branch) - s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") + l.Error("failed to call XRPC git.formatPatch", "xrpcerr", xrpcerr, "err", err, "source_branch", pull.PullSource.Branch) + s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull request. Try again later.") return } - l.Error("compare request failed", "err", err, "source_branch", pull.PullSource.Branch) + l.Error("failed to run format-patch", "err", err, "source_branch", pull.PullSource.Branch) s.pages.Notice(w, "resubmit-error", err.Error()) return } - var comparison types.RepoFormatPatchResponse - if err := json.Unmarshal(xrpcBytes, &comparison); err != nil { - l.Error("failed to decode XRPC compare response", "err", err) - s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") + if fpOut.Rev2 == nil { + l.Error("failed to parse git.formatPatch output", "err", "rev2 is missing") + s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull request. Try again later.") return } - sourceRev := comparison.Rev2 - patch := comparison.FormatPatchRaw - combined := comparison.CombinedPatchRaw + sourceRev := *fpOut.Rev2 + patch := fpOut.Patch - s.resubmitPullHelper(w, r, f, syntax.DID(user.Did), pull, patch, combined, sourceRev) + s.resubmitPullHelper(w, r, f, syntax.DID(user.Did), pull, patch, sourceRev) } func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) { @@ -192,67 +188,30 @@ func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) { return } - // update the hidden tracking branch to latest - client, err := s.oauth.ServiceClient( - r, - oauth.WithService(forkRepo.Knot), - oauth.WithLxm(tangled.RepoHiddenRefNSID), - oauth.WithDev(s.config.Core.Dev), - ) - if err != nil { - l.Error("failed to connect to knot server", "err", err, "fork_knot", forkRepo.Knot) - return - } + xrpcc := &indigoxrpc.Client{Host: s.config.KnotMirror.Url} - resp, err := tangled.RepoHiddenRef( - r.Context(), - client, - &tangled.RepoHiddenRef_Input{ - ForkRef: pull.PullSource.Branch, - RemoteRef: pull.TargetBranch, - Repo: forkRepo.RepoAt().String(), - }, - ) - if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { - s.logger.Error("failed to set hidden ref", "xrpcerr", xrpcerr, "err", err) - s.pages.Notice(w, "resubmit-error", xrpcerr.Error()) - return - } - if !resp.Success { - l.Error("failed to update tracking ref", "err", resp.Error, "fork_ref", pull.PullSource.Branch, "remote_ref", pull.TargetBranch) - s.pages.Notice(w, "resubmit-error", "Failed to update tracking ref.") - return - } - - hiddenRef := fmt.Sprintf("hidden/%s/%s", pull.PullSource.Branch, pull.TargetBranch) - // extract patch by performing compare - forkXrpcBytes, err := tangled.RepoCompare(r.Context(), s.knotClient(forkRepo.Knot), forkRepo.RepoIdentifier(), hiddenRef, pull.PullSource.Branch) + fpOut, err := tangled.GitTempFormatPatch(r.Context(), xrpcc, pull.RepoAt.String(), forkRepo.RepoAt().String(), pull.TargetBranch, pull.PullSource.Branch) if err != nil { if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { - l.Error("failed to call XRPC repo.compare for fork", "xrpcerr", xrpcerr, "err", err, "hidden_ref", hiddenRef, "source_branch", pull.PullSource.Branch) - s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") + l.Error("failed to call XRPC git.formatPatch", "xrpcerr", xrpcerr, "err", err) + s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - l.Error("failed to compare branches", "err", err, "hidden_ref", hiddenRef, "source_branch", pull.PullSource.Branch) - s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") + l.Error("failed to run format-patch", "err", err) + s.pages.Notice(w, "pull", err.Error()) return } - var forkComparison types.RepoFormatPatchResponse - if err := json.Unmarshal(forkXrpcBytes, &forkComparison); err != nil { - l.Error("failed to decode XRPC compare response for fork", "err", err) - s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") + if fpOut.Rev2 == nil { + l.Error("failed to parse git.formatPatch output", "err", "rev2 is missing") + s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") return } - // Use the fork comparison we already made - comparison := forkComparison - - sourceRev := comparison.Rev2 - patch := comparison.FormatPatchRaw - combined := comparison.CombinedPatchRaw + sourceRev := *fpOut.Rev2 + patch := fpOut.Patch - s.resubmitPullHelper(w, r, f, syntax.DID(user.Did), pull, patch, combined, sourceRev) + s.resubmitPullHelper(w, r, f, syntax.DID(user.Did), pull, patch, sourceRev) } func (s *Pulls) resubmitPullHelper( @@ -262,7 +221,6 @@ func (s *Pulls) resubmitPullHelper( userDid syntax.DID, pull *models.Pull, patch string, - combined string, sourceRev string, ) { l := s.logger.With("handler", "resubmitPullHelper", "user", userDid, "pull_id", pull.PullId, "target_branch", pull.TargetBranch) @@ -296,7 +254,6 @@ func (s *Pulls) resubmitPullHelper( newRoundNumber := len(pull.Submissions) newPatch := patch newSourceRev := sourceRev - combinedPatch := combined client, err := s.oauth.AuthorizedClient(r) if err != nil { @@ -340,7 +297,7 @@ func (s *Pulls) resubmitPullHelper( return } - err = db.ResubmitPull(s.db, pullAt, newRoundNumber, newPatch, combinedPatch, newSourceRev, blob.Blob) + err = db.ResubmitPull(s.db, pullAt, newRoundNumber, newPatch, newSourceRev, blob.Blob) if err != nil { l.Error("failed to resubmit pull request in database", "err", err, "round_number", newRoundNumber) s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") @@ -543,7 +500,6 @@ func (s *Pulls) resubmitStackedPullHelper( pullAt := op.AtUri() newRoundNumber := len(op.Submissions) newPatch := np.LatestPatch() - combinedPatch := np.LatestSubmission().Combined newSourceRev := np.LatestSha() blob, err := xrpc.RepoUploadBlob(r.Context(), client, gz(newPatch), ApplicationGzip) @@ -554,7 +510,7 @@ func (s *Pulls) resubmitStackedPullHelper( } // create new round - err = db.ResubmitPull(tx, pullAt, newRoundNumber, newPatch, combinedPatch, newSourceRev, blob.Blob) + err = db.ResubmitPull(tx, pullAt, newRoundNumber, newPatch, newSourceRev, blob.Blob) if err != nil { l.Error("failed to update pull in database", "err", err, "pull_id", op.PullId, "round_number", newRoundNumber) s.pages.Notice(w, "pull-resubmit-error", "Failed to resubmit pull request. Try again later.") diff --git a/appview/pulls/single.go b/appview/pulls/single.go index 459699f9..f9e75980 100644 --- a/appview/pulls/single.go +++ b/appview/pulls/single.go @@ -1,6 +1,7 @@ package pulls import ( + "encoding/json" "fmt" "net/http" "slices" @@ -119,6 +120,11 @@ func (s *Pulls) repoPullHelper(w http.ResponseWriter, r *http.Request, interdiff l.Error("failed to parse round id", "err", err, "round_number", roundIdInt) return } + if interdiff && roundIdInt < 1 { + http.Error(w, "bad round id", http.StatusBadRequest) + l.Error("failed to parse round id", "err", err, "round_number", roundIdInt) + return + } var diffOpts types.DiffOpts if d := r.URL.Query().Get("diff"); d == "split" { @@ -197,26 +203,85 @@ func (s *Pulls) repoPullHelper(w http.ResponseWriter, r *http.Request, interdiff } } - patch := pull.Submissions[roundIdInt].CombinedPatch() + ctx := r.Context() + xrpcc := &indigoxrpc.Client{Host: s.config.KnotMirror.Url} + var diff types.DiffRenderer - diff = patchutil.AsNiceDiff(patch, pull.TargetBranch) if interdiff { - currentPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt].CombinedPatch()) - if err != nil { - l.Error("failed to interdiff; current patch malformed", "err", err, "round_number", roundIdInt) - s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; current patch is invalid.") - return + if pull.IsForkBased() { + // calculate interdiff in appview + prevPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt-1].Patch) + if err != nil { + l.Error("failed to interdiff; previous patch malformed", "err", err, "round_number", roundIdInt) + s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; previous patch is invalid.") + return + } + currPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt].Patch) + if err != nil { + l.Error("failed to interdiff; current patch malformed", "err", err, "round_number", roundIdInt) + s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; current patch is invalid.") + return + } + diff = patchutil.Interdiff(prevPatch, currPatch) + } else { + var sourceRepo string + if pull.PullSource != nil && pull.PullSource.RepoAt != nil { + sourceRepo = pull.PullSource.RepoAt.String() + } + xrpcBytes, err := tangled.GitTempInterdiffRevs( + ctx, + xrpcc, + pull.TargetBranch, + pull.Submissions[roundIdInt-1].SourceRev, + pull.Submissions[roundIdInt].SourceRev, + sourceRepo, + pull.RepoAt.String(), + ) + if err != nil { + l.Error("failed to call git.interdiffRevs", "err", err, "round_number", roundIdInt) + s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff.") + return + } + + // NOTE: see comment at knotmirror/xrpc/git_interdiff_revs.go + var out struct{ + Patch1 string + Patch2 string + } + if err := json.Unmarshal(xrpcBytes, &out); err != nil { + l.Error("failed to decode XRPC response", "err", err) + s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff.") + return + } + + diff, err = func() (*patchutil.InterdiffResult, error) { + l.Debug("interdiff", "patch1", out.Patch1, "patch2", out.Patch2) + patch1, err := patchutil.AsDiff(out.Patch1) + if err != nil { + return nil, err + } + patch2, err := patchutil.AsDiff(out.Patch2) + if err != nil { + return nil, err + } + return patchutil.Interdiff(patch1, patch2), nil + }() + if err != nil { + l.Error("failed to interdiff", "err", err, "round_number", roundIdInt) + s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff.") + return + } } - - previousPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt-1].CombinedPatch()) + } else { + // diff from merge-base to pull sourceRev + out, err := tangled.GitTempCompareRevs(ctx, xrpcc, pull.RepoAt.String(), pull.TargetBranch, pull.Submissions[roundIdInt].SourceRev) if err != nil { - l.Error("failed to interdiff; previous patch malformed", "err", err, "round_number", roundIdInt) - s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; previous patch is invalid.") + l.Error("failed to get combined patch", "err", err) + s.pages.Error503(w) return } - - diff = patchutil.Interdiff(previousPatch, currentPatch) + diff = patchutil.AsNiceDiff(out.Patch, pull.TargetBranch) } err = s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{