App-RecordStream

 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 distribution
 view release on metacpan -  search on metacpan

( run in 0.595 second using v1.00-cache-2.02-grep-82fe00e-cpan-f73e49a70403 )