Allow revert by submission

When a change in Gerrit is submitted, it's possible that the submission
includes other changes:
1. Open parent changes (unless the submit type is cherry-pick).
2. Open changes with the same topic (if change.submitWholeTopic in
gerrit.config is set to true). Those changes with the same topic could
be in different repositories or different branches.

If the submission of a change introduced an issue, users often revert
the change to resolve the issue, but this may cause breakages if the
change had been submitted together with other changes. Usually changes
that are submitted together depend on each other, so that reverting
only one of the changes breaks the other changes. Hence if a submission
contains multiple changes, one needs to revert all of the changes which
have been submitted together. At the moment this can only be done by
calling the Revert Change REST endpoint for each of the changes one by
one.

The new Revert by Submission REST endpoint allows to revert all changes
of a submission. Since we don't have REST resources that represent
submissions, the REST endpoint is offered on change level, meaning that
this change and all changes that have been submitted together with this
change should be reverted. It's a new REST endpoint, rather than a new
flag for the existing Revert Change REST endpoint, because it needs to
return a set of revert changes which can't be done from the Revert
Change REST endpoint without breaking backwards compatibility (the
result of the existing Revert Change REST endpoint is a single change).

The only functionality added here is the ability to revert all
changes with a single button. However, the changes will not be rebased on
top of each other so the users may need to rebase them manually to make
them submittable.

The Revert by Submission REST endpoint has the following steps:
1. Check that the change for which the Revert by Submission endpoint is
invoked is merged. A change that is not merged does not have a submission
ID and thus we can't revert the submission of such change.
2. Find all changes that were submitted together: For this we take the
submission ID of the change on which the REST endpoint was invoked and
query for all changes with this submission ID. The ID of a submission is
already contained in the change index and internally we can easily query
changes by it (although querying changes by submission ID is not exposed
to users).
3. Next we make all necessary validations such as permission
validations, and ensuring the existence of all the changes.
4. Revert all changes one by one using the Revert REST endpoint. Each
newly created change will have a topic that was given by the user, or a
default "revert-<submission_id>-<random_string_of_size_10>".

What happens when users revert the same submission twice?
- Duplicate revert changes are created but they will have different
unique topics.

What if a submission contains a single change?
- The result is similar to the result of the Revert Change REST endpoint.
The only difference is that the topic of the revert change is set to
'revert-<submission-id>-<random_string_of_size_10>'.

Next steps:
* Optionally, when the revert submission is finished, the user should
see a list of the revert changes.
* When reverting a submission through the UI, the user should insert
the reason for reverting this submission.
* [Optional] Revert Submission action should show a preview of the
changes that are going to be reverted.
* Make the reverts stack on top of each other when in the same branch
and in the same repository. It should always succeed since it will not
rebase on top of the destination branch.
* Add an option to rebase automatically on top of the destination
branch.
* [Optional] Add an option for interactive revert that allows the user
to resolve conflicts when occur (similar to interactive rebase).
* Create all reverts in a single batch. This way we also avoid multiple
permissions checks.
* [Google only] Consider using sharded computation, similar to submitting
together multiple changes across multiple repositories.

Change-Id: I7188c0d520afa669fd78309c39d44656c38259dd
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 6b8281a..10fb741 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -1501,6 +1501,90 @@
   change is new
 ----
 
+[[revert-submission]]
+=== Revert Submission
+--
+'POST /changes/link:#change-id[\{change-id\}]/revert_submission'
+--
+
+Creates open revert changes for all of the changes of a certain submission.
+
+Details for the revert can be specified in the request body inside a link:#revert-input[
+RevertInput] The topic of all created revert changes will be
+`revert-{submission_id}-{random_string_of_size_10}`.
+
+The changes will not be rebased on onto the destination branch so the users may still
+have to manually rebase them to resolve conflicts and make them submittable.
+
+.Request
+----
+  POST /changes/myProject~master~I1ffe09a505e25f15ce1521bcfb222e51e62c2a14/revert_submission HTTP/1.0
+----
+
+As response link:#revert-submission-info[RevertSubmissionInfo] entity
+is returned. That entity describes the revert changes.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  "revert_changes":
+    [
+      {
+        "id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940",
+        "project": "myProject",
+        "branch": "master",
+        "topic": "revert--1571043962462-3640749-ABCEEZGHIJ",
+        "change_id": "I8473b95934b5732ac55d26311a706c9c2bde9940",
+        "subject": "Revert \"Implementing Feature X\"",
+        "status": "NEW",
+        "created": "2013-02-01 09:59:32.126000000",
+        "updated": "2013-02-21 11:16:36.775000000",
+        "mergeable": true,
+        "insertions": 6,
+        "deletions": 4,
+        "_number": 3965,
+        "owner": {
+          "name": "John Doe"
+        }
+      },
+      {
+        "id": "anyProject~master~1eee2c9d8f352483781e772f35dc586a69ff5646",
+        "project": "anyProject",
+        "branch": "master",
+        "topic": "revert--1571043962462-3640749-ABCEEZGHIJ",
+        "change_id": "I1eee2c9d8f352483781e772f35dc586a69ff5646",
+        "subject": "Revert \"Implementing Feature Y\"",
+        "status": "NEW",
+        "created": "2013-02-04 09:59:33.126000000",
+        "updated": "2013-02-21 11:16:37.775000000",
+        "mergeable": true,
+        "insertions": 62,
+        "deletions": 11,
+        "_number": 3966,
+        "owner": {
+          "name": "Jane Doe"
+        }
+      }
+    ]
+----
+
+If any of the changes cannot be reverted because the change state doesn't
+allow reverting the change, the response is "`409 Conflict`" and
+the error message is contained in the response body.
+
+.Response
+----
+  HTTP/1.1 409 Conflict
+  Content-Disposition: attachment
+  Content-Type: text/plain; charset=UTF-8
+
+  change is new
+----
+
 [[submit-change]]
 === Submit Change
 --
@@ -6931,8 +7015,22 @@
 Additional information about whom to notify about the revert as a map
 of recipient type to link:#notify-info[NotifyInfo] entity.
 |`topic`         |optional|
-Name of the topic for the revert change. If not set, the default is the topic
-of the change being reverted.
+Name of the topic for the revert change. If not set, the default for Revert
+endpoint is the topic of the change being reverted, and the default for the
+RevertSubmission endpoint is `revert-{submission_id}-{timestamp.now}`.
+|===========================
+
+[[revert-submission-info]]
+=== RevertSubmissionInfo
+The `RevertSubmissionInfo` describes the revert changes.
+
+[options="header",cols="1,6"]
+|===========================
+|Field Name       | Description
+|`revert_changes` |
+A list of #change-info[ChangeInfo] that describes the revert
+changes. Each entity in that list is a revert change that was created in that
+revert submission.
 |=============================
 
 [[review-info]]