diff options
Diffstat (limited to 'archive/perl5/ShellSequence.pm')
-rw-r--r-- | archive/perl5/ShellSequence.pm | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/archive/perl5/ShellSequence.pm b/archive/perl5/ShellSequence.pm new file mode 100644 index 00000000..7b07c798 --- /dev/null +++ b/archive/perl5/ShellSequence.pm @@ -0,0 +1,133 @@ +package ShellSequence; + +use strict; +use warnings; + +use Capture::Tiny 'tee_stdout'; +use Array::Iterator; +use Term::UI; +use Term::ReadLine; +use ScriptStatus; + +sub new { + my $class = shift; + + my $self = { + 'commands' => [] + }; + bless $self, $class; + + return $self; +} + +# the advantage of using the add_ functions and queuing up commands is +# that the user will be informed what the next command will be, which +# helps them decide whether to give up and skip the command (e.g.: `mr +# autoci` is failing, and `mr push` will be next) + +sub add_should_zero { + my $self = shift; + my @args = @_; + + my $cmd = ['ZERO', @args]; + + push @{$self->{'commands'}}, $cmd; +} + +sub add_should_succeed { + my $self = shift; + my @args = @_; + + my $cmd = ['SUCCEED', @args]; + + push @{$self->{'commands'}}, $cmd; +} + +sub should_zero { + my $self = shift; + my @args = @_; + + $self->add_should_zero(@args); + $self->run(); +} + +sub should_succeed { + my $self = shift; + my @args = @_; + + $self->add_should_succeed(@args); + $self->run(); +} + +sub choice { + my $i = shift @_; + my @args = @_; + my $term = Term::ReadLine->new('brand'); + + + my $shell = $term->ask_yn( + prompt => 'Spawn a shell to investigate?', + default => 'n', + ); + if ($shell) { + status "I will try running `@args' again when this shell exits"; + system $ENV{'SHELL'}; + return 1; + } else { + if ($i->peek()) { + my @maybe_next = @{$i->peek()}; + shift @maybe_next; + my @next = @maybe_next; + status "info: if you skip, the next command will be `@next'"; + } + my $give_up = $term->ask_yn( + prompt => 'Give up and skip this command?', + default => 'n', + ); + return !$give_up; + } +} + +sub run { + my $self = shift; + + my $i = Array::Iterator->new($self->{'commands'}); + + while ( my $cmd = $i->get_next() ) { + my $require = shift @$cmd; + my @args = @$cmd; + + # previously we always used tee_stdout, and then looked at + # both $output and its exit code. However, tee_stdout works + # badly for ncurses, such as debconf prompts which appeared + # during apt runs. So don't use tee_stdout except when we + # have to + while (42) { + status "running `@args'"; + if ($require eq 'SUCCEED') { + system @args; + my $exit = $? >> 8; + if ($exit != 0) { + status "`@args' failed but it was required to succeed"; + choice($i, @args) || last; + } else { + last; + } + } else { + (my $output, undef) = tee_stdout { + system @args; + }; + if (length($output)) { + status "`@args' was required to produce no output"; + choice($i, @args) || last; + } else { + last; + } + } + } + } + + $self->{'commands'} = []; +} + +1; |