File Coverage

lib/Command/Common.pm
Criterion Covered Total %
statement 57 71 80.2
branch 22 42 52.3
condition 4 12 33.3
subroutine 6 8 75.0
pod 1 4 25.0
total 90 137 65.6


line stmt bran cond sub pod time code
1             package Command::Common;
2              
3 20     20   469 use strict;
  20         26  
  20         507  
4 20     20   63 use warnings;
  20         20  
  20         452  
5              
6 20     20   65 use UR;
  20         26  
  20         126  
7              
8             # Once roles exist this should probably be a role.
9             class Command::Common {
10             is_abstract => 1,
11             valid_signals => [qw(error_die)],
12             };
13              
14             sub create {
15 17     17 1 243 my $class = shift;
16 17         189 my ($rule,%extra) = $class->define_boolexpr(@_);
17 17         78 my @params_list = $rule->params_list;
18 17         154 my $self = $class->SUPER::create(@params_list, %extra);
19 17 50       61 return unless $self;
20              
21             # set non-optional boolean flags to false.
22             # TODO: rename that property meta method if it is not ONLY used for shell args
23 17         215 for my $property_meta ($self->_shell_args_property_meta) {
24 94         152 my $property_name = $property_meta->property_name;
25 94 50 66     141 if (!$property_meta->is_optional and !defined($self->$property_name)) {
26 0 0 0     0 if (defined $property_meta->data_type and $property_meta->data_type =~ /Boolean/i) {
27 0         0 $self->$property_name(0);
28             }
29             }
30             }
31              
32 17         89 return $self;
33             }
34              
35             sub shortcut {
36 0     0 0 0 my $self = shift;
37 0 0       0 return unless $self->can('_shortcut_body');
38              
39 0         0 my $result = $self->_shortcut_body;
40 0         0 $self->result($result);
41              
42 0         0 return $result;
43             }
44              
45             sub execute {
46             # This is a wrapper for real execute() calls.
47             # All execute() methods are turned into _execute_body at class init,
48             # so this will get direct control when execute() is called.
49 18     18 0 7095 my $self = shift;
50              
51             #TODO handle calls to SUPER::execute() from another execute().
52              
53             # handle calls as a class method
54 18         35 my $was_called_as_class_method = 0;
55 18 100       79 if (ref($self)) {
56 16 50       99 if ($self->is_executed) {
57 0         0 Carp::confess("Attempt to re-execute an already executed command.");
58             }
59             }
60             else {
61             # called as class method
62             # auto-create an instance and execute it
63 2         17 $self = $self->create(@_);
64 2 50       8 return unless $self;
65 2         4 $was_called_as_class_method = 1;
66             }
67              
68             # handle __errors__ objects before execute
69 18 100       131 if (my @problems = $self->__errors__) {
70 2         4 for my $problem (@problems) {
71 2         51 my @properties = $problem->properties;
72             $self->error_message("Property " .
73 2         5 join(',', map { "'$_'" } @properties) .
  2         51  
74             ': ' . $problem->desc);
75             }
76 2         15 my $command_name = $self->command_name;
77 2         12 $self->error_message("Please see '$command_name --help' for more information.");
78 2 50       19 $self->delete() if $was_called_as_class_method;
79 2         14 return;
80             }
81              
82 16         30 my $result = eval { $self->_execute_body(@_); };
  16         103  
83 16         40 my $error = $@;
84 16 100 66     100 if ($error or not $result) {
85 1         4 my %error_data;
86              
87 1 50       11 $error_data{die_message} = defined($error) ? $error:'';
88 1 50       46 $error_data{error_message} = defined($self->error_message) ? $self->error_message:'';
89 1 50       2 $error_data{error_package} = defined($self->error_package) ? $self->error_package:'';
90 1 50       5 $error_data{error_file} = defined($self->error_file) ? $self->error_file:'';
91 1 50       4 $error_data{error_subroutine} = defined($self->error_subroutine) ? $self->error_subroutine:'';
92 1 50       5 $error_data{error_line} = defined($self->error_line) ? $self->error_line:'';
93 1         12 $self->__signal_observers__('error_die', %error_data);
94 1 50       10 die $error if $error;
95             }
96              
97 16         85 $self->is_executed(1);
98 16         73 $self->result($result);
99              
100 16 50       49 return $self if $was_called_as_class_method;
101 16         91 return $result;
102             }
103              
104             sub _execute_body {
105             # default implementation in the base class
106              
107             # Override "execute" or "_execute_body" to implement the body of the command.
108             # See above for details of internal implementation.
109              
110 0     0   0 my $self = shift;
111 0   0     0 my $class = ref($self) || $self;
112 0 0       0 if ($class eq __PACKAGE__) {
113 0         0 die "The execute() method is not defined for $_[0]!";
114             }
115 0         0 return 1;
116             }
117              
118             # Translates a true/false value from the command module's execute()
119             # from Perl (where positive means success), to shell (where 0 means success)
120             # Also, execute() could return a negative value; this is converted to
121             # positive and used as the shell exit code. NOTE: This means execute()
122             # returning 0 and -1 mean the same thing
123             sub exit_code_for_return_value {
124 3     3 0 8 my $self = shift;
125 3         11 my $return_value = shift;
126 3 100       15 if (! $return_value) {
    50          
127 1         2 $return_value = 1;
128             } elsif ($return_value < 0) {
129 0         0 $return_value = 0 - $return_value;
130             } else {
131 2         2 $return_value = 0
132             }
133 3         7 return $return_value;
134             }