Hello, On ketvirtadienis 27 Rugpjūtis 2009 23:52:31 Joey Hess wrote: > > On trečiadienis 26 Rugpjūtis 2009 23:56:30 Joey Hess wrote: > > > Why not instead allow build systems to hook into regular getopt > > > processing, so they can define their own first-class options? > > > > Sure, it would be nice. But how? _init() is executed before any of the > > build systems are loaded. And many of them are loaded in order to > > evaluate their autobuildable status. The only solution I can think of is > > to Getopt on the @ARGV of the remaining options after initial init() as > > soon as build system to be used is known, i.e. right after > > load_buildsystem() in buildsystems_do(). This will require (conditional) > > use of Getopt::Long::Configure("passthrough") in Dh_Getopt though. Is > > this acceptable? > > FWIW, I took a very similar approach in ikiwiki, and am happy with it > there. :)
Ok, so here it is a new patch with "multi-pass" mode for options and first class options for build systems. Full blown test suite is included. In fact, nothing remains from the first patch since solution is completely different (as you suggested). -- Modestas Vainius <modes...@vainius.eu>
From: Modestas Vainius <modes...@vainius.eu> Subject: [PATCH] Allow to pass options to buildsystems Allow to pass first-class build system specific options to dh_auto_* commands. The patch also makes necessary changes to the core Dh_Getopt and Dh_Lib modules to support "delayed" (i.e. post init()) parsing of extra options. Additional safeguards are put to ensure that either init() or parse_extra_options() gets called without "multipass_options=>1" once to fully complete option parsing. If not, such a buggy debhelper program would miss non-option arguments (at least). The patch includes a testsuite for new features. Signed-off-by: Modestas Vainius <modes...@vainius.eu> --- Debian/Debhelper/Buildsystem.pm | 7 + Debian/Debhelper/Dh_Buildsystems.pm | 10 +- Debian/Debhelper/Dh_Getopt.pm | 182 ++++++++++++----- Debian/Debhelper/Dh_Lib.pm | 28 +++- debhelper.pod | 6 + debian/changelog | 7 + .../Debian/Debhelper/Buildsystem/test.pm | 51 +++++ t/buildsystems/buildsystem_tests | 17 ++- t/getopt | 219 ++++++++++++++++++++ 9 files changed, 465 insertions(+), 62 deletions(-) diff --git a/Debian/Debhelper/Buildsystem.pm b/Debian/Debhelper/Buildsystem.pm index 62c45b5..12c2dea 100644 --- a/Debian/Debhelper/Buildsystem.pm +++ b/Debian/Debhelper/Buildsystem.pm @@ -35,6 +35,13 @@ sub DESCRIPTION { error("class lacking a DESCRIPTION"); } +# List of Getopt::Long style definitions of extra options for +# the build system. None is defined by default. +sub OPTIONS { + my $this=shift; + (); +} + # Default build directory. Can be overriden in the derived # class if really needed. sub DEFAULT_BUILD_DIRECTORY { diff --git a/Debian/Debhelper/Dh_Buildsystems.pm b/Debian/Debhelper/Dh_Buildsystems.pm index 4986267..0ce1261 100644 --- a/Debian/Debhelper/Dh_Buildsystems.pm +++ b/Debian/Debhelper/Dh_Buildsystems.pm @@ -113,7 +113,7 @@ sub buildsystems_init { my %options = ( "D=s" => \$opt_sourcedir, "sourcedirectory=s" => \$opt_sourcedir, - + "B:s" => \$opt_builddir, "builddirectory:s" => \$opt_builddir, @@ -124,7 +124,7 @@ sub buildsystems_init { "list" => \$opt_list, ); $args{options}{$_} = $options{$_} foreach keys(%options); - Debian::Debhelper::Dh_Lib::init(%args); + Debian::Debhelper::Dh_Lib::init(multipass_options => 1, %args); } sub buildsystems_list { @@ -164,16 +164,22 @@ sub buildsystems_do { } if ($opt_list) { + parse_extra_options(); # no extra options buildsystems_list($step); exit 0; } my $buildsystem = load_buildsystem($opt_buildsys, $step); if (defined $buildsystem) { + # Parse build system specific command line options + parse_extra_options(options => +{ $buildsystem->OPTIONS() }); $buildsystem->pre_building_step($step); $buildsystem->$step(@_, @{$dh{U_PARAMS}}); $buildsystem->post_building_step($step); } + else { + parse_extra_options(); # no extra options + } return 0; } diff --git a/Debian/Debhelper/Dh_Getopt.pm b/Debian/Debhelper/Dh_Getopt.pm index edb3be7..8a7dbc5 100644 --- a/Debian/Debhelper/Dh_Getopt.pm +++ b/Debian/Debhelper/Dh_Getopt.pm @@ -66,41 +66,32 @@ sub NonOption { push @{$dh{ARGV}}, @_; } -sub getoptions { - my $array=shift; - my %options=%{shift()} if ref $_[0]; - - my $oldwarn; - if ($ENV{DH_IGNORE_UNKNOWN_OPTIONS}) { - $oldwarn=$SIG{__WARN__}; - $SIG{__WARN__}=sub {}; - } - - my $ret=Getopt::Long::GetOptionsFromArray($array, +sub StandardOptions { + ( "v" => \$dh{VERBOSE}, "verbose" => \$dh{VERBOSE}, "no-act" => \$dh{NO_ACT}, - + "i" => \&AddPackage, "indep" => \&AddPackage, - + "a" => \&AddPackage, "arch" => \&AddPackage, - + "p=s" => \&AddPackage, - "package=s" => \&AddPackage, - + "package=s" => \&AddPackage, + "N=s" => \&ExcludePackage, "no-package=s" => \&ExcludePackage, - + "remaining-packages" => \$dh{EXCLUDE_LOGGED}, - + "dbg-package=s" => \&AddDebugPackage, - + "s" => \&AddPackage, "same-arch" => \&AddPackage, - + "n" => \$dh{NOSCRIPTS}, "noscripts" => \$dh{NOSCRIPTS}, "o" => \$dh{ONLYSCRIPTS}, @@ -108,9 +99,9 @@ sub getoptions { "X=s" => \&AddExclude, "exclude=s" => \&AddExclude, - + "d" => \$dh{D_FLAG}, - + "k" => \$dh{K_FLAG}, "keep" => \$dh{K_FLAG}, @@ -123,9 +114,9 @@ sub getoptions { "A" => \$dh{PARAMS_ALL}, "all" => \$dh{PARAMS_ALL}, - + "priority=s" => \$dh{PRIORITY}, - + "h|help" => \&showhelp, "mainpackage=s" => \$dh{MAINPACKAGE}, @@ -133,13 +124,37 @@ sub getoptions { "name=s" => \$dh{NAME}, "error-handler=s" => \$dh{ERROR_HANDLER}, - + "ignore=s" => \&AddIgnore, + ); +} - %options, +sub getoptions { + my $array=shift; + my %para...@_; + my %extraoptions=%{$params{options}} if $params{options}; + my @conf...@{$params{config}} if $params{config}; - "<>" => \&NonOption, - ); + # Silently succeed on empty array + return 1 if @$array == 0; + + # Setup hash of standard options. Silently succeed if there are no options + my %options = StandardOptions if !$params{nostandard}; + # Do not use <> with pass_through. It will "eat" all unrecognized options + # at that specific pass. + $options{"<>"}=\&NonOption if not grep /^pass_?through$/, @config; + return 1 if scalar(keys %options) == 0 && scalar(keys %extraoptions) == 0; + + # Prepare and parse + my $oldwarn; + if ($ENV{DH_IGNORE_UNKNOWN_OPTIONS}) { + $oldwarn=$SIG{__WARN__}; + $SIG{__WARN__}=sub {}; + } + + my $prevconfig = Getopt::Long::Configure(@config) if (@config); # save config + my $ret=Getopt::Long::GetOptionsFromArray($array, %options, %extraoptions); + Getopt::Long::Configure($prevconfig) if (@config); # restore previous config if ($ENV{DH_IGNORE_UNKNOWN_OPTIONS}) { $SIG{__WARN__}=$oldwarn; @@ -156,17 +171,42 @@ sub split_options_string { return split(/\s+/,$str); } +my %ARGVs = ( + int => [], + env => [], + cli => [], +); + +sub getoptions_ARGVs { + my $t=shift; + my $ret; + + $ret = getoptions($ARGVs{$t}, @_); + if (!$ret) { + # No error checking for int type + if ($t eq "env") { + warning("warning: ignored unknown options in DH_OPTIONS"); + } + elsif ($t eq "cli") { + warning("warning: unknown options will be a fatal error in a future debhelper release"); + #error("unknown option; aborting"); + } + } + return $ret; +} + # Parse options and set %dh values. sub parseopts { - my $options=shift; - - my @ARGV_extra; + my %para...@_; + my %getopts=( options => $params{options} ); + push @{$getopts{config}}, "pass_through" if $params{multipass_options}; + my $ret = 1; # DH_INTERNAL_OPTIONS is used to pass additional options from # dh through an override target to a command. if (defined $ENV{DH_INTERNAL_OPTIONS}) { - @ARGV_extra=split(/\x1e/, $ENV{DH_INTERNAL_OPTIONS}); - getoptions(\...@argv_extra, $options); + @{$ARGVs{int}}=split(/\x1e/, $ENV{DH_INTERNAL_OPTIONS}); + $ret &&= getoptions_ARGVs("int", %getopts); # Avoid forcing acting on packages specified in # DH_INTERNAL_OPTIONS. This way, -p can be specified @@ -189,18 +229,12 @@ sub parseopts { # to be parsed like @ARGV, but with unknown options # skipped. if (defined $ENV{DH_OPTIONS}) { - @ARGV_extra=split_options_string($ENV{DH_OPTIONS}); - my $ret=getoptions(\...@argv_extra, $options); - if (!$ret) { - warning("warning: ignored unknown options in DH_OPTIONS"); - } + @{$ARGVs{env}}=split_options_string($ENV{DH_OPTIONS}); + $ret &&= getoptions_ARGVs("env", %getopts); } - my $ret=getoptions(\...@argv, $options); - if (!$ret) { - warning("warning: unknown options will be a fatal error in a future debhelper release"); - #error("unknown option; aborting"); - } + @{$ARGVs{cli}} = @ARGV; + $ret &&= getoptions_ARGVs("cli", %getopts); # Check to see if -V was specified. If so, but no parameters were # passed, the variable will be defined but empty. @@ -247,17 +281,57 @@ sub parseopts { } if (defined $dh{U_PARAMS}) { - # Split the U_PARAMS up into an array. - my $u=$dh{U_PARAMS}; - undef $dh{U_PARAMS}; - push @{$dh{U_PARAMS}}, split(/\s+/,$u); - } - - # Anything left in @ARGV is options that appeared after a -- - # These options are added to the U_PARAMS array, while the - # non-option values we collected replace them in @ARGV; - push @{$dh{U_PARAMS}}, @ARGV, @ARGV_extra; - @ar...@{$dh{argv}} if exists $dh{ARGV}; + # Split the U_PARAMS up into an array. + my $u=$dh{U_PARAMS}; + undef $dh{U_PARAMS}; + push @{$dh{U_PARAMS}}, split(/\s+/,$u); + } + + # Complete option processing now if no extra options expected + if (!$params{multipass_options}) { + # Do not execute getoptions() on the ARGVs. That would break U_PARAMS + # because ARGVs no longer contain --. + parse_extraopts(%params, options => undef, nogetoptions => 1); + } + + return $ret; +} + +sub parse_extraopts { + my %para...@_; + my %getopts=( options => $params{options}, nostandard => 1 ); + push @{$getopts{config}}, "pass_through" if $params{multipass_options}; + + if (scalar(keys %ARGVs) == 0) { + # Called without multipass_options twice in a row. Wrong. + error("buggy debhelper program: unexpected processing of extra options"); + } + + # Get extra options from remaining arguments + my $ret = 1; + if (!$params{nogetoptions}) { + $ret &&= getoptions_ARGVs($_, %getopts) foreach qw{int env cli}; + } + + # Final pass MUST be without 'multipass_options' to parse U_PARAMS + # properly. + if (!$params{multipass_options}) { + # Anything left in ARGVs is options that appeared after a -- + # These options are added to the U_PARAMS array, while the + # non-option values we collected replace them in @ARGV; + push @{$dh{U_PARAMS}}, @{$ARGVs{$_}} for qw{int env cli}; + @ARGV = (exists $dh{ARGV}) ? @{$dh{ARGV}} : (); + + # Reset %ARGVs as indication that it has been fully processed + %ARGVs = (); + } + return $ret; +} + +END { + if (scalar(keys %ARGVs) > 0) { + error("buggy debhelper program: extra options have never been parsed"); + } } sub import { diff --git a/Debian/Debhelper/Dh_Lib.pm b/Debian/Debhelper/Dh_Lib.pm index 2d1934b..064e41b 100644 --- a/Debian/Debhelper/Dh_Lib.pm +++ b/Debian/Debhelper/Dh_Lib.pm @@ -16,12 +16,12 @@ use vars qw(@ISA @EXPORT %dh); &compat &addsubstvar &delsubstvar &excludefile &package_arch &is_udeb &udeb_filename &debhelper_script_subst &escape_shell &inhibit_log &load_log &write_log &dpkg_architecture_value - &sourcepackage); + &sourcepackage &parse_extra_options); my $max_compat=7; -sub init { - my %para...@_; +sub Dh_Getopt_run { + my $subname=shift; # Check to see if an option line starts with a dash, # or DH_OPTIONS is set. @@ -32,8 +32,19 @@ sub init { grep /^-/, @ARGV) { eval "use Debian::Debhelper::Dh_Getopt"; error($@) if $@; - Debian::Debhelper::Dh_Getopt::parseopts($params{options}); + my $sub = eval("*Debian::Debhelper::Dh_Getopt::$subname"); + return &$sub(@_); } + return; +} + +sub init { + my %para...@_; + + Dh_Getopt_run("parseopts", + options => $params{options}, + multipass_options => $params{multipass_options} + ); # Another way to set excludes. if (exists $ENV{DH_ALWAYS_EXCLUDE} && length $ENV{DH_ALWAYS_EXCLUDE}) { @@ -96,6 +107,15 @@ sub init { } } +# Process remaining program arguments with extra options. +# Must be run after either init(multipass_options=>1) or +# parse_extra_options(multipass_options=>1) call. Final +# call to parse_extra_options() must be done without +# multipass_options=>1. +sub parse_extra_options { + Dh_Getopt_run("parse_extraopts", @_); +} + # Run at exit. Add the command to the log files for the packages it acted # on, if it's exiting successfully. my $write_log=1; diff --git a/debhelper.pod b/debhelper.pod index de39057..deafa84 100644 --- a/debhelper.pod +++ b/debhelper.pod @@ -214,6 +214,12 @@ is manually specified with the I<--buildsystem> option. =back +Please note that a build system may accept any number of additional arbitrary +options which can be passed to all dh_auto_* debhelper programs when the build +system is either autoselected or manually specified. Consult documentation of +the build system you intend to use for the list of such options (if any) and +their effect on the build process. + =head1 NOTES =head2 Multiple binary package support diff --git a/debian/changelog b/debian/changelog index 1c067d1..e80d019 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +debhelper (7.4.4) UNRELEASED; urgency=low + + * Add support for build system specific options (to be passed to dh_auto_* + commands) (Closes: #543507). + + -- Modestas Vainius <modes...@vainius.eu> Fri, 23 Oct 2009 00:51:51 +0300 + debhelper (7.4.3) unstable; urgency=low [ Valery Perrin ] diff --git a/t/buildsystems/Debian/Debhelper/Buildsystem/test.pm b/t/buildsystems/Debian/Debhelper/Buildsystem/test.pm new file mode 100644 index 0000000..cc8df83 --- /dev/null +++ b/t/buildsystems/Debian/Debhelper/Buildsystem/test.pm @@ -0,0 +1,51 @@ +# A build system class for handling Perl Build based projects. +# +# Copyright: © 2008-2009 Joey Hess +# © 2008-2009 Modestas Vainius +# License: GPL-2+ + +package Debian::Debhelper::Buildsystem::test; + +use strict; +use base 'Debian::Debhelper::Buildsystem'; + +sub DESCRIPTION { + "test build system" +} + +sub OPTIONS { + my $this=shift; + ("test-foo=s" => \$this->{opt_foo}) +} + +sub new { + my $class=shift; + my $this= $class->SUPER::new(@_); + return $this; +} + +sub configure { + my $this=shift; + print "Option: ", "--test-foo=", $this->{opt_foo}, "\n" + if $this->{opt_foo}; + print "Param: ", $_, "\n" foreach @_; +} + +sub build { + my $this=shift; +} + +sub test { + my $this=shift; +} + +sub install { + my $this=shift; + my $destdir=shift; +} + +sub clean { + my $this=shift; +} + +1 diff --git a/t/buildsystems/buildsystem_tests b/t/buildsystems/buildsystem_tests index 8f7a275..f4eb2b3 100755 --- a/t/buildsystems/buildsystem_tests +++ b/t/buildsystems/buildsystem_tests @@ -1,6 +1,6 @@ #!/usr/bin/perl -use Test::More tests => 228; +use Test::More tests => 233; use strict; use warnings; @@ -13,6 +13,9 @@ use File::Basename (); # is expected to be the one where this test lives in. chdir File::Basename::dirname($0) or die "Unable to chdir to ".File::Basename::dirname($0); +# For loading 'test' build system +push @INC, "."; + use_ok( 'Debian::Debhelper::Dh_Lib' ); use_ok( 'Debian::Debhelper::Buildsystem' ); use_ok( 'Debian::Debhelper::Dh_Buildsystems' ); @@ -362,6 +365,16 @@ ok ( -d $builddir, "testing rmdir_builddir() 3: builddir parent '$builddir' not cleandir $tmpdir; +### Test build system specific options +is ( system("$TOPDIR/dh_auto_configure --buildsystem=test"), 0, "no buildsys specific option, no fail"); +isnt ( system("$TOPDIR/dh_auto_configure --buildsystem=test | grep -q '^Option: --test-foo=' "), + 0, "no buildsys specific option, not passed"); +is ( system("$TOPDIR/dh_auto_configure --buildsystem=test --test-foo=bar > /dev/null"), 0, "with buildsys specific option, no fail"); +is ( system("$TOPDIR/dh_auto_configure --buildsystem=test --test-foo=bar | grep -q '^Option: --test-foo=bar\$' "), + 0, "with buildsys specific option, parsed"); +is ( system("$TOPDIR/dh_auto_configure --buildsystem=test --test-foo=bar -- --external-param | grep -q '^Param: --external-param\$' "), + 0, "with buildsys specific option, test arguments after --"); + ### Test buildsystems_init() and commandline/env argument handling sub get_load_bs_source { my ($system, $step)=...@_; @@ -373,7 +386,7 @@ use strict; use warnings; use Debian::Debhelper::Dh_Buildsystems; -buildsystems_init(); +buildsystems_init(multipass_options => 0); my \$bs = load_buildsystem($system, $step); if (defined \$bs) { print 'NAME=', \$bs->NAME(), "\\n"; diff --git a/t/getopt b/t/getopt new file mode 100755 index 0000000..0cfb179 --- /dev/null +++ b/t/getopt @@ -0,0 +1,219 @@ +#!/usr/bin/perl + +use Test::More tests => 22; + +use strict; +use warnings; + +use IPC::Open2; + +sub readlines { + my $h=shift; + my @lines = <$h>; + close $h; + chop @lines; + return \...@lines; +} + +sub process_stdout { + my ($cmdline, $stdin) = @_; + my ($reader, $writer); + my ($pid, $lines); + + $pid = open2($reader, $writer, $cmdline) or die "Unable to exec $cmdline"; + print $writer $stdin if $stdin; + close $writer; + $lines = readlines($reader); + waitpid($pid, 0); + return ($? >> 8, $lines); +} + +sub do_perl { + my ($cmdline, $program, $env) = @_; + $env = "" if !defined $env; + return process_stdout("$env $^X -- - $cmdline", $program); +} + +my ($status, $output); +my $program; + +# This variable affects Dh_Getopt::getoptions() result. We will test it too. +delete $ENV{DH_IGNORE_UNKNOWN_OPTIONS} + if exists $ENV{DH_IGNORE_UNKNOWN_OPTIONS}; + +# Test standard single-pass option passing +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 abc -- def", <<'EOF'); +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh); +use Debian::Debhelper::Dh_Getopt; + +my $ret; +if ($ret = Debian::Debhelper::Dh_Getopt::parseopts()) { + print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + print $_, "\n" foreach @ARGV; + print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +} +exit (($ret)?0:2); +EOF +is( $status, 0, "STATUS: single-pass standard option parsing (with --)" ); +is_deeply( $output, [ "p=pkg1", "p=pkg2", "p=pkg3", "abc", "u=def" ], + "OUTPUT: single-pass standard option parsing (with --)" ); + +$program = <<'EOF'; +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh); +use Debian::Debhelper::Dh_Getopt; + +my $opt_foo; +my $ret; +if ($ret = Debian::Debhelper::Dh_Getopt::parseopts(options => { 'test-foo=s' => \$opt_foo })) { + print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + print '--test-foo=', $opt_foo, "\n" if $opt_foo; + print $_, "\n" foreach @ARGV; + print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +} +exit (($ret)?0:2); +EOF +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 --test-foo=bar", $program, "DH_OPTIONS=abc"); +is( $status, 0, "STATUS: single-pass custom option parsing + DH_OPTIONS" ); +is_deeply( $output, [ "p=pkg1", "p=pkg2", "p=pkg3", "--test-foo=bar", "abc" ], + "OUTPUT: single-pass custom option parsing + DH_OPTIONS" ); + +($status, $output) = do_perl("-ppkg1 --package pkg2 --test-foo=bar --test-unknownopt abc -- def 2>/dev/null", $program); +is( $status, 2, "STATUS: single-pass unrecognized option parsing" ); +is_deeply( $output, [ ], "OUTPUT: single-pass unrecognized option parsing" ); + +($status, $output) = do_perl("-ppkg1 --package pkg2 --test-foo=bar --test-unknownopt abc -- def", + $program, "DH_IGNORE_UNKNOWN_OPTIONS=1"); +is( $status, 0, "STATUS: single-pass unrecognized option parsing" ); +is_deeply( $output, [ "p=pkg1", "p=pkg2", "--test-foo=bar", "abc", "u=def" ], + "OUTPUT: single-pass unrecognized option parsing" ); + +# Test multi-pass option passing +$program = <<'EOF'; +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh parse_extra_options); +use Debian::Debhelper::Dh_Getopt; + +my $opt_foo; +my $ret; +if ($ret = Debian::Debhelper::Dh_Getopt::parseopts(multipass_options => 1)) { + print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + if ($ret = parse_extra_options(options => { 'test-foo=s' => \$opt_foo })) { + print '--test-foo=', $opt_foo, "\n" if $opt_foo; + } + print $_, "\n" foreach @ARGV; + print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +} +exit (($ret)?0:2); +EOF +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 abc def", $program); +is( $status, 0, "STATUS: multi-pass standard option parsing" ); +is_deeply( $output, [ "p=pkg1", "p=pkg2", "p=pkg3", "abc", "def" ], "OUTPUT: multi-pass standard option parsing" ); + +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 --test-foo=bar -- abc", $program); +is( $status, 0, "STATUS: multi-pass extra option parsing (with --)" ); +is_deeply( $output, [ "p=pkg1", "p=pkg2", "p=pkg3", "--test-foo=bar", "u=abc" ], + "OUTPUT: multi-pass extra option parsing (with --)" ); + +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 --test-unkownopt=bar abc -- def 2>/dev/null", $program); +is( $status, 2, "STATUS: multi-pass unrecognized option parsing" ); +is_deeply( [ @$output[0..2] ], [ "p=pkg1", "p=pkg2", "p=pkg3" ], + "OUTPUT: multi-pass unrecognized option parsing" ); + +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 --test-unkownopt=bar abc -- def", + $program, "DH_IGNORE_UNKNOWN_OPTIONS=1"); +is( $status, 0, "STATUS: multi-pass unrecognized option ignoring (with --)" ); +is_deeply( $output, [ "p=pkg1", "p=pkg2", "p=pkg3", "abc", "u=def" ], + "OUTPUT: multi-pass unrecognized option ignoring (with --)" ); + +# Test invalid multi-pass +($status, $output) = do_perl("-ppkg1 --package pkg2 --package=pkg3 abc def 2>/dev/null", <<'EOF'); +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh parse_extra_options); +use Debian::Debhelper::Dh_Getopt; + +my $ret; +if ($ret = Debian::Debhelper::Dh_Getopt::parseopts(multipass_options => 1)) { + print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + print $_, "\n" foreach @ARGV; + print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +} +exit (($ret)?0:2); +EOF +is( $status, 1, "STATUS: multi-pass unterminated" ); + +($status, $output) = do_perl("abc def 2>/dev/null", <<'EOF'); +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh parse_extra_options)); +use Debian::Debhelper::Dh_Getopt; + +my $ret; +if ($ret = Debian::Debhelper::Dh_Getopt::parseopts(multipass_options => 1)) { + print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + print $_, "\n" foreach @ARGV; + print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +} +parse_extra_options(); +parse_extra_options(); +exit (($ret)?0:2); +EOF +isnt( $status, 0, "STATUS: multi-pass terminated twice" ); + +# Test two levels of multi-pass +($status, $output) = do_perl("-ppkg1 --test-bar --test-foo abc -- def", <<'EOF'); +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh parse_extra_options); +use Debian::Debhelper::Dh_Getopt; + +my ($opt_foo, $opt_bar); +my $ret; +if ($ret = Debian::Debhelper::Dh_Getopt::parseopts(multipass_options => 1)) { + print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + if ($ret = parse_extra_options(options => { 'test-foo' => \$opt_foo }, multipass_options => 1)) { + print '--test-foo', "\n" if $opt_foo; + if ($ret = parse_extra_options(options => { 'test-bar' => \$opt_bar })) { + print '--test-bar', "\n" if $opt_bar; + } + } + print $_, "\n" foreach @ARGV; + print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +} +exit (($ret)?0:2); +EOF +is( $status, 0, "STATUS: multi-pass (multi level) option parsing (with --)" ); +is_deeply( $output, [ "p=pkg1", '--test-foo', '--test-bar', "abc", "u=def" ], + "OUTPUT: multi-pass (multi level) option parsing (with --)" ); + +# Finally test Dh_Lib::init() with regard to multi-pass option parsing +($status, $output) = do_perl("-ppkg1 --test-bar --test-foo abc -- def", <<'EOF'); +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(%dh init parse_extra_options); + +my ($opt_foo, $opt_bar); +my $ret; +init(multipass_options => 1); +print 'p=', $_, "\n" foreach @{$dh{DOPACKAGES}}; + +if ($ret = parse_extra_options(options => { 'test-foo' => \$opt_foo, 'test-bar' => \$opt_bar })) { + print '--test-foo', "\n" if $opt_foo; + print '--test-bar', "\n" if $opt_bar; +} +print $_, "\n" foreach @ARGV; +print 'u=', $_, "\n" foreach @{$dh{U_PARAMS}}; +exit (($ret)?0:2); +EOF +is( $status, 0, "STATUS: init() and multi-pass options (with --)" ); +is_deeply( $output, [ "p=pkg1", '--test-foo', '--test-bar', "abc", "u=def" ], + "OUTPUT: init() and multi-pass options (with --)" ); + +END { + system("dh_clean -ppkg1 -ppkg2 -ppkg3"); +} -- tg: (f2200dc..) patch/buildsystem_options (depends on: master)
signature.asc
Description: This is a digitally signed message part.