summaryrefslogtreecommitdiff
path: root/archive/perl5/ShellSequence.pm
diff options
context:
space:
mode:
Diffstat (limited to 'archive/perl5/ShellSequence.pm')
-rw-r--r--archive/perl5/ShellSequence.pm133
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;