Add new REST api for creating a merge patch set for change
Previously, we have a new feature that allow creating a new merge change
(C2PS1) by merge a change(C1PS1) into a branch (release). If the
original change (C1) is updated (C1PS2), the merged change also need to
update (C2PS2) with a new merge with the updated change.
master: C1PS1 -> C1PS2
\ \
release: C2PS1 -> C2PS2
Without this new merge patch set API, user have to abandon the old merge
change(C2PS1) and then create a new merge change (C3PS1).
REST api at `POST /changes/{change-id}/merge` and take a
MergePatchSetInput.
Change-Id: Ia3ba1bc5ff30920d1f8270f4fe28ccd7da7ed2a9
This commit is contained in:
@@ -517,6 +517,61 @@ describes the change.
|
||||
}
|
||||
----
|
||||
|
||||
[[create-merge-patch-set-for-change]]
|
||||
=== Create Merge Patch Set For Change
|
||||
--
|
||||
'POST /changes/link:#change-id[\{change-id\}]/merge'
|
||||
--
|
||||
|
||||
Update an existing change by using a
|
||||
link:#merge-patch-set-input[MergePatchSetInput] entity.
|
||||
|
||||
Gerrit will create a merge commit based on the information of
|
||||
MergePatchSetInput and add a new patch set to the change corresponding
|
||||
to the new merge commit.
|
||||
|
||||
.Request
|
||||
----
|
||||
POST /changes/test~master~Ic5466d107c5294414710935a8ef3b0180fb848dc/merge HTTP/1.0
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
{
|
||||
"source": "refs/12/1234/1"
|
||||
}
|
||||
----
|
||||
|
||||
As response a link:#change-info[ChangeInfo] entity with current revision is
|
||||
returned that describes the resulting change.
|
||||
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"id": "test~master~Ic5466d107c5294414710935a8ef3b0180fb848dc",
|
||||
"project": "test",
|
||||
"branch": "master",
|
||||
"hashtags": [],
|
||||
"change_id": "Ic5466d107c5294414710935a8ef3b0180fb848dc",
|
||||
"subject": "Merge dev_branch into master",
|
||||
"status": "NEW",
|
||||
"created": "2016-09-23 18:08:53.238000000",
|
||||
"updated": "2016-09-23 18:09:25.934000000",
|
||||
"submit_type": "MERGE_IF_NECESSARY",
|
||||
"mergeable": true,
|
||||
"insertions": 5,
|
||||
"deletions": 0,
|
||||
"_number": 72,
|
||||
"owner": {
|
||||
"_account_id": 1000000
|
||||
},
|
||||
"current_revision": "27cc4558b5a3d3387dd11ee2df7a117e7e581822"
|
||||
}
|
||||
----
|
||||
|
||||
[[get-change-detail]]
|
||||
=== Get Change Detail
|
||||
--
|
||||
@@ -5363,6 +5418,25 @@ The strategy of the merge, can be `recursive`, `resolve`,
|
||||
`simple-two-way-in-core`, `ours` or `theirs`, default will use project settings.
|
||||
|============================
|
||||
|
||||
[[merge-patch-set-input]]
|
||||
=== MergePatchSetInput
|
||||
The `MergePatchSetInput` entity contains information about updating a new
|
||||
change by creating a new merge commit.
|
||||
|
||||
[options="header",cols="1,^1,5"]
|
||||
|==================================
|
||||
|Field Name ||Description
|
||||
|`subject` |optional|
|
||||
The new subject for the change, if not specified, will reuse the current patch
|
||||
set's subject
|
||||
|`inheritParent` |optional, default to `false`|
|
||||
Use the current patch set's first parent as the merge tip when set to `true`.
|
||||
Otherwise, use the current branch tip of the destination branch.
|
||||
|`merge` ||
|
||||
The detail of the source commit for merge as a link:#merge-input[MergeInput]
|
||||
entity.
|
||||
|==================================
|
||||
|
||||
[[move-input]]
|
||||
=== MoveInput
|
||||
The `MoveInput` entity contains information for moving a change to a new branch.
|
||||
|
||||
@@ -61,9 +61,11 @@ import com.google.gerrit.extensions.common.ApprovalInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInput;
|
||||
import com.google.gerrit.extensions.common.ChangeMessageInfo;
|
||||
import com.google.gerrit.extensions.common.MergePatchSetInput;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.common.GitPerson;
|
||||
import com.google.gerrit.extensions.common.LabelInfo;
|
||||
import com.google.gerrit.extensions.common.MergeInput;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
@@ -71,6 +73,7 @@ import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Branch;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.LabelId;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
@@ -1930,6 +1933,86 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
+ r1.getChange().getId().id + ".");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMergePatchSet() throws Exception {
|
||||
PushOneCommit.Result start = pushTo("refs/heads/master");
|
||||
start.assertOkStatus();
|
||||
// create a change for master
|
||||
PushOneCommit.Result r = createChange();
|
||||
r.assertOkStatus();
|
||||
String changeId = r.getChangeId();
|
||||
|
||||
testRepo.reset(start.getCommit());
|
||||
PushOneCommit.Result currentMaster = pushTo("refs/heads/master");
|
||||
currentMaster.assertOkStatus();
|
||||
String parent = currentMaster.getCommit().getName();
|
||||
|
||||
// push a commit into dev branch
|
||||
createBranch(new Branch.NameKey(project, "dev"));
|
||||
PushOneCommit.Result changeA = pushFactory
|
||||
.create(db, user.getIdent(), testRepo, "change A", "A.txt", "A content")
|
||||
.to("refs/heads/dev");
|
||||
changeA.assertOkStatus();
|
||||
MergeInput mergeInput = new MergeInput();
|
||||
mergeInput.source = "dev";
|
||||
MergePatchSetInput in = new MergePatchSetInput();
|
||||
in.merge = mergeInput;
|
||||
in.subject = "update change by merge ps2";
|
||||
gApi.changes().id(changeId).createMergePatchSet(in);
|
||||
ChangeInfo changeInfo = gApi.changes().id(changeId)
|
||||
.get(EnumSet.of(ListChangesOption.ALL_REVISIONS,
|
||||
ListChangesOption.CURRENT_COMMIT,
|
||||
ListChangesOption.CURRENT_REVISION));
|
||||
assertThat(changeInfo.revisions.size()).isEqualTo(2);
|
||||
assertThat(changeInfo.subject).isEqualTo(in.subject);
|
||||
assertThat(
|
||||
changeInfo.revisions.get(changeInfo.currentRevision).commit.parents
|
||||
.get(0).commit).isEqualTo(parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMergePatchSetInheritParent() throws Exception {
|
||||
PushOneCommit.Result start = pushTo("refs/heads/master");
|
||||
start.assertOkStatus();
|
||||
// create a change for master
|
||||
PushOneCommit.Result r = createChange();
|
||||
r.assertOkStatus();
|
||||
String changeId = r.getChangeId();
|
||||
String parent = r.getCommit().getParent(0).getName();
|
||||
|
||||
// advance master branch
|
||||
testRepo.reset(start.getCommit());
|
||||
PushOneCommit.Result currentMaster = pushTo("refs/heads/master");
|
||||
currentMaster.assertOkStatus();
|
||||
|
||||
// push a commit into dev branch
|
||||
createBranch(new Branch.NameKey(project, "dev"));
|
||||
PushOneCommit.Result changeA = pushFactory
|
||||
.create(db, user.getIdent(), testRepo, "change A", "A.txt", "A content")
|
||||
.to("refs/heads/dev");
|
||||
changeA.assertOkStatus();
|
||||
MergeInput mergeInput = new MergeInput();
|
||||
mergeInput.source = "dev";
|
||||
MergePatchSetInput in = new MergePatchSetInput();
|
||||
in.merge = mergeInput;
|
||||
in.subject = "update change by merge ps2 inherit parent of ps1";
|
||||
in.inheritParent = true;
|
||||
gApi.changes().id(changeId).createMergePatchSet(in);
|
||||
ChangeInfo changeInfo = gApi.changes().id(changeId)
|
||||
.get(EnumSet.of(ListChangesOption.ALL_REVISIONS,
|
||||
ListChangesOption.CURRENT_COMMIT,
|
||||
ListChangesOption.CURRENT_REVISION));
|
||||
|
||||
assertThat(changeInfo.revisions.size()).isEqualTo(2);
|
||||
assertThat(changeInfo.subject).isEqualTo(in.subject);
|
||||
assertThat(
|
||||
changeInfo.revisions.get(changeInfo.currentRevision).commit.parents
|
||||
.get(0).commit).isEqualTo(parent);
|
||||
assertThat(
|
||||
changeInfo.revisions.get(changeInfo.currentRevision).commit.parents
|
||||
.get(0).commit).isNotEqualTo(currentMaster.getCommit().getName());
|
||||
}
|
||||
|
||||
private static Iterable<Account.Id> getReviewers(
|
||||
Collection<AccountInfo> r) {
|
||||
return Iterables.transform(r, a -> new Account.Id(a._accountId));
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.google.gerrit.extensions.api.changes;
|
||||
import com.google.gerrit.extensions.client.ListChangesOption;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.MergePatchSetInput;
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.common.EditInfo;
|
||||
import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
|
||||
@@ -95,6 +96,9 @@ public interface ChangeApi {
|
||||
*/
|
||||
ChangeApi revert(RevertInput in) throws RestApiException;
|
||||
|
||||
/** Create a merge patch set for the change. */
|
||||
ChangeInfo createMergePatchSet(MergePatchSetInput in) throws RestApiException;
|
||||
|
||||
List<ChangeInfo> submittedTogether() throws RestApiException;
|
||||
SubmittedTogetherInfo submittedTogether(
|
||||
EnumSet<SubmittedTogetherOption> options) throws RestApiException;
|
||||
@@ -412,5 +416,11 @@ public interface ChangeApi {
|
||||
EnumSet<SubmittedTogetherOption> b) throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeInfo createMergePatchSet(MergePatchSetInput in)
|
||||
throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.extensions.common;
|
||||
|
||||
public class MergePatchSetInput {
|
||||
public String subject;
|
||||
public boolean inheritParent;
|
||||
public MergeInput merge;
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import com.google.gerrit.extensions.api.changes.SubmittedTogetherOption;
|
||||
import com.google.gerrit.extensions.client.ListChangesOption;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.MergePatchSetInput;
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.common.EditInfo;
|
||||
import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
|
||||
@@ -63,7 +64,9 @@ import com.google.gerrit.server.change.Reviewers;
|
||||
import com.google.gerrit.server.change.Revisions;
|
||||
import com.google.gerrit.server.change.SubmittedTogether;
|
||||
import com.google.gerrit.server.change.SuggestChangeReviewers;
|
||||
import com.google.gerrit.server.change.CreateMergePatchSet;
|
||||
import com.google.gerrit.server.git.UpdateException;
|
||||
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
@@ -91,6 +94,7 @@ class ChangeApiImpl implements ChangeApi {
|
||||
private final Abandon abandon;
|
||||
private final Revert revert;
|
||||
private final Restore restore;
|
||||
private final CreateMergePatchSet updateByMerge;
|
||||
private final Provider<SubmittedTogether> submittedTogether;
|
||||
private final PublishDraftPatchSet.CurrentRevision
|
||||
publishDraftChange;
|
||||
@@ -122,6 +126,7 @@ class ChangeApiImpl implements ChangeApi {
|
||||
Abandon abandon,
|
||||
Revert revert,
|
||||
Restore restore,
|
||||
CreateMergePatchSet updateByMerge,
|
||||
Provider<SubmittedTogether> submittedTogether,
|
||||
PublishDraftPatchSet.CurrentRevision publishDraftChange,
|
||||
DeleteDraftChange deleteDraftChange,
|
||||
@@ -151,6 +156,7 @@ class ChangeApiImpl implements ChangeApi {
|
||||
this.suggestReviewers = suggestReviewers;
|
||||
this.abandon = abandon;
|
||||
this.restore = restore;
|
||||
this.updateByMerge = updateByMerge;
|
||||
this.submittedTogether = submittedTogether;
|
||||
this.publishDraftChange = publishDraftChange;
|
||||
this.deleteDraftChange = deleteDraftChange;
|
||||
@@ -267,6 +273,17 @@ class ChangeApiImpl implements ChangeApi {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeInfo createMergePatchSet(MergePatchSetInput in)
|
||||
throws RestApiException {
|
||||
try {
|
||||
return updateByMerge.apply(change, in).value();
|
||||
} catch (IOException | UpdateException | InvalidChangeOperationException
|
||||
| NoSuchChangeException | OrmException e) {
|
||||
throw new RestApiException("Cannot update change by merge", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChangeInfo> submittedTogether() throws RestApiException {
|
||||
SubmittedTogetherInfo info = submittedTogether(
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server.change;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gerrit.common.TimeUtil;
|
||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
|
||||
import com.google.gerrit.extensions.client.ListChangesOption;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.MergePatchSetInput;
|
||||
import com.google.gerrit.extensions.common.MergeInput;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.MergeConflictException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||
import com.google.gerrit.reviewdb.client.Branch;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.PatchSetUtil;
|
||||
import com.google.gerrit.server.git.BatchUpdate;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.git.MergeIdenticalTreeException;
|
||||
import com.google.gerrit.server.git.MergeUtil;
|
||||
import com.google.gerrit.server.git.UpdateException;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gerrit.server.project.ProjectControl;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.util.ChangeIdUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.EnumSet;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@Singleton
|
||||
public class CreateMergePatchSet implements
|
||||
RestModifyView<ChangeResource, MergePatchSetInput> {
|
||||
|
||||
private final Provider<ReviewDb> db;
|
||||
private final GitRepositoryManager gitManager;
|
||||
private final TimeZone serverTimeZone;
|
||||
private final Provider<CurrentUser> user;
|
||||
private final ChangeJson.Factory jsonFactory;
|
||||
private final PatchSetUtil psUtil;
|
||||
private final MergeUtil.Factory mergeUtilFactory;
|
||||
private final BatchUpdate.Factory batchUpdateFactory;
|
||||
private final PatchSetInserter.Factory patchSetInserterFactory;
|
||||
|
||||
@Inject
|
||||
CreateMergePatchSet(Provider<ReviewDb> db,
|
||||
GitRepositoryManager gitManager,
|
||||
@GerritPersonIdent PersonIdent myIdent,
|
||||
Provider<CurrentUser> user,
|
||||
ChangeJson.Factory json,
|
||||
PatchSetUtil psUtil,
|
||||
MergeUtil.Factory mergeUtilFactory,
|
||||
BatchUpdate.Factory batchUpdateFactory,
|
||||
PatchSetInserter.Factory patchSetInserterFactory) {
|
||||
this.db = db;
|
||||
this.gitManager = gitManager;
|
||||
this.serverTimeZone = myIdent.getTimeZone();
|
||||
this.user = user;
|
||||
this.jsonFactory = json;
|
||||
this.psUtil = psUtil;
|
||||
this.mergeUtilFactory = mergeUtilFactory;
|
||||
this.batchUpdateFactory = batchUpdateFactory;
|
||||
this.patchSetInserterFactory = patchSetInserterFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<ChangeInfo> apply(ChangeResource req, MergePatchSetInput in)
|
||||
throws NoSuchChangeException, OrmException, IOException,
|
||||
InvalidChangeOperationException, RestApiException, UpdateException {
|
||||
if (in.merge == null) {
|
||||
throw new BadRequestException("merge field is required");
|
||||
}
|
||||
|
||||
MergeInput merge = in.merge;
|
||||
if (Strings.isNullOrEmpty(merge.source)) {
|
||||
throw new BadRequestException("merge.source must be non-empty");
|
||||
}
|
||||
|
||||
ChangeControl ctl = req.getControl();
|
||||
if (!ctl.isVisible(db.get())) {
|
||||
throw new InvalidChangeOperationException(
|
||||
"Base change not found: " + req.getId());
|
||||
}
|
||||
PatchSet ps = psUtil.current(db.get(), ctl.getNotes());
|
||||
if (!ctl.canAddPatchSet(db.get())) {
|
||||
throw new AuthException("cannot add patch set");
|
||||
}
|
||||
|
||||
ProjectControl projectControl = ctl.getProjectControl();
|
||||
Change change = ctl.getChange();
|
||||
Project.NameKey project = change.getProject();
|
||||
Branch.NameKey dest = change.getDest();
|
||||
try (Repository git = gitManager.openRepository(project);
|
||||
ObjectInserter oi = git.newObjectInserter();
|
||||
RevWalk rw = new RevWalk(oi.newReader())) {
|
||||
|
||||
RevCommit sourceCommit =
|
||||
MergeUtil.resolveCommit(git, rw, merge.source);
|
||||
if (!projectControl.canReadCommit(db.get(), git, sourceCommit)) {
|
||||
throw new ResourceNotFoundException(
|
||||
"cannot find source commit: " + merge.source + " to merge.");
|
||||
}
|
||||
|
||||
RevCommit currentPsCommit =
|
||||
rw.parseCommit(ObjectId.fromString(ps.getRevision().get()));
|
||||
|
||||
Timestamp now = TimeUtil.nowTs();
|
||||
IdentifiedUser me = user.get().asIdentifiedUser();
|
||||
PersonIdent author = me.newCommitterIdent(now, serverTimeZone);
|
||||
|
||||
RevCommit newCommit =
|
||||
createMergeCommit(in, projectControl, dest, git, oi, rw,
|
||||
currentPsCommit, sourceCommit, author,
|
||||
ObjectId.fromString(change.getKey().get().substring(1)));
|
||||
|
||||
PatchSet.Id nextPsId = ChangeUtil.nextPatchSetId(ps.getId());
|
||||
PatchSetInserter psInserter =
|
||||
patchSetInserterFactory.create(ctl, nextPsId, newCommit);
|
||||
try (BatchUpdate bu = batchUpdateFactory
|
||||
.create(db.get(), project, me, now)) {
|
||||
bu.setRepository(git, rw, oi);
|
||||
bu.addOp(ctl.getId(), psInserter
|
||||
.setMessage("Uploaded patch set " + nextPsId.get() + ".")
|
||||
.setDraft(ps.isDraft())
|
||||
.setNotify(NotifyHandling.NONE));
|
||||
bu.execute();
|
||||
}
|
||||
|
||||
ChangeJson json =
|
||||
jsonFactory.create(EnumSet.of(ListChangesOption.CURRENT_REVISION));
|
||||
return Response.ok(json.format(psInserter.getChange()));
|
||||
}
|
||||
}
|
||||
|
||||
private RevCommit createMergeCommit(MergePatchSetInput in,
|
||||
ProjectControl projectControl, Branch.NameKey dest, Repository git,
|
||||
ObjectInserter oi, RevWalk rw, RevCommit currentPsCommit,
|
||||
RevCommit sourceCommit, PersonIdent author, ObjectId changeId)
|
||||
throws ResourceNotFoundException, MergeIdenticalTreeException,
|
||||
MergeConflictException, IOException {
|
||||
|
||||
ObjectId parentCommit;
|
||||
if (in.inheritParent) {
|
||||
// inherit first parent from previous patch set
|
||||
parentCommit = currentPsCommit.getParent(0);
|
||||
} else {
|
||||
// get the current branch tip of destination branch
|
||||
Ref destRef = git.getRefDatabase().exactRef(dest.get());
|
||||
if (destRef != null) {
|
||||
parentCommit = destRef.getObjectId();
|
||||
} else {
|
||||
throw new ResourceNotFoundException("cannot find destination branch");
|
||||
}
|
||||
}
|
||||
RevCommit mergeTip = rw.parseCommit(parentCommit);
|
||||
|
||||
String commitMsg;
|
||||
if (Strings.emptyToNull(in.subject) != null) {
|
||||
commitMsg = ChangeIdUtil.insertId(in.subject, changeId);
|
||||
} else {
|
||||
// reuse previous patch set commit message
|
||||
commitMsg = currentPsCommit.getFullMessage();
|
||||
}
|
||||
|
||||
String mergeStrategy = MoreObjects.firstNonNull(
|
||||
Strings.emptyToNull(in.merge.strategy),
|
||||
mergeUtilFactory.create(projectControl.getProjectState())
|
||||
.mergeStrategyName());
|
||||
|
||||
return MergeUtil.createMergeCommit(git, oi, mergeTip, sourceCommit,
|
||||
mergeStrategy, author, commitMsg, rw);
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ public class Module extends RestApiModule {
|
||||
DynamicMap.mapOf(binder(), VOTE_KIND);
|
||||
|
||||
get(CHANGE_KIND).to(GetChange.class);
|
||||
post(CHANGE_KIND, "merge").to(CreateMergePatchSet.class);
|
||||
get(CHANGE_KIND, "detail").to(GetDetail.class);
|
||||
get(CHANGE_KIND, "topic").to(GetTopic.class);
|
||||
get(CHANGE_KIND, "in").to(IncludedIn.class);
|
||||
|
||||
Reference in New Issue
Block a user