Allow editing of commit message from UI.
This change adds a small edit icon on the top right
corner of the commit message box on the change screen.
Clicking it lets the user edit the commit message and a
new patch set will be created.
Change-Id: I2c4d4a3ba520d4c12ade4bb3b47a55ce7f1b19df
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
index f8fdaa3..23969a0 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
@@ -29,6 +29,7 @@
protected AccountInfoCache accounts;
protected boolean allowsAnonymous;
protected boolean canAbandon;
+ protected boolean canEditCommitMessage;
protected boolean canPublish;
protected boolean canRebase;
protected boolean canRestore;
@@ -77,6 +78,14 @@
canAbandon = a;
}
+ public boolean canEditCommitMessage() {
+ return canEditCommitMessage;
+ }
+
+ public void setCanEditCommitMessage(final boolean a) {
+ canEditCommitMessage = a;
+ }
+
public boolean canPublish() {
return canPublish;
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java
index 996eed9..516dba3 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java
@@ -31,6 +31,11 @@
@Audit
@SignInRequired
+ void createNewPatchSet(final PatchSet.Id patchSetId, final String newCommitMessage,
+ final AsyncCallback<ChangeDetail> callback);
+
+ @Audit
+ @SignInRequired
void revertChange(PatchSet.Id patchSetId, String message,
AsyncCallback<ChangeDetail> callback);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index 6f569ff..acd8f86 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -129,6 +129,9 @@
String headingRevertMessage();
String revertChangeTitle();
+ String headingEditCommitMessage();
+ String titleEditCommitMessage();
+
String buttonAbandonChangeBegin();
String buttonAbandonChangeSend();
String headingAbandonMessage();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 788b283..240f9b3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -114,6 +114,9 @@
headingRevertMessage = Revert Commit Message:
revertChangeTitle = Code Review - Revert Merged Change
+headingEditCommitMessage = Commit Message
+titleEditCommitMessage = Create New Patch Set
+
buttonRestoreChangeBegin = Restore Change
restoreChangeTitle = Code Review - Restore Change
headingRestoreMessage = Restore Message:
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java
index 32d92fe..5cd6cdb 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java
@@ -36,9 +36,11 @@
initWidget(hp);
}
- public void display(Change chg, Boolean starred, PatchSetInfo info,
+ public void display(Change chg, Boolean starred, Boolean canEditCommitMessage,
+ PatchSetInfo info,
final AccountInfoCache acc, SubmitTypeRecord submitTypeRecord) {
infoBlock.display(chg, acc, submitTypeRecord);
- messageBlock.display(chg.getId(), starred, info.getMessage());
+ messageBlock.display(chg.currentPatchSetId(), starred,
+ canEditCommitMessage, info.getMessage());
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
index 5868be4..57bbf44 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
@@ -281,6 +281,7 @@
descriptionBlock.display(detail.getChange(),
detail.isStarred(),
+ detail.canEditCommitMessage(),
detail.getCurrentPatchSetDetail().getInfo(),
detail.getAccounts(), detail.getSubmitTypeRecord());
dependsOn.display(detail.getDependsOn());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
index eff3cd5..18b4f0c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
@@ -17,16 +17,22 @@
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.ui.ChangeLink;
import com.google.gerrit.client.ui.CommentLinkProcessor;
+import com.google.gerrit.client.ui.CommentedActionDialog;
+import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.PreElement;
import com.google.gwt.dom.client.Style.Display;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
@@ -60,12 +66,13 @@
}
public void display(final String commitMessage) {
- display(null, null, commitMessage);
+ display(null, null, false, commitMessage);
}
- public void display(Change.Id changeId, Boolean starred, String commitMessage) {
+ public void display(final PatchSet.Id patchSetId,
+ Boolean starred, Boolean canEditCommitMessage, final String commitMessage) {
starPanel.clear();
-
+ Change.Id changeId = patchSetId.getParentKey();
if (changeId != null && starred != null && Gerrit.isSignedIn()) {
StarredChanges.Icon star = StarredChanges.createIcon(changeId, starred);
star.setStyleName(Gerrit.RESOURCES.css().changeScreenStarIcon());
@@ -79,7 +86,33 @@
permalinkPanel.clear();
if (changeId != null) {
permalinkPanel.add(new ChangeLink(Util.C.changePermalink(), changeId));
- permalinkPanel.add(new CopyableLabel(ChangeLink.permalink(changeId), false));
+ permalinkPanel.add(new CopyableLabel(ChangeLink.permalink(changeId),
+ false));
+ if (canEditCommitMessage) {
+ final Image edit = new Image(Gerrit.RESOURCES.edit());
+ edit.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(final ClickEvent event) {
+ new CommentedActionDialog<ChangeDetail>(Util.C
+ .titleEditCommitMessage(), Util.C.headingEditCommitMessage(),
+ new ChangeDetailCache.IgnoreErrorCallback() {}) {
+ {
+ message.setCharacterWidth(80);
+ message.setVisibleLines(20);
+ message.setText(commitMessage);
+ }
+
+ @Override
+ public void onSend() {
+ Util.MANAGE_SVC.createNewPatchSet(patchSetId, getMessageText(),
+ createCallback());
+ }
+ }.center();
+ }
+ });
+
+ permalinkPanel.add(edit);
+ }
}
String[] splitCommitMessage = commitMessage.split("\n", 2);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
index f9d036a..9c45486 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
@@ -274,7 +274,7 @@
private void display(final PatchSetPublishDetail r) {
setPageTitle(Util.M.publishComments(r.getChange().getKey().abbreviate(),
patchSetId.get()));
- descBlock.display(r.getChange(), null, r.getPatchSetInfo(), r.getAccounts(),
+ descBlock.display(r.getChange(), null, false, r.getPatchSetInfo(), r.getAccounts(),
r.getSubmitTypeRecord());
if (r.getChange().getStatus().isOpen()) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
index 7150b67..5418be3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
@@ -154,6 +154,7 @@
detail.setCanRevert(change.getStatus() == Change.Status.MERGED && control.canAddPatchSet());
detail.setCanEdit(control.getRefControl().canWrite());
+ detail.setCanEditCommitMessage(change.getStatus().isOpen() && control.canAddPatchSet());
detail.setCanEditTopicName(control.canEditTopicName());
List<SubmitRecord> submitRecords = control.getSubmitRecords(db, patch);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java
index e04176b..67bd0fd 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java
@@ -17,6 +17,7 @@
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.ChangeManageService;
import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet.Id;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.inject.Inject;
@@ -28,6 +29,7 @@
private final RevertChange.Factory revertChangeFactory;
private final PublishAction.Factory publishAction;
private final DeleteDraftChange.Factory deleteDraftChangeFactory;
+ private final EditCommitMessageHandler.Factory editCommitMessageHandlerFactory;
@Inject
ChangeManageServiceImpl(final SubmitAction.Factory patchSetAction,
@@ -35,13 +37,15 @@
final RestoreChangeHandler.Factory restoreChangeHandlerFactory,
final RevertChange.Factory revertChangeFactory,
final PublishAction.Factory publishAction,
- final DeleteDraftChange.Factory deleteDraftChangeFactory) {
+ final DeleteDraftChange.Factory deleteDraftChangeFactory,
+ final EditCommitMessageHandler.Factory editCommitMessageHandler) {
this.submitAction = patchSetAction;
this.rebaseChangeFactory = rebaseChangeFactory;
this.restoreChangeHandlerFactory = restoreChangeHandlerFactory;
this.revertChangeFactory = revertChangeFactory;
this.publishAction = publishAction;
this.deleteDraftChangeFactory = deleteDraftChangeFactory;
+ this.editCommitMessageHandlerFactory = editCommitMessageHandler;
}
public void submit(final PatchSet.Id patchSetId,
@@ -73,4 +77,9 @@
final AsyncCallback<VoidResult> callback) {
deleteDraftChangeFactory.create(patchSetId).to(callback);
}
+
+ public void createNewPatchSet(Id patchSetId, String message,
+ AsyncCallback<ChangeDetail> callback) {
+ editCommitMessageHandlerFactory.create(patchSetId, message).to(callback);
+ }
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
index d3085aa..fab8a09 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
@@ -28,6 +28,7 @@
install(new FactoryModule() {
@Override
protected void configure() {
+ factory(EditCommitMessageHandler.Factory.class);
factory(RestoreChangeHandler.Factory.class);
factory(RevertChange.Factory.class);
factory(RebaseChangeHandler.Factory.class);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/EditCommitMessageHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/EditCommitMessageHandler.java
new file mode 100644
index 0000000..c2baa6e
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/EditCommitMessageHandler.java
@@ -0,0 +1,112 @@
+// Copyright (C) 2012 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.httpd.rpc.changedetail;
+
+import com.google.gerrit.common.ChangeHooks;
+import com.google.gerrit.common.data.ChangeDetail;
+import com.google.gerrit.common.errors.NoSuchEntityException;
+import com.google.gerrit.httpd.rpc.Handler;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.mail.EmailException;
+import com.google.gerrit.server.patch.PatchSetInfoFactory;
+import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
+import com.google.gerrit.server.project.ChangeControl;
+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;
+import com.google.inject.assistedinject.Assisted;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.PersonIdent;
+
+import java.io.IOException;
+
+import javax.annotation.Nullable;
+
+class EditCommitMessageHandler extends Handler<ChangeDetail> {
+ interface Factory {
+ EditCommitMessageHandler create(PatchSet.Id patchSetId, String message);
+ }
+
+ private final ChangeControl.Factory changeControlFactory;
+ private final ReviewDb db;
+ private final IdentifiedUser currentUser;
+ private final ChangeDetailFactory.Factory changeDetailFactory;
+ private final GitReferenceUpdated replication;
+
+ private final PatchSet.Id patchSetId;
+ @Nullable
+ private final String message;
+
+ private final ChangeHooks hooks;
+
+ private final GitRepositoryManager gitManager;
+ private final PatchSetInfoFactory patchSetInfoFactory;
+
+ private final PersonIdent myIdent;
+
+ @Inject
+ EditCommitMessageHandler(final ChangeControl.Factory changeControlFactory,
+ final ReviewDb db, final IdentifiedUser currentUser,
+ final ChangeDetailFactory.Factory changeDetailFactory,
+ @Assisted final PatchSet.Id patchSetId,
+ @Assisted @Nullable final String message, final ChangeHooks hooks,
+ final GitRepositoryManager gitManager,
+ final PatchSetInfoFactory patchSetInfoFactory,
+ final GitReferenceUpdated replication,
+ @GerritPersonIdent final PersonIdent myIdent) {
+ this.changeControlFactory = changeControlFactory;
+ this.db = db;
+ this.currentUser = currentUser;
+ this.changeDetailFactory = changeDetailFactory;
+
+ this.patchSetId = patchSetId;
+ this.message = message;
+ this.hooks = hooks;
+ this.gitManager = gitManager;
+
+ this.patchSetInfoFactory = patchSetInfoFactory;
+ this.replication = replication;
+ this.myIdent = myIdent;
+ }
+
+ @Override
+ public ChangeDetail call() throws NoSuchChangeException, OrmException,
+ EmailException, NoSuchEntityException, PatchSetInfoNotAvailableException,
+ MissingObjectException, IncorrectObjectTypeException, IOException,
+ InvalidChangeOperationException {
+
+ final Change.Id changeId = patchSetId.getParentKey();
+ final ChangeControl control = changeControlFactory.validateFor(changeId);
+ if (!control.canAddPatchSet()) {
+ throw new InvalidChangeOperationException(
+ "Not allowed to add new Patch Sets to: " + changeId.toString());
+ }
+
+ ChangeUtil.editCommitMessage(patchSetId, currentUser, message, db,
+ hooks, gitManager, patchSetInfoFactory, replication, myIdent);
+
+ return changeDetailFactory.create(changeId).call();
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
index 41a8af1..06213d8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -19,6 +19,7 @@
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.client.TrackingId;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -31,7 +32,10 @@
import com.google.gerrit.server.mail.ReplyToChangeSender;
import com.google.gerrit.server.mail.RevertedSender;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
+import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
+import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gwtorm.server.AtomicUpdate;
import com.google.gwtorm.server.OrmConcurrencyException;
import com.google.gwtorm.server.OrmException;
@@ -293,6 +297,154 @@
}
}
+ public static Change.Id editCommitMessage(final PatchSet.Id patchSetId,
+ final IdentifiedUser user, final String message, final ReviewDb db,
+ final ChangeHooks hooks, GitRepositoryManager gitManager,
+ final PatchSetInfoFactory patchSetInfoFactory,
+ final GitReferenceUpdated replication, PersonIdent myIdent)
+ throws NoSuchChangeException, EmailException, OrmException,
+ MissingObjectException, IncorrectObjectTypeException, IOException,
+ InvalidChangeOperationException, PatchSetInfoNotAvailableException {
+ final Change.Id changeId = patchSetId.getParentKey();
+ final PatchSet patch = db.patchSets().get(patchSetId);
+ if (patch == null) {
+ throw new NoSuchChangeException(changeId);
+ }
+
+ if (message == null || message.length() == 0) {
+ throw new InvalidChangeOperationException("The commit message cannot be empty");
+ }
+
+ final Repository git;
+ try {
+ git = gitManager.openRepository(db.changes().get(changeId).getProject());
+ } catch (RepositoryNotFoundException e) {
+ throw new NoSuchChangeException(changeId, e);
+ }
+
+ try {
+ final RevWalk revWalk = new RevWalk(git);
+ try {
+ Change change = db.changes().get(changeId);
+
+ RevCommit commit =
+ revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get()));
+
+ PersonIdent authorIdent =
+ user.newCommitterIdent(myIdent.getWhen(), myIdent.getTimeZone());
+
+ CommitBuilder commitBuilder = new CommitBuilder();
+ commitBuilder.addParentId(commit);
+ commitBuilder.setTreeId(commit.getTree());
+ commitBuilder.setAuthor(authorIdent);
+ commitBuilder.setCommitter(myIdent);
+ commitBuilder.setMessage(message);
+
+ RevCommit newCommit;
+ final ObjectInserter oi = git.newObjectInserter();
+ try {
+ ObjectId id = oi.insert(commitBuilder);
+ oi.flush();
+ newCommit = revWalk.parseCommit(id);
+ } finally {
+ oi.release();
+ }
+
+ change.nextPatchSetId();
+
+ final PatchSet originalPS = db.patchSets().get(patchSetId);
+
+ final PatchSet newPatchSet = new PatchSet(change.currPatchSetId());
+ newPatchSet.setCreatedOn(change.getCreatedOn());
+ newPatchSet.setUploader(change.getOwner());
+ newPatchSet.setRevision(new RevId(newCommit.name()));
+ newPatchSet.setDraft(originalPS.isDraft());
+
+ final PatchSetInfo info =
+ patchSetInfoFactory.get(newCommit, newPatchSet.getId());
+
+ final RefUpdate ru = git.updateRef(newPatchSet.getRefName());
+ ru.setExpectedOldObjectId(ObjectId.zeroId());
+ ru.setNewObjectId(newCommit);
+ ru.disableRefLog();
+ if (ru.update(revWalk) != RefUpdate.Result.NEW) {
+ throw new IOException(String.format(
+ "Failed to create ref %s in %s: %s", newPatchSet.getRefName(),
+ change.getDest().getParentKey().get(), ru.getResult()));
+ }
+ replication.fire(change.getProject(), ru.getName());
+
+ db.changes().beginTransaction(change.getId());
+ try {
+ Change updatedChange =
+ db.changes().atomicUpdate(change.getId(), new AtomicUpdate<Change>() {
+ @Override
+ public Change update(Change change) {
+ if (change.getStatus().isOpen()) {
+ change.updateNumberOfPatchSets(newPatchSet.getPatchSetId());
+ return change;
+ } else {
+ return null;
+ }
+ }
+ });
+ if (updatedChange != null) {
+ change = updatedChange;
+ } else {
+ throw new InvalidChangeOperationException(String.format(
+ "Change %s is closed", change.getId()));
+ }
+
+ ChangeUtil.insertAncestors(db, newPatchSet.getId(), commit);
+ db.patchSets().insert(Collections.singleton(newPatchSet));
+ updatedChange =
+ db.changes().atomicUpdate(change.getId(), new AtomicUpdate<Change>() {
+ @Override
+ public Change update(Change change) {
+ if (change.getStatus().isClosed()) {
+ return null;
+ }
+ if (!change.currentPatchSetId().equals(patchSetId)) {
+ return null;
+ }
+ if (change.getStatus() != Change.Status.DRAFT) {
+ change.setStatus(Change.Status.NEW);
+ }
+ change.setLastSha1MergeTested(null);
+ change.setCurrentPatchSet(info);
+ ChangeUtil.updated(change);
+ return change;
+ }
+ });
+ if (updatedChange != null) {
+ change = updatedChange;
+ } else {
+ throw new InvalidChangeOperationException(String.format(
+ "Change %s was modified", change.getId()));
+ }
+
+ final ChangeMessage cmsg =
+ new ChangeMessage(new ChangeMessage.Key(changeId,
+ ChangeUtil.messageUUID(db)), user.getAccountId(), patchSetId);
+ final String msg = "Patch Set " + newPatchSet.getPatchSetId() + ": Commit message was updated";
+ cmsg.setMessage(msg);
+ db.changeMessages().insert(Collections.singleton(cmsg));
+ db.commit();
+ } finally {
+ db.rollback();
+ }
+
+ hooks.doPatchsetCreatedHook(change, newPatchSet, db);
+
+ return change.getId();
+ } finally {
+ revWalk.release();
+ }
+ } finally {
+ git.close();
+ }
+ }
+
public static void deleteDraftChange(final PatchSet.Id patchSetId,
GitRepositoryManager gitManager,
final GitReferenceUpdated replication, final ReviewDb db)