X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSystem%2FIntrospector%2FUtil.pm;h=530f9f90e53ad5669d64f4923230492b424cae0d;hb=1b608727eb3a7c5c9b54193d1b537aa51dbf8352;hp=f2a755525d24300b1a5617be6ade6e7e59181ff3;hpb=db5ba31ffa3a13279b863257a8ef35bfcfb9968b;p=scpubgit%2FSystem-Introspector.git diff --git a/lib/System/Introspector/Util.pm b/lib/System/Introspector/Util.pm index f2a7555..530f9f9 100644 --- a/lib/System/Introspector/Util.pm +++ b/lib/System/Introspector/Util.pm @@ -3,21 +3,35 @@ use strictures 1; package System::Introspector::Util; use Exporter 'import'; use IPC::Run qw( run ); +use IPC::Open2; +use File::Spec; +use Scalar::Util qw( blessed ); +use Capture::Tiny qw( capture_stderr ); our @EXPORT_OK = qw( handle_from_command handle_from_file - files_from_dir output_from_command output_from_file + lines_from_command + files_from_dir transform_exceptions ); +do { + package System::Introspector::_Exception; + use Moo; + has message => (is => 'ro'); +}; + +sub fail { die System::Introspector::_Exception->new(message => shift) } +sub is_report_exception { ref(shift) eq 'System::Introspector::_Exception' } + sub files_from_dir { my ($dir) = @_; my $dh; opendir $dh, $dir - or die "Unable to read directory $dir: $!\n"; + or fail "Unable to read directory $dir: $!"; my @files; while (defined( my $item = readdir $dh )) { next if -d "$dir/$item"; @@ -28,10 +42,12 @@ sub files_from_dir { sub transform_exceptions (&) { my ($code) = @_; - local $@; my $result = eval { $code->() }; - return { error => "$@" } - if $@; + if (my $error = $@) { + return { __error__ => $error->message } + if is_report_exception $error; + die $@; + } return $result; } @@ -45,22 +61,54 @@ sub output_from_command { if wantarray; $command = join ' ', @$command if ref $command; - die "Error running command ($command): $err\n" + fail "Error running command ($command): $err" unless $ok; return $out; } +sub lines_from_command { + my ($command) = @_; + my $output = output_from_command $command; + chomp $output; + return split m{\n}, $output; +} + sub handle_from_command { my ($command) = @_; - open my $pipe, '-|', $command - or die "Unable to read from command '$command': $!\n"; + my $pipe; + local $@; + my $ok = eval { + my $out; + my $child_pid; + my @lines; + my ($err) = capture_stderr { + $child_pid = open2($out, File::Spec->devnull, $command); + @lines = <$out>; + close $out; + waitpid $child_pid, 0; + }; + my $content = join '', @lines; + my $status = $? >> 8; + $err = "Unknown error" + unless defined $err; + fail "Command error ($command): $err\n" + if $status; + open $pipe, '<', \$content; + 1; + }; + unless ($ok) { + my $err = $@; + die $err + if blessed($err) and $err->isa('System::Introspector::_Exception'); + fail "Error from command '$command': $err"; + } return $pipe; } sub handle_from_file { my ($file) = @_; open my $fh, '<', $file - or die "Unable to read $file: $!\n"; + or fail "Unable to read $file: $!"; return $fh; }