// 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.common.base.MoreObjects; import com.google.common.collect.Lists; import com.google.gerrit.common.data.SubmitRecord; import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.TestSubmitRuleInput; import com.google.gerrit.extensions.common.TestSubmitRuleInput.Filters; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.rules.RulesCache; import com.google.gerrit.server.account.AccountLoader; import com.google.gerrit.server.project.SubmitRuleEvaluator; import com.google.gerrit.server.query.change.ChangeData; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.kohsuke.args4j.Option; public class TestSubmitRule implements RestModifyView<RevisionResource, TestSubmitRuleInput> { private final Provider<ReviewDb> db; private final ChangeData.Factory changeDataFactory; private final RulesCache rules; private final AccountLoader.Factory accountInfoFactory; @Option(name = "--filters", usage = "impact of filters in parent projects") private Filters filters = Filters.RUN; @Inject TestSubmitRule( Provider<ReviewDb> db, ChangeData.Factory changeDataFactory, RulesCache rules, AccountLoader.Factory infoFactory) { this.db = db; this.changeDataFactory = changeDataFactory; this.rules = rules; this.accountInfoFactory = infoFactory; } @Override public List<Record> apply(RevisionResource rsrc, TestSubmitRuleInput input) throws AuthException, OrmException { if (input == null) { input = new TestSubmitRuleInput(); } if (input.rule != null && !rules.isProjectRulesEnabled()) { throw new AuthException("project rules are disabled"); } input.filters = MoreObjects.firstNonNull(input.filters, filters); SubmitRuleEvaluator evaluator = new SubmitRuleEvaluator(changeDataFactory.create(db.get(), rsrc.getControl())); List<SubmitRecord> records = evaluator .setPatchSet(rsrc.getPatchSet()) .setLogErrors(false) .setSkipSubmitFilters(input.filters == Filters.SKIP) .setRule(input.rule) .evaluate(); List<Record> out = Lists.newArrayListWithCapacity(records.size()); AccountLoader accounts = accountInfoFactory.create(true); for (SubmitRecord r : records) { out.add(new Record(r, accounts)); } if (!out.isEmpty()) { out.get(0).prologReductionCount = evaluator.getReductionsConsumed(); } accounts.fill(); return out; } static class Record { SubmitRecord.Status status; String errorMessage; Map<String, AccountInfo> ok; Map<String, AccountInfo> reject; Map<String, None> need; Map<String, AccountInfo> may; Map<String, None> impossible; Long prologReductionCount; Record(SubmitRecord r, AccountLoader accounts) { this.status = r.status; this.errorMessage = r.errorMessage; if (r.labels != null) { for (SubmitRecord.Label n : r.labels) { AccountInfo who = n.appliedBy != null ? accounts.get(n.appliedBy) : new AccountInfo(null); label(n, who); } } } private void label(SubmitRecord.Label n, AccountInfo who) { switch (n.status) { case OK: if (ok == null) { ok = new LinkedHashMap<>(); } ok.put(n.label, who); break; case REJECT: if (reject == null) { reject = new LinkedHashMap<>(); } reject.put(n.label, who); break; case NEED: if (need == null) { need = new LinkedHashMap<>(); } need.put(n.label, new None()); break; case MAY: if (may == null) { may = new LinkedHashMap<>(); } may.put(n.label, who); break; case IMPOSSIBLE: if (impossible == null) { impossible = new LinkedHashMap<>(); } impossible.put(n.label, new None()); break; } } } static class None {} }