// updateReviewDiffs updates the status of a differential review so that it matches the state of the repo. // // This consists of making sure the latest commit pushed to the review ref has a corresponding // diff in the differential review. func (arc Arcanist) updateReviewDiffs(repo repository.Repo, review differentialReview, headCommit string, req request.Request, comments map[string]comment.Comment) { if review.isClosed() { return } headRevision := repository.Revision(headCommit) mergeBase, err := repo.GetMergeBase(repository.Revision(req.TargetRef), headRevision) if err != nil { // This can happen if the target ref has been deleted while we were performing the updates. return } for _, hashPair := range review.Hashes { if len(hashPair) == 2 && hashPair[0] == commitHashType && hashPair[1] == headCommit { // The review already has the hash of the HEAD commit, so we have nothing to do beyond mirroring comments // and build status if applicable arc.mirrorCommentsIntoReview(repo, review, comments) return } } diff, err := arc.createDifferentialDiff(repo, mergeBase, headRevision, req, review.Diffs) if err != nil { log.Fatal(err) } if diff == nil { // This means that phabricator silently refused to create the diff. Just move on. return } updateRequest := differentialUpdateRevisionRequest{ID: review.ID, DiffID: strconv.Itoa(diff.ID)} var updateResponse differentialUpdateRevisionResponse runArcCommandOrDie("differential.updaterevision", updateRequest, &updateResponse) if updateResponse.Error != "" { log.Fatal(updateResponse.ErrorMessage) } }
// EnsureRequestExists runs the "arcanist" command-line tool to create a Differential diff for the given request, if one does not already exist. func (arc Arcanist) EnsureRequestExists(repo repository.Repo, revision repository.Revision, req request.Request, comments map[string]comment.Comment) { // If this revision has been previously closed shortcut all processing if closedRevisionsMap[revision] { return } mergeBase, err := repo.GetMergeBase(repository.Revision(req.TargetRef), revision) if err != nil { // There are lots of reasons that we might not be able to compute a merge base, // (e.g. the revision already being merged in, or being dropped and garbage collected), // but they all indicate that the review request is no longer valid. log.Printf("Ignoring review request '%v', because we could not compute a merge base", req) return } existingReviews := arc.listDifferentialReviewsOrDie(req.ReviewRef, revision) if mergeBase == revision { // The change has already been merged in, so we should simply close any open reviews. for _, review := range existingReviews { if !review.isClosed() { review.close() } } closedRevisionsMap[revision] = true return } headDetails, err := repo.GetDetails(repository.Revision(req.ReviewRef)) if err != nil { // The given review ref has been deleted (or never existed), but the change wasn't merged. // TODO(ojarjur): We should mark the existing reviews as abandoned. log.Printf("Ignoring review because the review ref '%s' does not exist", req.ReviewRef) return } if len(existingReviews) > 0 { // The change is still pending, but we already have existing reviews, so we should just update those. for _, review := range existingReviews { arc.updateReviewDiffs(repo, review, headDetails.Commit, req, comments) } return } diff, err := arc.createDifferentialDiff(repo, mergeBase, revision, req, []string{}) if err != nil { log.Fatal(err) } if diff == nil { // The revision is already merged in, ignore it. return } rev, err := arc.createDifferentialRevision(repo, revision, diff.ID, req) if err != nil { log.Fatal(err) } log.Printf("Created diff %v and revision %v for the review of %s", diff, rev, revision) // If the review already contains multiple commits by the time we mirror it, then // we need to ensure that at least the first and last ones are added. existingReviews = arc.listDifferentialReviewsOrDie(req.ReviewRef, revision) for _, review := range existingReviews { arc.updateReviewDiffs(repo, review, headDetails.Commit, req, comments) } }