in git-codereview/branch.go [232:318]
func (b *Branch) loadPending() {
if b.loadedPending {
return
}
b.loadedPending = true
// In case of early return.
// But avoid the git exec unless really needed.
b.branchpoint = ""
defer func() {
if b.branchpoint == "" {
b.branchpoint = gitHash("HEAD")
}
}()
if b.DetachedHead() {
return
}
// Note: This runs in parallel with "git fetch -q",
// so the commands may see a stale version of origin/master.
// The use of origin here is for identifying what the branch has
// in common with origin (what's old on the branch).
// Any new commits in origin do not affect that.
// Note: --topo-order means child first, then parent.
origin := b.OriginBranch()
const numField = 9
all := trim(cmdOutput("git", "log", "--topo-order",
"--format=format:%H%x00%h%x00%P%x00%T%x00%B%x00%s%x00%an%x00%ae%x00%at%x00",
origin+".."+b.FullName(), "--"))
fields := strings.Split(all, "\x00")
if len(fields) < numField {
return // nothing pending
}
for i, field := range fields {
fields[i] = strings.TrimLeft(field, "\r\n")
}
Log:
for i := 0; i+numField <= len(fields); i += numField {
parents := strings.Fields(fields[i+2])
c := &Commit{
Hash: fields[i],
ShortHash: fields[i+1],
Parents: parents,
Tree: fields[i+3],
Message: fields[i+4],
Subject: fields[i+5],
AuthorName: fields[i+6],
AuthorEmail: fields[i+7],
AuthorDate: fields[i+8],
}
if len(c.Parents) > 0 {
c.Parent = c.Parents[0]
}
if len(c.Parents) > 1 {
// Found merge point.
// Merges break the invariant that the last shared commit (the branchpoint)
// is the parent of the final commit in the log output.
// If c.Parent is on the origin branch, then since we are reading the log
// in (reverse) topological order, we know that c.Parent is the actual branchpoint,
// even if we later see additional commits on a different branch leading down to
// a lower location on the same origin branch.
// Check c.Merge (the second parent) too, so we don't depend on the parent order.
for _, parent := range c.Parents {
if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", parent), " remotes/"+origin+"\n") {
b.pending = append(b.pending, c)
b.branchpoint = parent
break Log
}
}
}
for _, line := range lines(c.Message) {
// Note: Keep going even if we find one, so that
// we take the last Change-Id line, just in case
// there is a commit message quoting another
// commit message.
// I'm not sure this can come up at all, but just in case.
if strings.HasPrefix(line, "Change-Id: ") {
c.ChangeID = line[len("Change-Id: "):]
}
}
b.pending = append(b.pending, c)
b.branchpoint = c.Parent
}
b.commitsAhead = len(b.pending)
}