Add idForNewChange parameter for cherry-picking a change
Add capability when performing the cherry-pick change method to
specify the numeric change-id of the new change that is to be created.
Cherry-pick is also possible to an existing change, and it will just
create a new patchset; in this case, we check to see that the inputs
given to the function agree with the Change-Id and the Id of that
change, otherwise we throw an error.
This change is useful when performing a batchUpdate. When performing a
batchUpdate it is necessary to know the numeric change id in advance, so
without passing the numeric change id as a parameter it will not be
possible to perform a batchUpdate with both the cherry-pick and any
other update that involves the newly created change (e.g sending
notifications).
Change-Id: I156d30ff719106041f499f0e73b456478f1e1e97
diff --git a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
index 1973b00..35ede48 100644
--- a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
@@ -170,6 +170,7 @@
dest,
null,
null,
+ null,
null);
}
@@ -204,7 +205,16 @@
throws IOException, InvalidChangeOperationException, IntegrationException, UpdateException,
RestApiException, ConfigInvalidException, NoSuchProjectException {
return cherryPick(
- batchUpdateFactory, sourceChange, project, sourceCommit, input, dest, null, null, null);
+ batchUpdateFactory,
+ sourceChange,
+ project,
+ sourceCommit,
+ input,
+ dest,
+ null,
+ null,
+ null,
+ null);
}
/**
@@ -223,12 +233,15 @@
* @param revertedChange The id of the change that is reverted. This is used for the "revertOf"
* field to mark the created cherry pick change as "revertOf" the original change that was
* reverted.
- * @param changeIdForNewChange The Change-Id that the new change that of the cherry pick will
- * have.
+ * @param changeIdForNewChange The Change-Id that the new change of the cherry pick will have.
+ * @param idForNewChange The ID that the new change of the cherry pick will have. If provided and
+ * the cherry-pick doesn't result in creating a new change, then
+ * InvalidChangeOperationException is thrown.
* @return Result object that describes the cherry pick.
* @throws IOException Unable to open repository or read from the database.
* @throws InvalidChangeOperationException Parent or branch don't exist, or two changes with same
- * key exist in the branch.
+ * key exist in the branch. Also thrown when idForNewChange is not null but cherry-pick only
+ * creates a new patchset rather than a new change.
* @throws IntegrationException Merge conflict or trees are identical after cherry pick.
* @throws UpdateException Problem updating the database using batchUpdateFactory.
* @throws RestApiException Error such as invalid SHA1
@@ -244,7 +257,8 @@
BranchNameKey dest,
@Nullable String topic,
@Nullable Change.Id revertedChange,
- @Nullable ObjectId changeIdForNewChange)
+ @Nullable ObjectId changeIdForNewChange,
+ @Nullable Change.Id idForNewChange)
throws IOException, InvalidChangeOperationException, IntegrationException, UpdateException,
RestApiException, ConfigInvalidException, NoSuchProjectException {
@@ -336,7 +350,19 @@
Change.Id changeId;
if (destChanges.size() == 1) {
// The change key exists on the destination branch. The cherry pick
- // will be added as a new patch set.
+ // will be added as a new patch set. If "idForNewChange" is not null we must fail,
+ // since we are not expecting an already existing change.
+ if (idForNewChange != null) {
+ throw new InvalidChangeOperationException(
+ String.format(
+ "Expected that cherry-pick of commit %s with Change-Id %s to branch %s"
+ + "in project %s creates a new change, but found existing change %d",
+ sourceCommit.getName(),
+ changeKey,
+ dest.branch(),
+ dest.project(),
+ destChanges.get(0).getId().get()));
+ }
changeId = insertPatchSet(bu, git, destChanges.get(0).notes(), cherryPickCommit);
} else {
// Change key not found on destination branch. We can create a new
@@ -356,7 +382,8 @@
sourceChange,
sourceCommit,
input,
- revertedChange);
+ revertedChange,
+ idForNewChange);
}
bu.execute();
return Result.create(changeId, cherryPickCommit.getFilesWithGitConflicts());
@@ -436,9 +463,10 @@
@Nullable Change sourceChange,
@Nullable ObjectId sourceCommit,
CherryPickInput input,
- @Nullable Change.Id revertOf)
+ @Nullable Change.Id revertOf,
+ @Nullable Change.Id idForNewChange)
throws IOException {
- Change.Id changeId = Change.id(seq.nextChangeId());
+ Change.Id changeId = idForNewChange != null ? idForNewChange : Change.id(seq.nextChangeId());
ChangeInserter ins = changeInserterFactory.create(changeId, cherryPickCommit, refName);
ins.setRevertOf(revertOf);
BranchNameKey sourceBranch = sourceChange == null ? null : sourceChange.getDest();