@@ -1,9 +1,17 @@
Revision history for System-Sub.
+0.142280 2014-08-16 DOLMEN (Olivier Mengué)
+ Add option '&?' to handle exit code != 0.
+ Add common options (an ARRAY as first import arg) that will apply
+ to all the commands on the import list.
+ Doc: add link to Shell.pm (Thanks Slaven Rezic, RT#84739).
+
0.130210 2013-01-21 DOLMEN (Olivier Mengué)
Add option '()' to define the prototype of the sub.
0.130180 2013-01-18 DOLMEN (Olivier Mengué)
+ Define the DEBUG compile symbol with 'constant.pm'. This fixes
+ Pod::Coverage tests.
Minor fixes from BOOK (Philippe Bruhat).
0.123440 2012-12-09 DOLMEN (Olivier Mengué)
@@ -22,7 +22,7 @@ This is free software, licensed under:
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
- 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -1,3 +1,4 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.019.
Changes
LICENSE
MANIFEST
@@ -15,6 +16,10 @@ t/20-hostname.t
t/21-AUTOLOAD.t
t/22-ENV.t
t/23-prototype.t
+t/24-error.t
+t/25-common-opts.t
+t/exiterr.pl
+t/print.pl
t/printenv.pl
xt/release/kwalitee.t
xt/release/pod-coverage.t
@@ -4,7 +4,7 @@
"Olivier Mengue <dolmen@cpan.org>"
],
"dynamic_config" : 0,
- "generated_by" : "Dist::Zilla version 4.300028, CPAN::Meta::Converter version 2.120921",
+ "generated_by" : "Dist::Zilla version 5.019, CPAN::Meta::Converter version 2.140640",
"license" : [
"perl_5"
],
@@ -22,6 +22,7 @@
"develop" : {
"requires" : {
"Pod::Coverage::TrustPod" : "0",
+ "Test::Kwalitee" : "1.12",
"Test::Pod" : "1.41",
"Test::Pod::Coverage" : "1.08"
}
@@ -42,22 +43,15 @@
},
"test" : {
"requires" : {
- "File::Find" : "0",
"File::Spec" : "0",
- "File::Temp" : "0",
- "Test::More" : "0"
+ "IO::Handle" : "0",
+ "IPC::Open3" : "0",
+ "Test::More" : "0",
+ "perl" : "5.006"
}
}
},
"release_status" : "stable",
- "resources" : {
- "homepage" : "https://github.com/dolmen/p5-System-Sub",
- "repository" : {
- "type" : "git",
- "url" : "https://github.com/dolmen/p5-System-Sub.git",
- "web" : "https://github.com/dolmen/p5-System-Sub"
- }
- },
- "version" : "0.130210"
+ "version" : "0.142280"
}
@@ -3,31 +3,29 @@ abstract: 'Wrap external command with a DWIM sub'
author:
- 'Olivier Mengue <dolmen@cpan.org>'
build_requires:
- File::Find: 0
- File::Spec: 0
- File::Temp: 0
- Test::More: 0
+ File::Spec: '0'
+ IO::Handle: '0'
+ IPC::Open3: '0'
+ Test::More: '0'
+ perl: '5.006'
configure_requires:
- ExtUtils::MakeMaker: 6.30
+ ExtUtils::MakeMaker: '6.30'
dynamic_config: 0
-generated_by: 'Dist::Zilla version 4.300028, CPAN::Meta::Converter version 2.120921'
+generated_by: 'Dist::Zilla version 5.019, CPAN::Meta::Converter version 2.140640'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
- version: 1.4
+ version: '1.4'
name: System-Sub
requires:
- Carp: 0
- File::Which: 0
- IPC::Run: 0
- Scalar::Util: 1.11
- Sub::Name: 0
- Symbol: 0
- constant: 0
- perl: 5.006
- strict: 0
- warnings: 0
-resources:
- homepage: https://github.com/dolmen/p5-System-Sub
- repository: https://github.com/dolmen/p5-System-Sub.git
-version: 0.130210
+ Carp: '0'
+ File::Which: '0'
+ IPC::Run: '0'
+ Scalar::Util: '1.11'
+ Sub::Name: '0'
+ Symbol: '0'
+ constant: '0'
+ perl: '5.006'
+ strict: '0'
+ warnings: '0'
+version: '0.142280'
@@ -1,4 +1,5 @@
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.019.
use strict;
use warnings;
@@ -11,12 +12,6 @@ use ExtUtils::MakeMaker 6.30;
my %WriteMakefileArgs = (
"ABSTRACT" => "Wrap external command with a DWIM sub",
"AUTHOR" => "Olivier Mengue <dolmen\@cpan.org>",
- "BUILD_REQUIRES" => {
- "File::Find" => 0,
- "File::Spec" => 0,
- "File::Temp" => 0,
- "Test::More" => 0
- },
"CONFIGURE_REQUIRES" => {
"ExtUtils::MakeMaker" => "6.30"
},
@@ -35,24 +30,40 @@ my %WriteMakefileArgs = (
"strict" => 0,
"warnings" => 0
},
- "VERSION" => "0.130210",
+ "TEST_REQUIRES" => {
+ "File::Spec" => 0,
+ "IO::Handle" => 0,
+ "IPC::Open3" => 0,
+ "Test::More" => 0
+ },
+ "VERSION" => "0.142280",
"test" => {
"TESTS" => "t/*.t"
}
);
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
- my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
- my $pp = $WriteMakefileArgs{PREREQ_PM};
- for my $mod ( keys %$br ) {
- if ( exists $pp->{$mod} ) {
- $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
- }
- else {
- $pp->{$mod} = $br->{$mod};
- }
- }
+my %FallbackPrereqs = (
+ "Carp" => 0,
+ "File::Spec" => 0,
+ "File::Which" => 0,
+ "IO::Handle" => 0,
+ "IPC::Open3" => 0,
+ "IPC::Run" => 0,
+ "Scalar::Util" => "1.11",
+ "Sub::Name" => 0,
+ "Symbol" => 0,
+ "Test::More" => 0,
+ "constant" => 0,
+ "strict" => 0,
+ "warnings" => 0
+);
+
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+ delete $WriteMakefileArgs{TEST_REQUIRES};
+ delete $WriteMakefileArgs{BUILD_REQUIRES};
+ $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
@@ -1,7 +1,7 @@
This archive contains the distribution System-Sub,
-version 0.130210:
+version 0.142280:
Wrap external command with a DWIM sub
@@ -11,3 +11,5 @@ This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
+This README file was generated by Dist::Zilla::Plugin::Readme v5.019.
+
@@ -1,10 +1,7 @@
use strict;
use warnings;
package System::Sub::AutoLoad;
-{
- $System::Sub::AutoLoad::VERSION = '0.130210';
-}
-
+$System::Sub::AutoLoad::VERSION = '0.142280';
use System::Sub ();
sub _croak
@@ -59,7 +56,7 @@ System::Sub::AutoLoad - Auto-wrap external commands as DWIM subs
=head1 VERSION
-version 0.130210
+version 0.142280
=head1 SYNOPSIS
@@ -1,10 +1,7 @@
use strict;
use warnings;
package System::Sub;
-{
- $System::Sub::VERSION = '0.130210';
-}
-
+$System::Sub::VERSION = '0.142280';
use File::Which ();
use Sub::Name 'subname';
use Symbol 'gensym';
@@ -23,6 +20,7 @@ my %OPTIONS = (
'>' => '',
'<' => '',
'ENV' => 'HASH',
+ '?' => 'CODE',
);
sub _croak
@@ -42,6 +40,9 @@ sub import
my $pkg = (caller)[0];
shift;
+ my $common_options;
+ $common_options = shift if @_ && ref($_[0]) eq 'ARRAY';
+
while (@_) {
my $name = shift;
# Must be a scalar
@@ -57,22 +58,30 @@ sub import
$fq_name = $pkg.'::'.$name;
}
+ my $options;
+ if (@_ && ref $_[0]) {
+ $options = shift;
+ splice(@$options, 0, 0, @$common_options) if $common_options;
+ } elsif ($common_options) {
+ # Just duplicate common options
+ $options = [ @$common_options ];
+ }
+
my $cmd = $name;
my $args;
my %options;
- if (@_ && ref $_[0]) {
- my $options = shift;
+ if ($options) {
while (@$options) {
my $opt = shift @$options;
- (my $opt_short = $opt) =~ s/^[\$\@\%]//;
+ (my $opt_short = $opt) =~ s/^[\$\@\%\&]//;
if ($opt eq '--') {
- _croak 'duplicate @ARGV' if $args;
+ _croak 'duplicate @ARGV' if $args && !$common_options;
$args = $options;
last
} elsif ($opt eq '()') {
$proto = shift @$options;
- } elsif ($opt =~ /^\$?0$/) { # $0
+ } elsif ($opt =~ /^\$?0$/s) { # $0
$cmd = shift @$options;
} elsif ($opt =~ /^\@?ARGV$/) { # @ARGV
_croak "$name: invalid \@ARGV" if ref($options->[0]) ne 'ARRAY';
@@ -113,6 +122,16 @@ sub import
}
}
+sub _handle_error
+{
+ my ($name, $code, $cmd, $handler) = @_;
+ if ($handler) {
+ $handler->($name, $?, $cmd);
+ } else {
+ _croak "$name error ".($?>>8)
+ }
+}
+
sub _build_sub
{
my ($name, $cmd, $options) = @_;
@@ -166,7 +185,7 @@ sub _build_sub
}
close $out;
finish $h;
- _croak "$name error ".($?>>8) if $? >> 8;
+ _handle_error($name, $?, \@cmd, $options->{'?'}) if $? >> 8;
return @output
} elsif (defined wantarray) {
# Only the first line
@@ -174,7 +193,7 @@ sub _build_sub
defined($output = <$out>) and chomp $output;
close $out;
finish $h;
- _croak "$name error ".($?>>8) if $? >> 8;
+ _handle_error($name, $?, \@cmd, $options->{'?'}) if $? >> 8;
_croak "no output" unless defined $output;
return $output
} else { # void context
@@ -186,7 +205,7 @@ sub _build_sub
}
close $out;
finish $h;
- _croak "$name error ".($?>>8) if $? >> 8;
+ _handle_error($name, $?, \@cmd, $options->{'?'}) if $? >> 8;
return
}
}
@@ -204,7 +223,7 @@ System::Sub - Wrap external command with a DWIM sub
=head1 VERSION
-version 0.130210
+version 0.142280
=head1 SYNOPSIS
@@ -251,6 +270,7 @@ version 0.130210
# Import with a prototype (see perlsub)
use System::Sub 'hostname()'; # Empty prototype: no args allowed
+ use System::Sub hostname => [ '()' => '' ]; # Alternate syntax
use strict;
# This will fail at compile time with "Too many arguments"
hostname("xx");
@@ -341,6 +361,23 @@ C<E<gt>>: I/O layers for the data fed to the command.
C<E<lt>>: I/O layers for the data read from the command output.
+=item *
+
+C<&?>: sub that will be called if ($? >> 8) != 0.
+
+ sub {
+ my $name = shift; # name of the sub
+ my $code = shift; # exit code ($?)
+ my $cmd = shift; # array ref to the executed command
+
+ # Default implementation:
+ require Carp;
+ Carp::croak("$name error ".($code >> 8));
+ }
+
+Mnemonic: C<&> is the sigil for subs and C<$?> is the exit code of the last
+command.
+
=back
=head1 SUB USAGE
@@ -407,6 +444,8 @@ If you do not specify a callback, the behavior is currently unspecified
=over 4
+=item * L<Shell>, distributed with Perl 5 to 5.14. Removed from core in 5.16.
+
=item * L<perlipc>, L<perlfaq8>
=item * L<IPC::Run>
@@ -1,73 +1,51 @@
-#!perl
-
+use 5.006;
use strict;
use warnings;
-use Test::More;
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.043
+use Test::More tests => 2 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
-use File::Find;
-use File::Temp qw{ tempdir };
-my @modules;
-find(
- sub {
- return if $File::Find::name !~ /\.pm\z/;
- my $found = $File::Find::name;
- $found =~ s{^lib/}{};
- $found =~ s{[/\\]}{::}g;
- $found =~ s/\.pm$//;
- # nothing to skip
- push @modules, $found;
- },
- 'lib',
+my @module_files = (
+ 'System/Sub.pm',
+ 'System/Sub/AutoLoad.pm'
);
-sub _find_scripts {
- my $dir = shift @_;
-
- my @found_scripts = ();
- find(
- sub {
- return unless -f;
- my $found = $File::Find::name;
- # nothing to skip
- open my $FH, '<', $_ or do {
- note( "Unable to open $found in ( $! ), skipping" );
- return;
- };
- my $shebang = <$FH>;
- return unless $shebang =~ /^#!.*?\bperl\b\s*$/;
- push @found_scripts, $found;
- },
- $dir,
- );
-
- return @found_scripts;
-}
-my @scripts;
-do { push @scripts, _find_scripts($_) if -d $_ }
- for qw{ bin script scripts };
-my $plan = scalar(@modules) + scalar(@scripts);
-$plan ? (plan tests => $plan) : (plan skip_all => "no tests to run");
+# no fake home requested
+
+my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib';
+
+use File::Spec;
+use IPC::Open3;
+use IO::Handle;
+
+open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
+my @warnings;
+for my $lib (@module_files)
{
- # fake home for cpan-testers
- # no fake requested ## local $ENV{HOME} = tempdir( CLEANUP => 1 );
-
- like( qx{ $^X -Ilib -e "require $_; print '$_ ok'" }, qr/^\s*$_ ok/s, "$_ loaded ok" )
- for sort @modules;
-
- SKIP: {
- eval "use Test::Script 1.05; 1;";
- skip "Test::Script needed to test script compilation", scalar(@scripts) if $@;
- foreach my $file ( @scripts ) {
- my $script = $file;
- $script =~ s!.*/!!;
- script_compiles( $file, "$script script compiles" );
- }
+ # see L<perlfaq8/How can I capture STDERR from an external command?>
+ my $stderr = IO::Handle->new;
+
+ my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]");
+ binmode $stderr, ':crlf' if $^O eq 'MSWin32';
+ my @_warnings = <$stderr>;
+ waitpid($pid, 0);
+ is($?, 0, "$lib loaded ok");
+
+ if (@_warnings)
+ {
+ warn @_warnings;
+ push @warnings, @_warnings;
}
}
+
+
+
+is(scalar(@warnings), 0, 'no warnings found') if $ENV{AUTHOR_TESTING};
+
+
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+use Test::More tests => 8;
+use File::Spec;
+
+use System::Sub exiterr => [
+ 0 => $^X,
+ ARGV => [ File::Spec->catfile(qw(t exiterr.pl)) ],
+ '()' => '$',
+ '&?' => sub {
+ my ($name, $code, $cmd) = @_;
+ is($name, 'exiterr', 'name');
+ is($cmd->[0], $^X, '$cmd[0]');
+ is($?, $code, '$code == $?');
+ is($? >> 8, $cmd->[2]);
+ },
+];
+
+exiterr 4;
+exiterr 5;
+
+# vim:set et sw=4 sts=4:
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+use Test::More tests => 5;
+use File::Spec;
+
+# Test common options and prototypes
+use System::Sub [ 0 => $^X, ARGV => [ File::Spec->catfile(qw(t print.pl)) ] ],
+ qw< print1($) print2($$) >,
+ printenv => [
+ ENV => { Toto => 'Lulu' },
+ '--' => File::Spec->catfile(qw(t printenv.pl)), 'Toto'
+ ];
+
+is( scalar print1('x'), 'x', 'print1 (scalar)');
+is_deeply([ print1('y') ], [ 'y' ], 'print1 (list)');
+
+is( scalar print2('x', 'y'), 'x', 'print2 (scalar)');
+is_deeply([ print2('x', 'y') ], [ qw< x y > ], 'print2 (list)');
+
+is_deeply([ printenv ], [ 'Lulu' ], 'printenv Toto');
+
+# vim:set et sw=4 sts=4:
@@ -0,0 +1,3 @@
+#!/usr/bin/perl
+
+exit shift;
@@ -0,0 +1,3 @@
+#!/usr/bin/perl
+
+print $_, $/ for @ARGV;
@@ -1,9 +1,4 @@
-#!perl
-
-# This test is generated by Dist::Zilla::Plugin::Test::Kwalitee
+# this test was generated with Dist::Zilla::Plugin::Test::Kwalitee 2.07
use strict;
use warnings;
-use Test::More; # needed to provide plan.
-eval "use Test::Kwalitee";
-
-plan skip_all => "Test::Kwalitee required for testing kwalitee" if $@;
+use Test::Kwalitee;
@@ -1,13 +1,7 @@
#!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests.
-use Test::More;
-
-eval "use Test::Pod::Coverage 1.08";
-plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage"
- if $@;
-
-eval "use Pod::Coverage::TrustPod";
-plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage"
- if $@;
+use Test::Pod::Coverage 1.08;
+use Pod::Coverage::TrustPod;
all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });
@@ -1,7 +1,6 @@
#!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
use Test::More;
-
-eval "use Test::Pod 1.41";
-plan skip_all => "Test::Pod 1.41 required for testing POD" if $@;
+use Test::Pod 1.41;
all_pod_files_ok();