Port "mark reviewed" to new JSON API

Defines /changes/*/revisions/*/files/* as the JSON endpoint for file
resources, escaping / as %2F as in /projects. Add an endpoint
/reviewed under this to mark/unmark files as reviewed with PUT/DELETE.

Change-Id: I1de9934b709bdad8014d1d30a25703d7fd55be88
This commit is contained in:
Dave Borowitz
2013-01-28 14:15:27 -08:00
parent ed786b3518
commit 2d99233a29
11 changed files with 224 additions and 24 deletions

View File

@@ -15,23 +15,25 @@
package com.google.gerrit.client.patches;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.changes.PatchTable;
import com.google.gerrit.client.changes.PatchTable.PatchValidator;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.ChangeLink;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.VoidResult;
public class ReviewedPanels {
@@ -98,18 +100,28 @@ public class ReviewedPanels {
fileList.updateReviewedStatus(patchKey, reviewed);
}
PatchUtil.DETAIL_SVC.setReviewedByCurrentUser(patchKey, reviewed,
new AsyncCallback<VoidResult>() {
@Override
public void onFailure(Throwable arg0) {
// nop
}
PatchSet.Id ps = patchKey.getParentKey();
RestApi api = new RestApi("/changes/").id(ps.getParentKey().get())
.view("revisions").id(ps.get())
.view("files").id(patchKey.getFileName())
.view("reviewed");
@Override
public void onSuccess(VoidResult result) {
// nop
}
});
AsyncCallback<VoidResult> cb = new AsyncCallback<VoidResult>() {
@Override
public void onFailure(Throwable arg0) {
// nop
}
@Override
public void onSuccess(VoidResult result) {
// nop
}
};
if (reviewed) {
api.put(cb);
} else {
api.delete(cb);
}
}
public void go() {

View File

@@ -210,6 +210,10 @@ public class RestApi {
return idRaw(URL.encodeQueryString(id));
}
public RestApi id(int id) {
return idRaw(Integer.toString(id));
}
public RestApi idRaw(String name) {
if (hasQueryParams) {
throw new IllegalStateException();

View File

@@ -57,7 +57,7 @@ class CreateDraft implements RestModifyView<RevisionResource, Input> {
new Patch.Key(rsrc.getPatchSet().getId(), in.path),
ChangeUtil.messageUUID(db.get())),
in.line != null ? in.line : 0,
rsrc.getAuthorId(),
rsrc.getAccountId(),
Url.decode(in.inReplyTo));
c.setStatus(Status.DRAFT);
c.setSide(in.side == GetDraft.Side.PARENT ? (short) 0 : (short) 1);

View File

@@ -64,7 +64,7 @@ class Drafts implements ChildCollection<RevisionResource, DraftResource> {
for (PatchLineComment c : dbProvider.get().patchComments()
.draftByPatchSetAuthor(
rev.getPatchSet().getId(),
rev.getAuthorId())) {
rev.getAccountId())) {
if (uuid.equals(c.getKey().get())) {
return new DraftResource(rev, c);
}

View File

@@ -49,7 +49,7 @@ class ListDrafts implements RestReadView<RevisionResource> {
for (PatchLineComment c : db.get().patchComments()
.draftByPatchSetAuthor(
rsrc.getPatchSet().getId(),
rsrc.getAuthorId())) {
rsrc.getAccountId())) {
Comment o = new Comment(c);
List<Comment> list = out.get(o.path);
if (list == null) {

View File

@@ -16,11 +16,14 @@ package com.google.gerrit.server.change;
import static com.google.gerrit.server.change.ChangeResource.CHANGE_KIND;
import static com.google.gerrit.server.change.DraftResource.DRAFT_KIND;
import static com.google.gerrit.server.change.PatchResource.PATCH_KIND;
import static com.google.gerrit.server.change.ReviewerResource.REVIEWER_KIND;
import static com.google.gerrit.server.change.RevisionResource.REVISION_KIND;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.gerrit.server.change.Reviewed.DeleteReviewed;
import com.google.gerrit.server.change.Reviewed.PutReviewed;
import com.google.gerrit.server.config.FactoryModule;
public class Module extends RestApiModule {
@@ -29,9 +32,11 @@ public class Module extends RestApiModule {
bind(Revisions.class);
bind(Reviewers.class);
bind(Drafts.class);
bind(Patches.class);
DynamicMap.mapOf(binder(), CHANGE_KIND);
DynamicMap.mapOf(binder(), DRAFT_KIND);
DynamicMap.mapOf(binder(), PATCH_KIND);
DynamicMap.mapOf(binder(), REVIEWER_KIND);
DynamicMap.mapOf(binder(), REVISION_KIND);
@@ -58,6 +63,10 @@ public class Module extends RestApiModule {
put(DRAFT_KIND).to(PutDraft.class);
delete(DRAFT_KIND).to(DeleteDraft.class);
child(REVISION_KIND, "files").to(Patches.class);
put(PATCH_KIND, "reviewed").to(PutReviewed.class);
delete(PATCH_KIND, "reviewed").to(DeleteReviewed.class);
install(new FactoryModule() {
@Override
protected void configure() {

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2013 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.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.inject.TypeLiteral;
public class PatchResource implements RestResource {
public static final TypeLiteral<RestView<PatchResource>> PATCH_KIND =
new TypeLiteral<RestView<PatchResource>>() {};
private final RevisionResource rev;
private final Patch.Key key;
PatchResource(RevisionResource rev, String name) {
this.rev = rev;
this.key = new Patch.Key(rev.getPatchSet().getId(), name);
}
public Patch.Key getPatchKey() {
return key;
}
Account.Id getAccountId() {
return rev.getAccountId();
}
}

View File

@@ -0,0 +1,49 @@
// Copyright (C) 2013 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.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
class Patches implements ChildCollection<RevisionResource, PatchResource> {
private final DynamicMap<RestView<PatchResource>> views;
@Inject
Patches(DynamicMap<RestView<PatchResource>> views) {
this.views = views;
}
@Override
public DynamicMap<RestView<PatchResource>> views() {
return views;
}
@Override
public RestView<RevisionResource> list() throws AuthException {
throw new UnsupportedOperationException();
}
@Override
public PatchResource parse(RevisionResource rev, IdString id)
throws ResourceNotFoundException, OrmException, AuthException {
return new PatchResource(rev, id.get());
}
}

View File

@@ -161,7 +161,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
input.notify,
change,
revision.getPatchSet(),
revision.getAuthorId(),
revision.getAccountId(),
message,
comments).sendAsync();
fireCommentAddedHook(revision);
@@ -285,7 +285,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
new Patch.Key(rsrc.getPatchSet().getId(), path),
ChangeUtil.messageUUID(db)),
c.line,
rsrc.getAuthorId(),
rsrc.getAccountId(),
parent);
} else if (parent != null) {
e.setParentUuid(parent);
@@ -326,7 +326,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
Map<String, PatchLineComment> drafts = Maps.newHashMap();
for (PatchLineComment c : db.patchComments().draftByPatchSetAuthor(
rsrc.getPatchSet().getId(),
rsrc.getAuthorId())) {
rsrc.getAccountId())) {
drafts.put(c.getKey().get(), c);
}
return drafts;
@@ -375,7 +375,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
} else if (c == null) {
c = new PatchSetApproval(new PatchSetApproval.Key(
rsrc.getPatchSet().getId(),
rsrc.getAuthorId(),
rsrc.getAccountId(),
at.getCategory().getId()),
ent.getValue());
c.setGranted(timestamp);
@@ -405,7 +405,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
// as a reviewer by picking the first server-wide ApprovalType.
PatchSetApproval c = new PatchSetApproval(new PatchSetApproval.Key(
rsrc.getPatchSet().getId(),
rsrc.getAuthorId(),
rsrc.getAccountId(),
approvalTypes.getApprovalTypes().get(0).getCategory().getId()),
(short) 0);
c.setGranted(timestamp);
@@ -428,7 +428,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
List<PatchSetApproval> del) throws OrmException {
Map<String, PatchSetApproval> current = Maps.newHashMap();
for (PatchSetApproval a : db.patchSetApprovals().byPatchSetUser(
rsrc.getPatchSet().getId(), rsrc.getAuthorId())) {
rsrc.getPatchSet().getId(), rsrc.getAccountId())) {
if (ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
continue;
}
@@ -475,7 +475,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
message = new ChangeMessage(
new ChangeMessage.Key(change.getId(), ChangeUtil.messageUUID(db)),
rsrc.getAuthorId(),
rsrc.getAccountId(),
timestamp,
rsrc.getPatchSet().getId());
message.setMessage(String.format(

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2013 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.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.AccountPatchReview;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collections;
class Reviewed {
static class Input {
}
static class PutReviewed implements RestModifyView<PatchResource, Input> {
private final Provider<ReviewDb> dbProvider;
@Inject
PutReviewed(Provider<ReviewDb> dbProvider) {
this.dbProvider = dbProvider;
}
@Override
public Object apply(PatchResource resource, Input input)
throws OrmException {
ReviewDb db = dbProvider.get();
AccountPatchReview apr = getExisting(db, resource);
if (apr == null) {
db.accountPatchReviews().insert(
Collections.singleton(new AccountPatchReview(resource.getPatchKey(),
resource.getAccountId())));
return Response.created("");
} else {
return Response.ok("");
}
}
}
static class DeleteReviewed implements RestModifyView<PatchResource, Input> {
private final Provider<ReviewDb> dbProvider;
@Inject
DeleteReviewed(Provider<ReviewDb> dbProvider) {
this.dbProvider = dbProvider;
}
@Override
public Object apply(PatchResource resource, Input input)
throws OrmException {
ReviewDb db = dbProvider.get();
AccountPatchReview apr = getExisting(db, resource);
if (apr != null) {
db.accountPatchReviews().delete(Collections.singleton(apr));
}
return Response.none();
}
}
private static AccountPatchReview getExisting(ReviewDb db,
PatchResource resource) throws OrmException {
AccountPatchReview.Key key = new AccountPatchReview.Key(
resource.getPatchKey(), resource.getAccountId());
return db.accountPatchReviews().get(key);
}
private Reviewed() {
}
}

View File

@@ -47,7 +47,7 @@ public class RevisionResource implements RestResource {
return ps;
}
Account.Id getAuthorId() {
Account.Id getAccountId() {
return ((IdentifiedUser) getControl().getCurrentUser()).getAccountId();
}
}