[ https://issues.apache.org/jira/browse/GROOVY-8577?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16475145#comment-16475145 ]
ASF GitHub Bot commented on GROOVY-8577: ---------------------------------------- Github user remkop commented on a diff in the pull request: https://github.com/apache/groovy/pull/704#discussion_r188142573 --- Diff: src/main/groovy/org/codehaus/groovy/tools/GrapeMain.groovy --- @@ -19,290 +19,323 @@ package org.codehaus.groovy.tools import groovy.grape.Grape -import groovy.transform.Field -import org.apache.commons.cli.CommandLine -import org.apache.commons.cli.DefaultParser -import org.apache.commons.cli.HelpFormatter -import org.apache.commons.cli.Option -import org.apache.commons.cli.OptionGroup -import org.apache.commons.cli.Options import org.apache.ivy.util.DefaultMessageLogger import org.apache.ivy.util.Message - -//commands - -@Field install = {arg, cmd -> - if (arg.size() > 5 || arg.size() < 3) { - println 'install requires two to four arguments: <group> <module> [<version> [<classifier>]]' - return - } - def ver = '*' - if (arg.size() >= 4) { - ver = arg[3] - } - def classifier = null - if (arg.size() >= 5) { - classifier = arg[4] +import picocli.CommandLine +import picocli.CommandLine.Command +import picocli.CommandLine.Option +import picocli.CommandLine.Parameters +import picocli.CommandLine.ParentCommand +import picocli.CommandLine.RunLast +import picocli.CommandLine.Unmatched + +@Command(name = "grape", description = "Allows for the inspection and management of the local grape cache.", + subcommands = [ + Install.class, + Uninstall.class, + ListCommand.class, + Resolve.class, + picocli.CommandLine.HelpCommand.class]) +class GrapeMain implements Runnable { + @Option(names = ["-D", "--define"], description = "define a system property", paramLabel = "<name=value>") + private Map<String, String> properties = new LinkedHashMap<String, String>() + + @Option(names = ["-r", "--resolver"], description = "define a grab resolver (for install)", paramLabel = "<url>") + private List<String> resolvers = new ArrayList<String>() + + @Option(names = ["-q", "--quiet"], description = "Log level 0 - only errors") + private boolean quiet + + @Option(names = ["-w", "--warn"], description = "Log level 1 - errors and warnings") + private boolean warn + + @Option(names = ["-i", "--info"], description = "Log level 2 - info") + private boolean info + + @Option(names = ["-V", "--verbose"], description = "Log level 3 - verbose") + private boolean verbose + + @Option(names = ["-d", "--debug"], description = "Log level 4 - debug") + private boolean debug + + @Unmatched List<String> unmatched = new ArrayList<String>() + + private CommandLine parser + + public static void main(String[] args) { + GrapeMain grape = new GrapeMain() + def parser = new CommandLine(grape) + parser.addMixin("helpOptions", new HelpOptionsMixin()) + parser.subcommands.findAll { k, v -> k != 'help' }.each { k, v -> v.addMixin("helpOptions", new HelpOptionsMixin()) } + + grape.parser = parser + parser.parseWithHandler(new RunLast(), args) } - // set the instance so we can re-set the logger - Grape.getInstance() - setupLogging() + void run() { + if (unmatched) { + System.err.println "grape: '${unmatched[0]}' is not a grape command. See 'grape --help'" + } else { + parser.usage(System.out) // if no subcommand was specified + } + } - cmd.getOptionValues('r')?.each { String url -> - Grape.addResolver(name:url, root:url) + private void init() { + properties.each { k, v -> + System.setProperty(k, v) + } } - try { - Grape.grab(autoDownload: true, group: arg[1], module: arg[2], version: ver, classifier: classifier, noExceptions: true) - } catch (Exception e) { - println "An error occured : $ex" + private void setupLogging(int defaultLevel = 2) { // = Message.MSG_INFO -> some parsing error :( + if (quiet) { + Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_ERR)) + } else if (warn) { + Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_WARN)) + } else if (info) { + Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_INFO)) + } else if (verbose) { + Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_VERBOSE)) + } else if (debug) { + Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_DEBUG)) + } else { + Message.setDefaultLogger(new DefaultMessageLogger(defaultLevel)) + } } -} -@Field uninstall = {arg, cmd -> - if (arg.size() != 4) { - println 'uninstall requires three arguments: <group> <module> <version>' - // TODO make version optional? support classifier? -// println 'uninstall requires two to four arguments, <group> <module> [<version>] [<classifier>]' - return + /** + * Defines help options (--help and --version) and a version provider used by the top-level command and all subcommands. + * Intended to be installed as a picocli mixin. + */ + // IMPLEMENTATION NOTE: + // The @Command(mixinStandardHelpOptions = true) attribute cannot be used because + // the unix standard short option for version help is uppercase -V, while previous versions + // of this class use lowercase -v. This custom mixin preserves option compatibility. + @Command(versionProvider = VersionProvider.class, sortOptions = false, + parameterListHeading = "%nParameters:%n", + optionListHeading = "%nOptions:%n", + descriptionHeading = "%n") + private static class HelpOptionsMixin { + @Option(names = ["-h", "--help"], description = "usage information") boolean isHelpRequested + @Option(names = ["-v", "--version"], description = "display the Groovy and JVM versions") boolean isVersionRequested } - String group = arg[1] - String module = arg[2] - String ver = arg[3] -// def classifier = null - - // set the instance so we can re-set the logger - Grape.getInstance() - setupLogging() - - if (!Grape.enumerateGrapes().find {String groupName, Map g -> - g.any {String moduleName, List<String> versions -> - group == groupName && module == moduleName && ver in versions - } - }) { - println "uninstall did not find grape matching: $group $module $ver" - def fuzzyMatches = Grape.enumerateGrapes().findAll { String groupName, Map g -> - g.any {String moduleName, List<String> versions -> - groupName.contains(group) || moduleName.contains(module) || - group.contains(groupName) || module.contains(moduleName) - } - } - if (fuzzyMatches) { - println 'possible matches:' - fuzzyMatches.each { String groupName, Map g -> println " $groupName: $g" } + + private static class VersionProvider implements CommandLine.IVersionProvider { + String[] getVersion() { + String version = GroovySystem.getVersion() + return "Groovy Version: $version JVM: ${System.getProperty('java.version')}" } - return } - Grape.instance.uninstallArtifact(group, module, ver) -} -@Field list = {arg, cmd -> - println "" + @Command(name = 'install', header = 'Installs a particular grape', + synopsisHeading = 'Usage: grape ', --- End diff -- This synopsisHeading ensures that help for subcommands also mentions the `grape` top level command, so usage looks like this: ``` Usage: grape install <group> <module> [<version>] [<classifier>] Usage: grape uninstall <group> <module> <version> Usage: grape list ... ``` From picocli 3.0.1, prefixing subcommands with the parent command name is done automatically, so this may need to change when upgrading. > Migrate org.codehaus.groovy.tools.GrapeMain.groovy to picocli > ------------------------------------------------------------- > > Key: GROOVY-8577 > URL: https://issues.apache.org/jira/browse/GROOVY-8577 > Project: Groovy > Issue Type: Task > Reporter: Remko Popma > Priority: Major > > Migrate org.codehaus.groovy.tools.GrapeMain.groovy to picocli as part of > GROOVY-8556. -- This message was sent by Atlassian JIRA (v7.6.3#76005)