private PrologEnvironment getPrologEnvironment(CurrentUser user) throws RuleEvalException { ProjectState projectState = control.getProjectControl().getProjectState(); PrologEnvironment env; try { if (rule == null) { env = projectState.newPrologEnvironment(); } else { env = projectState.newPrologEnvironment("stdin", new StringReader(rule)); } } catch (CompileException err) { String msg; if (rule == null && control.getProjectControl().isOwner()) { msg = String.format("Cannot load rules.pl for %s: %s", getProjectName(), err.getMessage()); } else if (rule != null) { msg = err.getMessage(); } else { msg = String.format("Cannot load rules.pl for %s", getProjectName()); } throw new RuleEvalException(msg, err); } env.set(StoredValues.REVIEW_DB, cd.db()); env.set(StoredValues.CHANGE_DATA, cd); env.set(StoredValues.CHANGE_CONTROL, control); if (user != null) { env.set(StoredValues.CURRENT_USER, user); } return env; }
private List<Term> evaluateImpl( String userRuleLocatorName, String userRuleWrapperName, String filterRuleLocatorName, String filterRuleWrapperName, CurrentUser user) throws RuleEvalException { PrologEnvironment env = getPrologEnvironment(user); try { Term sr = env.once("gerrit", userRuleLocatorName, new VariableTerm()); if (fastEvalLabels) { env.once("gerrit", "assume_range_from_label"); } List<Term> results = new ArrayList<>(); try { for (Term[] template : env.all("gerrit", userRuleWrapperName, sr, new VariableTerm())) { results.add(template[1]); } } catch (ReductionLimitException err) { throw new RuleEvalException( String.format( "%s on change %d of %s", err.getMessage(), cd.getId().get(), getProjectName())); } catch (RuntimeException err) { throw new RuleEvalException( String.format( "Exception calling %s on change %d of %s", sr, cd.getId().get(), getProjectName()), err); } finally { reductionsConsumed = env.getReductions(); } Term resultsTerm = toListTerm(results); if (!skipFilters) { resultsTerm = runSubmitFilters(resultsTerm, env, filterRuleLocatorName, filterRuleWrapperName); } List<Term> r; if (resultsTerm instanceof ListTerm) { r = Lists.newArrayList(); for (Term t = resultsTerm; t instanceof ListTerm; ) { ListTerm l = (ListTerm) t; r.add(l.car().dereference()); t = l.cdr().dereference(); } } else { r = Collections.emptyList(); } submitRule = sr; return r; } finally { env.close(); } }
private Term runSubmitFilters( Term results, PrologEnvironment env, String filterRuleLocatorName, String filterRuleWrapperName) throws RuleEvalException { ProjectState projectState = control.getProjectControl().getProjectState(); PrologEnvironment childEnv = env; for (ProjectState parentState : projectState.parents()) { PrologEnvironment parentEnv; try { parentEnv = parentState.newPrologEnvironment(); } catch (CompileException err) { throw new RuleEvalException( "Cannot consult rules.pl for " + parentState.getProject().getName(), err); } parentEnv.copyStoredValues(childEnv); Term filterRule = parentEnv.once("gerrit", filterRuleLocatorName, new VariableTerm()); try { if (fastEvalLabels) { env.once("gerrit", "assume_range_from_label"); } Term[] template = parentEnv.once( "gerrit", filterRuleWrapperName, filterRule, results, new VariableTerm()); results = template[2]; } catch (ReductionLimitException err) { throw new RuleEvalException( String.format( "%s on change %d of %s", err.getMessage(), cd.getId().get(), parentState.getProject().getName())); } catch (RuntimeException err) { throw new RuleEvalException( String.format( "Exception calling %s on change %d of %s", filterRule, cd.getId().get(), parentState.getProject().getName()), err); } finally { reductionsConsumed += env.getReductions(); } childEnv = parentEnv; } return results; }