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
}