App-Env

 view release on metacpan or  search on metacpan

lib/App/Env.pm  view on Meta::CPAN

    my ( @res, $res );

    my $wantarray = wantarray;    ## no critic (Community::Wantarray)

    eval {
        if ( $wantarray ) {
            @res = IPC::System::Simple::capture( @_ );
        }
        else {
            $res = IPC::System::Simple::capture( @_ );
        }
        1;
    } // do {
        App::Env::_Util::croak( $@ ) if $self->_opt->{SysFatal};
        # should return false, but need to keep API backwards compat
        return undef;
    };

    return $wantarray ? @res : $res;
}

#-------------------------------------------------------

sub capture {
    my $self = shift;
    my @args = @_;

    my $redirect;
    $redirect = pop @args if 'HASH' eq ref $args[-1];

    local %ENV = %{$self};

    my $wantarray = wantarray;    ## no critic (Community::Wantarray)

    require Capture::Tiny;
    require IPC::System::Simple;

    my $exit;

    my $sub
      = $self->_opt->{SysFatal}
      ? sub { $exit = IPC::System::Simple::system( @args ) }
      : sub { $exit = CORE::system( @args ) };

    # Capture::Tiny::capture is prototyped as (&;@). App::Env
    # lazy-loads Capture::Tiny and thus nominally avoids the prototype
    # check. However, if Capture::Tiny is explicitly loaded prior to
    # App::Env, the prototype check will be performed when App::Env is
    # compiled.  In that case the following calls to capture are
    # singled out, as while the calls are correct, the prototype
    # requires an explicit block or sub{}.  So, explicitly
    # ignore prototypes.


    my @return;
    eval {
        ## no critic (AmpersandSigils,AmpersandSubCalls )

        if ( $redirect ) {
            my %redirect;
            for my $stream ( 'stdout', 'stderr' ) {
                next unless exists $redirect->{$stream};
                my $handle = $redirect->{$stream};
                $handle = IO::File->new( $handle, '>' )
                  if ref $handle eq q{};
                $redirect{$stream} = $handle;
            }
            &Capture::Tiny::capture( $sub, %redirect );
            $return[0] = $exit;
        }
        elsif ( $wantarray ) {
            @return = &Capture::Tiny::capture( $sub );
        }
        else {
            $return[0] = &Capture::Tiny::capture( $sub );
        }
        1;
    } // App::Env::_Util::croak( $@ );

    ## no critic (EmptyReturn)
    return if !defined $wantarray;
    return $wantarray ? @return : $return[0];
}

#-------------------------------------------------------

sub exec {    ## no critic (Subroutines::ProhibitBuiltinHomonyms)
    my $self = shift;

    local %ENV = %{$self};
    exec( @_ );
}


#-------------------------------------------------------

sub which {
    require File::Which;
    my $self = shift;

    {
        local %ENV = %{$self};
        return File::Which::which( @_ );
    }
}

1;

#
# This file is part of App-Env
#
# This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
#
# This is free software, licensed under:
#
#   The GNU General Public License, Version 3, June 2007
#

__END__

=pod

lib/App/Env.pm  view on Meta::CPAN

Not all variable names may be set with a shell command, but may be
inherited from the parent environment.  This option controls whether
such variables are returned by L</str>.  It defaults to false.

=back

=item system

  $env->system( $command, @args );

This runs the passed command in the environment defined by B<$env>.
It has the same argument and returned value convention as the core
Perl B<system> command.

If the B<SysFatal> flag is set for this environment,
B<IPC::System::Simple::system> is called, which will cause this method
to throw an exception if the command returned a non-zero exit value.
It also avoid invoking a shell to run the command if possible.

=item exec

  $env->exec( $command, @args );

This execs the passed command in the environment defined by B<$env>.
It has the same argument and returned value convention as the core
Perl B<exec> command.

=item qexec

  $output = $env->qexec( $command, @args );
  @lines = $env->qexec( $command, @args );

This acts like the B<qx{}> Perl operator.  It executes the passed
command in the environment defined by B<$env> and returns its
(standard) output.  If called in a list context the output is
split into lines.

If the B<SysFatal> flag is set for this environment,
B<IPC::System::Simple::capture> is called, which will cause this
method to throw an exception if the command returned a non-zero exit
value.  It also avoid invoking a shell to run the command if possible.

=item capture

Execute a command in the environment defined by B<$env> and returns or
redirects the content of its standard output and error streams.
Check the C<$?> variable for the exit value of the command.

=over

=item *

Return the standard output stream

  $stdout = $env->capture( $command, @args );

=item *

Return output, error and command exit value.

  ($stdout, $stderro, $exit) = $env->capture( $command, @args );

=item *

Return exit value and redirect standard output or error streams.

  $exit = $env->capture( $command, @args,
                 { stdout => $out, stderr => $err }
               );

C<$out> and C<$err> may either by filehandles (e.g. L<IO::File>
objects) or file names.

=back

For even more control of the output streams, consider calling
L<Capture::Tiny/capture> directly, e.g.

  my $exit;
  capture { $exit = $env->system( $command, @args ) }

If the B<SysFatal> flag is set for this environment,
B<IPC::System::Simple::capture> is called, which will cause this
method to throw an exception if the command returned a non-zero exit
value.  It also avoids invoking a shell to run the command if possible.

=item which

  $path = $env->which( $command );
  @paths = $env->which( $command );

Return the path (or paths in list mode) of the passed command using
L<File::Which>.  It returns C<undef> or an empty list if the command
is not found.

=back

=head2 Changing Default Option Values

Default values for some options may be changed via any of the
following:

=over

=item *

Passing a hashref as the only argument when initially importing the
package:

  use App::Env \%Default;

=item *

Calling the B<config> function:

  App::Env::config( %Default );

=back

The following options may have their default values changed:

  Force  Cache  Site  SysFatal

=head1 EXAMPLE USAGE

=head2 A single application

This is the simplest case.  If you don't care if you "pollute" the



( run in 3.061 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )