Allow rebase with conflicts

So far if a change could not be rebased due to conflicts the Rebase
Change REST endpoint failed with '409 Conflict'. This change adds a new
input option that allows the rebase to succeed even if there are
conflicts. Adding this option e.g. enables third-party integrators to
implement an online editor that allows users to rebase changes and then
resolve conflicts online.

If the new option is set and there are conflicts, the rebase succeeds
and the new patch set is created, the change is set to work-in-progress,
the conflicting files contain git conflict markers and a change message
with the conflicting files is posted. In addition the returned
ChangeInfo has the 'contains_git_conflicts' field set to true so that
callers can detect that there were conflicts. This is consistent with
the same option that change Ib6bc8eedf added for the Create Change and
Create Merge Patch Set REST endpoints. The implementation follows the
example of these existing options, but some things are worth to be
pointed out:

* rebasing with conflicts only works if content merges are enabled
  (see RebaseChangeOp#setForceContentMerge(boolean)):
  - this is always true for the Rebase Change REST endpoint
  - this is not true for Rebases that are automatically done on submit
  - the forceContentMerge decides which Merger is used to create the
    merge commit, if forceContentMerge is true, the created Merger is a
    ResolveMerger, which is the Merger that allows to merge with
    conflicts
* to convey the information about which files have conflicts we need to
  create a CodeReviewCommit rather than a RevCommit:
  - to create a CodeReviewCommit we need a CodeReviewRevWalk, this rev
    walk must be set on the BatchUpdate that executes the rebase
    operation (the rebase operation can then cast the RevWalk from the
    context to CodeReviewRevWalk, this is a bit error prone, but a
    pattern that we already use, e.g. in SubmitStrategyOp)
  - when the rebase operation is used from a submit strategy the RevWalk
    in the context already was a CodeReviewRevWalk, for the Rebase
    Change REST endpoint we are setting it now
* the 'contains_git_conflicts' field in ChangeInfo is only populated in
  the ChangeInfo that is returned by the Rebase Change REST endpoint,
  but not when then ChangeInfo is newly retrieved from the server (this
  is because the information whether the change has conflicts is not
  persisted, which is the same as for the other REST endpoints that
  support this field)
* in the Java API we had to add a new method that exposes the ChangeInfo
  that is returned by the Rebase Change REST endpoint
  (RevisionApi#rebaseAsInfo(RebaseInput)), this follows the example of
  the Changes#createAsInfo(ChangeInput) method

Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: Ie26fbd03b890dd197509ca1fc6133b3ea7151916
This commit is contained in:
Edwin Kempin
2021-01-13 13:51:42 +01:00
parent 1f60e356ee
commit 9a6f054350
8 changed files with 247 additions and 24 deletions

View File

@@ -16,4 +16,12 @@ package com.google.gerrit.extensions.api.changes;
public class RebaseInput {
public String base;
/**
* Whether the rebase should succeed if there are conflicts.
*
* <p>If there are conflicts the file contents of the rebased change contain git conflict markers
* to indicate the conflicts.
*/
public boolean allowConflicts;
}

View File

@@ -68,6 +68,8 @@ public interface RevisionApi {
ChangeApi rebase(RebaseInput in) throws RestApiException;
ChangeInfo rebaseAsInfo(RebaseInput in) throws RestApiException;
boolean canRebase() throws RestApiException;
RevisionReviewerApi reviewer(String id) throws RestApiException;
@@ -217,6 +219,11 @@ public interface RevisionApi {
throw new NotImplementedException();
}
@Override
public ChangeInfo rebaseAsInfo(RebaseInput in) throws RestApiException {
throw new NotImplementedException();
}
@Override
public boolean canRebase() throws RestApiException {
throw new NotImplementedException();

View File

@@ -83,7 +83,8 @@ public class ChangeInfo {
* com.google.gerrit.server.restapi.change.CreateChange}, {@link
* com.google.gerrit.server.restapi.change.CreateMergePatchSet}, {@link
* com.google.gerrit.server.restapi.change.CherryPick}, {@link
* com.google.gerrit.server.restapi.change.CherryPickCommit}
* com.google.gerrit.server.restapi.change.CherryPickCommit}, {@link
* com.google.gerrit.server.restapi.change.Rebase}
*/
public Boolean containsGitConflicts;