From 316a1b3361382ed5f460b673637dfc0c964934e1 Mon Sep 17 00:00:00 2001 From: Michael Pyne Date: Sun, 26 Jan 2014 00:03:08 -0500 Subject: [PATCH] cmdline: Restore support for arbitrary global option handling. The recent port to Getopt::Long broke the ability to use --foo=bar type of options (where is a global option name known to the build context). It also replaced the --module,foo=bar options with --set-module-option-value=module,foo,bar. While it's possible to use the latter syntax for global options (by using 'global' as the module name) that is undocumented and may not work forever. And either way, --foo options did use to work, and I noted it was broken in the refactor. So now that someone else has noticed I've reimplemented the feature. It's difficult to do entirely from within Getopt::Long since the documentation for that module gives you essentially one catch-all, which only supports *non-options*. So what I've done instead is to have kdesrc-build dynamically introspect its list of global options and flags and then add them to the list of valid options we pass to Getopt::Long. This also should mean that we don't need to pass 'pass_through' as an option to Getopt::Long anymore, though we'll see. This code path won't be used for options that already have a command line option (such as --async/--no-async) so that is still a misfeature compared to how it was before, but I guess it can't be perfect. =D I've tried to ensure that "flags" support the 'false' value to mean boolean false, but be careful to pass false or 0 if that's what you mean... specifying --dont-foo without giving it a value defaults it to true. BUG:330386 --- modules/ksb/Application.pm | 56 ++++++++++++++++++++++++++++++-------- modules/ksb/Updater/Svn.pm | 2 +- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/modules/ksb/Application.pm b/modules/ksb/Application.pm index f8af2cf..a06e0c2 100644 --- a/modules/ksb/Application.pm +++ b/modules/ksb/Application.pm @@ -121,9 +121,7 @@ sub new # See pendingOptions for the special note about the value of this listref # when start-options is in effect. # -# phases - to hold the list of phases to run. See . -# This will be the PhaseList that should be used for the global context -# object. +# ctx - to hold the global build state. # # @options - The remainder of the arguments are treated as command line # arguments to process. @@ -134,7 +132,8 @@ sub new sub _readCommandLineOptionsAndSelectors { my $self = shift; - my ($pendingOptionsRef, $selectorsRef, $phases, @options) = @_; + my ($pendingOptionsRef, $selectorsRef, $ctx, @options) = @_; + my $phases = $ctx->phases(); my @savedOptions = @options; # Copied for use in debugging. my $version = "kdesrc-build $SCRIPT_VERSION"; my $author = < sub { say $version; exit }, author => sub { say $author; exit }, @@ -189,13 +193,13 @@ DONE }, prefix => sub { my ($optName, $arg) = @_; - $foundOptions{prefix} = $arg; + $auxOptions{prefix} = $arg; $foundOptions{kdedir} = $arg; #TODO: Still needed for compat? $foundOptions{reconfigure} = 1; }, pretend => sub { # Set pretend mode but also force the build process to run. - $foundOptions{pretend} = 1; + $auxOptions{pretend} = 1; $foundOptions{'build-when-unchanged'} = 1; }, verbose => sub { $foundOptions{'debug-level'} = ksb::Debug::WHISPER }, @@ -229,6 +233,25 @@ DONE }, ); + # Handle any "cmdline-eligible" options not already covered. + my $flagHandler = sub { + my ($optName, $optValue) = @_; + + # Assume to set if nothing provided. + $optValue = 1 if (!defined $optValue or $optValue eq ''); + $optValue = 0 if lc($optValue) eq 'false'; + $optValue = 0 if !$optValue; + + $auxOptions{$optName} = $optValue; + }; + + foreach my $option (keys %ksb::BuildContext::defaultGlobalFlags) { + if (!exists $foundOptions{$option}) { + $foundOptions{$option} = $flagHandler; # A ref to a sub here! + } + } + + # Actually read the options. GetOptionsFromArray(\@options, \%foundOptions, 'version', 'author', 'help', 'disable-snapshots|no-snapshots', 'install', 'uninstall', 'no-src|no-svn', 'no-install', 'no-build', @@ -237,15 +260,21 @@ DONE 'reconfigure', 'colorful-output|color!', 'async!', 'src-only|svn-only', 'build-only', 'build-system-only', 'rc-file=s', 'prefix=s', 'niceness|nice:10', 'ignore-modules=s{,}', - 'pretend|dry-run|p', 'refresh-build', 'delete-my-patches', + 'pretend|dry-run|p', 'refresh-build', 'start-program|run=s{,}', - 'delete-my-settings', 'revision=i', 'resume-from=s', 'resume-after=s', + 'revision=i', 'resume-from=s', 'resume-after=s', 'stop-after=s', 'stop-before=s', 'set-module-option-value=s', + + # Special sub used (see above), but have to tell Getopt::Long to look + # for strings + (map { "$_:s" } (keys %ksb::BuildContext::defaultGlobalFlags)), + + # Default handling fine, still have to ask for strings. + (map { "$_:s" } (keys %ksb::BuildContext::defaultGlobalOptions)), + '<>', # Required to read non-option args ); - # TODO: Handle unrecognized options by searching within our list of global - # preset options as before? say "Warning: Unrecognized option $_" foreach @options; $pendingOptionsRef->{'global'} //= { }; @@ -262,6 +291,9 @@ DONE # with hashref syntax everywhere. @{ $pendingOptionsRef->{'global'} }{@readOptionNames} = @foundOptions{@readOptionNames}; + + @{ $pendingOptionsRef->{'global'} }{keys %auxOptions} + = values %auxOptions; } # Method: _resolveSelectorsIntoModules @@ -482,7 +514,7 @@ sub generateModuleList # Process --help, --install, etc. first. my @selectors; $self->_readCommandLineOptionsAndSelectors($pendingOptions, \@selectors, - $ctx->phases(), @argv); + $ctx, @argv); my %ignoredSelectors; @ignoredSelectors{@{$pendingGlobalOptions->{'ignore-modules'}}} = undef; diff --git a/modules/ksb/Updater/Svn.pm b/modules/ksb/Updater/Svn.pm index ae78402..1b6d226 100644 --- a/modules/ksb/Updater/Svn.pm +++ b/modules/ksb/Updater/Svn.pm @@ -463,7 +463,7 @@ sub run_svn my $module = $self->module(); my $revision = $module->getOption('revision'); - if ($revision ne '0') + if ($revision && $revision ne '0') { my @tmp = @{$arg_ref};