Merge "Refactor test-submit-rule, remove duplicated code"

This commit is contained in:
Shawn Pearce
2012-11-23 13:26:14 -08:00
committed by Gerrit Code Review

View File

@@ -19,10 +19,8 @@ import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.rules.PrologEnvironment; import com.google.gerrit.rules.PrologEnvironment;
import com.google.gerrit.rules.StoredValues;
import com.google.gerrit.server.OutputFormat; import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.AnonymousCowardName; import com.google.gerrit.server.config.AnonymousCowardName;
@@ -30,33 +28,18 @@ import com.google.gerrit.server.events.AccountAttribute;
import com.google.gerrit.server.events.SubmitLabelAttribute; import com.google.gerrit.server.events.SubmitLabelAttribute;
import com.google.gerrit.server.events.SubmitRecordAttribute; import com.google.gerrit.server.events.SubmitRecordAttribute;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ProjectState; import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.sshd.SshCommand; import com.google.gerrit.sshd.SshCommand;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.googlecode.prolog_cafe.compiler.CompileException;
import com.googlecode.prolog_cafe.lang.BufferingPrologControl;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.ListTerm;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologClassLoader;
import com.googlecode.prolog_cafe.lang.PrologException;
import com.googlecode.prolog_cafe.lang.PrologMachineCopy;
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term; import com.googlecode.prolog_cafe.lang.Term;
import com.googlecode.prolog_cafe.lang.VariableTerm;
import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option; import org.kohsuke.args4j.Option;
import java.io.InputStreamReader;
import java.io.PushbackReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
/** Command that allows testing of prolog submit-rules in a live instance. */ /** Command that allows testing of prolog submit-rules in a live instance. */
final class TestSubmitRule extends SshCommand { final class TestSubmitRule extends SshCommand {
@@ -88,26 +71,14 @@ final class TestSubmitRule extends SshCommand {
usage = "Don't run the submit_filter/2 from the parent projects") usage = "Don't run the submit_filter/2 from the parent projects")
private boolean skipSubmitFilters; private boolean skipSubmitFilters;
private static final String[] PACKAGE_LIST = {Prolog.BUILTIN, "gerrit"};
@Inject @Inject
public TestSubmitRule(@AnonymousCowardName String anonymous) { public TestSubmitRule(@AnonymousCowardName String anonymous) {
anonymousCowardName = anonymous; anonymousCowardName = anonymous;
} }
private PrologMachineCopy newMachine() {
BufferingPrologControl ctl = new BufferingPrologControl();
ctl.setMaxDatabaseSize(16 * 1024);
ctl.setPrologClassLoader(new PrologClassLoader(getClass().getClassLoader()));
return PrologMachineCopy.save(ctl);
}
@Override @Override
protected void run() throws UnloggedFailure { protected void run() throws UnloggedFailure {
PushbackReader inReader = new PushbackReader(new InputStreamReader(in));
try { try {
PrologEnvironment pcl;
List<Change> changeList = List<Change> changeList =
db.changes().byKey(new Change.Key(changeId)).toList(); db.changes().byKey(new Change.Key(changeId)).toList();
if (changeList.size() != 1) if (changeList.size() != 1)
@@ -120,38 +91,17 @@ final class TestSubmitRule extends SshCommand {
// user are not allowed to see the change. // user are not allowed to see the change.
// See http://code.google.com/p/gerrit/issues/detail?id=1586 // See http://code.google.com/p/gerrit/issues/detail?id=1586
ChangeControl cc = ccFactory.controlFor(c); ChangeControl cc = ccFactory.controlFor(c);
ProjectState projectState = cc.getProjectControl().getProjectState();
if (useStdin) { SubmitRuleEvaluator evaluator = new SubmitRuleEvaluator(
pcl = envFactory.create(newMachine()); db, ps, cc.getProjectControl(), cc, c, null,
} else { false, "locate_submit_rule", "can_submit",
pcl = projectState.newPrologEnvironment(); "locate_submit_filter", "filter_submit_results",
} skipSubmitFilters, useStdin ? in : null);
@SuppressWarnings("unchecked")
List<Term> results = evaluator.evaluate().toJava();
pcl.set(StoredValues.REVIEW_DB, db); List<SubmitRecord> res = cc.resultsToSubmitRecord(evaluator.getSubmitRule(),
pcl.set(StoredValues.CHANGE, c); results);
pcl.set(StoredValues.PATCH_SET, ps);
pcl.set(StoredValues.CHANGE_CONTROL, cc);
if (useStdin) {
pcl.initialize(PACKAGE_LIST);
pcl.execute(Prolog.BUILTIN, "consult_stream",
SymbolTerm.intern("stdin"), new JavaObjectTerm(inReader));
}
List<Term> results = new ArrayList<Term>();
Term submitRule =
pcl.once("gerrit", "locate_submit_rule", new VariableTerm());
for (Term[] template : pcl.all("gerrit", "can_submit", submitRule,
new VariableTerm())) {
results.add(template[1]);
}
if (!skipSubmitFilters) {
runSubmitFilters(projectState, results, pcl);
}
List<SubmitRecord> res = cc.resultsToSubmitRecord(submitRule, results);
for (SubmitRecord r : res) { for (SubmitRecord r : res) {
if (format.isJson()) { if (format.isJson()) {
SubmitRecordAttribute submitRecord = new SubmitRecordAttribute(); SubmitRecordAttribute submitRecord = new SubmitRecordAttribute();
@@ -190,52 +140,4 @@ final class TestSubmitRule extends SshCommand {
throw new UnloggedFailure("Processing of prolog script failed: " + e); throw new UnloggedFailure("Processing of prolog script failed: " + e);
} }
} }
private void runSubmitFilters(ProjectState projectState, List<Term> results,
PrologEnvironment pcl) throws UnloggedFailure {
ProjectState parentState = projectState.getParentState();
PrologEnvironment childEnv = pcl;
Set<Project.NameKey> projectsSeen = new HashSet<Project.NameKey>();
projectsSeen.add(projectState.getProject().getNameKey());
while (parentState != null) {
if (!projectsSeen.add(parentState.getProject().getNameKey())) {
// parent has been seen before, stop walk up inheritance tree
break;
}
PrologEnvironment parentEnv;
try {
parentEnv = parentState.newPrologEnvironment();
} catch (CompileException err) {
throw new UnloggedFailure("Cannot consult rules.pl for "
+ parentState.getProject().getName() + err);
}
parentEnv.copyStoredValues(childEnv);
Term filterRule =
parentEnv.once("gerrit", "locate_submit_filter", new VariableTerm());
if (filterRule != null) {
try {
Term resultsTerm = ChangeControl.toListTerm(results);
results.clear();
Term[] template =
parentEnv.once("gerrit", "filter_submit_results", filterRule,
resultsTerm, new VariableTerm());
@SuppressWarnings("unchecked")
final List<? extends Term> termList =
((ListTerm) template[2]).toJava();
results.addAll(termList);
} catch (PrologException err) {
throw new UnloggedFailure("Exception calling " + filterRule + " of "
+ parentState.getProject().getName() + err);
} catch (RuntimeException err) {
throw new UnloggedFailure("Exception calling " + filterRule + " of "
+ parentState.getProject().getName() + err);
}
}
parentState = parentState.getParentState();
childEnv = parentEnv;
}
}
} }