Adds a "revert change"-button to a submitted patchset.
Change-Id: I409e656c88a7021f604c021ca3987d2e917c18d9
This commit is contained in:
parent
0908bff975
commit
262629e6d3
@ -31,6 +31,7 @@ public class ChangeDetail {
|
||||
protected boolean allowsAnonymous;
|
||||
protected boolean canAbandon;
|
||||
protected boolean canRestore;
|
||||
protected boolean canRevert;
|
||||
protected Change change;
|
||||
protected boolean starred;
|
||||
protected List<ChangeInfo> dependsOn;
|
||||
@ -78,6 +79,14 @@ public class ChangeDetail {
|
||||
canRestore = a;
|
||||
}
|
||||
|
||||
public boolean canRevert() {
|
||||
return canRevert;
|
||||
}
|
||||
|
||||
public void setCanRevert(boolean a) {
|
||||
canRevert = a;
|
||||
}
|
||||
|
||||
public Change getChange() {
|
||||
return change;
|
||||
}
|
||||
|
@ -30,6 +30,10 @@ public interface ChangeManageService extends RemoteJsonService {
|
||||
void abandonChange(PatchSet.Id patchSetId, String message,
|
||||
AsyncCallback<ChangeDetail> callback);
|
||||
|
||||
@SignInRequired
|
||||
void revertChange(PatchSet.Id patchSetId, String message,
|
||||
AsyncCallback<ChangeDetail> callback);
|
||||
|
||||
@SignInRequired
|
||||
void restoreChange(PatchSet.Id patchSetId, String message,
|
||||
AsyncCallback<ChangeDetail> callback);
|
||||
|
@ -20,6 +20,8 @@ public interface GerritCss extends CssResource {
|
||||
String greenCheckClass();
|
||||
String abandonChangeDialog();
|
||||
String abandonMessage();
|
||||
String revertChangeDialog();
|
||||
String revertMessage();
|
||||
String accountContactOnFile();
|
||||
String accountContactPrivacyDetails();
|
||||
String accountDashboard();
|
||||
|
@ -100,6 +100,12 @@ public interface ChangeConstants extends Constants {
|
||||
String patchSetInfoCommitter();
|
||||
String patchSetInfoDownload();
|
||||
|
||||
String buttonRevertChangeBegin();
|
||||
String buttonRevertChangeSend();
|
||||
String buttonRevertChangeCancel();
|
||||
String headingRevertMessage();
|
||||
String revertChangeTitle();
|
||||
|
||||
String buttonAbandonChangeBegin();
|
||||
String buttonAbandonChangeSend();
|
||||
String buttonAbandonChangeCancel();
|
||||
|
@ -83,6 +83,12 @@ buttonAbandonChangeCancel = Cancel
|
||||
headingAbandonMessage = Abandon Message:
|
||||
abandonChangeTitle = Code Review - Abandon Change
|
||||
|
||||
buttonRevertChangeBegin = Revert Change
|
||||
buttonRevertChangeSend = Revert Change
|
||||
buttonRevertChangeCancel = Cancel
|
||||
headingRevertMessage = Revert Commit Message:
|
||||
revertChangeTitle = Code Review - Revert Merged Change
|
||||
|
||||
buttonRestoreChangeBegin = Restore Change
|
||||
restoreChangeTitle = Code Review - Restore Change
|
||||
buttonRestoreChangeCancel = Cancel
|
||||
|
@ -24,6 +24,8 @@ public interface ChangeMessages extends Messages {
|
||||
String changesMergedInProject(String string);
|
||||
String changesAbandonedInProject(String string);
|
||||
|
||||
String revertChangeDefaultMessage(String commitMsg, String commitId);
|
||||
|
||||
String changeScreenTitleId(String changeId);
|
||||
String patchSetHeader(int id);
|
||||
String loadingPatchSet(int id);
|
||||
|
@ -5,6 +5,8 @@ changesOpenInProject = Open Changes In {0}
|
||||
changesMergedInProject = Merged Changes In {0}
|
||||
changesAbandonedInProject = Abandoned Changes In {0}
|
||||
|
||||
revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}
|
||||
|
||||
changeScreenTitleId = Change {0}
|
||||
patchSetHeader = Patch Set {0}
|
||||
loadingPatchSet = Loading Patch Set {0} ...
|
||||
|
@ -47,6 +47,14 @@ public abstract class CommentedChangeActionDialog extends AutoCenterDialogBox im
|
||||
final String dialogHeading, final String buttonSend,
|
||||
final String buttonCancel, final String dialogStyle,
|
||||
final String messageStyle) {
|
||||
this(psi, callback, dialogTitle, dialogHeading, buttonSend, buttonCancel, dialogStyle, messageStyle, null);
|
||||
}
|
||||
|
||||
public CommentedChangeActionDialog(final PatchSet.Id psi,
|
||||
final AsyncCallback<ChangeDetail> callback, final String dialogTitle,
|
||||
final String dialogHeading, final String buttonSend,
|
||||
final String buttonCancel, final String dialogStyle,
|
||||
final String messageStyle, final String defaultMessage) {
|
||||
super(/* auto hide */false, /* modal */true);
|
||||
setGlassEnabled(true);
|
||||
|
||||
@ -67,6 +75,7 @@ public abstract class CommentedChangeActionDialog extends AutoCenterDialogBox im
|
||||
message = new NpTextArea();
|
||||
message.setCharacterWidth(60);
|
||||
message.setVisibleLines(10);
|
||||
message.setText(defaultMessage);
|
||||
DOM.setElementPropertyBoolean(message.getElement(), "spellcheck", true);
|
||||
mwrap.add(message);
|
||||
|
||||
|
@ -395,6 +395,26 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements O
|
||||
actionsPanel.add(b);
|
||||
}
|
||||
|
||||
if (changeDetail.canRevert()) {
|
||||
final Button b = new Button(Util.C.buttonRevertChangeBegin());
|
||||
b.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
b.setEnabled(false);
|
||||
new CommentedChangeActionDialog(patchSet.getId(), createCommentedCallback(b),
|
||||
Util.C.revertChangeTitle(), Util.C.headingRevertMessage(),
|
||||
Util.C.buttonRevertChangeSend(), Util.C.buttonRevertChangeCancel(),
|
||||
Gerrit.RESOURCES.css().revertChangeDialog(), Gerrit.RESOURCES.css().revertMessage(),
|
||||
Util.M.revertChangeDefaultMessage(detail.getInfo().getSubject(), detail.getPatchSet().getRevision().get())) {
|
||||
public void onSend() {
|
||||
Util.MANAGE_SVC.revertChange(getPatchSetId() , getMessageText(), createCallback());
|
||||
}
|
||||
}.center();
|
||||
}
|
||||
});
|
||||
actionsPanel.add(b);
|
||||
}
|
||||
|
||||
if (changeDetail.canAbandon()) {
|
||||
final Button b = new Button(Util.C.buttonAbandonChangeBegin());
|
||||
b.addClickHandler(new ClickHandler() {
|
||||
|
@ -1230,6 +1230,31 @@ a:hover.downloadLink {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
/** RevertChangeDialog **/
|
||||
|
||||
.revertChangeDialog .gwt-DisclosurePanel .header td {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.revertChangeDialog .smallHeading {
|
||||
font-size: small;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.revertChangeDialog .revertMessage {
|
||||
margin-left: 10px;
|
||||
background: trimColor;
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
.revertChangeDialog .revertMessage textarea {
|
||||
font-size: small;
|
||||
}
|
||||
.revertChangeDialog .gwt-Hyperlink {
|
||||
white-space: nowrap;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
|
||||
/** PatchBrowserPopup **/
|
||||
.patchBrowserPopup {
|
||||
|
@ -100,10 +100,14 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
|
||||
detail = new ChangeDetail();
|
||||
detail.setChange(change);
|
||||
detail.setAllowsAnonymous(control.forAnonymousUser().isVisible());
|
||||
|
||||
detail.setCanAbandon(change.getStatus().isOpen() && control.canAbandon());
|
||||
detail.setCanRestore(change.getStatus() == Change.Status.ABANDONED && control.canRestore());
|
||||
detail.setStarred(control.getCurrentUser().getStarredChanges().contains(
|
||||
changeId));
|
||||
|
||||
detail.setCanRevert(change.getStatus() == Change.Status.MERGED && control.canAddPatchSet());
|
||||
|
||||
loadPatchSets();
|
||||
loadMessages();
|
||||
if (change.currentPatchSetId() != null) {
|
||||
|
@ -24,14 +24,17 @@ class ChangeManageServiceImpl implements ChangeManageService {
|
||||
private final SubmitAction.Factory submitAction;
|
||||
private final AbandonChange.Factory abandonChangeFactory;
|
||||
private final RestoreChange.Factory restoreChangeFactory;
|
||||
private final RevertChange.Factory revertChangeFactory;
|
||||
|
||||
@Inject
|
||||
ChangeManageServiceImpl(final SubmitAction.Factory patchSetAction,
|
||||
final AbandonChange.Factory abandonChangeFactory,
|
||||
final RestoreChange.Factory restoreChangeFactory) {
|
||||
final RestoreChange.Factory restoreChangeFactory,
|
||||
final RevertChange.Factory revertChangeFactory) {
|
||||
this.submitAction = patchSetAction;
|
||||
this.abandonChangeFactory = abandonChangeFactory;
|
||||
this.restoreChangeFactory = restoreChangeFactory;
|
||||
this.revertChangeFactory = revertChangeFactory;
|
||||
}
|
||||
|
||||
public void submit(final PatchSet.Id patchSetId,
|
||||
@ -44,6 +47,11 @@ class ChangeManageServiceImpl implements ChangeManageService {
|
||||
abandonChangeFactory.create(patchSetId, message).to(callback);
|
||||
}
|
||||
|
||||
public void revertChange(final PatchSet.Id patchSetId, final String message,
|
||||
final AsyncCallback<ChangeDetail> callback) {
|
||||
revertChangeFactory.create(patchSetId, message).to(callback);
|
||||
}
|
||||
|
||||
public void restoreChange(final PatchSet.Id patchSetId, final String message,
|
||||
final AsyncCallback<ChangeDetail> callback) {
|
||||
restoreChangeFactory.create(patchSetId, message).to(callback);
|
||||
|
@ -30,6 +30,7 @@ public class ChangeModule extends RpcServletModule {
|
||||
protected void configure() {
|
||||
factory(AbandonChange.Factory.class);
|
||||
factory(RestoreChange.Factory.class);
|
||||
factory(RevertChange.Factory.class);
|
||||
factory(ChangeDetailFactory.Factory.class);
|
||||
factory(IncludedInDetailFactory.Factory.class);
|
||||
factory(PatchSetDetailFactory.Factory.class);
|
||||
|
@ -0,0 +1,114 @@
|
||||
// Copyright (C) 2011 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.ChangeHookRunner;
|
||||
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.Change;
|
||||
import com.google.gerrit.reviewdb.PatchSet;
|
||||
import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.git.ReplicationQueue;
|
||||
import com.google.gerrit.server.mail.EmailException;
|
||||
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.ChangeControl;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gwtorm.client.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 RevertChange extends Handler<ChangeDetail> {
|
||||
interface Factory {
|
||||
RevertChange create(PatchSet.Id patchSetId, String message);
|
||||
}
|
||||
|
||||
private final ChangeControl.Factory changeControlFactory;
|
||||
private final ReviewDb db;
|
||||
private final IdentifiedUser currentUser;
|
||||
private final RevertedSender.Factory revertedSenderFactory;
|
||||
private final ChangeDetailFactory.Factory changeDetailFactory;
|
||||
private final ReplicationQueue replication;
|
||||
|
||||
private final PatchSet.Id patchSetId;
|
||||
@Nullable
|
||||
private final String message;
|
||||
|
||||
private final ChangeHookRunner hooks;
|
||||
|
||||
private final GitRepositoryManager gitManager;
|
||||
private final PatchSetInfoFactory patchSetInfoFactory;
|
||||
|
||||
private final PersonIdent myIdent;
|
||||
|
||||
@Inject
|
||||
RevertChange(final ChangeControl.Factory changeControlFactory,
|
||||
final ReviewDb db, final IdentifiedUser currentUser,
|
||||
final RevertedSender.Factory revertedSenderFactory,
|
||||
final ChangeDetailFactory.Factory changeDetailFactory,
|
||||
@Assisted final PatchSet.Id patchSetId,
|
||||
@Assisted @Nullable final String message, final ChangeHookRunner hooks,
|
||||
final GitRepositoryManager gitManager,
|
||||
final PatchSetInfoFactory patchSetInfoFactory,
|
||||
final ReplicationQueue replication,
|
||||
@GerritPersonIdent final PersonIdent myIdent) {
|
||||
this.changeControlFactory = changeControlFactory;
|
||||
this.db = db;
|
||||
this.currentUser = currentUser;
|
||||
this.revertedSenderFactory = revertedSenderFactory;
|
||||
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 {
|
||||
|
||||
final Change.Id changeId = patchSetId.getParentKey();
|
||||
final ChangeControl control = changeControlFactory.validateFor(changeId);
|
||||
if (!control.canAddPatchSet()) {
|
||||
throw new NoSuchChangeException(changeId);
|
||||
}
|
||||
|
||||
ChangeUtil.revert(patchSetId, currentUser, message, db,
|
||||
revertedSenderFactory, hooks, gitManager, patchSetInfoFactory,
|
||||
replication, myIdent);
|
||||
|
||||
return changeDetailFactory.create(changeId).call();
|
||||
}
|
||||
}
|
@ -17,31 +17,48 @@ package com.google.gerrit.server;
|
||||
import static com.google.gerrit.reviewdb.ApprovalCategory.SUBMIT;
|
||||
|
||||
import com.google.gerrit.common.ChangeHookRunner;
|
||||
import com.google.gerrit.common.data.ChangeDetail;
|
||||
import com.google.gerrit.reviewdb.Change;
|
||||
import com.google.gerrit.reviewdb.ChangeMessage;
|
||||
import com.google.gerrit.reviewdb.Change;
|
||||
import com.google.gerrit.reviewdb.PatchSet;
|
||||
import com.google.gerrit.reviewdb.PatchSetApproval;
|
||||
import com.google.gerrit.reviewdb.PatchSetInfo;
|
||||
import com.google.gerrit.reviewdb.RevId;
|
||||
import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.reviewdb.TrackingId;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.config.TrackingFooter;
|
||||
import com.google.gerrit.server.config.TrackingFooters;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.git.MergeOp;
|
||||
import com.google.gerrit.server.git.MergeQueue;
|
||||
import com.google.gerrit.server.git.ReplicationQueue;
|
||||
import com.google.gerrit.server.patch.PatchSetInfoFactory;
|
||||
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gerrit.server.mail.AbandonedSender;
|
||||
import com.google.gerrit.server.mail.EmailException;
|
||||
import com.google.gerrit.server.mail.RevertedSender;
|
||||
import com.google.gwtorm.client.AtomicUpdate;
|
||||
import com.google.gwtorm.client.OrmConcurrencyException;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
||||
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.CommitBuilder;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.RefUpdate;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.FooterLine;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.util.Base64;
|
||||
import org.eclipse.jgit.util.NB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@ -248,6 +265,108 @@ public class ChangeUtil {
|
||||
hooks.doChangeAbandonedHook(updatedChange, user.getAccount(), message);
|
||||
}
|
||||
|
||||
public static void revert(final PatchSet.Id patchSetId,
|
||||
final IdentifiedUser user, final String message, final ReviewDb db,
|
||||
final RevertedSender.Factory revertedSenderFactory,
|
||||
final ChangeHookRunner hooks, GitRepositoryManager gitManager,
|
||||
final PatchSetInfoFactory patchSetInfoFactory,
|
||||
final ReplicationQueue replication, PersonIdent myIdent)
|
||||
throws NoSuchChangeException, EmailException, OrmException,
|
||||
MissingObjectException, IncorrectObjectTypeException, IOException,
|
||||
PatchSetInfoNotAvailableException {
|
||||
|
||||
final Change.Id changeId = patchSetId.getParentKey();
|
||||
final PatchSet patch = db.patchSets().get(patchSetId);
|
||||
if (patch == null) {
|
||||
throw new NoSuchChangeException(changeId);
|
||||
}
|
||||
|
||||
final Repository git;
|
||||
try {
|
||||
git = gitManager.openRepository(db.changes().get(changeId).getProject());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
throw new NoSuchChangeException(changeId, e);
|
||||
};
|
||||
|
||||
final RevWalk revWalk = new RevWalk(git);
|
||||
try {
|
||||
RevCommit commitToRevert =
|
||||
revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get()));
|
||||
|
||||
PersonIdent authorIdent =
|
||||
user.newCommitterIdent(myIdent.getWhen(), myIdent.getTimeZone());
|
||||
|
||||
RevCommit parentToCommitToRevert = commitToRevert.getParent(0);
|
||||
revWalk.parseHeaders(parentToCommitToRevert);
|
||||
|
||||
CommitBuilder revertCommit = new CommitBuilder();
|
||||
revertCommit.addParentId(commitToRevert);
|
||||
revertCommit.setTreeId(parentToCommitToRevert.getTree());
|
||||
revertCommit.setAuthor(authorIdent);
|
||||
revertCommit.setCommitter(myIdent);
|
||||
revertCommit.setMessage(message);
|
||||
|
||||
final ObjectInserter oi = git.newObjectInserter();;
|
||||
ObjectId id;
|
||||
try {
|
||||
id = oi.insert(revertCommit);
|
||||
oi.flush();
|
||||
} finally {
|
||||
oi.release();
|
||||
}
|
||||
|
||||
Change.Key changeKey = new Change.Key("I" + id.name());
|
||||
final Change change =
|
||||
new Change(changeKey, new Change.Id(db.nextChangeId()),
|
||||
user.getAccountId(), db.changes().get(changeId).getDest());
|
||||
change.nextPatchSetId();
|
||||
|
||||
final PatchSet ps = new PatchSet(change.currPatchSetId());
|
||||
ps.setCreatedOn(change.getCreatedOn());
|
||||
ps.setUploader(user.getAccountId());
|
||||
ps.setRevision(new RevId(id.getName()));
|
||||
|
||||
db.patchSets().insert(Collections.singleton(ps));
|
||||
|
||||
final PatchSetInfo info =
|
||||
patchSetInfoFactory.get(revWalk.parseCommit(id), ps.getId());
|
||||
change.setCurrentPatchSet(info);
|
||||
ChangeUtil.updated(change);
|
||||
db.changes().insert(Collections.singleton(change));
|
||||
|
||||
final RefUpdate ru = git.updateRef(ps.getRefName());
|
||||
ru.setNewObjectId(id);
|
||||
ru.disableRefLog();
|
||||
if (ru.update(revWalk) != RefUpdate.Result.NEW) {
|
||||
throw new IOException("Failed to create ref " + ps.getRefName()
|
||||
+ " in " + git.getDirectory() + ": " + ru.getResult());
|
||||
}
|
||||
replication.scheduleUpdate(db.changes().get(changeId).getProject(),
|
||||
ru.getName());
|
||||
|
||||
final ChangeMessage cmsg =
|
||||
new ChangeMessage(new ChangeMessage.Key(changeId,
|
||||
ChangeUtil.messageUUID(db)), user.getAccountId());
|
||||
final StringBuilder msgBuf =
|
||||
new StringBuilder("Patch Set " + patchSetId.get() + ": Reverted");
|
||||
msgBuf.append("\n\n");
|
||||
msgBuf.append("This patchset was reverted in change: " + changeKey.get());
|
||||
|
||||
cmsg.setMessage(msgBuf.toString());
|
||||
db.changeMessages().insert(Collections.singleton(cmsg));
|
||||
|
||||
final RevertedSender cm = revertedSenderFactory.create(change);
|
||||
cm.setFrom(user.getAccountId());
|
||||
cm.setChangeMessage(cmsg);
|
||||
cm.send();
|
||||
|
||||
hooks.doPatchsetCreatedHook(change, ps);
|
||||
} finally {
|
||||
revWalk.release();
|
||||
git.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void restore(final PatchSet.Id patchSetId,
|
||||
final IdentifiedUser user, final String message, final ReviewDb db,
|
||||
final AbandonedSender.Factory abandonedSenderFactory,
|
||||
|
@ -32,6 +32,7 @@ import com.google.gerrit.server.mail.MergeFailSender;
|
||||
import com.google.gerrit.server.mail.MergedSender;
|
||||
import com.google.gerrit.server.mail.RegisterNewEmailSender;
|
||||
import com.google.gerrit.server.mail.ReplacePatchSetSender;
|
||||
import com.google.gerrit.server.mail.RevertedSender;
|
||||
import com.google.gerrit.server.patch.PublishComments;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.ProjectControl;
|
||||
@ -66,6 +67,7 @@ public class GerritRequestModule extends FactoryModule {
|
||||
factory(PublishComments.Factory.class);
|
||||
factory(ReplacePatchSetSender.Factory.class);
|
||||
factory(AbandonedSender.Factory.class);
|
||||
factory(RevertedSender.Factory.class);
|
||||
factory(CommentSender.Factory.class);
|
||||
factory(MergedSender.Factory.class);
|
||||
factory(MergeFailSender.Factory.class);
|
||||
|
@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2011 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.mail;
|
||||
|
||||
import com.google.gerrit.reviewdb.Change;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
/** Send notice about a change being reverted. */
|
||||
public class RevertedSender extends ReplyToChangeSender {
|
||||
public static interface Factory {
|
||||
RevertedSender create(Change change);
|
||||
}
|
||||
|
||||
@Inject
|
||||
public RevertedSender(EmailArguments ea, @Assisted Change c) {
|
||||
super(ea, c, "revert");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() throws EmailException {
|
||||
super.init();
|
||||
|
||||
ccAllApprovals();
|
||||
bccStarredBy();
|
||||
bccWatchesNotifyAllComments();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void formatChange() throws EmailException {
|
||||
appendText(velocifyFile("Reverted.vm"));
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
## Copyright (C) 2010 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.
|
||||
##
|
||||
##
|
||||
## Template Type:
|
||||
## -------------
|
||||
## This is a velocity mail template, see: http://velocity.apache.org and the
|
||||
## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates.
|
||||
##
|
||||
## Template File Names and extensions:
|
||||
## ----------------------------------
|
||||
## Gerrit will use templates ending in ".vm" but will ignore templates ending
|
||||
## in ".vm.example". If a .vm template does not exist, the default internal
|
||||
## gerrit template which is the same as the .vm.example will be used. If you
|
||||
## want to override the default template, copy the .vm.exmaple file to a .vm
|
||||
## file and edit it appropriately.
|
||||
##
|
||||
## This Template:
|
||||
## --------------
|
||||
## The Reverted.vm template will determine the contents of the email related
|
||||
## to a change being reverted. It is a ChangeEmail: see ChangeSubject.vm and
|
||||
## ChangeFooter.vm.
|
||||
##
|
||||
$fromName has reverted this change.
|
||||
|
||||
Change subject: $change.subject
|
||||
......................................................................
|
||||
|
||||
|
||||
#if ($coverLetter)
|
||||
$coverLetter
|
||||
|
||||
#end
|
Loading…
Reference in New Issue
Block a user