App-RecordStream
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
lib/App/RecordStream/Operation/chain.pm view on Meta::CPAN
my $idx = @$operations;
my $push_shim = App::RecordStream::Operation::chain::PushShim->new($operations, $idx);
if ( App::RecordStream::Operation::is_recs_operation($single_command->[0]) ) {
my ($sc1, @args) = @$single_command;
my $operation = App::RecordStream::Operation::create_operation($sc1, \@args, $push_shim);
push @$operations, ['RECS', $operation, \@args];
}
else {
push @$operations, ['SHELL', [@$single_command]];
}
}
sub setup_fork {
my $this = shift;
my $command_arguments = shift;
my $continuation_pid = open(STDOUT, "|-");
die "cannot fork: $!" unless defined $continuation_pid;
if ( ! $continuation_pid ) {
# in continuation
return 1;
}
# in parent, now split off the shell command as well
my $shell_pid = open(STDOUT, "|-");
die "cannot fork: $!" unless defined $shell_pid;
if ( ! $shell_pid ) {
# the child runs the shell command
exec (@$command_arguments);
}
# still in parent, we're responsible for the children so we keep the PID
# around (shell pid can be waited for via close(STDOUT)).
return (0, $continuation_pid);
}
sub wants_input {
return 0;
}
sub stream_done {
my $this = shift;
if ( my $args = $this->{'SAVED_ARGS'} ) {
$this->print_chain($args);
}
if ( $this->{'DRY_RUN'} ) {
return;
}
my $head = $this->{'CHAIN_HEAD'};
if ( $head ) {
my $head_operation = $head->[1];
my $head_args = $head->[2];
if ( $head_operation->wants_input() ) {
local @ARGV = @$head_args;
while(my $line = <>) {
chomp $line;
App::RecordStream::Operation::set_current_filename($ARGV);
if ( ! $head_operation->accept_line($line) ) {
last;
}
}
}
$head_operation->finish();
}
else {
while(<>) {
chomp;
$this->push_line($_);
}
}
# wait for shell child (if we even have one)
close(STDOUT);
# wait for possible other child (next sequence of recs operations)
my $continuation_pid = $this->{'CONTINUATION_PID'};
if ( $continuation_pid ) {
# We have recs operation processes wait for the next recs operation
# process to the "right" in the chain. so that the left-most is last to
# exit. The shell is waiting on this left-most process to exit so this
# exit order ensures everyone finishes up before the shell notice the
# left-most PID is done and resumes control.
waitpid $continuation_pid, 0;
}
else {
# no next sequence, we must be the last sequence of recs operations
}
}
sub get_exit_value {
my $this = shift;
if ( my $tail = $this->{'CHAIN_TAIL'} ) {
return $tail->[1]->get_exit_value();
}
return 0;
}
sub add_help_types {
my $this = shift;
$this->use_help_type('keyspecs');
}
sub usage {
my $this = shift;
my $options = [
['show-chain', 'Before running the commands, print out what will happen in the chain'],
['n', 'Do not run commands, implies --show-chain'],
];
my $args_string = $this->options_string($options);
view all matches for this distributionview release on metacpan - search on metacpan
( run in 0.595 second using v1.00-cache-2.02-grep-82fe00e-cpan-f73e49a70403 )