Merge "Update web UI to use /review"

This commit is contained in:
Martin Fick
2012-11-23 14:28:55 -08:00
committed by Gerrit Code Review
9 changed files with 71 additions and 436 deletions

View File

@@ -18,17 +18,16 @@ import com.google.gerrit.common.audit.Audit;
import com.google.gerrit.common.auth.SignInRequired;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.Patch.Key;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Patch.Key;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.RemoteJsonService;
import com.google.gwtjsonrpc.common.RpcImpl;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtjsonrpc.common.RpcImpl.Version;
import com.google.gwtjsonrpc.common.VoidResult;
import java.util.List;
import java.util.Set;
@@ -65,12 +64,6 @@ public interface PatchDetailService extends RemoteJsonService {
@SignInRequired
void deleteDraftPatchSet(PatchSet.Id psid, AsyncCallback<ChangeDetail> callback);
@Audit
@SignInRequired
void publishComments(PatchSet.Id psid, String message,
Set<ApprovalCategoryValue.Id> approvals,
AsyncCallback<VoidResult> callback);
@Audit
@SignInRequired
void addReviewers(Change.Id id, List<String> reviewers, boolean confirmed,

View File

@@ -70,7 +70,7 @@ public class ChangeApi {
return new RestApi("/changes/" + id + "/" + action);
}
private static String emptyToNull(String str) {
public static String emptyToNull(String str) {
return str == null || str.isEmpty() ? null : str;
}
}

View File

@@ -17,8 +17,8 @@ package com.google.gerrit.client.changes;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.patches.CommentEditorContainer;
import com.google.gerrit.client.patches.CommentEditorPanel;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.AccountScreen;
import com.google.gerrit.client.ui.PatchLink;
@@ -36,6 +36,7 @@ import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
@@ -53,7 +54,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -62,6 +62,7 @@ public class PublishCommentScreen extends AccountScreen implements
private static SavedState lastState;
private final PatchSet.Id patchSetId;
private String revision;
private Collection<ValueRadioButton> approvalButtons;
private ChangeDescriptionBlock descBlock;
private ApprovalTable approvals;
@@ -252,8 +253,7 @@ public class PublishCommentScreen extends AccountScreen implements
continue;
}
final ValueRadioButton b =
new ValueRadioButton(buttonValue, ct.getCategory().getName());
ValueRadioButton b = new ValueRadioButton(ct.getCategory(), buttonValue);
b.setText(buttonValue.format());
if (lastState != null && patchSetId.equals(lastState.patchSetId)
@@ -292,6 +292,7 @@ public class PublishCommentScreen extends AccountScreen implements
draftsPanel.clear();
commentEditors = new ArrayList<CommentEditorPanel>();
revision = r.getPatchSetInfo().getRevId();
if (!r.getDrafts().isEmpty()) {
draftsPanel.add(new SmallHeading(Util.C.headingPatchComments()));
@@ -348,20 +349,23 @@ public class PublishCommentScreen extends AccountScreen implements
}
private void onSend2(final boolean submit) {
final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> values =
new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>();
ReviewInput data = ReviewInput.create();
data.message(ChangeApi.emptyToNull(message.getText().trim()));
data.init();
for (final ValueRadioButton b : approvalButtons) {
if (b.getValue()) {
values.put(b.value.getCategoryId(), b.value.getId());
data.label(b.category.getLabelName(), b.value.getValue());
}
}
enableForm(false);
PatchUtil.DETAIL_SVC.publishComments(patchSetId, message.getText().trim(),
new HashSet<ApprovalCategoryValue.Id>(values.values()),
new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) {
if(submit) {
new RestApi("/changes/" + patchSetId.getParentKey().get()
+ "/revisions/" + revision + "/review")
.data(data)
.post(new GerritCallback<ReviewInput>() {
@Override
public void onSuccess(ReviewInput result) {
if (submit) {
submit();
} else {
saveStateOnUnload = false;
@@ -377,6 +381,23 @@ public class PublishCommentScreen extends AccountScreen implements
});
}
private static class ReviewInput extends JavaScriptObject {
static ReviewInput create() {
return (ReviewInput) createObject();
}
final native void message(String m) /*-{ if(m)this.message=m; }-*/;
final native void label(String n, short v) /*-{ this.labels[n]=v; }-*/;
final native void init() /*-{
this.labels = {};
this.strict_labels = true;
this.drafts = 'PUBLISH';
}-*/;
protected ReviewInput() {
}
}
private void submit() {
Util.MANAGE_SVC.submit(patchSetId,
new GerritCallback<ChangeDetail>() {
@@ -399,10 +420,12 @@ public class PublishCommentScreen extends AccountScreen implements
}
private static class ValueRadioButton extends RadioButton {
final ApprovalCategory category;
final ApprovalCategoryValue value;
ValueRadioButton(final ApprovalCategoryValue v, final String label) {
super(label);
ValueRadioButton(ApprovalCategory c, ApprovalCategoryValue v) {
super(c.getLabelName());
category = c;
value = v;
}
}

View File

@@ -24,25 +24,22 @@ import com.google.gerrit.common.data.ReviewResult;
import com.google.gerrit.common.data.ReviewerResult;
import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.httpd.rpc.changedetail.ChangeDetailFactory;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gerrit.reviewdb.client.AccountPatchReview;
import com.google.gerrit.reviewdb.client.ApprovalCategory;
import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.Patch.Key;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Patch.Key;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountInfoCacheFactory;
import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.patch.PublishComments;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.workflow.FunctionState;
@@ -71,7 +68,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
private final DeleteDraftPatchSet.Factory deleteDraftPatchSetFactory;
private final RemoveReviewerHandler.Factory removeReviewerHandlerFactory;
private final FunctionState.Factory functionStateFactory;
private final PublishComments.Factory publishCommentsFactory;
private final PatchScriptFactory.Factory patchScriptFactoryFactory;
private final SaveDraft.Factory saveDraftFactory;
private final ChangeDetailFactory.Factory changeDetailFactory;
@@ -87,7 +83,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
final DeleteDraftPatchSet.Factory deleteDraftPatchSetFactory,
final FunctionState.Factory functionStateFactory,
final PatchScriptFactory.Factory patchScriptFactoryFactory,
final PublishComments.Factory publishCommentsFactory,
final SaveDraft.Factory saveDraftFactory,
final ChangeDetailFactory.Factory changeDetailFactory) {
super(schema, currentUser);
@@ -100,7 +95,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
this.deleteDraftPatchSetFactory = deleteDraftPatchSetFactory;
this.functionStateFactory = functionStateFactory;
this.patchScriptFactoryFactory = patchScriptFactoryFactory;
this.publishCommentsFactory = publishCommentsFactory;
this.saveDraftFactory = saveDraftFactory;
this.changeDetailFactory = changeDetailFactory;
}
@@ -178,12 +172,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
});
}
public void publishComments(final PatchSet.Id psid, final String msg,
final Set<ApprovalCategoryValue.Id> tags,
final AsyncCallback<VoidResult> cb) {
Handler.wrap(publishCommentsFactory.create(psid, msg, tags, false)).to(cb);
}
/**
* Update the reviewed status for the file by user @code{account}
*/

View File

@@ -51,14 +51,14 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
class PostReview implements RestModifyView<RevisionResource, Input> {
public class PostReview implements RestModifyView<RevisionResource, Input> {
private static final Logger log = LoggerFactory.getLogger(PostReview.class);
static class Input {
public static class Input {
@DefaultInput
String message;
public String message;
Map<String, Short> labels;
public Map<String, Short> labels;
Map<String, List<Comment>> comments;
/**
@@ -68,16 +68,16 @@ class PostReview implements RestModifyView<RevisionResource, Input> {
* execute anyway, but the proposed labels given by the user will be
* modified to be the "best" value allowed by the access controls.
*/
boolean strictLabels = true;
public boolean strictLabels = true;
/**
* How to process draft comments already in the database that were not also
* described in this input request.
*/
DraftHandling drafts = DraftHandling.DELETE;
public DraftHandling drafts = DraftHandling.DELETE;
}
static enum DraftHandling {
public static enum DraftHandling {
DELETE, PUBLISH, KEEP;
}

View File

@@ -44,7 +44,6 @@ import com.google.gerrit.server.mail.RebasedPatchSetSender;
import com.google.gerrit.server.mail.ReplacePatchSetSender;
import com.google.gerrit.server.mail.RestoredSender;
import com.google.gerrit.server.patch.AddReviewer;
import com.google.gerrit.server.patch.PublishComments;
import com.google.gerrit.server.patch.RemoveReviewer;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.CreateProject;
@@ -81,7 +80,6 @@ public class GerritRequestModule extends FactoryModule {
factory(AddReviewerSender.Factory.class);
factory(CreateChangeSender.Factory.class);
factory(DeleteDraftPatchSet.Factory.class);
factory(PublishComments.Factory.class);
factory(PublishDraft.Factory.class);
factory(RebaseChange.Factory.class);
factory(ReplacePatchSetSender.Factory.class);

View File

@@ -1,380 +0,0 @@
// Copyright (C) 2009 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.patch;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.client.ApprovalCategory;
import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.mail.CommentSender;
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.util.RequestScopePropagator;
import com.google.gerrit.server.workflow.FunctionState;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
public class PublishComments implements Callable<VoidResult> {
private static final Logger log =
LoggerFactory.getLogger(PublishComments.class);
public interface Factory {
PublishComments create(PatchSet.Id patchSetId, String messageText,
Set<ApprovalCategoryValue.Id> approvals, boolean forceMessage);
}
private final SchemaFactory<ReviewDb> schemaFactory;
private final ReviewDb db;
private final IdentifiedUser user;
private final ApprovalTypes types;
private final CommentSender.Factory commentSenderFactory;
private final PatchSetInfoFactory patchSetInfoFactory;
private final ChangeControl.Factory changeControlFactory;
private final FunctionState.Factory functionStateFactory;
private final ChangeHooks hooks;
private final WorkQueue workQueue;
private final RequestScopePropagator requestScopePropagator;
private final PatchSet.Id patchSetId;
private final String messageText;
private final Set<ApprovalCategoryValue.Id> approvals;
private final boolean forceMessage;
private Change change;
private PatchSet patchSet;
private ChangeMessage message;
private List<PatchLineComment> drafts;
@Inject
PublishComments(final SchemaFactory<ReviewDb> sf, final ReviewDb db,
final IdentifiedUser user,
final ApprovalTypes approvalTypes,
final CommentSender.Factory commentSenderFactory,
final PatchSetInfoFactory patchSetInfoFactory,
final ChangeControl.Factory changeControlFactory,
final FunctionState.Factory functionStateFactory,
final ChangeHooks hooks,
final WorkQueue workQueue,
final RequestScopePropagator requestScopePropagator,
@Assisted final PatchSet.Id patchSetId,
@Assisted final String messageText,
@Assisted final Set<ApprovalCategoryValue.Id> approvals,
@Assisted final boolean forceMessage) {
this.schemaFactory = sf;
this.db = db;
this.user = user;
this.types = approvalTypes;
this.patchSetInfoFactory = patchSetInfoFactory;
this.commentSenderFactory = commentSenderFactory;
this.changeControlFactory = changeControlFactory;
this.functionStateFactory = functionStateFactory;
this.hooks = hooks;
this.workQueue = workQueue;
this.requestScopePropagator = requestScopePropagator;
this.patchSetId = patchSetId;
this.messageText = messageText;
this.approvals = approvals;
this.forceMessage = forceMessage;
}
@Override
public VoidResult call() throws NoSuchChangeException,
InvalidChangeOperationException, OrmException {
final Change.Id changeId = patchSetId.getParentKey();
final ChangeControl ctl = changeControlFactory.validateFor(changeId);
change = ctl.getChange();
patchSet = db.patchSets().get(patchSetId);
if (patchSet == null) {
throw new NoSuchChangeException(changeId);
}
drafts = drafts();
db.changes().beginTransaction(changeId);
try {
publishDrafts();
final boolean isCurrent = patchSetId.equals(change.currentPatchSetId());
if (isCurrent && change.getStatus().isOpen()) {
publishApprovals(ctl);
} else if (approvals.isEmpty() || forceMessage) {
publishMessageOnly();
} else {
throw new InvalidChangeOperationException("Change is closed");
}
touchChange();
db.commit();
} finally {
db.rollback();
}
email();
fireHook();
return VoidResult.INSTANCE;
}
private void publishDrafts() throws OrmException {
for (final PatchLineComment c : drafts) {
c.setStatus(PatchLineComment.Status.PUBLISHED);
c.updated();
}
db.patchComments().update(drafts);
}
private void publishApprovals(ChangeControl ctl)
throws InvalidChangeOperationException, OrmException {
ChangeUtil.updated(change);
final Set<ApprovalCategory.Id> dirty = new HashSet<ApprovalCategory.Id>();
final List<PatchSetApproval> ins = new ArrayList<PatchSetApproval>();
final List<PatchSetApproval> upd = new ArrayList<PatchSetApproval>();
final Collection<PatchSetApproval> all =
db.patchSetApprovals().byPatchSet(patchSetId).toList();
final Map<ApprovalCategory.Id, PatchSetApproval> mine = mine(all);
// Ensure any new approvals are stored properly.
//
for (final ApprovalCategoryValue.Id want : approvals) {
PatchSetApproval a = mine.get(want.getParentKey());
if (a == null) {
a = new PatchSetApproval(new PatchSetApproval.Key(//
patchSetId, user.getAccountId(), want.getParentKey()), want.get());
a.cache(change);
ins.add(a);
all.add(a);
mine.put(a.getCategoryId(), a);
dirty.add(a.getCategoryId());
}
}
// Normalize all of the items the user is changing.
//
final FunctionState functionState =
functionStateFactory.create(ctl, patchSetId, all);
for (final ApprovalCategoryValue.Id want : approvals) {
final PatchSetApproval a = mine.get(want.getParentKey());
final short o = a.getValue();
a.setValue(want.get());
a.cache(change);
if (!ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
functionState.normalize(types.byId(a.getCategoryId()), a);
}
if (want.get() != a.getValue()) {
throw new InvalidChangeOperationException(
types.byId(a.getCategoryId()).getCategory().getLabelName()
+ "=" + want.get() + " not permitted");
}
if (o != a.getValue()) {
// Value changed, ensure we update the database.
//
a.setGranted();
dirty.add(a.getCategoryId());
}
if (!ins.contains(a)) {
upd.add(a);
}
}
// Format a message explaining the actions taken.
//
final StringBuilder msgbuf = new StringBuilder();
for (final ApprovalType at : types.getApprovalTypes()) {
if (dirty.contains(at.getCategory().getId())) {
final PatchSetApproval a = mine.get(at.getCategory().getId());
if (a.getValue() == 0 && ins.contains(a)) {
// Don't say "no score" for an initial entry.
continue;
}
final ApprovalCategoryValue val = at.getValue(a);
if (msgbuf.length() > 0) {
msgbuf.append("; ");
}
if (val != null && val.getName() != null && !val.getName().isEmpty()) {
msgbuf.append(val.getName());
} else {
msgbuf.append(at.getCategory().getName());
msgbuf.append(" ");
if (a.getValue() > 0) msgbuf.append('+');
msgbuf.append(a.getValue());
}
}
}
// Update dashboards for everyone else.
//
for (PatchSetApproval a : all) {
if (!user.getAccountId().equals(a.getAccountId())) {
a.cache(change);
upd.add(a);
}
}
db.patchSetApprovals().update(upd);
db.patchSetApprovals().insert(ins);
summarizeInlineComments(msgbuf);
message(msgbuf.toString());
}
private void publishMessageOnly() throws OrmException {
StringBuilder msgbuf = new StringBuilder();
summarizeInlineComments(msgbuf);
message(msgbuf.toString());
}
private void message(String actions) throws OrmException {
if ((actions == null || actions.isEmpty())
&& (messageText == null || messageText.isEmpty())) {
// They had nothing to say?
//
return;
}
final StringBuilder msgbuf = new StringBuilder();
msgbuf.append("Patch Set " + patchSetId.get() + ":");
if (actions != null && !actions.isEmpty()) {
msgbuf.append(" ");
msgbuf.append(actions);
}
msgbuf.append("\n\n");
msgbuf.append(messageText != null ? messageText : "");
message = new ChangeMessage(new ChangeMessage.Key(change.getId(),//
ChangeUtil.messageUUID(db)), user.getAccountId(), patchSetId);
message.setMessage(msgbuf.toString());
db.changeMessages().insert(Collections.singleton(message));
}
private Map<ApprovalCategory.Id, PatchSetApproval> mine(
Collection<PatchSetApproval> all) {
Map<ApprovalCategory.Id, PatchSetApproval> r =
new HashMap<ApprovalCategory.Id, PatchSetApproval>();
for (PatchSetApproval a : all) {
if (user.getAccountId().equals(a.getAccountId())) {
r.put(a.getCategoryId(), a);
}
}
return r;
}
private void touchChange() {
try {
ChangeUtil.touch(change, db);
} catch (OrmException e) {
}
}
private List<PatchLineComment> drafts() throws OrmException {
return db.patchComments().draftByPatchSetAuthor(patchSetId, user.getAccountId()).toList();
}
private void email() {
if (message == null) {
return;
}
workQueue.getDefaultQueue()
.submit(requestScopePropagator.wrap(new Runnable() {
@Override
public void run() {
PatchSetInfo patchSetInfo;
try {
ReviewDb reviewDb = schemaFactory.open();
try {
patchSetInfo = patchSetInfoFactory.get(reviewDb, patchSetId);
} finally {
reviewDb.close();
}
} catch (PatchSetInfoNotAvailableException e) {
log.error("Cannot read PatchSetInfo of " + patchSetId, e);
return;
} catch (Exception e) {
log.error("Cannot email comments for " + patchSetId, e);
return;
}
try {
final CommentSender cm = commentSenderFactory.create(change);
cm.setFrom(user.getAccountId());
cm.setPatchSet(patchSet, patchSetInfo);
cm.setChangeMessage(message);
cm.setPatchLineComments(drafts);
cm.send();
} catch (Exception e) {
log.error("Cannot email comments for " + patchSetId, e);
}
}
@Override
public String toString() {
return "send-email comments";
}
}));
}
private void fireHook() throws OrmException {
final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> changed =
new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>();
for (ApprovalCategoryValue.Id v : approvals) {
changed.put(v.getParentKey(), v);
}
hooks.doCommentAddedHook(change, user.getAccount(), patchSet, messageText, changed, db);
}
private void summarizeInlineComments(StringBuilder in) {
if (!drafts.isEmpty()) {
if (in.length() != 0) {
in.append("\n\n");
}
if (drafts.size() == 1) {
in.append("(1 inline comment)");
} else {
in.append("(" + drafts.size() + " inline comments)");
}
}
}
}

View File

@@ -15,7 +15,6 @@
package com.google.gerrit.sshd.commands;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.reviewdb.client.ApprovalCategory;
import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
import org.kohsuke.args4j.CmdLineException;
@@ -100,8 +99,8 @@ final class ApproveOption implements Option, Setter<Short> {
return false;
}
ApprovalCategory.Id getCategoryId() {
return type.getCategory().getId();
String getLabelName() {
return type.getCategory().getLabelName();
}
public static class Handler extends OneArgumentOptionHandler<Short> {

View File

@@ -14,11 +14,14 @@
package com.google.gerrit.sshd.commands;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.ReviewResult;
import com.google.gerrit.common.data.ReviewResult.Error.Type;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.ApprovalCategory;
import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
@@ -28,11 +31,12 @@ import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.change.Abandon;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.PostReview;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
import com.google.gerrit.server.changedetail.PublishDraft;
import com.google.gerrit.server.changedetail.RestoreChange;
import com.google.gerrit.server.changedetail.Submit;
import com.google.gerrit.server.patch.PublishComments;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
@@ -124,7 +128,7 @@ public class ReviewCommand extends SshCommand {
private Provider<Abandon> abandonProvider;
@Inject
private PublishComments.Factory publishCommentsFactory;
private Provider<PostReview> reviewProvider;
@Inject
private PublishDraft.Factory publishDraftFactory;
@@ -195,23 +199,29 @@ public class ReviewCommand extends SshCommand {
changeComment = "";
}
Set<ApprovalCategoryValue.Id> aps = new HashSet<ApprovalCategoryValue.Id>();
PostReview.Input review = new PostReview.Input();
review.message = Strings.emptyToNull(changeComment);
review.labels = Maps.newTreeMap();
review.drafts = PostReview.DraftHandling.PUBLISH;
review.strictLabels = false;
for (ApproveOption ao : optionList) {
Short v = ao.value();
if (v != null) {
aps.add(new ApprovalCategoryValue.Id(ao.getCategoryId(), v));
review.labels.put(ao.getLabelName(), v);
}
}
try {
publishCommentsFactory.create(patchSetId, changeComment, aps, forceMessage).call();
ChangeControl ctl =
changeControlFactory.controlFor(patchSetId.getParentKey());
reviewProvider.get().apply(new RevisionResource(
new ChangeResource(ctl),
db.patchSets().get(patchSetId)), review);
if (abandonChange) {
final Abandon abandon = abandonProvider.get();
final Abandon.Input input = new Abandon.Input();
input.message = changeComment;
ChangeControl ctl =
changeControlFactory.controlFor(patchSetId.getParentKey());
try {
abandon.apply(new ChangeResource(ctl), input);
} catch(AuthException e) {
@@ -234,6 +244,10 @@ public class ReviewCommand extends SshCommand {
throw error(e.getMessage());
} catch (IllegalStateException e) {
throw error(e.getMessage());
} catch (AuthException e) {
throw error(e.getMessage());
} catch (BadRequestException e) {
throw error(e.getMessage());
}
if (publishPatchSet) {