Add a helper for assigning commits to groups heuristically

Implement a GroupCollector helper that observes all commits processed,
e.g. during the main ReceiveCommits RevWalk, and assigns them to
groups using a set of heuristics.

The general idea is that the group for a commit is the SHA-1 of the
rootmost commit of an open change reachable from the tip of the push.
This rootmost commit may be a new patch set, in which case the group
is that commit's SHA-1; or it may be an existing patch set, in which
case the group is that patch set's group. (Note that the patch
set's group might be the commit of a merged change--that is ok, and
can in fact prove useful to link related changes together even when
some have been merged.)

When merge commits are involved, we try to choose a single group and
use it for all ancestors along all parent paths, such that all
not-yet-seen ancestors of a merge end up in the same group. This
doesn't always work out, and there are some corner cases where we
assign multiple groups to a merge commit as a result.

The actual rules for assigning commits to groups are subtle and
explained in detail in the GroupCollector javadoc. The tests are
intended to be readable and may be more intuitive and illuminating
than an explanation of the rules.

Change-Id: Ib00dbf1eecaf61a53facb3a77ff1f8b5c0577b26
2 files changed