Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduce a picocli-based subcommand CLI architecture to replace the flat, flag-based jopt-simple interface. The legacy jopt-simple path is fully preserved and routed via
Main.isLegacyInvocation(), ensuring backward compatibility during the transition. Several code quality improvements are included alongside the new CLI infrastructure.Changes
app,worker,stage,plugin,extension,api-key) with leaf subcommandsisLegacyInvocation()routes between jopt-simple and picocliScopeType.INHERITonGlobalOptionsDatashareHelpFactorywith two-column layout, alphabetical sorting, and a dedicated Global Options sectionMain.main()into focused private methodsDatashareHelpFactory.apply()withheadedSection,ownOptionRows,globalOptionRowshelpersputIfNotNulltoDatashareOptions; addOAUTH_CLAIM_ID_ATTRIBUTE_OPTconstantDatashareVersionProvider(try-with-resources)defaultProjectnow falls back tolocal-datashareinstead of passing throughdefaultProjectfallback, legacy invocation routingBreaking changes
The new subcommand interface is not yet the default path (the legacy invocation is still selected automatically for existing callers). However, users who integrate with the CLI programmatically or parse its output should be aware:
--helpoutputapp start,worker run,stage run,plugin list/install/delete, etc.) are new entry points that do not exist in the legacy interface; tooling that wraps the CLI will need updating when the legacy path is eventually removedArchitecture
Invocation routing
Main.main()is now a two-liner that delegates toresolveProperties(), which picks the right parser:flowchart TD A["./datashare <args>"] --> B{isLegacyInvocation?} B -->|"no args\nfirst arg starts with -\nfirst arg not a known subcommand"| C[Legacy path\nDatashareCli / jopt-simple] B -->|"first arg is app / worker /\nstage / plugin / extension /\napi-key / help"| D[Picocli path\nrunPicocli] C --> E[cli.properties] D --> F[cmd.collectProperties] E --> G[startApplication] F --> GSubcommand tree
Parent commands (
app,worker, etc.) print usage when invoked without a subcommand. All leaf commands implement bothRunnableandDatashareSubcommand.Property assembly
flowchart LR G[GlobalOptions.toProperties] --> M[DatashareCommand\n.collectProperties] S[LeafCommand.getSubcommandProperties] -->|"overrides globals"| M M --> P[DatashareOptions.postProcess\ndigestProjectName · oauthUserProjectsAttribute · port alias] P --> R[Properties passed to\nCommonMode.create]Subcommand properties are merged last, so subcommand-specific values override global defaults.
Global options and position independence
Every option in
GlobalOptionscarriesscope = ScopeType.INHERIT. picocli propagates them down to every leaf command spec, so they are accepted at any position:DatashareHelpFactoryfilterso.inherited()from each subcommand's own option list to prevent duplicate rendering, then renders inherited options in a separate Global Options section.Help rendering
DatashareHelpFactoryapplies a yarn-inspired style to every command in the tree:[OPTIONS]):are auto-bolded as headingsGlobalOptions(leaf subcommands only)Column widths are sized to the widest option label across both the Options and Global Options sections so both blocks align. Options are sorted alphabetically by long name.
Shell script routing
The
datasharelaunch script detects the invocation style from the first argument:Both paths inject
--elasticsearchPath,--elasticsearchSettings, and--elasticsearchDataPathfrom shell-resolved defaults ($DATASHARE_HOME). User-provided options are appended last and override the injected defaults (picocli'ssetOverwrittenOptionsAllowed(true)). ES setup runs for--mode EMBEDDEDin both paths.