Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to picocli #572

Merged
merged 8 commits into from May 20, 2021
Merged

Conversation

ancho
Copy link
Member

@ancho ancho commented Nov 17, 2018

using https://github.com/remkop/picocli as a replacement for args4j.

picocl-80

picocli-wide

@coveralls
Copy link

Coverage Status

Coverage increased (+0.3%) to 81.087% when pulling 24fd40e on ancho:feature/picocli-integration into 1903219 on jbake-org:master.

@coveralls
Copy link

coveralls commented Nov 17, 2018

Coverage Status

Coverage increased (+1.04%) to 81.818% when pulling 9cb42b5 on ancho:feature/picocli-integration into c9989a3 on jbake-org:master.

@ancho
Copy link
Member Author

ancho commented Nov 17, 2018

only openjdk 10 build is failing with the following error:

FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all files for configuration ':jbake-core:compileClasspath'.
> Could not resolve info.picocli:picocli:3.8.0.
  Required by:
      project :jbake-core
   > Could not resolve info.picocli:picocli:3.8.0.
      > Could not get resource 'https://jcenter.bintray.com/info/picocli/picocli/3.8.0/picocli-3.8.0.pom'.
         > Could not GET 'https://jcenter.bintray.com/info/picocli/picocli/3.8.0/picocli-3.8.0.pom'.
            > sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

See https://travis-ci.org/jbake-org/jbake/jobs/456215263

@ancho ancho force-pushed the feature/picocli-integration branch from 621d58e to 6ac0eb6 Compare May 1, 2020 13:41
@manikmagar
Copy link
Member

@ancho There is change is one behavior - With args4j version -t had dependency on -i. Running jbake -t groovy used to fail with error description that it must be used with -i. With picocli version, runing jbake -t groovy just prints the help section with no clues to why -t did not work.

@lefou
Copy link
Member

lefou commented May 10, 2020

Looks like it's time to really replace args4j? Yay! I haven't reviewed this one, but just wanted to note that I once created another replacement in pull request #120. It must be really really outdated by now, but just in case you want to compare I thought I provide a link here. Feel free to ignore it!

@ancho
Copy link
Member Author

ancho commented May 11, 2020

@manikmagar thanks for catching this. I will restore that behaviour.

@ancho
Copy link
Member Author

ancho commented May 11, 2020

@lefou interesting. will have a look. even though i think that picocli is the way to go. it has a lot of nice features like creating manpages, autocomplete scripts and supports internationalization. see https://picocli.info/autocomplete.html and https://picocli.info/#_generate_man_page_documentation

@manikmagar
Copy link
Member

Something related to what @lefou also mentioned in the discussion on his PR, make it easier when using JBake as library. Main.main() method causes System.exit, which could be fine when using from CLI. Should we make run(String[] args) method as public instead of protected? This then enables to use it as a library and call new Main().run(... args ..) from another code. This method nor rightly throws exception instead of causing System.exit.

@ancho
Copy link
Member Author

ancho commented May 12, 2020

Yeah. A cleanup of everything cli related needs to be done. And to be honest I would move everything cli related to the jbake-dist repo (which was originaly named jbake-cli).
I don't really see a benefit for Main to be exposed to the public as an api.

What use case do you have in mind?

@manikmagar
Copy link
Member

No specific use case right now. Seeing Tobias's comment reminded me of the similar issue I ran into when using Liquibase as a library. Good that their run method is public and I could switch from main to calling run directly. We could defer it until someone ask for it.

@lefou
Copy link
Member

lefou commented May 13, 2020

Yeah, having a public static run method alongside the main is a common pattern. The only difference: main uses System.exit whereas run throws a App-specific exception, ideally also containing the desired exit code (that allows to exit the app early disregarding the presence of errors).

@ancho
Copy link
Member Author

ancho commented May 13, 2020

Allright. That's what the proteced run method already does ;)
Except the thing with the desired exit code. Thats a nice idea.
But I still don't see why a developer wants to use the Main class in it's own code.

@lefou
Copy link
Member

lefou commented May 13, 2020

It's more the integration point (like the use as a library). E.g. jbake is integrated in different build tools. The easiest integration is to just run a sub-process and evaluating the exit code. This is the most stable integration, but also gives you the least control, it's also the slowest and heaviest, as you need to create a new process, need more memory, etc.

Next level we allow with the pulbic run method: We can just load jbake as library or use an isolated classloader, but still don't need to learn the whole JBake API. We can still (re-)use the construction logic for the commandline, but without the extra process. We can use the same (hot) JVM. We can even give the user the choice to decide (classloader or process) without much efforts. But the integration logic is very simple, just some strings. It's even easy to do in reflection (e.g. when using an isolated classloaded without any extra glue API). It's also very stable against all API refactorings as long as the cmdline keeps compatible.

@lefou
Copy link
Member

lefou commented May 13, 2020

See https://github.com/lefou/mill-jbake.

From the plugin documentation:

  • def jbakeProcessMode: ProcessMode - Specify how the JBake tool should be executed.

Supported value:

  • ClassLoader runs JBake in an isolated classpath in the same JVM.
  • SubProcess spawns a new Java sub-process of each JBake tool invokation.

Defaults to ClassLoader which is also faster.
If you experience stability or out-of-memory issues, try to change this to SubProcess.


The current implementation needs to use a custom SecurityManager to intercept the System.exit calls, which does work, but not so well when used in mills parallel evaluation mode.

https://github.com/lefou/mill-jbake/blob/a538ffb5f177c56ec25de996c59558c2fad9004d/jbake/src/de/tobiasroeser/mill/jbake/JBakeWorkerClassloaderImpl.scala#L35

@ancho
Copy link
Member Author

ancho commented May 13, 2020

Ok. Got it. Thanks for the clarification. That shifts my perspective. So lets do this.
How would you extend the JbakeException to add the desired exit value?
Just an attribute with a default value of 1 with the possibility to define it on exception instantiation?

Like new JBakeException("something went wrong") // ex.exit == 1
new JBakeException("serious error", SystemExit.SERIOUS) // ex.exit == 2

Where SystemExit has predefined error codes.

@lefou
Copy link
Member

lefou commented May 13, 2020

Yeah, looks reasonable. Personally, I would move the exit code to the first argument and avoid the default.

gradle.properties Outdated Show resolved Hide resolved
@ancho ancho changed the title switch to picocli [WIP] switch to picocli May 13, 2020
@ancho ancho marked this pull request as draft May 13, 2020 17:36
@ancho ancho marked this pull request as ready for review May 13, 2020 19:09
@ancho ancho changed the title [WIP] switch to picocli switch to picocli May 13, 2020
@ancho ancho force-pushed the feature/picocli-integration branch from a57a960 to 3956f60 Compare May 13, 2020 20:24
Comment on lines 12 to 16
public enum SystemExit {
ERROR(1),
CONFIGURATION_ERROR(2),
INIT_ERROR(3),
SERVER_ERROR(4);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You forgot the success case (exit code 0).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I can add that. But I don't see why I would throw an exception and exit with 0.

Copy link
Member

@lefou lefou May 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found these useful, but my understanding of JBakes codebase is a very dated, so there is probably currently no use for it. E.g. I sometime use it to exit early, e.g. when the user added a -h to the cmdline to get the help.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-h or calling jbake without arguments prints the usage information. As there was no exception thrown the status code of the cli is implicitly 0.

jbake -h; echo "status: $?" 
JBake v2.7.0-SNAPSHOT (2020-05-13 22:55:59nachm.) [http://jbake.org]

Usage: jbake [-i[=-i] [-t=<template>]] [-bhs] [--reset] [<source>]
             [<destination>]
JBake is a Java based, open source, static site/blog generator for developers &
designers
      [<source>]        source folder of site content (with templates and
                          assets), if not supplied will default to current
                          directory
      [<destination>]   destination folder for output, if not supplied will
                          default to a folder called "output" in the current
                          directory
  -b, --bake            performs a bake
  -h, --help            prints this message
      --reset           clears the local cache, enforcing rendering from scratch
  -s, --server          runs HTTP server to serve out baked site, if no <value>
                          is supplied will default to a folder called "output"
                          in the current directory
JBake initialization
  -i, --init[=-i]       initialises required folder structure with default
                          templates (defaults to current directory if <value>
                          is not supplied)
  -t, --template=<template>
                        use specified template engine for default templates
                          (uses Freemarker if <value> is not supplied)
status: 0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could move the internal SystemExit class and add the SUCCESS status so a user can use it. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Success execution with 0 looks good to me.

@ancho ancho force-pushed the feature/picocli-integration branch from 3956f60 to ee490b4 Compare May 13, 2020 21:26
Copy link
Member

@jonbullock jonbullock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, lots of scope for improvement of the CLI with this.

@ancho ancho force-pushed the feature/picocli-integration branch from 9cb42b5 to 5391a3b Compare February 24, 2021 22:46
@jonbullock jonbullock added this to the v2.7.0 milestone May 6, 2021
@jonbullock
Copy link
Member

Marked it for 2.7.0 so it's reviewed.

@ancho ancho force-pushed the feature/picocli-integration branch from 5391a3b to 96156b0 Compare May 11, 2021 20:25
@ancho ancho added this to PR requiring manual merge in v2.7.0 Release May 12, 2021
@ancho
Copy link
Member Author

ancho commented May 12, 2021

Should be merged and aligned after #615

@jonbullock jonbullock moved this from PR requiring manual merge to PR ready to merge in in v2.7.0 Release May 19, 2021
@jonbullock jonbullock merged commit dcc0e83 into jbake-org:master May 20, 2021
@jonbullock jonbullock moved this from PR ready to merge in to Done in v2.7.0 Release May 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

None yet

5 participants