Define API to invoke the REST API from within extensions and plugins
The REST API available over HTTP is planned to be supported for a long time in the future. It is very well documented and has fairly clean resource semantics. Extension and plugin authors want to use this API from within the server itself to access resources, shielding them from any internal changes. GerritApi is a simple API exposed to plugins as an interface. The API mirrors the REST API resource tree. Posting a review on a commit is similar: @Inject private GerritApi api; [...] ReviewInput input = new ReviewInput(); input.message = "Looks good!"; input.labels = new HashMap<String, Short>(); input.labels.put("Code-Review", (short) 2); api.changes().id(12345).revision("c0ffee....").review(input); In this commit we provide only the basic skeleton and a single API call for posting review comments. An alternative approach is to use reflection to generate a proxy implementation of the interfaces and bind everything dynamically at runtime similar to the way RestApiServlet is implemented. The hand coded implementation offered here provides some compile-time assurances the server has each API implemented and the API accepts the correct input type. Change-Id: Ic25c69c0660e2796d090a4a37445820726e543d2
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
// 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.extensions.api;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.Changes;
|
||||
|
||||
public interface GerritApi {
|
||||
public Changes changes();
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
// 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.extensions.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
|
||||
public interface ChangeApi {
|
||||
RevisionApi revision(int id) throws RestApiException;
|
||||
RevisionApi revision(String id) throws RestApiException;
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
// 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.extensions.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
|
||||
public interface Changes {
|
||||
ChangeApi id(int id) throws RestApiException;
|
||||
ChangeApi id(String triplet) throws RestApiException;
|
||||
ChangeApi id(String project, String branch, String id)
|
||||
throws RestApiException;
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
// 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.extensions.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.DefaultInput;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Input passed to {@code POST /changes/{id}/revisions/{id}/review}. */
|
||||
public class ReviewInput {
|
||||
@DefaultInput
|
||||
public String message;
|
||||
|
||||
public Map<String, Short> labels;
|
||||
public Map<String, List<Comment>> comments;
|
||||
|
||||
/**
|
||||
* If true require all labels to be within the user's permitted ranges based
|
||||
* on access controls, attempting to use a label not granted to the user
|
||||
* will fail the entire modify operation early. If false the operation will
|
||||
* execute anyway, but the proposed labels given by the user will be
|
||||
* modified to be the "best" value allowed by the access controls, or
|
||||
* ignored if the label does not exist.
|
||||
*/
|
||||
public boolean strictLabels = true;
|
||||
|
||||
/**
|
||||
* How to process draft comments already in the database that were not also
|
||||
* described in this input request.
|
||||
*/
|
||||
public DraftHandling drafts = DraftHandling.DELETE;
|
||||
|
||||
/** Who to send email notifications to after review is stored. */
|
||||
public NotifyHandling notify = NotifyHandling.ALL;
|
||||
|
||||
/**
|
||||
* Account ID, name, email address or username of another user. The review
|
||||
* will be posted/updated on behalf of this named user instead of the
|
||||
* caller. Caller must have the labelAs-$NAME permission granted for each
|
||||
* label that appears in {@link #labels}. This is in addition to the named
|
||||
* user also needing to have permission to use the labels.
|
||||
* <p>
|
||||
* {@link #strictLabels} impacts how labels is processed for the named user,
|
||||
* not the caller.
|
||||
*/
|
||||
public String onBehalfOf;
|
||||
|
||||
public static enum DraftHandling {
|
||||
DELETE, PUBLISH, KEEP;
|
||||
}
|
||||
|
||||
public static enum NotifyHandling {
|
||||
NONE, OWNER, OWNER_REVIEWERS, ALL;
|
||||
}
|
||||
|
||||
public static enum Side {
|
||||
PARENT, REVISION;
|
||||
}
|
||||
|
||||
public static class Comment {
|
||||
public String id;
|
||||
public Side side;
|
||||
public int line;
|
||||
public String inReplyTo;
|
||||
public String message;
|
||||
public Range range;
|
||||
|
||||
public static class Range {
|
||||
public int startLine;
|
||||
public int startCharacter;
|
||||
public int endLine;
|
||||
public int endCharacter;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
// 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.extensions.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
|
||||
public interface RevisionApi {
|
||||
void review(ReviewInput in) throws RestApiException;
|
||||
}
|
@@ -15,7 +15,7 @@
|
||||
package com.google.gerrit.extensions.restapi;
|
||||
|
||||
/** Root exception type for JSON API failures. */
|
||||
public abstract class RestApiException extends Exception {
|
||||
public class RestApiException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private CacheControl caching = CacheControl.NONE;
|
||||
|
||||
|
@@ -0,0 +1,34 @@
|
||||
// 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.api;
|
||||
|
||||
import com.google.gerrit.extensions.api.GerritApi;
|
||||
import com.google.gerrit.extensions.api.changes.Changes;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
class GerritApiImpl implements GerritApi {
|
||||
private final Provider<Changes> changes;
|
||||
|
||||
@Inject
|
||||
GerritApiImpl(Provider<Changes> changes) {
|
||||
this.changes = changes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Changes changes() {
|
||||
return changes.get();
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
// 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.api;
|
||||
|
||||
import com.google.gerrit.extensions.api.GerritApi;
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
public class Module extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(GerritApi.class).to(GerritApiImpl.class);
|
||||
|
||||
install(new com.google.gerrit.server.api.changes.Module());
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
// 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.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.ChangeApi;
|
||||
import com.google.gerrit.extensions.api.changes.RevisionApi;
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.server.change.ChangeResource;
|
||||
import com.google.gerrit.server.change.Revisions;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
class ChangeApiImpl implements ChangeApi {
|
||||
interface Factory {
|
||||
ChangeApiImpl create(ChangeResource change);
|
||||
}
|
||||
|
||||
private final Revisions revisions;
|
||||
private final RevisionApiImpl.Factory revisionApi;
|
||||
private final ChangeResource change;
|
||||
|
||||
@Inject
|
||||
ChangeApiImpl(Revisions revisions,
|
||||
RevisionApiImpl.Factory api,
|
||||
@Assisted ChangeResource change) {
|
||||
this.revisions = revisions;
|
||||
this.revisionApi = api;
|
||||
this.change = change;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RevisionApi revision(int id) throws RestApiException {
|
||||
return revision(String.valueOf(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RevisionApi revision(String id) throws RestApiException {
|
||||
try {
|
||||
return revisionApi.create(
|
||||
revisions.parse(change, IdString.fromDecoded(id)));
|
||||
} catch (OrmException e) {
|
||||
throw new RestApiException("Cannot parse revision", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
// 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.api.changes;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gerrit.extensions.api.changes.ChangeApi;
|
||||
import com.google.gerrit.extensions.api.changes.Changes;
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
import com.google.gerrit.server.change.ChangesCollection;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
class ChangesImpl implements Changes {
|
||||
private final ChangesCollection changes;
|
||||
private final ChangeApiImpl.Factory api;
|
||||
|
||||
@Inject
|
||||
ChangesImpl(ChangesCollection changes, ChangeApiImpl.Factory api) {
|
||||
this.changes = changes;
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeApi id(int id) throws RestApiException {
|
||||
return id(String.valueOf(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeApi id(String project, String branch, String id)
|
||||
throws RestApiException {
|
||||
return id(Joiner.on('~').join(ImmutableList.of(
|
||||
Url.encode(project),
|
||||
Url.encode(branch),
|
||||
Url.encode(id))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeApi id(String id) throws RestApiException {
|
||||
try {
|
||||
return api.create(changes.parse(
|
||||
TopLevelResource.INSTANCE,
|
||||
IdString.fromUrl(id)));
|
||||
} catch (OrmException e) {
|
||||
throw new RestApiException("Cannot parse change", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
// 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.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.Changes;
|
||||
import com.google.gerrit.server.config.FactoryModule;
|
||||
|
||||
public class Module extends FactoryModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(Changes.class).to(ChangesImpl.class);
|
||||
|
||||
factory(ChangeApiImpl.Factory.class);
|
||||
factory(RevisionApiImpl.Factory.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
// 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.api.changes;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.changes.RevisionApi;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.server.change.PostReview;
|
||||
import com.google.gerrit.server.change.RevisionResource;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class RevisionApiImpl implements RevisionApi {
|
||||
interface Factory {
|
||||
RevisionApiImpl create(RevisionResource r);
|
||||
}
|
||||
|
||||
private final Provider<PostReview> review;
|
||||
private final RevisionResource revision;
|
||||
|
||||
@Inject
|
||||
RevisionApiImpl(Provider<PostReview> review,
|
||||
@Assisted RevisionResource r) {
|
||||
this.review = review;
|
||||
this.revision = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void review(ReviewInput in) throws RestApiException {
|
||||
try {
|
||||
review.get().apply(revision, in);
|
||||
} catch (OrmException e) {
|
||||
throw new RestApiException("Cannot post review", e);
|
||||
} catch (IOException e) {
|
||||
throw new RestApiException("Cannot post review", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,7 +31,6 @@ import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -69,8 +68,7 @@ public class ChangesCollection implements
|
||||
|
||||
@Override
|
||||
public ChangeResource parse(TopLevelResource root, IdString id)
|
||||
throws ResourceNotFoundException, OrmException,
|
||||
UnsupportedEncodingException {
|
||||
throws ResourceNotFoundException, OrmException {
|
||||
List<Change> changes = findChanges(id.encoded());
|
||||
if (changes.size() != 1) {
|
||||
throw new ResourceNotFoundException(id);
|
||||
|
@@ -15,6 +15,7 @@
|
||||
package com.google.gerrit.server.change;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
||||
@@ -22,7 +23,6 @@ import com.google.gerrit.reviewdb.client.PatchLineComment;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.change.PostReview.NotifyHandling;
|
||||
import com.google.gerrit.server.git.WorkQueue;
|
||||
import com.google.gerrit.server.mail.CommentSender;
|
||||
import com.google.gerrit.server.patch.PatchSetInfoFactory;
|
||||
@@ -61,7 +61,7 @@ class EmailReviewComments implements Runnable, RequestContext {
|
||||
private final SchemaFactory<ReviewDb> schemaFactory;
|
||||
private final ThreadLocalRequestContext requestContext;
|
||||
|
||||
private final PostReview.NotifyHandling notify;
|
||||
private final NotifyHandling notify;
|
||||
private final Change change;
|
||||
private final PatchSet patchSet;
|
||||
private final Account.Id authorId;
|
||||
|
@@ -23,14 +23,17 @@ import com.google.common.collect.Maps;
|
||||
import com.google.common.util.concurrent.CheckedFuture;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.gerrit.common.ChangeHooks;
|
||||
import com.google.gerrit.common.changes.Side;
|
||||
import com.google.gerrit.common.data.LabelType;
|
||||
import com.google.gerrit.common.data.LabelTypes;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.common.data.PermissionRange;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.Comment;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.Side;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.DefaultInput;
|
||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
@@ -44,7 +47,6 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.account.AccountsCollection;
|
||||
import com.google.gerrit.server.change.PostReview.Input;
|
||||
import com.google.gerrit.server.index.ChangeIndexer;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.util.TimeUtil;
|
||||
@@ -62,67 +64,11 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PostReview implements RestModifyView<RevisionResource, Input> {
|
||||
public class PostReview implements RestModifyView<RevisionResource, ReviewInput> {
|
||||
private static final Logger log = LoggerFactory.getLogger(PostReview.class);
|
||||
|
||||
public static class Input {
|
||||
@DefaultInput
|
||||
public String message;
|
||||
|
||||
public Map<String, Short> labels;
|
||||
public Map<String, List<Comment>> comments;
|
||||
|
||||
/**
|
||||
* If true require all labels to be within the user's permitted ranges based
|
||||
* on access controls, attempting to use a label not granted to the user
|
||||
* will fail the entire modify operation early. If false the operation will
|
||||
* execute anyway, but the proposed labels given by the user will be
|
||||
* modified to be the "best" value allowed by the access controls, or
|
||||
* ignored if the label does not exist.
|
||||
*/
|
||||
public boolean strictLabels = true;
|
||||
|
||||
/**
|
||||
* How to process draft comments already in the database that were not also
|
||||
* described in this input request.
|
||||
*/
|
||||
public DraftHandling drafts = DraftHandling.DELETE;
|
||||
|
||||
/** Who to send email notifications to after review is stored. */
|
||||
public NotifyHandling notify = NotifyHandling.ALL;
|
||||
|
||||
/**
|
||||
* Account ID, name, email address or username of another user. The review
|
||||
* will be posted/updated on behalf of this named user instead of the
|
||||
* caller. Caller must have the labelAs-$NAME permission granted for each
|
||||
* label that appears in {@link #labels}. This is in addition to the named
|
||||
* user also needing to have permission to use the labels.
|
||||
* <p>
|
||||
* {@link #strictLabels} impacts how labels is processed for the named user,
|
||||
* not the caller.
|
||||
*/
|
||||
public String onBehalfOf;
|
||||
}
|
||||
|
||||
public static enum DraftHandling {
|
||||
DELETE, PUBLISH, KEEP;
|
||||
}
|
||||
|
||||
public static enum NotifyHandling {
|
||||
NONE, OWNER, OWNER_REVIEWERS, ALL;
|
||||
}
|
||||
|
||||
public static class Comment {
|
||||
public String id;
|
||||
public Side side;
|
||||
public int line;
|
||||
public String inReplyTo;
|
||||
public String message;
|
||||
public CommentRange range;
|
||||
}
|
||||
|
||||
public static class Output {
|
||||
public Map<String, Short> labels;
|
||||
static class Output {
|
||||
Map<String, Short> labels;
|
||||
}
|
||||
|
||||
private final Provider<ReviewDb> db;
|
||||
@@ -152,7 +98,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object apply(RevisionResource revision, Input input)
|
||||
public Object apply(RevisionResource revision, ReviewInput input)
|
||||
throws AuthException, BadRequestException, OrmException,
|
||||
UnprocessableEntityException, IOException {
|
||||
if (input.onBehalfOf != null) {
|
||||
@@ -210,7 +156,7 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
|
||||
return output;
|
||||
}
|
||||
|
||||
private RevisionResource onBehalfOf(RevisionResource rev, Input in)
|
||||
private RevisionResource onBehalfOf(RevisionResource rev, ReviewInput in)
|
||||
throws BadRequestException, AuthException, UnprocessableEntityException,
|
||||
OrmException {
|
||||
if (in.labels == null || in.labels.isEmpty()) {
|
||||
@@ -370,7 +316,13 @@ public class PostReview implements RestModifyView<RevisionResource, Input> {
|
||||
e.setWrittenOn(timestamp);
|
||||
e.setSide(c.side == Side.PARENT ? (short) 0 : (short) 1);
|
||||
e.setMessage(c.message);
|
||||
e.setRange(c.range);
|
||||
if (c.range != null) {
|
||||
e.setRange(new CommentRange(
|
||||
c.range.startLine,
|
||||
c.range.startCharacter,
|
||||
c.range.endLine,
|
||||
c.range.endCharacter));
|
||||
}
|
||||
(create ? ins : upd).add(e);
|
||||
}
|
||||
}
|
||||
|
@@ -226,6 +226,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
install(new AuditModule());
|
||||
install(new com.google.gerrit.server.access.Module());
|
||||
install(new com.google.gerrit.server.account.Module());
|
||||
install(new com.google.gerrit.server.api.Module());
|
||||
install(new com.google.gerrit.server.change.Module());
|
||||
install(new com.google.gerrit.server.config.Module());
|
||||
install(new com.google.gerrit.server.group.Module());
|
||||
|
@@ -17,13 +17,13 @@ package com.google.gerrit.server.mail;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.gerrit.common.errors.EmailException;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.CommentRange;
|
||||
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.server.change.PostReview.NotifyHandling;
|
||||
import com.google.gerrit.server.patch.PatchFile;
|
||||
import com.google.gerrit.server.patch.PatchList;
|
||||
import com.google.gerrit.server.patch.PatchListNotAvailableException;
|
||||
|
@@ -18,10 +18,10 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.change.ChangeInserter;
|
||||
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.project.ChangeControl;
|
||||
|
||||
@@ -70,13 +70,13 @@ public abstract class AbstractIndexQueryChangesTest
|
||||
Change change = ins.insert();
|
||||
ChangeControl ctl = changeControlFactory.controlFor(change, user);
|
||||
|
||||
PostReview.Input input = new PostReview.Input();
|
||||
ReviewInput input = new ReviewInput();
|
||||
input.message = "toplevel";
|
||||
PostReview.Comment comment = new PostReview.Comment();
|
||||
ReviewInput.Comment comment = new ReviewInput.Comment();
|
||||
comment.line = 1;
|
||||
comment.message = "inline";
|
||||
input.comments = ImmutableMap.<String, List<PostReview.Comment>> of(
|
||||
"Foo.java", ImmutableList.<PostReview.Comment> of(comment));
|
||||
input.comments = ImmutableMap.<String, List<ReviewInput.Comment>> of(
|
||||
"Foo.java", ImmutableList.<ReviewInput.Comment> of(comment));
|
||||
postReview.apply(new RevisionResource(
|
||||
new ChangeResource(ctl), ins.getPatchSet()), input);
|
||||
|
||||
|
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
@@ -359,7 +360,7 @@ public abstract class AbstractQueryChangesTest {
|
||||
Change change = ins.insert();
|
||||
ChangeControl ctl = changeControlFactory.controlFor(change, user);
|
||||
|
||||
PostReview.Input input = new PostReview.Input();
|
||||
ReviewInput input = new ReviewInput();
|
||||
input.message = "toplevel";
|
||||
input.labels = ImmutableMap.<String, Short> of("Code-Review", (short) 1);
|
||||
postReview.apply(new RevisionResource(
|
||||
@@ -476,7 +477,7 @@ public abstract class AbstractQueryChangesTest {
|
||||
assertResultEquals(change2, results.get(0));
|
||||
assertResultEquals(change1, results.get(1));
|
||||
|
||||
PostReview.Input input = new PostReview.Input();
|
||||
ReviewInput input = new ReviewInput();
|
||||
input.message = "toplevel";
|
||||
postReview.apply(new RevisionResource(
|
||||
new ChangeResource(ctl1), ins1.getPatchSet()), input);
|
||||
@@ -509,7 +510,7 @@ public abstract class AbstractQueryChangesTest {
|
||||
assertResultEquals(change2, results.get(0));
|
||||
assertResultEquals(change1, results.get(1));
|
||||
|
||||
PostReview.Input input = new PostReview.Input();
|
||||
ReviewInput input = new ReviewInput();
|
||||
input.message = "toplevel";
|
||||
postReview.apply(new RevisionResource(
|
||||
new ChangeResource(ctl1), ins1.getPatchSet()), input);
|
||||
|
@@ -22,6 +22,8 @@ import com.google.gerrit.common.data.LabelType;
|
||||
import com.google.gerrit.common.data.LabelValue;
|
||||
import com.google.gerrit.common.data.ReviewResult;
|
||||
import com.google.gerrit.common.data.ReviewResult.Error.Type;
|
||||
import com.google.gerrit.extensions.api.GerritApi;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
@@ -32,7 +34,6 @@ 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.DeleteDraftPatchSet;
|
||||
import com.google.gerrit.server.change.PostReview;
|
||||
import com.google.gerrit.server.change.Restore;
|
||||
import com.google.gerrit.server.change.RevisionResource;
|
||||
import com.google.gerrit.server.change.Submit;
|
||||
@@ -146,7 +147,7 @@ public class ReviewCommand extends SshCommand {
|
||||
private Provider<Abandon> abandonProvider;
|
||||
|
||||
@Inject
|
||||
private Provider<PostReview> reviewProvider;
|
||||
private Provider<GerritApi> api;
|
||||
|
||||
@Inject
|
||||
private PublishDraft.Factory publishDraftFactory;
|
||||
@@ -213,9 +214,11 @@ public class ReviewCommand extends SshCommand {
|
||||
}
|
||||
|
||||
private void applyReview(final ChangeControl ctl, final PatchSet patchSet,
|
||||
final PostReview.Input review) throws Exception {
|
||||
reviewProvider.get().apply(new RevisionResource(
|
||||
new ChangeResource(ctl), patchSet), review);
|
||||
final ReviewInput review) throws Exception {
|
||||
api.get().changes()
|
||||
.id(ctl.getChange().getChangeId())
|
||||
.revision(patchSet.getRevision().get())
|
||||
.review(review);
|
||||
}
|
||||
|
||||
private void approveOne(final PatchSet patchSet) throws Exception {
|
||||
@@ -224,10 +227,10 @@ public class ReviewCommand extends SshCommand {
|
||||
changeComment = "";
|
||||
}
|
||||
|
||||
PostReview.Input review = new PostReview.Input();
|
||||
ReviewInput review = new ReviewInput();
|
||||
review.message = Strings.emptyToNull(changeComment);
|
||||
review.labels = Maps.newTreeMap();
|
||||
review.drafts = PostReview.DraftHandling.PUBLISH;
|
||||
review.drafts = ReviewInput.DraftHandling.PUBLISH;
|
||||
review.strictLabels = false;
|
||||
for (ApproveOption ao : optionList) {
|
||||
Short v = ao.value();
|
||||
|
Reference in New Issue
Block a user