File Coverage

lib/Command/Shell.pm
Criterion Covered Total %
statement 9 29 31.0
branch 0 4 0.0
condition n/a
subroutine 3 6 50.0
pod 0 2 0.0
total 12 41 29.2


line stmt bran cond sub pod time code
1             package Command::Shell;
2 1     1   403 use strict;
  1         1  
  1         28  
3 1     1   3 use warnings;
  1         1  
  1         26  
4 1     1   347 use Command::V2;
  1         2  
  1         11  
5              
6             class Command::Shell {
7             is => 'Command::V2',
8             is_abstract => 1,
9             subclassify_by => "_shell_command_subclass",
10             has_input => [
11             delegate_type => { is => 'Text', shell_args_position => 1,
12             doc => 'the class name of the command to be executed' },
13              
14             argv => { is => 'Text', is_many => 1, is_optional => 1, shell_args_position => 2,
15             doc => 'list of command-line arguments to be translated into parameters' },
16             ],
17             has_transient => [
18             delegate => { is => 'Command',
19             doc => 'the command which this adaptor wraps' },
20             _shell_command_subclass => { calculate_from => ['delegate_type'],
21             calculate =>
22             sub {
23             my $delegate_type = shift;
24             my $subclass = $delegate_type . "::Shell";
25             eval "$subclass->class";
26             if ($@) {
27             my $new_subclass = UR::Object::Type->define(
28             class_name => $subclass,
29             is => __PACKAGE__
30             );
31             die "Failed to fabricate subclass $subclass!" unless $new_subclass;
32             }
33             return $subclass;
34             },
35             },
36             ],
37             has_output => [
38             exit_code => => { is => 'Number',
39             doc => 'the exit code to be returned to the shell', }
40             ],
41             doc => 'an adaptor to create and run commands as specified from a standard command-line shell (bash)'
42             };
43              
44             sub help_synopsis {
45             return <
46              
47             In the "foo" executable:
48              
49             #!/usr/bin/env perl
50             use Foo;
51             exit Command::Shell->run("Foo",@ARGV);
52              
53             The run() static method will construct the appropriate Command::Shell object, have it build its delegate,
54             run the delegate's execution method in an in-memory transaction sandbox, and capture an exit code.
55              
56             If the correct environment variables are set, it will respond to a bash tab-completion request, such that
57             the "foo" script can be used as a self-completer.
58              
59             EOS
60              
61 0     0 0   }
62              
63             sub run {
64 0     0 0   my $class = shift;
65 0           my $delegate_type = shift;
66 0           my @argv = @_;
67 0           my $cmd = $class->create(delegate_type => $delegate_type, argv => \@argv);
68             #print STDERR "created $cmd\n";
69 0           $cmd->execute;
70 0           my $exit_code = $cmd->exit_code;
71 0           $cmd->delete;
72 0           return $exit_code;
73             }
74              
75             sub execute {
76 0     0     my $self = shift;
77 0           my $delegate_type = $self->delegate_type;
78 0           eval "use above '$delegate_type'";
79 0 0         if ($@) {
80 0           my $t = UR::Object::Type->get($delegate_type);
81 0 0         unless ($t) {
82 0           die "Failure to use delegate class $delegate_type!:\n$@";
83             }
84             }
85 0           my @argv = $self->argv;
86              
87 0           my $exit_code = $delegate_type->_cmdline_run(@argv);
88 0           $self->exit_code($exit_code);
89 0           return 1;
90             }
91              
92             # TODO: migrate all methods in Command::V2 which live in the Command::Dispatch::Shell module to this package
93             # Methods which address $self to get to shell-specific things still call $self
94             # Methods which address $self to get to the underlying command should instead call $self->delegate
95              
96             1;
97