Add REST APIs to test submit_rule and submit_filter
These are available over SSH, but not on HTTP. Make them available on HTTP with REST API views on the revision resource. Use the REST implementations to back the SSH commands, so the implementation is not duplicated. To match the REST API the SSH test-submit rule command no longer accepts a format parameter. Output is in pretty formatted JSON. Change-Id: I6a57b4561067eaa32d407a426c95ea61a96f1948
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
import com.google.gerrit.server.OutputFormat;
|
||||
import com.google.gerrit.server.change.ChangesCollection;
|
||||
import com.google.gerrit.server.change.RevisionResource;
|
||||
import com.google.gerrit.server.change.Revisions;
|
||||
import com.google.gerrit.server.change.TestSubmitRule.Filters;
|
||||
import com.google.gerrit.server.change.TestSubmitRule.Input;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.jgit.util.IO;
|
||||
import org.eclipse.jgit.util.RawParseUtils;
|
||||
import org.kohsuke.args4j.Argument;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
abstract class BaseTestPrologCommand extends SshCommand {
|
||||
private Input input = new Input();
|
||||
|
||||
@Inject
|
||||
private ChangesCollection changes;
|
||||
|
||||
@Inject
|
||||
private Revisions revisions;
|
||||
|
||||
@Argument(index = 0, required = true, usage = "ChangeId to load in prolog environment")
|
||||
protected String changeId;
|
||||
|
||||
@Option(name = "-s",
|
||||
usage = "Read prolog script from stdin instead of reading rules.pl from the refs/meta/config branch")
|
||||
protected boolean useStdin;
|
||||
|
||||
@Option(name = "--no-filters", aliases = {"-n"},
|
||||
usage = "Don't run the submit_filter/2 from the parent projects")
|
||||
void setNoFilters(boolean no) {
|
||||
input.filters = no ? Filters.SKIP : Filters.RUN;
|
||||
}
|
||||
|
||||
protected abstract RestModifyView<RevisionResource, Input> createView();
|
||||
|
||||
protected final void run() throws UnloggedFailure {
|
||||
try {
|
||||
RevisionResource revision = revisions.parse(
|
||||
changes.parse(
|
||||
TopLevelResource.INSTANCE,
|
||||
IdString.fromUrl(changeId)),
|
||||
IdString.fromUrl("current"));
|
||||
if (useStdin) {
|
||||
ByteBuffer buf = IO.readWholeStream(in, 4096);
|
||||
input.rule = RawParseUtils.decode(
|
||||
buf.array(),
|
||||
buf.arrayOffset(),
|
||||
buf.limit());
|
||||
}
|
||||
Object result = createView().apply(revision, input);
|
||||
OutputFormat.JSON.newGson().toJson(result, stdout);
|
||||
stdout.print('\n');
|
||||
} catch (Exception e) {
|
||||
throw new UnloggedFailure("Processing of prolog script failed: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.OutputFormat;
|
||||
import com.google.gerrit.server.account.AccountCache;
|
||||
import com.google.gerrit.server.config.AnonymousCowardName;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gerrit.server.project.SubmitRuleEvaluator;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import com.googlecode.prolog_cafe.lang.ListTerm;
|
||||
import com.googlecode.prolog_cafe.lang.Term;
|
||||
|
||||
import org.kohsuke.args4j.Argument;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
abstract class BaseTestSubmit extends SshCommand {
|
||||
@Inject
|
||||
protected ReviewDb db;
|
||||
|
||||
@Inject
|
||||
private ChangeControl.Factory ccFactory;
|
||||
|
||||
@Inject
|
||||
protected AccountCache accountCache;
|
||||
|
||||
@Inject
|
||||
@AnonymousCowardName
|
||||
protected String anonymousCowardName;
|
||||
|
||||
@Argument(index = 0, required = true, usage = "ChangeId to load in prolog environment")
|
||||
protected String changeId;
|
||||
|
||||
@Option(name = "-s",
|
||||
usage = "Read prolog script from stdin instead of reading rules.pl from the refs/meta/config branch")
|
||||
protected boolean useStdin;
|
||||
|
||||
@Option(name = "--format", metaVar = "FMT", usage = "Output display format")
|
||||
protected OutputFormat format = OutputFormat.TEXT;
|
||||
|
||||
@Option(name = "--no-filters", aliases = {"-n"},
|
||||
usage = "Don't run the submit_filter/2 from the parent projects")
|
||||
protected boolean skipSubmitFilters;
|
||||
|
||||
private Change change;
|
||||
|
||||
private ChangeControl changeControl;
|
||||
|
||||
protected abstract SubmitRuleEvaluator createEvaluator(PatchSet ps)
|
||||
throws Exception;
|
||||
protected abstract void processResults(ListTerm results, Term submitRule)
|
||||
throws Exception;
|
||||
|
||||
protected final void run() throws UnloggedFailure {
|
||||
try {
|
||||
PatchSet ps = db.patchSets().get(getChange().currentPatchSetId());
|
||||
SubmitRuleEvaluator evaluator = createEvaluator(ps);
|
||||
processResults(evaluator.evaluate(), evaluator.getSubmitRule());
|
||||
} catch (Exception e) {
|
||||
throw new UnloggedFailure("Processing of prolog script failed: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
protected final Change getChange() throws OrmException, UnloggedFailure {
|
||||
if (change == null) {
|
||||
List<Change> changeList =
|
||||
db.changes().byKey(new Change.Key(changeId)).toList();
|
||||
if (changeList.size() != 1)
|
||||
throw new UnloggedFailure(1, "Invalid ChangeId");
|
||||
|
||||
change = changeList.get(0);
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
protected final ChangeControl getChangeControl() throws OrmException,
|
||||
NoSuchChangeException, UnloggedFailure {
|
||||
if (changeControl == null) {
|
||||
// Will throw exception if current user can not access this change, and
|
||||
// thus will leak information that a change-id is valid even though the
|
||||
// user are not allowed to see the change.
|
||||
// See http://code.google.com/p/gerrit/issues/detail?id=1586
|
||||
changeControl = ccFactory.controlFor(getChange());
|
||||
}
|
||||
return changeControl;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ public class MasterCommandModule extends CommandModule {
|
||||
command(gerrit, RenameGroupCommand.class);
|
||||
command(gerrit, CreateProjectCommand.class);
|
||||
command(gerrit, AdminQueryShell.class);
|
||||
command(gerrit, TestSubmitRule.class);
|
||||
command(gerrit, SetReviewersCommand.class);
|
||||
command(gerrit, Receive.class);
|
||||
command(gerrit, AdminSetParent.class);
|
||||
@@ -43,7 +42,7 @@ public class MasterCommandModule extends CommandModule {
|
||||
command(gerrit, SetProjectCommand.class);
|
||||
|
||||
command(gerrit, "test-submit").toProvider(new DispatchCommandProvider(testSubmit));
|
||||
command(testSubmit, TestSubmitRule.class);
|
||||
command(testSubmit, TestSubmitType.class);
|
||||
command(testSubmit, TestSubmitRuleCommand.class);
|
||||
command(testSubmit, TestSubmitTypeCommand.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.AccountInfo;
|
||||
import com.google.gerrit.common.data.SubmitRecord;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.server.events.AccountAttribute;
|
||||
import com.google.gerrit.server.events.SubmitLabelAttribute;
|
||||
import com.google.gerrit.server.events.SubmitRecordAttribute;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.SubmitRuleEvaluator;
|
||||
import com.google.gerrit.sshd.CommandMetaData;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import com.googlecode.prolog_cafe.lang.ListTerm;
|
||||
import com.googlecode.prolog_cafe.lang.Term;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/** Command that allows testing of prolog submit-rules in a live instance. */
|
||||
@CommandMetaData(name = "rule", descr = "Test prolog submit rules")
|
||||
final class TestSubmitRule extends BaseTestSubmit {
|
||||
|
||||
protected SubmitRuleEvaluator createEvaluator(PatchSet ps) throws Exception {
|
||||
ChangeControl cc = getChangeControl();
|
||||
return new SubmitRuleEvaluator(
|
||||
db, ps, cc.getProjectControl(), cc, getChange(), null,
|
||||
false, "locate_submit_rule", "can_submit",
|
||||
"locate_submit_filter", "filter_submit_results",
|
||||
skipSubmitFilters, useStdin ? in : null);
|
||||
}
|
||||
|
||||
protected void processResults(ListTerm results, Term submitRule) throws Exception {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<SubmitRecord> res = getChangeControl().resultsToSubmitRecord(submitRule,
|
||||
results.toJava());
|
||||
if (res.isEmpty()) {
|
||||
// Should never occur for a well written rule
|
||||
Change c = getChange();
|
||||
stderr.print("Submit rule " + submitRule + " for change " + c.getChangeId()
|
||||
+ " of " + c.getProject().get() + " has no solution");
|
||||
return;
|
||||
}
|
||||
for (SubmitRecord r : res) {
|
||||
if (format.isJson()) {
|
||||
SubmitRecordAttribute submitRecord = new SubmitRecordAttribute();
|
||||
submitRecord.status = r.status.name();
|
||||
|
||||
List<SubmitLabelAttribute> submitLabels = new LinkedList<SubmitLabelAttribute>();
|
||||
for(SubmitRecord.Label l : r.labels) {
|
||||
SubmitLabelAttribute label = new SubmitLabelAttribute();
|
||||
label.label = l.label;
|
||||
label.status= l.status.name();
|
||||
if(l.appliedBy != null) {
|
||||
Account a = accountCache.get(l.appliedBy).getAccount();
|
||||
label.by = new AccountAttribute();
|
||||
label.by.email = a.getPreferredEmail();
|
||||
label.by.name = a.getFullName();
|
||||
label.by.username = a.getUserName();
|
||||
}
|
||||
submitLabels.add(label);
|
||||
}
|
||||
submitRecord.labels = submitLabels;
|
||||
format.newGson().toJson(submitRecord, new TypeToken<SubmitRecordAttribute>() {}.getType(), stdout);
|
||||
stdout.print('\n');
|
||||
} else {
|
||||
for(SubmitRecord.Label l : r.labels) {
|
||||
stdout.print(l.label + ": " + l.status);
|
||||
if(l.appliedBy != null) {
|
||||
AccountInfo a = new AccountInfo(accountCache.get(l.appliedBy).getAccount());
|
||||
stdout.print(" by " + a.getNameEmail(anonymousCowardName));
|
||||
}
|
||||
stdout.print('\n');
|
||||
}
|
||||
stdout.print("\n" + r.status.name() + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||
import com.google.gerrit.server.change.RevisionResource;
|
||||
import com.google.gerrit.server.change.TestSubmitRule;
|
||||
import com.google.gerrit.server.change.TestSubmitRule.Input;
|
||||
import com.google.gerrit.sshd.CommandMetaData;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/** Command that allows testing of prolog submit-rules in a live instance. */
|
||||
@CommandMetaData(name = "rule", descr = "Test prolog submit rules")
|
||||
final class TestSubmitRuleCommand extends BaseTestPrologCommand {
|
||||
@Inject
|
||||
private Provider<TestSubmitRule> view;
|
||||
|
||||
@Override
|
||||
protected RestModifyView<RevisionResource, Input> createView() {
|
||||
return view.get();
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.SubmitRuleEvaluator;
|
||||
import com.google.gerrit.sshd.CommandMetaData;
|
||||
|
||||
import com.googlecode.prolog_cafe.lang.ListTerm;
|
||||
import com.googlecode.prolog_cafe.lang.Term;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@CommandMetaData(name = "type", descr = "Test prolog submit type")
|
||||
final class TestSubmitType extends BaseTestSubmit {
|
||||
|
||||
@Override
|
||||
protected SubmitRuleEvaluator createEvaluator(PatchSet ps) throws Exception {
|
||||
ChangeControl cc = getChangeControl();
|
||||
return new SubmitRuleEvaluator(
|
||||
db, ps, cc.getProjectControl(), cc, getChange(), null,
|
||||
false, "locate_submit_type", "get_submit_type",
|
||||
"locate_submit_type_filter", "filter_submit_type_results",
|
||||
skipSubmitFilters, useStdin ? in : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResults(ListTerm resultsTerm, Term submitRule)
|
||||
throws Exception {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> results = resultsTerm.toJava();
|
||||
if (results.isEmpty()) {
|
||||
// Should never occur for a well written rule
|
||||
Change c = getChange();
|
||||
stderr.print("Submit rule " + submitRule + " for change " + c.getChangeId()
|
||||
+ " of " + c.getProject().get() + " has no solution");
|
||||
return;
|
||||
}
|
||||
String typeName = results.get(0);
|
||||
stdout.print(typeName);
|
||||
stdout.print('\n');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||
import com.google.gerrit.server.change.RevisionResource;
|
||||
import com.google.gerrit.server.change.TestSubmitRule.Input;
|
||||
import com.google.gerrit.server.change.TestSubmitType;
|
||||
import com.google.gerrit.sshd.CommandMetaData;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
@CommandMetaData(name = "type", descr = "Test prolog submit type")
|
||||
final class TestSubmitTypeCommand extends BaseTestPrologCommand {
|
||||
@Inject
|
||||
private Provider<TestSubmitType> view;
|
||||
|
||||
@Override
|
||||
protected RestModifyView<RevisionResource, Input> createView() {
|
||||
return view.get();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user