func updateReviewStatus()

in cmd/cl/cl.go [243:346]


func updateReviewStatus(cl *CL, gerritAccounts *GerritAccounts) {
	var initialReviewer, firstResponder string

	cl.scores = map[string]int{}

	authorEmail, err := gerritAccounts.LookupByGerritEmail(cl.gerritCL.Metas[0].Commit.Author.Email(), true)
	if err != nil {
		return // We can't resolve the author.
	}

	// Find the initial reviewer, and the first responder (always exclude the author in both cases).
	// Also update the scores map.
	for _, meta := range cl.gerritCL.Metas {
		if firstResponder == "" {
			responder, err := gerritAccounts.LookupByGerritEmail(meta.Commit.Author.Email(), true)
			if err == nil && responder.Email != authorEmail.Email {
				firstResponder = responder.Email
			}
		}

		if meta.Commit.Reviewer == nil {
			continue
		}

		reviewer, err := gerritAccounts.LookupByGerritEmail(meta.Commit.Reviewer.Email(), true)
		if err != nil {
			continue
		}

		codeReviewIdx := strings.Index(meta.Commit.Msg, tagCodeReview)

		if codeReviewIdx > 0 {
			prefix := len(tagCodeReview)
			// Extract and convert the point(s). This line takes the form "Label: Code-Review=+1".
			val, err := strconv.Atoi(meta.Commit.Msg[codeReviewIdx+prefix : codeReviewIdx+prefix+2])
			if err == nil {
				cl.scores[reviewer.Email] = val
			}
		}

		if initialReviewer == "" && reviewer.Email != "" && authorEmail.Email != reviewer.Email {
			initialReviewer = reviewer.Email
		}
	}

	if initialReviewer != "" {
		cl.reviewerEmail = initialReviewer
	}

	// maybe sets the reviewerEmail if it's not set yet.
	maybe := func(who string) {
		// The initial reviewer always gets the highest priority.
		if cl.reviewerEmail == "" || who == initialReviewer {
			cl.reviewerEmail = who
		}
	}

	// Determine reviewer, in priority order.

	// 1. Anyone who -2'ed the CL.
	for who, score := range cl.scores {
		if score == -2 {
			maybe(who)
		}
	}

	// 2. Anyone who +2'ed the CL.
	for who, score := range cl.scores {
		if score == +2 {
			maybe(who)
		}
	}

	// 3. Whoever responds first.
	if firstResponder != "" {
		maybe(firstResponder)
	}

	// Now that we know who the reviewer is,
	// figure out whether the CL is in need of review
	// (or else is waiting for the author to do more work).
	for _, meta := range cl.gerritCL.Metas {
		if meta.Commit.Author == nil { // Happens for Gerrit-generated messages.
			continue
		}

		accountInfo, err := gerritAccounts.LookupByGerritEmail(meta.Commit.Author.Email(), true)
		if err != nil {
			continue
		}

		if strings.Contains(meta.Commit.Msg, "Uploaded patch set ") || accountInfo.Email != cl.reviewerEmail {
			cl.needsReview = true
			cl.needsReviewChanged = meta.Commit.CommitTime
		}

		if accountInfo.Email == cl.reviewerEmail {
			cl.needsReview = false
			cl.needsReviewChanged = meta.Commit.CommitTime
		}
	}

	// TODO: Support do not review, close, and postpone to next go release
}