func submit()

in git-codereview/submit.go [79:153]


func submit(b *Branch, c *Commit) *GerritChange {
	if strings.Contains(strings.ToLower(c.Message), "do not submit") {
		dief("%s: CL says DO NOT SUBMIT", c.ShortHash)
	}

	// Fetch Gerrit information about this change.
	g, err := b.GerritChange(c, "LABELS", "CURRENT_REVISION")
	if err != nil {
		dief("%v", err)
	}

	// Pre-check that this change appears submittable.
	// The final submit will check this too, but it is better to fail now.
	if err = submitCheck(g); err != nil {
		dief("cannot submit: %v", err)
	}

	// Upload most recent revision if not already on server.

	if c.Hash != g.CurrentRevision {
		run("git", "push", "-q", "origin", b.PushSpec(c))

		// Refetch change information.
		g, err = b.GerritChange(c, "LABELS", "CURRENT_REVISION")
		if err != nil {
			dief("%v", err)
		}
	}

	if *noRun {
		printf("stopped before submit")
		return g
	}

	// Otherwise, try the submit. Sends back updated GerritChange,
	// but we need extended information and the reply is in the
	// "SUBMITTED" state anyway, so ignore the GerritChange
	// in the response and fetch a new one below.
	if err := gerritAPI("/a/changes/"+fullChangeID(b, c)+"/submit", []byte(`{"wait_for_merge": true}`), nil); err != nil {
		dief("cannot submit: %v", err)
	}

	// It is common to get back "SUBMITTED" for a split second after the
	// request is made. That indicates that the change has been queued for submit,
	// but the first merge (the one wait_for_merge waited for)
	// failed, possibly due to a spurious condition. We see this often, and the
	// status usually changes to MERGED shortly thereafter.
	// Wait a little while to see if we can get to a different state.
	const steps = 6
	const max = 2 * time.Second
	for i := 0; i < steps; i++ {
		time.Sleep(max * (1 << uint(i+1)) / (1 << steps))
		g, err = b.GerritChange(c, "LABELS", "CURRENT_REVISION")
		if err != nil {
			dief("waiting for merge: %v", err)
		}
		if g.Status != "SUBMITTED" {
			break
		}
	}

	switch g.Status {
	default:
		dief("submit error: unexpected post-submit Gerrit change status %q", g.Status)

	case "MERGED":
		// good

	case "SUBMITTED":
		// see above
		dief("cannot submit: timed out waiting for change to be submitted by Gerrit")
	}

	return g
}