// 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, review review.Review) {
	revision := review.Revision
	req := review.Request

	// If this revision has been previously closed shortcut all processing
	if closedRevisionsMap[revision] {
		return
	}
	existingReviews := arc.listDifferentialReviewsOrDie(revision)
	if review.Submitted {
		// The change has already been merged in, so we should simply close any open reviews.
		for _, differentialReview := range existingReviews {
			if !differentialReview.isClosed() {
				differentialReview.close()
			}
		}
		closedRevisionsMap[revision] = true
		return
	}

	base, err := review.GetBaseCommit()
	if err != nil {
		// There are lots of reasons that we might not be able to compute a base commit,
		// (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 base commit", req)
		return
	}

	head, err := review.GetHeadCommit()
	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 _, existing := range existingReviews {
			arc.updateReviewDiffs(repo, existing, head, req, review)
		}
		return
	}

	diff, err := arc.createDifferentialDiff(repo, base, 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(revision)
	for _, existing := range existingReviews {
		arc.updateReviewDiffs(repo, existing, head, req, review)
	}
}