[bs-135] Add support for closure-style options declarations
E.g. options { option "foo", "Foo set" option "bar", "Bar has an argument of type int" withOptionalArg() ofType Integer } println "Hello ${options.nonOptionArguments()}: " + "${options.has('foo')} ${options.valueOf('bar')}" [#50427095] [bs-135] Plugin model for spring commands
This commit is contained in:
parent
dcdf2d00b8
commit
bf30e2de90
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.bootstrap.cli.command;
|
package org.springframework.bootstrap.cli.command;
|
||||||
|
|
||||||
|
import groovy.lang.Closure;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -28,9 +30,10 @@ import joptsimple.OptionSpecBuilder;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class OptionHandler {
|
public class OptionHandler {
|
||||||
|
|
||||||
private OptionParser parser;
|
private OptionParser parser;
|
||||||
|
private Closure<Void> closure;
|
||||||
|
|
||||||
public OptionSpecBuilder option(String name, String description) {
|
public OptionSpecBuilder option(String name, String description) {
|
||||||
return getParser().accepts(name, description);
|
return getParser().accepts(name, description);
|
||||||
|
@ -40,7 +43,7 @@ public abstract class OptionHandler {
|
||||||
return getParser().acceptsAll(aliases, description);
|
return getParser().acceptsAll(aliases, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OptionParser getParser() {
|
public OptionParser getParser() {
|
||||||
if (this.parser == null) {
|
if (this.parser == null) {
|
||||||
this.parser = new OptionParser();
|
this.parser = new OptionParser();
|
||||||
options();
|
options();
|
||||||
|
@ -48,14 +51,23 @@ public abstract class OptionHandler {
|
||||||
return this.parser;
|
return this.parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void options();
|
protected void options() {
|
||||||
|
if (this.closure != null) {
|
||||||
|
this.closure.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptions(Closure<Void> closure) {
|
||||||
|
this.closure = closure;
|
||||||
|
}
|
||||||
|
|
||||||
public final void run(String... args) throws Exception {
|
public final void run(String... args) throws Exception {
|
||||||
OptionSet options = getParser().parse(args);
|
OptionSet options = getParser().parse(args);
|
||||||
run(options);
|
run(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void run(OptionSet options) throws Exception;
|
protected void run(OptionSet options) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
public String getHelp() {
|
public String getHelp() {
|
||||||
OutputStream out = new ByteArrayOutputStream();
|
OutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.springframework.bootstrap.cli.command;
|
||||||
import org.springframework.bootstrap.cli.Command;
|
import org.springframework.bootstrap.cli.Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for any {@link Command}s that use an {@link OptionHandler}.
|
* Base class for a {@link Command} that uses an {@link OptionHandler}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
|
|
@ -15,12 +15,18 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.bootstrap.cli.command;
|
package org.springframework.bootstrap.cli.command;
|
||||||
|
|
||||||
|
import groovy.lang.Closure;
|
||||||
|
import groovy.lang.GroovyObjectSupport;
|
||||||
|
import groovy.lang.MetaClass;
|
||||||
|
import groovy.lang.MetaMethod;
|
||||||
import groovy.lang.Script;
|
import groovy.lang.Script;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import joptsimple.OptionParser;
|
||||||
|
|
||||||
import org.apache.ivy.util.FileUtil;
|
import org.apache.ivy.util.FileUtil;
|
||||||
import org.codehaus.groovy.control.CompilationFailedException;
|
import org.codehaus.groovy.control.CompilationFailedException;
|
||||||
import org.springframework.bootstrap.cli.Command;
|
import org.springframework.bootstrap.cli.Command;
|
||||||
|
@ -79,16 +85,32 @@ public class ScriptCommand implements Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) throws Exception {
|
public void run(String... args) throws Exception {
|
||||||
if (getMain() instanceof Command) {
|
run(getMain(), args);
|
||||||
((Command) getMain()).run(args);
|
}
|
||||||
} else if (getMain() instanceof OptionHandler) {
|
|
||||||
|
private void run(Object main, String[] args) throws Exception {
|
||||||
|
if (main instanceof Command) {
|
||||||
|
((Command) main).run(args);
|
||||||
|
} else if (main instanceof OptionHandler) {
|
||||||
((OptionHandler) getMain()).run(args);
|
((OptionHandler) getMain()).run(args);
|
||||||
} else if (this.main instanceof Runnable) {
|
} else if (main instanceof Closure) {
|
||||||
((Runnable) this.main).run();
|
((Closure<?>) main).call((Object[]) args);
|
||||||
} else if (this.main instanceof Script) {
|
} else if (main instanceof Runnable) {
|
||||||
|
((Runnable) main).run();
|
||||||
|
} else if (main instanceof Script) {
|
||||||
Script script = (Script) this.main;
|
Script script = (Script) this.main;
|
||||||
script.setProperty("args", args);
|
script.setProperty("args", args);
|
||||||
script.run();
|
if (this.main instanceof GroovyObjectSupport) {
|
||||||
|
GroovyObjectSupport object = (GroovyObjectSupport) this.main;
|
||||||
|
if (object.getMetaClass().hasProperty(object, "parser") != null) {
|
||||||
|
OptionParser parser = (OptionParser) object.getProperty("parser");
|
||||||
|
if (parser != null) {
|
||||||
|
script.setProperty("options", parser.parse(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object result = script.run();
|
||||||
|
run(result, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +139,16 @@ public class ScriptCommand implements Command {
|
||||||
throw new IllegalStateException("Cannot create main class: " + this.name,
|
throw new IllegalStateException("Cannot create main class: " + this.name,
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
|
if (this.main instanceof OptionHandler) {
|
||||||
|
((OptionHandler) this.main).options();
|
||||||
|
} else if (this.main instanceof GroovyObjectSupport) {
|
||||||
|
GroovyObjectSupport object = (GroovyObjectSupport) this.main;
|
||||||
|
MetaClass metaClass = object.getMetaClass();
|
||||||
|
MetaMethod options = metaClass.getMetaMethod("options", null);
|
||||||
|
if (options != null) {
|
||||||
|
options.doMethodInvoke(this.main, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.main;
|
return this.main;
|
||||||
}
|
}
|
||||||
|
@ -144,16 +176,25 @@ public class ScriptCommand implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
private File locateSource(String name) {
|
private File locateSource(String name) {
|
||||||
String resource = "commands/" + name + ".groovy";
|
String resource = name;
|
||||||
|
if (!name.endsWith(".groovy")) {
|
||||||
|
resource = "commands/" + name + ".groovy";
|
||||||
|
}
|
||||||
URL url = getClass().getClassLoader().getResource(resource);
|
URL url = getClass().getClassLoader().getResource(resource);
|
||||||
File file = null;
|
File file = null;
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
try {
|
if (url.toString().startsWith("file:")) {
|
||||||
file = File.createTempFile(name, ".groovy");
|
file = new File(url.toString().substring("file:".length()));
|
||||||
FileUtil.copy(url, file, null);
|
} else {
|
||||||
} catch (IOException e) {
|
// probably in JAR file
|
||||||
throw new IllegalStateException("Could not create temp file for source: "
|
try {
|
||||||
+ name);
|
file = File.createTempFile(name, ".groovy");
|
||||||
|
file.deleteOnExit();
|
||||||
|
FileUtil.copy(url, file, null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Could not create temp file for source: " + name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String home = System.getProperty("SPRING_HOME", System.getenv("SPRING_HOME"));
|
String home = System.getProperty("SPRING_HOME", System.getenv("SPRING_HOME"));
|
||||||
|
|
|
@ -15,16 +15,40 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.bootstrap.cli.command;
|
package org.springframework.bootstrap.cli.command;
|
||||||
|
|
||||||
|
import groovy.lang.Mixin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import joptsimple.OptionParser;
|
||||||
|
import joptsimple.OptionSet;
|
||||||
|
import joptsimple.OptionSpecBuilder;
|
||||||
|
|
||||||
|
import org.codehaus.groovy.ast.AnnotationNode;
|
||||||
|
import org.codehaus.groovy.ast.ClassHelper;
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
|
import org.codehaus.groovy.ast.MethodNode;
|
||||||
|
import org.codehaus.groovy.ast.Parameter;
|
||||||
|
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
|
||||||
|
import org.codehaus.groovy.ast.expr.ClassExpression;
|
||||||
|
import org.codehaus.groovy.ast.expr.ClosureExpression;
|
||||||
|
import org.codehaus.groovy.ast.expr.Expression;
|
||||||
|
import org.codehaus.groovy.ast.expr.MethodCallExpression;
|
||||||
|
import org.codehaus.groovy.ast.stmt.BlockStatement;
|
||||||
|
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
|
||||||
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
import org.codehaus.groovy.classgen.GeneratorContext;
|
import org.codehaus.groovy.classgen.GeneratorContext;
|
||||||
import org.codehaus.groovy.control.CompilationFailedException;
|
import org.codehaus.groovy.control.CompilationFailedException;
|
||||||
import org.codehaus.groovy.control.CompilePhase;
|
import org.codehaus.groovy.control.CompilePhase;
|
||||||
import org.codehaus.groovy.control.SourceUnit;
|
import org.codehaus.groovy.control.SourceUnit;
|
||||||
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
|
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
|
||||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.springframework.bootstrap.cli.Command;
|
import org.springframework.bootstrap.cli.Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Customizer for the compilation of CLI commands.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -37,10 +61,22 @@ public class ScriptCompilationCustomizer extends CompilationCustomizer {
|
||||||
@Override
|
@Override
|
||||||
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode)
|
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode)
|
||||||
throws CompilationFailedException {
|
throws CompilationFailedException {
|
||||||
// AnnotationNode mixin = new AnnotationNode(ClassHelper.make(Mixin.class));
|
addOptionHandlerMixin(classNode);
|
||||||
// mixin.addMember("value",
|
overrideOptionsMethod(source, classNode);
|
||||||
// new ClassExpression(ClassHelper.make(OptionHandler.class)));
|
addImports(source, context, classNode);
|
||||||
// classNode.addAnnotation(mixin);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add imports to the class node to make writing simple commands easier. No need to
|
||||||
|
* import {@link OptionParser}, {@link OptionSet}, {@link Command} or
|
||||||
|
* {@link OptionHandler}.
|
||||||
|
*
|
||||||
|
* @param source the source node
|
||||||
|
* @param context the current context
|
||||||
|
* @param classNode the class node to manipulate
|
||||||
|
*/
|
||||||
|
private void addImports(SourceUnit source, GeneratorContext context,
|
||||||
|
ClassNode classNode) {
|
||||||
ImportCustomizer importCustomizer = new ImportCustomizer();
|
ImportCustomizer importCustomizer = new ImportCustomizer();
|
||||||
importCustomizer.addImports("joptsimple.OptionParser", "joptsimple.OptionSet",
|
importCustomizer.addImports("joptsimple.OptionParser", "joptsimple.OptionSet",
|
||||||
OptionParsingCommand.class.getCanonicalName(),
|
OptionParsingCommand.class.getCanonicalName(),
|
||||||
|
@ -48,4 +84,73 @@ public class ScriptCompilationCustomizer extends CompilationCustomizer {
|
||||||
importCustomizer.call(source, context, classNode);
|
importCustomizer.call(source, context, classNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the script defines a block in this form:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* options {
|
||||||
|
* option "foo", "My Foo option"
|
||||||
|
* option "bar", "Bar has a value" withOptionalArg() ofType Integer
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Then the block is taken and used to override the {@link OptionHandler#options()}
|
||||||
|
* method. In the example "option" is a call to
|
||||||
|
* {@link OptionHandler#option(String, String)}, and hence returns an
|
||||||
|
* {@link OptionSpecBuilder}. Makes a nice readable DSL for adding options.
|
||||||
|
*
|
||||||
|
* @param source the source node
|
||||||
|
* @param classNode the class node to manipulate
|
||||||
|
*/
|
||||||
|
private void overrideOptionsMethod(SourceUnit source, ClassNode classNode) {
|
||||||
|
|
||||||
|
BlockStatement block = source.getAST().getStatementBlock();
|
||||||
|
List<Statement> statements = block.getStatements();
|
||||||
|
|
||||||
|
for (Statement statement : new ArrayList<Statement>(statements)) {
|
||||||
|
if (statement instanceof ExpressionStatement) {
|
||||||
|
ExpressionStatement expr = (ExpressionStatement) statement;
|
||||||
|
Expression expression = expr.getExpression();
|
||||||
|
if (expression instanceof MethodCallExpression) {
|
||||||
|
MethodCallExpression method = (MethodCallExpression) expression;
|
||||||
|
if (method.getMethod().getText().equals("options")) {
|
||||||
|
expression = method.getArguments();
|
||||||
|
if (expression instanceof ArgumentListExpression) {
|
||||||
|
ArgumentListExpression arguments = (ArgumentListExpression) expression;
|
||||||
|
expression = arguments.getExpression(0);
|
||||||
|
|
||||||
|
if (expression instanceof ClosureExpression) {
|
||||||
|
ClosureExpression closure = (ClosureExpression) expression;
|
||||||
|
classNode.addMethod(new MethodNode("options",
|
||||||
|
Opcodes.ACC_PROTECTED, ClassHelper.VOID_TYPE,
|
||||||
|
new Parameter[0], new ClassNode[0], closure
|
||||||
|
.getCode()));
|
||||||
|
statements.remove(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add {@link OptionHandler} as a mixin to the class node if it doesn't already
|
||||||
|
* declare it as a super class.
|
||||||
|
*
|
||||||
|
* @param classNode the class node to manipulate
|
||||||
|
*/
|
||||||
|
private void addOptionHandlerMixin(ClassNode classNode) {
|
||||||
|
// If we are not an OptionHandler then add that class as a mixin
|
||||||
|
if (!classNode.isDerivedFrom(ClassHelper.make(OptionHandler.class))
|
||||||
|
&& !classNode.isDerivedFrom(ClassHelper.make("OptionHandler"))) {
|
||||||
|
AnnotationNode mixin = new AnnotationNode(ClassHelper.make(Mixin.class));
|
||||||
|
mixin.addMember("value",
|
||||||
|
new ClassExpression(ClassHelper.make(OptionHandler.class)));
|
||||||
|
classNode.addAnnotation(mixin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.bootstrap.cli.command;
|
package org.springframework.bootstrap.cli.command;
|
||||||
|
|
||||||
|
import groovy.lang.GroovyObjectSupport;
|
||||||
import groovy.lang.Script;
|
import groovy.lang.Script;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +46,30 @@ public class ScriptCommandTests {
|
||||||
((String[]) ((Script) command.getMain()).getProperty("args"))[0]);
|
((String[]) ((Script) command.getMain()).getProperty("args"))[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocateFile() throws Exception {
|
||||||
|
ScriptCommand command = new ScriptCommand(
|
||||||
|
"src/test/resources/commands/script.groovy");
|
||||||
|
command.setPaths(new String[] { "." });
|
||||||
|
command.run("World");
|
||||||
|
assertEquals("World",
|
||||||
|
((String[]) ((Script) command.getMain()).getProperty("args"))[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRunnable() throws Exception {
|
||||||
|
ScriptCommand command = new ScriptCommand("runnable");
|
||||||
|
command.run("World");
|
||||||
|
assertTrue(executed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClosure() throws Exception {
|
||||||
|
ScriptCommand command = new ScriptCommand("closure");
|
||||||
|
command.run("World");
|
||||||
|
assertTrue(executed);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCommand() throws Exception {
|
public void testCommand() throws Exception {
|
||||||
ScriptCommand command = new ScriptCommand("command");
|
ScriptCommand command = new ScriptCommand("command");
|
||||||
|
@ -52,12 +78,42 @@ public class ScriptCommandTests {
|
||||||
assertTrue(executed);
|
assertTrue(executed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateClassName() throws Exception {
|
||||||
|
ScriptCommand command1 = new ScriptCommand("handler");
|
||||||
|
ScriptCommand command2 = new ScriptCommand("command");
|
||||||
|
assertNotSame(command1.getMain().getClass(), command2.getMain().getClass());
|
||||||
|
assertEquals(command1.getMain().getClass().getName(), command2.getMain()
|
||||||
|
.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOptions() throws Exception {
|
public void testOptions() throws Exception {
|
||||||
ScriptCommand command = new ScriptCommand("test");
|
ScriptCommand command = new ScriptCommand("handler");
|
||||||
command.run("World", "--foo");
|
|
||||||
String out = ((OptionHandler) command.getMain()).getHelp();
|
String out = ((OptionHandler) command.getMain()).getHelp();
|
||||||
assertTrue("Wrong output: " + out, out.contains("--foo"));
|
assertTrue("Wrong output: " + out, out.contains("--foo"));
|
||||||
|
command.run("World", "--foo");
|
||||||
|
assertTrue(executed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMixin() throws Exception {
|
||||||
|
ScriptCommand command = new ScriptCommand("mixin");
|
||||||
|
GroovyObjectSupport object = (GroovyObjectSupport) command.getMain();
|
||||||
|
String out = (String) object.getProperty("help");
|
||||||
|
assertTrue("Wrong output: " + out, out.contains("--foo"));
|
||||||
|
command.run("World", "--foo");
|
||||||
|
assertTrue(executed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMixinWithBlock() throws Exception {
|
||||||
|
ScriptCommand command = new ScriptCommand("test");
|
||||||
|
GroovyObjectSupport object = (GroovyObjectSupport) command.getMain();
|
||||||
|
String out = (String) object.getProperty("help");
|
||||||
|
System.err.println(out);
|
||||||
|
assertTrue("Wrong output: " + out, out.contains("--foo"));
|
||||||
|
command.run("World", "--foo", "--bar=2");
|
||||||
assertTrue(executed);
|
assertTrue(executed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
def run = { msg ->
|
||||||
|
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
||||||
|
println "Hello ${msg}"
|
||||||
|
}
|
||||||
|
|
||||||
|
run
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.test.command
|
||||||
|
|
||||||
|
class TestCommand implements Command {
|
||||||
|
|
||||||
|
String name = "foo"
|
||||||
|
|
||||||
|
String description = "My script command"
|
||||||
|
|
||||||
|
String help = "No options"
|
||||||
|
|
||||||
|
String usageHelp = "Not very useful"
|
||||||
|
|
||||||
|
void run(String... args) {
|
||||||
|
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
||||||
|
println "Hello ${args[0]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.test.command
|
||||||
|
|
||||||
|
@Grab("org.eclipse.jgit:org.eclipse.jgit:2.3.1.201302201838-r")
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
|
||||||
|
class TestCommand extends OptionHandler {
|
||||||
|
|
||||||
|
void options() {
|
||||||
|
option "foo", "Foo set"
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(OptionSet options) {
|
||||||
|
// Demonstrate use of Grape.grab to load dependencies before running
|
||||||
|
println "Clean : " + Git.open(".." as File).status().call().isClean()
|
||||||
|
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
||||||
|
println "Hello ${options.nonOptionArguments()}: ${options.has('foo')}"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
void options() {
|
||||||
|
option "foo", "Foo set"
|
||||||
|
}
|
||||||
|
|
||||||
|
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
||||||
|
println "Hello ${options.nonOptionArguments()}: ${options.has('foo')}"
|
|
@ -0,0 +1,11 @@
|
||||||
|
class TestCommand implements Runnable {
|
||||||
|
def msg
|
||||||
|
TestCommand(String msg) {
|
||||||
|
this.msg = msg
|
||||||
|
}
|
||||||
|
void run() {
|
||||||
|
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
||||||
|
println "Hello ${msg}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new TestCommand(args[0])
|
|
@ -1,19 +1,7 @@
|
||||||
package org.test.command
|
options {
|
||||||
|
option "foo", "Foo set"
|
||||||
@Grab("org.eclipse.jgit:org.eclipse.jgit:2.3.1.201302201838-r")
|
option "bar", "Bar has an argument of type int" withOptionalArg() ofType Integer
|
||||||
import org.eclipse.jgit.api.Git
|
|
||||||
|
|
||||||
class TestCommand extends OptionHandler {
|
|
||||||
|
|
||||||
void options() {
|
|
||||||
option "foo", "Foo set"
|
|
||||||
}
|
|
||||||
|
|
||||||
void run(OptionSet options) {
|
|
||||||
// Demonstrate use of Grape.grab to load dependencies before running
|
|
||||||
println "Clean : " + Git.open(".." as File).status().call().isClean()
|
|
||||||
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
|
||||||
println "Hello ${options.nonOptionArguments()}: ${options.has('foo')}"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
org.springframework.bootstrap.cli.command.ScriptCommandTests.executed = true
|
||||||
|
println "Hello ${options.nonOptionArguments()}: ${options.has('foo')} ${options.valueOf('bar')}"
|
||||||
|
|
Loading…
Reference in New Issue