"test-submit type" command.
This adds a new subcommand "type" to the "test-submit" command which is used to test Prolog based submit type for a change. Since "rule" and "type" subcommands have identical options and arguments most of the implementation was moved to a common base class. Change-Id: I59f87f9ae7dd679eb367e7664d7d9f0a13749c20
This commit is contained in:
		@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					// 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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -42,5 +42,6 @@ public class MasterCommandModule extends CommandModule {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    command(gerrit, "test-submit").toProvider(new DispatchCommandProvider(testSubmit));
 | 
					    command(gerrit, "test-submit").toProvider(new DispatchCommandProvider(testSubmit));
 | 
				
			||||||
    command(testSubmit, "rule").to(TestSubmitRule.class);
 | 
					    command(testSubmit, "rule").to(TestSubmitRule.class);
 | 
				
			||||||
 | 
					    command(testSubmit, "type").to(TestSubmitType.class);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,89 +19,42 @@ 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.server.ReviewDb;
 | 
					 | 
				
			||||||
import com.google.gerrit.rules.PrologEnvironment;
 | 
					 | 
				
			||||||
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.events.AccountAttribute;
 | 
					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.SubmitRuleEvaluator;
 | 
					import com.google.gerrit.server.project.SubmitRuleEvaluator;
 | 
				
			||||||
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.googlecode.prolog_cafe.lang.ListTerm;
 | 
				
			||||||
import com.googlecode.prolog_cafe.lang.Term;
 | 
					import com.googlecode.prolog_cafe.lang.Term;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.kohsuke.args4j.Argument;
 | 
					 | 
				
			||||||
import org.kohsuke.args4j.Option;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.LinkedList;
 | 
					import java.util.LinkedList;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 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 BaseTestSubmit {
 | 
				
			||||||
  @Inject
 | 
					 | 
				
			||||||
  private ReviewDb db;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Inject
 | 
					  protected SubmitRuleEvaluator createEvaluator(PatchSet ps) throws Exception {
 | 
				
			||||||
  private PrologEnvironment.Factory envFactory;
 | 
					    ChangeControl cc = getChangeControl();
 | 
				
			||||||
 | 
					    return new SubmitRuleEvaluator(
 | 
				
			||||||
  @Inject
 | 
					        db, ps, cc.getProjectControl(), cc, getChange(), null,
 | 
				
			||||||
  private ChangeControl.Factory ccFactory;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Inject
 | 
					 | 
				
			||||||
  private AccountCache accountCache;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  final @AnonymousCowardName String anonymousCowardName;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Argument(index = 0, required = true, usage = "ChangeId to load in prolog environment")
 | 
					 | 
				
			||||||
  private String changeId;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Option(name = "-s",
 | 
					 | 
				
			||||||
      usage = "Read prolog script from stdin instead of reading rules.pl from the refs/meta/config branch")
 | 
					 | 
				
			||||||
  private boolean useStdin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Option(name = "--format", metaVar = "FMT", usage = "Output display format")
 | 
					 | 
				
			||||||
  private OutputFormat format = OutputFormat.TEXT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Option(name = "--no-filters", aliases = {"-n"},
 | 
					 | 
				
			||||||
      usage = "Don't run the submit_filter/2 from the parent projects")
 | 
					 | 
				
			||||||
  private boolean skipSubmitFilters;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Inject
 | 
					 | 
				
			||||||
  public TestSubmitRule(@AnonymousCowardName String anonymous) {
 | 
					 | 
				
			||||||
    anonymousCowardName = anonymous;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Override
 | 
					 | 
				
			||||||
  protected void run() throws UnloggedFailure {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      List<Change> changeList =
 | 
					 | 
				
			||||||
          db.changes().byKey(new Change.Key(changeId)).toList();
 | 
					 | 
				
			||||||
      if (changeList.size() != 1)
 | 
					 | 
				
			||||||
        throw new UnloggedFailure(1, "Invalid ChangeId");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Change c = changeList.get(0);
 | 
					 | 
				
			||||||
      PatchSet ps = db.patchSets().get(c.currentPatchSetId());
 | 
					 | 
				
			||||||
      // 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 cc = ccFactory.controlFor(c);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      SubmitRuleEvaluator evaluator = new SubmitRuleEvaluator(
 | 
					 | 
				
			||||||
          db, ps, cc.getProjectControl(), cc, c, null,
 | 
					 | 
				
			||||||
        false, "locate_submit_rule", "can_submit",
 | 
					        false, "locate_submit_rule", "can_submit",
 | 
				
			||||||
        "locate_submit_filter", "filter_submit_results",
 | 
					        "locate_submit_filter", "filter_submit_results",
 | 
				
			||||||
        skipSubmitFilters, useStdin ? in : null);
 | 
					        skipSubmitFilters, useStdin ? in : null);
 | 
				
			||||||
      @SuppressWarnings("unchecked")
 | 
					  }
 | 
				
			||||||
      List<Term> results = evaluator.evaluate().toJava();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      List<SubmitRecord> res = cc.resultsToSubmitRecord(evaluator.getSubmitRule(),
 | 
					  protected void processResults(ListTerm results, Term submitRule) throws Exception {
 | 
				
			||||||
          results);
 | 
					    @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) {
 | 
					    for (SubmitRecord r : res) {
 | 
				
			||||||
      if (format.isJson()) {
 | 
					      if (format.isJson()) {
 | 
				
			||||||
        SubmitRecordAttribute submitRecord = new SubmitRecordAttribute();
 | 
					        SubmitRecordAttribute submitRecord = new SubmitRecordAttribute();
 | 
				
			||||||
@@ -136,8 +89,5 @@ final class TestSubmitRule extends SshCommand {
 | 
				
			|||||||
        stdout.print("\n" + r.status.name() + "\n");
 | 
					        stdout.print("\n" + r.status.name() + "\n");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    } catch (Exception e) {
 | 
					 | 
				
			||||||
      throw new UnloggedFailure("Processing of prolog script failed: " + e);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					// 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.googlecode.prolog_cafe.lang.ListTerm;
 | 
				
			||||||
 | 
					import com.googlecode.prolog_cafe.lang.Term;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user