You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by remkop <gi...@git.apache.org> on 2018/05/11 19:19:07 UTC

[GitHub] groovy pull request #704: GROOVY-8577 Migrate org.codehaus.groovy.tools.Grap...

GitHub user remkop opened a pull request:

    https://github.com/apache/groovy/pull/704

    GROOVY-8577 Migrate org.codehaus.groovy.tools.GrapeMain.groovy to picocli

    GROOVY-8577 Migrate org.codehaus.groovy.tools.GrapeMain.groovy to picocli

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/remkop/groovy GROOVY-8577-GrapeMain(attempt2)

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/groovy/pull/704.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #704
    
----
commit 92d40dbb0305a901fcbacf6a313f1e5776889a70
Author: Remko Popma <re...@...>
Date:   2018-05-10T16:27:36Z

    GROOVY-8577 Migrate org.codehaus.groovy.tools.GrapeMain.groovy to picocli

----


---

[GitHub] groovy pull request #704: GROOVY-8577 Migrate org.codehaus.groovy.tools.Grap...

Posted by asfgit <gi...@git.apache.org>.
Github user asfgit closed the pull request at:

    https://github.com/apache/groovy/pull/704


---

[GitHub] groovy pull request #704: GROOVY-8577 Migrate org.codehaus.groovy.tools.Grap...

Posted by remkop <gi...@git.apache.org>.
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.



---