File Coverage

blib/lib/App/Framework/Core/Script.pm
Criterion Covered Total %
statement 56 67 83.5
branch 12 20 60.0
condition 3 5 60.0
subroutine 10 11 90.9
pod 5 5 100.0
total 86 108 79.6


line stmt bran cond sub pod time code
1             package App::Framework::Core::Script ;
2              
3             =head1 NAME
4              
5             App::Framework::Core::Script - App::Framework command line script personality
6              
7             =head1 SYNOPSIS
8              
9             # Script is loaded by default as if the script contained:
10             use App::Framework ':Script' ;
11              
12              
13             =head1 DESCRIPTION
14              
15             This personality implements a standard command line script.
16              
17             B
18              
19             Derived object from App::Framework::Core. Should only be called via App::Framework import.
20              
21             Adds command line script specific additions to base properties. Adds the following
22             additional options:
23              
24             'v|"verbose"' Make script output more verbose
25             'dryrun|"norun"' Do not execute anything that would alter the file system, just show the commands that would have executed
26            
27             Defines the exit() method which just calls standard exit.
28              
29             Defines a usage_fn which gets called by App::Framework::Core->uage(). This function calls pod2usage to display help, man page
30             etc.
31              
32             =cut
33              
34 26     26   6915 use strict ;
  26         53  
  26         922  
35 26     26   136 use Carp ;
  26         54  
  26         2304  
36              
37             our $VERSION = "1.003" ;
38              
39              
40             #============================================================================================
41             # USES
42             #============================================================================================
43 26     26   145 use App::Framework::Core ;
  26         54  
  26         547  
44              
45 26     26   41984 use File::Temp ();
  26         1671809  
  26         736  
46 26     26   312817 use Pod::Usage ;
  26         6699303  
  26         24427  
47              
48              
49            
50             #============================================================================================
51             # OBJECT HIERARCHY
52             #============================================================================================
53             our @ISA = qw(App::Framework::Core) ;
54              
55             #============================================================================================
56             # GLOBALS
57             #============================================================================================
58              
59             our $class_debug = 0 ;
60              
61             # Set of script-related default options
62             my @SCRIPT_OPTIONS = (
63             ['v|"verbose"', 'Verbose output', 'Make script output more verbose', ],
64             ['dryrun|"norun"', 'Dry run', 'Do not execute anything that would alter the file system, just show the commands that would have executed'],
65             ) ;
66              
67              
68             #============================================================================================
69              
70             =head2 FIELDS
71              
72             None
73              
74             =over 4
75              
76             =cut
77              
78              
79              
80             #============================================================================================
81              
82             =back
83              
84             =head2 CONSTRUCTOR METHODS
85              
86             =over 4
87              
88             =cut
89              
90             #============================================================================================
91              
92              
93             =item B
94              
95             Create a new App::Framework::Script.
96              
97             The %args are specified as they would be in the B method, for example:
98              
99             'mmap_handler' => $mmap_handler
100              
101             The full list of possible arguments are :
102              
103             'fields' => Either ARRAY list of valid field names, or HASH of field names with default values
104              
105             =cut
106              
107             sub new
108             {
109 26     26 1 262 my ($obj, %args) = @_ ;
110              
111 26   33     235 my $class = ref($obj) || $obj ;
112 26 50       104 print "App::Framework::Core::Script->new() class=$class\n" if $class_debug;
113            
114             # Create object
115 26         315 my $this = $class->SUPER::new(
116             %args,
117             ) ;
118             $this->set(
119 0     0   0 'usage_fn' => sub { $this->script_usage(@_); },
120 26         1082 ) ;
121              
122             ## Set options
123 26         171 $this->feature('Options')->append_options(\@SCRIPT_OPTIONS) ;
124              
125 26 50       161 print "App::Framework::Core::Script->new() - END\n" if $class_debug;
126            
127 26         591 return($this) ;
128             }
129              
130              
131              
132             #============================================================================================
133              
134             =back
135              
136             =head2 CLASS METHODS
137              
138             =over 4
139              
140             =cut
141              
142             #============================================================================================
143              
144             #----------------------------------------------------------------------------
145              
146             =item B
147              
148             Class instance object is not allowed
149            
150             =cut
151              
152             sub allowed_class_instance
153             {
154 26     26 1 143 return 0 ;
155             }
156              
157             #============================================================================================
158              
159             =back
160              
161             =head2 OBJECT METHODS
162              
163             =over 4
164              
165             =cut
166              
167             #============================================================================================
168              
169              
170              
171             #----------------------------------------------------------------------------
172              
173             =item B
174              
175             Exit the application.
176            
177             =cut
178              
179              
180             sub exit
181             {
182 36     36 1 382 my $this = shift ;
183 36         479 my ($exit_code) = @_ ;
184              
185 36         248 $this->_dbg_prt(["EXIT: $exit_code\n"]) ;
186              
187 36         1098 my $exit_type = $this->exit_type() ;
188 36 100       210 if (lc($exit_type) eq 'die')
189             {
190 19         469 die '' ;
191             }
192             else
193             {
194 17         2984 exit $exit_code ;
195             }
196              
197             }
198              
199             #----------------------------------------------------------------------------
200              
201             =item B
202              
203             Function that gets called on errors. $error is as defined in L
204              
205             =cut
206              
207             sub catch_error
208             {
209 1     1 1 9 my $this = shift ;
210 1         3 my ($error) = @_ ;
211              
212 1         10 $this->_dbg_prt(["catch_error()\n"]) ;
213              
214 1         17 $this->SUPER::catch_error($error) ;
215              
216             #TODO: This is just the App::Framework::Base::Object::ErrorHandle default_error_handler() code - could just use that (return handled=0)
217 1         2 my $handled = 0 ;
218              
219             # If it's an error, stop
220 1 50       18 if ($this->is_error($error))
221             {
222 1         16 my ($msg, $exitcode) = $this->error_split($error) ;
223 1         19 die "Error: $msg\n" ;
224 0         0 $handled = 1 ;
225             }
226 0 0       0 if ($this->is_warning($error))
227             {
228 0         0 my ($msg, $exitcode) = $this->error_split($error) ;
229 0         0 warn "Warning: $msg\n" ;
230 0         0 $handled = 1 ;
231             }
232 0 0       0 if ($this->is_note($error))
233             {
234 0         0 my ($msg, $exitcode) = $this->error_split($error) ;
235 0         0 print "Note: $msg\n" ;
236 0         0 $handled = 1 ;
237             }
238              
239 0         0 return $handled ;
240             }
241              
242              
243             # ============================================================================================
244             # NEW METHODS
245             # ============================================================================================
246              
247             # TODO: Move to Pod feature
248              
249             #----------------------------------------------------------------------------
250              
251             =item B
252              
253             Show usage.
254              
255             $level is a string containg the level of usage to display
256              
257             'opt' is equivalent to pod2usage(2)
258              
259             'help' is equivalent to pod2usage(1)
260              
261             'man' is equivalent to pod2usage(-verbose => 2)
262              
263             =cut
264              
265             sub script_usage
266             {
267 8     8 1 16 my $this = shift ;
268 8         26 my ($app, $level) = @_ ;
269              
270 8   100     58 $level ||= "" ;
271              
272             #$this->debug(1);
273 8         43 $this->_dbg_prt(["Start of script_usage($level)\n"]) ;
274            
275             # TODO: Work out a better way to convert pod without the use of external file!
276            
277             # get temp file
278 8         142 my $fh = new File::Temp();
279 8         401252 my $fname = $fh->filename;
280            
281             # write pod
282 8 100       76 my $developer = $level eq 'man-dev' ? 1 : 0 ;
283 8         105 print $fh $this->pod($developer) ;
284 8         22921 close $fh ;
285              
286             # pod2usage
287 8         36 my ($exitval, $verbose) = (0, 0) ;
288 8 50       60 ($exitval, $verbose) = (2, 0) if ($level eq 'opt') ;
289 8 100       39 ($exitval, $verbose) = (1, 0) if ($level eq 'help') ;
290 8 100       50 ($exitval, $verbose) = (0, 2) if ($level =~ /^man/) ;
291              
292             #print "level=$level, exit=$exitval, verbose=$verbose\n";
293              
294             # make file readable by all - in case we're running as root
295 8         344 chmod 0644, $fname ;
296              
297             # system("perldoc", $fname) ;
298 8         414 pod2usage(
299             -verbose => $verbose,
300             # -exitval => $exitval,
301             -exitval => 'noexit',
302             -input => $fname,
303             -noperldoc =>1,
304            
305             -title => $this->name(),
306             -section => 1,
307             ) ;
308              
309 8         151614 $this->_dbg_prt(["End of script_usage()\n"]) ;
310            
311             # remove temp file
312 8         1517 unlink $fname ;
313              
314             }
315              
316              
317             # ============================================================================================
318             # PRIVATE METHODS
319             # ============================================================================================
320              
321              
322              
323              
324             # ============================================================================================
325             # END OF PACKAGE
326              
327             =back
328              
329             =head1 DIAGNOSTICS
330              
331             Setting the debug flag to level 1 prints out (to STDOUT) some debug messages, setting it to level 2 prints out more verbose messages.
332              
333             =head1 AUTHOR
334              
335             Steve Price C<< >>
336              
337             =head1 BUGS
338              
339             None that I know of!
340              
341             =cut
342              
343             1;
344              
345             __END__