Files
gerrit/java/com
Gal Paikin 653a8528f6 Support Revert Submission with rebasing on previous reverts
This is another step in the implementation of Revert Submission
initiated in change I7188c0d52.

Now instead of just reverting all changes normally, we revert the
changes and then rebase them on top of the most recent revert change,
when needed.
These are the steps we take:

1. Loop over all of the projects in that submission, and for each
project we loop over all of the branches in the submission.
For each project + branch, the changes are reverted in topological
ordering.
This means if A is a parent of B, we ensure that B is reverted before A.
For each change we do either Option A or Option B:

Option A:
If this is the first change that should be reverted in that project
+ branch, we revert the change normally, and remember the created revert
change so that it can be used as base when we continue with the next
change. Then, continue to the next change in the list.

Option B:
Otherwise, if this change is not the first one that should be reverted
in that project + branch, it is reverted on top of the last revert
change which was created for the project / branch That means we now:
1. Revert the change, but only by creating a commit, without creating
a change. This is useful because we don't want to create an unnecessary
change that should be deleted after the relevant cherry-pick.
2. Do the following as a BatchUpdate:
2.1. Create the cherry-pick of the revert-commit. The first
cherry-pick of that project + branch will be done on top of the most
recent change of that submission, and then it will stack on top of
the latest revert created. E.g, the second revert will be on top of the
first revert. Special case with merge commits described below.
2.2. Post the Revert message on the original change that points to the
newly created revert change with PostRevertedMessageOp.
2.3. Notify whoever subscribed to notifications on the reverted change
with NotifyOp.

And then finally:
As a response return the list of revert changes as ChangeInfos

Special case - merge commit:
A special case that involves merge commits can happen if the submission
contains multiple changes for the same project and branch which are not
part of the same change series, and if the submit strategy is
"MERGE_ALWAYS" or "MERGE_IF_NECESSARY".
In case of merge commit, the revert is done on top of the merge commit.
There is a getBase() method which purpose is to find the base that the
first revert of a project + branch should be based on.
The function goes over all commits (of the branches that were updated by
the submission) in topological order by BFS (Breadth first search) until
it finds a commit that is part of the submission or finds a merge commit
that only has parent commits that belong to the changes that are part of
the submission (or other merge commits that satisfy that condition).
If it finds a commit that is part of the submission, we just return it,
since it's the same as the one found by WalkSorter earlier to be the
first one topologically.
Otherwise, we return the first merge commit that satisfy that condition.

Examples:
1. Submission that contains only a single change will have the same
behavior as performing a regular revert. The topic will also be set to
'Revert-<submission-ID>-<RandomString>.
2. The submission contains parent changes:
The changes are reverted in topological order, starting from the most
recent change. The first revert is regular revert and its parent change
is reverted on to of the revert change.
Afterwards, all other reverts would have as parent the last created
revert change (E.g A->B->C would have C's revert on top of C, and then B's
revert would be on top of C's revert, and so on).
3. The submission contains changes from multiple branches of the same
repository: loop over all of the branches and revert the changes from
that branch independently as in example 2. The parent of the first
revert should be the most recent change of that branch.
4. The submission contains changes from multiple repositories: Same as
different branches, essentially.
5. The submission contains a merge commit:
The revert changes are created on top of the  merge commit, which will be
found as described in the special case above. In case of a merge commit,
we will always need to rebase on top of the merge commit.

Change-Id: I220ae8ef23022af8f16305d920f311c98ff5eaf9
2019-12-16 13:08:42 +01:00
..