diff --git a/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java b/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java index 5e500b2207..bef260eee0 100644 --- a/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java +++ b/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java @@ -12,7 +12,9 @@ import java.util.List; * {@link CLICommand} that acts on a series of {@link AbstractBuild}s. * * @author Kohsuke Kawaguchi + * @deprecated rather use {@link RunRangeCommand} */ +@Deprecated public abstract class AbstractBuildRangeCommand extends CLICommand { @Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0) public AbstractProject job; diff --git a/core/src/main/java/hudson/cli/BuildCommand.java b/core/src/main/java/hudson/cli/BuildCommand.java index d02ea9afcc..cd6a13efa1 100644 --- a/core/src/main/java/hudson/cli/BuildCommand.java +++ b/core/src/main/java/hudson/cli/BuildCommand.java @@ -25,7 +25,6 @@ package hudson.cli; import hudson.Util; import hudson.console.ModelHyperlinkNote; -import hudson.model.AbstractProject; import hudson.model.Cause.UserIdCause; import hudson.model.CauseAction; import hudson.model.Job; diff --git a/core/src/main/java/hudson/cli/ConsoleCommand.java b/core/src/main/java/hudson/cli/ConsoleCommand.java index 379cd8132b..f98fdc95a2 100644 --- a/core/src/main/java/hudson/cli/ConsoleCommand.java +++ b/core/src/main/java/hudson/cli/ConsoleCommand.java @@ -2,10 +2,10 @@ package hudson.cli; import hudson.Extension; import hudson.console.AnnotatedLargeText; -import hudson.model.AbstractBuild; -import hudson.model.AbstractProject; import hudson.model.Item; +import hudson.model.Job; import hudson.model.PermalinkProjectAction.Permalink; +import hudson.model.Run; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -29,7 +29,7 @@ public class ConsoleCommand extends CLICommand { } @Argument(metaVar="JOB",usage="Name of the job",required=true) - public AbstractProject job; + public Job job; @Argument(metaVar="BUILD",usage="Build number or permalink to point to the build. Defaults to the last build",required=false,index=1) public String build="lastBuild"; @@ -43,7 +43,7 @@ public class ConsoleCommand extends CLICommand { protected int run() throws Exception { job.checkPermission(Item.BUILD); - AbstractBuild run; + Run run; try { int n = Integer.parseInt(build); @@ -54,7 +54,7 @@ public class ConsoleCommand extends CLICommand { // maybe a permalink? Permalink p = job.getPermalinks().get(build); if (p!=null) { - run = (AbstractBuild)p.resolve(job); + run = p.resolve(job); if (run==null) throw new IllegalStateException("Permalink "+build+" produced no build"); } else { @@ -94,7 +94,7 @@ public class ConsoleCommand extends CLICommand { /** * Find the byte offset in the log input stream that marks "last N lines". */ - private long seek(AbstractBuild run) throws IOException { + private long seek(Run run) throws IOException { class RingBuffer { long[] lastNlines = new long[n]; int ptr=0; diff --git a/core/src/main/java/hudson/cli/DeleteBuildsCommand.java b/core/src/main/java/hudson/cli/DeleteBuildsCommand.java index cfe21e072e..db86c433ab 100644 --- a/core/src/main/java/hudson/cli/DeleteBuildsCommand.java +++ b/core/src/main/java/hudson/cli/DeleteBuildsCommand.java @@ -24,21 +24,23 @@ package hudson.cli; import hudson.Extension; -import hudson.model.AbstractBuild; import hudson.model.Run; import java.io.IOException; import java.io.PrintStream; import java.util.HashSet; import java.util.List; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.DoNotUse; /** * Deletes builds records in a bulk. * * @author Kohsuke Kawaguchi */ +@Restricted(DoNotUse.class) // command implementation only @Extension -public class DeleteBuildsCommand extends AbstractBuildRangeCommand { +public class DeleteBuildsCommand extends RunRangeCommand { @Override public String getShortDescription() { return Messages.DeleteBuildsCommand_ShortDescription(); @@ -52,12 +54,12 @@ public class DeleteBuildsCommand extends AbstractBuildRangeCommand { } @Override - protected int act(List> builds) throws IOException { + protected int act(List> builds) throws IOException { job.checkPermission(Run.DELETE); final HashSet hsBuilds = new HashSet(); - for (AbstractBuild build : builds) { + for (Run build : builds) { if (!hsBuilds.contains(build.number)) { build.delete(); hsBuilds.add(build.number); diff --git a/core/src/main/java/hudson/cli/ListChangesCommand.java b/core/src/main/java/hudson/cli/ListChangesCommand.java index feb1720810..8da2000073 100644 --- a/core/src/main/java/hudson/cli/ListChangesCommand.java +++ b/core/src/main/java/hudson/cli/ListChangesCommand.java @@ -1,10 +1,11 @@ package hudson.cli; import hudson.Extension; -import hudson.model.AbstractBuild; +import hudson.model.Run; import hudson.scm.ChangeLogSet; import hudson.scm.ChangeLogSet.Entry; import hudson.util.QuotedStringTokenizer; +import jenkins.scm.RunWithSCM; import org.kohsuke.args4j.Option; import org.kohsuke.stapler.export.Flavor; import org.kohsuke.stapler.export.Model; @@ -13,14 +14,17 @@ import org.kohsuke.stapler.export.ModelBuilder; import java.io.IOException; import java.io.PrintWriter; import java.util.List; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.DoNotUse; /** * Retrieves a change list for the specified builds. * * @author Kohsuke Kawaguchi */ +@Restricted(DoNotUse.class) // command implementation only @Extension -public class ListChangesCommand extends AbstractBuildRangeCommand { +public class ListChangesCommand extends RunRangeCommand { @Override public String getShortDescription() { return Messages.ListChangesCommand_ShortDescription(); @@ -39,40 +43,50 @@ public class ListChangesCommand extends AbstractBuildRangeCommand { public Format format = Format.PLAIN; @Override - protected int act(List> builds) throws IOException { + protected int act(List> builds) throws IOException { // Loading job for this CLI command requires Item.READ permission. // No other permission check needed. switch (format) { case XML: PrintWriter w = new PrintWriter(stdout); w.println(""); - for (AbstractBuild build : builds) { - w.println(""); - ChangeLogSet cs = build.getChangeSet(); - Model p = new ModelBuilder().get(cs.getClass()); - p.writeTo(cs,Flavor.XML.createDataWriter(cs,w)); - w.println(""); + for (Run build : builds) { + if (build instanceof RunWithSCM) { + w.println(""); + for (ChangeLogSet cs : ((RunWithSCM) build).getChangeSets()) { + Model p = new ModelBuilder().get(cs.getClass()); + p.writeTo(cs, Flavor.XML.createDataWriter(cs, w)); + } + w.println(""); + } } w.println(""); w.flush(); break; case CSV: - for (AbstractBuild build : builds) { - ChangeLogSet cs = build.getChangeSet(); - for (Entry e : cs) { - stdout.printf("%s,%s%n", - QuotedStringTokenizer.quote(e.getAuthor().getId()), - QuotedStringTokenizer.quote(e.getMsg())); + for (Run build : builds) { + if (build instanceof RunWithSCM) { + for (ChangeLogSet cs : ((RunWithSCM) build).getChangeSets()) { + for (Entry e : cs) { + stdout.printf("%s,%s%n", + QuotedStringTokenizer.quote(e.getAuthor().getId()), + QuotedStringTokenizer.quote(e.getMsg())); + } + } } } break; case PLAIN: - for (AbstractBuild build : builds) { - ChangeLogSet cs = build.getChangeSet(); - for (Entry e : cs) { - stdout.printf("%s\t%s%n",e.getAuthor(),e.getMsg()); - for (String p : e.getAffectedPaths()) - stdout.println(" "+p); + for (Run build : builds) { + if (build instanceof RunWithSCM) { + for (ChangeLogSet cs : ((RunWithSCM) build).getChangeSets()) { + for (Entry e : cs) { + stdout.printf("%s\t%s%n", e.getAuthor(), e.getMsg()); + for (String p : e.getAffectedPaths()) { + stdout.println(" " + p); + } + } + } } } break; diff --git a/core/src/main/java/hudson/cli/ReloadJobCommand.java b/core/src/main/java/hudson/cli/ReloadJobCommand.java index 17b0379f73..c8849a317f 100644 --- a/core/src/main/java/hudson/cli/ReloadJobCommand.java +++ b/core/src/main/java/hudson/cli/ReloadJobCommand.java @@ -29,6 +29,8 @@ import hudson.model.AbstractItem; import hudson.model.AbstractProject; import hudson.model.Item; +import hudson.model.Items; +import hudson.model.TopLevelItem; import jenkins.model.Jenkins; import org.kohsuke.args4j.Argument; @@ -69,7 +71,6 @@ public class ReloadJobCommand extends CLICommand { AbstractItem job = null; try { - // TODO: JENKINS-30786 Item item = jenkins.getItemByFullName(job_s); if (item instanceof AbstractItem) { job = (AbstractItem) item; @@ -78,11 +79,10 @@ public class ReloadJobCommand extends CLICommand { } if(job == null) { - // TODO: JENKINS-30785 - AbstractProject project = AbstractProject.findNearest(job_s); + AbstractItem project = Items.findNearest(AbstractItem.class, job_s, jenkins); throw new IllegalArgumentException(project == null ? - "No such job \u2018" + job_s + "\u2019 exists." : - String.format("No such job \u2018%s\u2019 exists. Perhaps you meant \u2018%s\u2019?", + "No such item \u2018" + job_s + "\u2019 exists." : + String.format("No such item \u2018%s\u2019 exists. Perhaps you meant \u2018%s\u2019?", job_s, project.getFullName())); } diff --git a/core/src/main/java/hudson/cli/RunRangeCommand.java b/core/src/main/java/hudson/cli/RunRangeCommand.java new file mode 100644 index 0000000000..2ba4b3b015 --- /dev/null +++ b/core/src/main/java/hudson/cli/RunRangeCommand.java @@ -0,0 +1,29 @@ +package hudson.cli; + +import hudson.model.Fingerprint.RangeSet; +import hudson.model.Job; +import hudson.model.Run; +import org.kohsuke.args4j.Argument; + +import java.io.IOException; +import java.util.List; + +/** + * {@link CLICommand} that acts on a series of {@link Run}s. + * @since FIXME + */ +public abstract class RunRangeCommand extends CLICommand { + @Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0) + public Job job; + + @Argument(metaVar="RANGE",usage="Range of the build records to delete. 'N-M', 'N,M', or 'N'",required=true,index=1) + public String range; + + protected int run() throws Exception { + RangeSet rs = RangeSet.fromString(range,false); + + return act((List)job.getBuilds(rs)); + } + + protected abstract int act(List> builds) throws IOException; +} diff --git a/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java b/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java index 1863e5a22e..3322929125 100644 --- a/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java +++ b/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java @@ -1,7 +1,7 @@ package hudson.cli; import hudson.Extension; -import hudson.model.AbstractProject; +import hudson.model.Job; import hudson.model.Run; import java.io.Serializable; @@ -18,7 +18,7 @@ public class SetBuildDescriptionCommand extends CLICommand implements Serializab } @Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0) - public transient AbstractProject job; + public transient Job job; @Argument(metaVar="BUILD#",usage="Number of the build",required=true,index=1) public int number; diff --git a/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java b/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java index f52dc58a57..50717a7469 100644 --- a/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java +++ b/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java @@ -1,7 +1,7 @@ package hudson.cli; import hudson.Extension; -import hudson.model.AbstractProject; +import hudson.model.Job; import hudson.model.Run; import org.apache.commons.io.IOUtils; import org.kohsuke.args4j.Argument; @@ -18,7 +18,7 @@ public class SetBuildDisplayNameCommand extends CLICommand implements Serializab } @Argument(metaVar="JOB", usage="Name of the job to build", required=true, index=0) - public transient AbstractProject job; + public transient Job job; @Argument(metaVar="BUILD#", usage="Number of the build", required=true, index=1) public int number; diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java index 33468f3b68..6e6f5977f2 100644 --- a/core/src/main/java/hudson/model/AbstractItem.java +++ b/core/src/main/java/hudson/model/AbstractItem.java @@ -850,11 +850,11 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet */ @CLIResolver public static AbstractItem resolveForCLI( - @Argument(required=true,metaVar="NAME",usage="Job name") String name) throws CmdLineException { + @Argument(required=true,metaVar="NAME",usage="Item name") String name) throws CmdLineException { // TODO can this (and its pseudo-override in AbstractProject) share code with GenericItemOptionHandler, used for explicit CLICommand’s rather than CLIMethod’s? AbstractItem item = Jenkins.getInstance().getItemByFullName(name, AbstractItem.class); if (item==null) { - AbstractProject project = AbstractProject.findNearest(name); // TODO should be Items.findNearest + AbstractItem project = Items.findNearest(AbstractItem.class, name, Jenkins.getInstance()); throw new CmdLineException(null, project == null ? Messages.AbstractItem_NoSuchJobExistsWithoutSuggestion(name) : Messages.AbstractItem_NoSuchJobExists(name, project.getFullName())); } diff --git a/test/src/test/java/hudson/cli/ReloadJobCommandTest.java b/test/src/test/java/hudson/cli/ReloadJobCommandTest.java index a012090070..994af1691d 100644 --- a/test/src/test/java/hudson/cli/ReloadJobCommandTest.java +++ b/test/src/test/java/hudson/cli/ReloadJobCommandTest.java @@ -91,7 +91,7 @@ public class ReloadJobCommandTest { assertThat(result, failedWith(3)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("ERROR: No such job \u2018aProject\u2019 exists.")); + assertThat(result.stderr(), containsString("ERROR: No such item ‘aProject’ exists.")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); } @@ -121,7 +121,7 @@ public class ReloadJobCommandTest { .invokeWithArgs("never_created"); assertThat(result, failedWith(3)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("ERROR: No such job \u2018never_created\u2019 exists.")); + assertThat(result.stderr(), containsString("ERROR: No such item ‘never_created’ exists.")); } @Test public void reloadJobShouldFailIfJobDoesNotExistButNearExists() throws Exception { @@ -133,7 +133,7 @@ public class ReloadJobCommandTest { .invokeWithArgs("never_created1"); assertThat(result, failedWith(3)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("ERROR: No such job \u2018never_created1\u2019 exists. Perhaps you meant \u2018never_created\u2019?")); + assertThat(result.stderr(), containsString("ERROR: No such item ‘never_created1’ exists. Perhaps you meant ‘never_created’?")); } @Test public void reloadJobManyShouldSucceed() throws Exception { @@ -182,7 +182,7 @@ public class ReloadJobCommandTest { assertThat(result, failedWith(5)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("never_created: No such job \u2018never_created\u2019 exists.")); + assertThat(result.stderr(), containsString("never_created: No such item ‘never_created’ exists.")); assertThat(result.stderr(), containsString("ERROR: " + CLICommand.CLI_LISTPARAM_SUMMARY_ERROR_TEXT)); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 2")); @@ -208,7 +208,7 @@ public class ReloadJobCommandTest { assertThat(result, failedWith(5)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("never_created: No such job \u2018never_created\u2019 exists.")); + assertThat(result.stderr(), containsString("never_created: No such item ‘never_created’ exists.")); assertThat(result.stderr(), containsString("ERROR: " + CLICommand.CLI_LISTPARAM_SUMMARY_ERROR_TEXT)); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 2")); @@ -234,7 +234,7 @@ public class ReloadJobCommandTest { assertThat(result, failedWith(5)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("never_created: No such job \u2018never_created\u2019 exists.")); + assertThat(result.stderr(), containsString("never_created: No such item ‘never_created’ exists.")); assertThat(result.stderr(), containsString("ERROR: " + CLICommand.CLI_LISTPARAM_SUMMARY_ERROR_TEXT)); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 2")); @@ -260,8 +260,8 @@ public class ReloadJobCommandTest { assertThat(result, failedWith(5)); assertThat(result, hasNoStandardOutput()); - assertThat(result.stderr(), containsString("never_created1: No such job \u2018never_created1\u2019 exists.")); - assertThat(result.stderr(), containsString("never_created2: No such job \u2018never_created2\u2019 exists.")); + assertThat(result.stderr(), containsString("never_created1: No such item ‘never_created1’ exists.")); + assertThat(result.stderr(), containsString("never_created2: No such item ‘never_created2’ exists.")); assertThat(result.stderr(), containsString("ERROR: " + CLICommand.CLI_LISTPARAM_SUMMARY_ERROR_TEXT)); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 2")); diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java b/test/src/test/java/hudson/cli/RunRangeCommand2Test.java similarity index 97% rename from test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java rename to test/src/test/java/hudson/cli/RunRangeCommand2Test.java index bea2d8de8a..233a32cd01 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java +++ b/test/src/test/java/hudson/cli/RunRangeCommand2Test.java @@ -54,14 +54,14 @@ import static org.hamcrest.Matchers.not; /** * @author pjanouse */ -public class AbstractBuildRangeCommand2Test { +public class RunRangeCommand2Test { private CLICommandInvoker command; @Rule public final JenkinsRule j = new JenkinsRule(); @Before public void setUp() { - command = new CLICommandInvoker(j, new AbstractBuildRangeCommandTest.DummyRangeCommand()); + command = new CLICommandInvoker(j, new RunRangeCommandTest.DummyRangeCommand()); } @Test public void dummyRangeShouldFailIfJobNameIsEmptyOnEmptyJenkins() throws Exception { diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java b/test/src/test/java/hudson/cli/RunRangeCommandTest.java similarity index 99% rename from test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java rename to test/src/test/java/hudson/cli/RunRangeCommandTest.java index cda886fc85..5e45c56493 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java +++ b/test/src/test/java/hudson/cli/RunRangeCommandTest.java @@ -25,9 +25,9 @@ package hudson.cli; import hudson.Extension; -import hudson.model.AbstractBuild; import hudson.model.FreeStyleProject; import hudson.model.Job; +import hudson.model.Run; import jenkins.model.Jenkins; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -48,7 +48,7 @@ import static org.hamcrest.Matchers.not; /** * @author pjanouse */ -public class AbstractBuildRangeCommandTest { +public class RunRangeCommandTest { private static CLICommandInvoker command = null; private static FreeStyleProject project = null; @@ -977,18 +977,18 @@ public class AbstractBuildRangeCommandTest { } @Extension - public static class DummyRangeCommand extends AbstractBuildRangeCommand { + public static class DummyRangeCommand extends RunRangeCommand { @Override public String getShortDescription() { return "DummyRangeCommand"; } @Override - protected int act(List> builds) throws IOException { + protected int act(List> builds) throws IOException { boolean comma = false; stdout.print("Builds: "); - for (AbstractBuild build : builds) { + for (Run build : builds) { if (comma) stdout.print(","); else