File Coverage

blib/lib/App/Sqitch/Command.pm
Criterion Covered Total %
statement 155 155 100.0
branch 58 62 93.5
condition 23 29 79.3
subroutine 29 29 100.0
pod 10 10 100.0
total 275 285 96.4


line stmt bran cond sub pod time code
1              
2             use 5.010;
3 50     50   1995 use strict;
  50         189  
4 50     50   267 use warnings;
  50         84  
  50         1043  
5 50     50   1142 use utf8;
  50         162  
  50         1506  
6 50     50   292 use Try::Tiny;
  50         77  
  50         316  
7 50     50   1197 use Locale::TextDomain qw(App-Sqitch);
  50         115  
  50         2962  
8 50     50   311 use App::Sqitch::X qw(hurl);
  50         94  
  50         443  
9 50     50   9493 use Hash::Merge 'merge';
  50         98  
  50         562  
10 50     50   14845 use File::Path qw(make_path);
  50         97  
  50         2655  
11 50     50   299 use Moo;
  50         89  
  50         2148  
12 50     50   269 use App::Sqitch::Types qw(Sqitch Target);
  50         76  
  50         385  
13 50     50   18152  
  50         83  
  50         434  
14             our $VERSION = 'v1.3.0'; # VERSION
15              
16             use constant ENGINES => qw(
17 50         95777 pg
18             sqlite
19             mysql
20             oracle
21             firebird
22             vertica
23             exasol
24             snowflake
25             );
26 50     50   35508  
  50         96  
27             has sqitch => (
28             is => 'ro',
29             isa => Sqitch,
30             required => 1,
31             handles => [qw(
32             run
33             shell
34             quote_shell
35             capture
36             probe
37             verbosity
38             trace
39             trace_literal
40             debug
41             debug_literal
42             info
43             info_literal
44             comment
45             comment_literal
46             emit
47             emit_literal
48             vent
49             vent_literal
50             warn
51             warn_literal
52             page
53             page_literal
54             prompt
55             ask_y_n
56             )],
57             );
58              
59             has default_target => (
60             is => 'ro',
61             isa => Target,
62             lazy => 1,
63             default => sub {
64             my $self = shift;
65             my $sqitch = $self->sqitch;
66             my @params = $self->target_params;
67             unless (
68             $sqitch->config->get(key => 'core.engine')
69             || $sqitch->config->get(key => 'core.target')
70             ) {
71             # No specified engine, so specify an engineless URI.
72             require URI::db;
73             unshift @params, uri => URI::db->new('db:');
74             }
75             require App::Sqitch::Target;
76             return App::Sqitch::Target->new(@params);
77             },
78             );
79              
80             my $class = ref $_[0] || shift;
81             return '' if $class eq __PACKAGE__;
82 256   66 256 1 19737 my $pkg = quotemeta __PACKAGE__;
83 256 100       695 $class =~ s/^$pkg\:://;
84 253         456 $class =~ s/_/-/g;
85 253         1817 return $class;
86 253         667 }
87 253         1125  
88             my ( $class, $sqitch, $cmd ) = @_;
89              
90             $cmd =~ s/-/_/g;
91 65     65 1 1084  
92             # Load the command class.
93 65         200 my $pkg = __PACKAGE__ . "::$cmd";
94             eval "require $pkg; 1" or do {
95             # Emit the original error for debugging.
96 65         210 $sqitch->debug($@);
97 65 100       3888 return undef;
98             };
99 9         359 return $pkg;
100 4         231 }
101              
102 56         359 my ( $class, $p ) = @_;
103             # We should have a command.
104             my $cmd = delete $p->{command} or $class->usage;
105             my $pkg = $class->class_for($p->{sqitch}, $cmd) or hurl {
106 39     39 1 52624 ident => 'command',
107             exitval => 1,
108 39 100       250 message => __x(
109 38 100       187 '"{command}" is not a valid command',
110             command => $cmd,
111             ),
112             };
113             $pkg->create($p);
114             }
115              
116             my ( $class, $p ) = @_;
117 35         255  
118             # Merge the command-line options and configuration parameters
119             my $params = $class->configure(
120             $p->{config},
121 44     44 1 1243 $class->_parse_opts( $p->{args} )
122             );
123              
124             # Instantiate and return the command.
125             $params->{sqitch} = $p->{sqitch};
126             return $class->new($params);
127 44         291 }
128              
129             my ( $class, $config, $options ) = @_;
130 44         2192  
131 44         747 return Hash::Merge->new->merge(
132             $options,
133             $config->get_section( section => $class->command ),
134             );
135 93     93 1 21546 }
136              
137 93         566 return;
138             }
139              
140             my ( $class, $args ) = @_;
141             return {} unless $args && @{$args};
142              
143             my %opts;
144 7     7 1 50 Getopt::Long::Configure(qw(bundling no_pass_through));
145             Getopt::Long::GetOptionsFromArray( $args, \%opts, $class->options )
146             or $class->usage;
147              
148 49     49   3395 # Convert dashes to underscores.
149 49 100 100     596 for my $k (keys %opts) {
  20         395  
150             next unless ( my $nk = $k ) =~ s/-/_/g;
151 16         31 $opts{$nk} = delete $opts{$k};
152 16         80 }
153 16 100       910  
154             return \%opts;
155             }
156              
157 16         5824 require File::Basename;
158 10 100       54 File::Basename::basename($0);
159 2         5 }
160              
161             my ( $self, %params ) = @_;
162 16         159 my $command = $self->command;
163             require Pod::Find;
164             require Pod::Usage;
165             my $bn = _bn;
166 11     11   33 my $find_pod = sub {
167 11         388 Pod::Find::pod_where({ '-inc' => 1, '-script' => 1 }, shift );
168             };
169             $params{'-input'} ||= $find_pod->("$bn-$command")
170             || $find_pod->("sqitch-$command")
171 8     8   41801 || $find_pod->($bn)
172 8         29 || $find_pod->('sqitch')
173 8         43 || $find_pod->(ref $self || $self)
174 8         28 || $find_pod->(__PACKAGE__);
175 8         23 Pod::Usage::pod2usage(
176             '-verbose' => 99,
177 26     26   18555 '-sections' => '(?i:(Usage|Synopsis|Options))',
178 8         47 '-exitval' => 2,
179 8   33     46 %params,
      66        
180             );
181             }
182              
183             my $self = shift;
184             hurl(
185 8         52 'The execute() method must be called from a subclass of '
186             . __PACKAGE__
187             ) if ref $self eq __PACKAGE__;
188              
189             hurl 'The execute() method has not been overridden in ' . ref $self;
190             }
191              
192             my $self = shift;
193             require Pod::Find;
194 2     2 1 81 my $upod = _bn . '-' . $self->command . '-usage';
195 2 100       12 $self->_pod2usage(
196             '-input' => Pod::Find::pod_where( { '-inc' => 1 }, $upod ) || undef,
197             '-message' => join '', @_
198             );
199             }
200 1         6  
201             return (sqitch => shift->sqitch);
202             }
203              
204 3     3 1 80178 my ($self, %p) = @_;
205 3         19 my $config = $self->sqitch->config;
206 3         8 my @params = $self->target_params;
207 3   50     2642  
208             # Load the specified or default target.
209             require App::Sqitch::Target;
210             my $deftarget_err;
211             my $target = try {
212             App::Sqitch::Target->new( @params, name => $p{target} )
213             } catch {
214 249     249 1 2328 # Die if a target was specified; otherwise keep the error for later.
215             die $_ if $p{target};
216             $deftarget_err = $_;
217             undef;
218 177     177 1 40124 };
219 177         4642  
220 177         3725 # Set up the default results.
221             my (%seen, %target_for);
222             my %rec = map { $_ => [] } qw(targets unknown);
223 177         1660 $rec{changes} = [] unless $p{no_changes};
224 177         328 if ($p{target}) {
225             push @{ $rec{targets} } => $target;
226             $seen{$target->name}++;
227 177     177   11611 }
228              
229 4 100   4   5226 # Iterate over the args to look for changes, engines, plans, or targets.
230 3         6 my %engines = map { $_ => 1 } ENGINES;
231 3         9 for my $arg (@{ $p{args} }) {
232 177         1510 if ( !$p{no_changes} && $target && -e $target->plan_file && $target->plan->contains($arg) ) {
233             # A change.
234             push @{ $rec{changes} } => $arg;
235 176         15597 } elsif ($config->get( key => "target.$arg.uri") || URI->new($arg)->isa('URI::db')) {
236 176         384 # A target. Instantiate and keep for subsequente change searches.
  352         1105  
237 176 100       708 $target = App::Sqitch::Target->new( @params, name => $arg );
238 176 100       461 push @{ $rec{targets} } => $target unless $seen{$target->name}++;
239 44         100 } elsif ($engines{$arg}) {
  44         121  
240 44         175 # An engine. Add its target.
241             my $name = $config->get(key => "engine.$arg.target") || "db:$arg:";
242             $target = App::Sqitch::Target->new( @params, name => $name );
243             push @{ $rec{targets} } => $target unless $seen{$target->name}++;
244 176         656 } elsif (-e $arg) {
  1408         2904  
245 176         370 # Maybe it's a plan file?
  176         505  
246 191 100 100     3711 %target_for = map {
    100 100        
    100 100        
    100 100        
247             $_->plan_file => $_
248 47         69 } reverse App::Sqitch::Target->all_targets(@params) unless %target_for;
  47         211  
249             if ($target_for{$arg}) {
250             # It *is* a plan file.
251 39         10030 $target = $target_for{$arg};
252 38 50       3117 push @{ $rec{targets} } => $target unless $seen{$target->name}++;
  38         649  
253             } else {
254             # Nah, who knows.
255 21   66     3960 push @{ $rec{unknown} } => $arg;
256 21         2799 }
257 21 50       1692 } else {
  21         410  
258             # Who knows?
259             push @{ $rec{unknown} } => $arg;
260             }
261 7 50       1544 }
  14         2105  
262              
263 7 100       2426 # Replace missing names with unknown values.
264             my @names = map { $_ || shift @{ $rec{unknown} } } @{ $p{names} || [] };
265 6         80  
266 6 50       142 # Die on unknowns.
  6         238  
267             if (my @unknown = @{ $rec{unknown} } ) {
268             hurl $self->command => __nx(
269 1         2 'Unknown argument "{arg}"',
  1         5  
270             'Unknown arguments: {arg}',
271             scalar @unknown,
272             arg => join ', ', @unknown
273 77         14497 );
  77         549  
274             }
275              
276             # Figure out what targets to access. Use default unless --all.
277             my @targets = @{ $rec{targets} };
278 175 100       932 if ($p{all}) {
  65 100       212  
  58         213  
  175         836  
279             # Got --all.
280             hurl $self->command => __(
281 175 100       310 'Cannot specify both --all and engine, target, or plan arugments'
  175         580  
282 21         115 ) if @targets;
283             @targets = App::Sqitch::Target->all_targets(@params );
284             } elsif (!@targets) {
285             # Use all if tag.all is set, otherwise just the default.
286             my $key = $self->command . '.all';
287             @targets = $self->sqitch->config->get(key => $key, as => 'bool')
288             ? App::Sqitch::Target->all_targets(@params )
289             : do {
290             # Fall back on the default unless it's invalid.
291 154         267 die $deftarget_err if $deftarget_err;
  154         316  
292 154 100       565 ($target)
    100          
293             }
294 12 100       77 }
295              
296             return (@names, \@targets, $rec{changes});
297 8         74 }
298              
299             my ( $self, $dir ) = @_;
300 64         355 $self->debug( ' ', __x 'Created {file}', file => $dir )
301             if make_path $dir, { error => \my $err };
302              
303 64 100       1390 my $diag = shift @{ $err } or return $self;
304              
305 60 100       7016 my ( $path, $msg ) = %{ $diag };
306 59         169 hurl $self->command => __x(
307             'Error creating {path}: {error}',
308             path => $path,
309             error => $msg,
310 149         1244 ) if $path;
311             hurl $self->command => $msg;
312             }
313              
314 162     162   84369 1;
315 162 100       8368  
316              
317             =head1 Name
318 162 100       33937  
  162         673  
319             App::Sqitch::Command - Sqitch Command support
320 2         4  
  2         8  
321 2 100       9 =head1 Synopsis
322              
323             my $cmd = App::Sqitch::Command->load( deploy => \%params );
324             $cmd->run;
325              
326 1         6 =head1 Description
327              
328             App::Sqitch::Command is the base class for all Sqitch commands.
329              
330             =head1 Interface
331              
332             =head2 Constants
333              
334             =head3 C<ENGINES>
335              
336             Returns the list of supported engines, currently:
337              
338             =over
339              
340             =item * C<firebird>
341              
342             =item * C<mysql>
343              
344             =item * C<oracle>
345              
346             =item * C<pg>
347              
348             =item * C<sqlite>
349              
350             =item * C<vertica>
351              
352             =item * C<exasol>
353              
354             =item * C<snowflake>
355              
356             =back
357              
358             =head2 Class Methods
359              
360             =head3 C<options>
361              
362             my @spec = App::Sqitch::Command->options;
363              
364             Returns a list of L<Getopt::Long> options specifications. When C<load> loads
365             the class, any options passed to the command will be parsed using these
366             values. The keys in the resulting hash will be the first part of each option,
367             with dashes converted to underscores. This hash will be passed to C<configure>
368             along with a L<App::Sqitch::Config> object for munging into parameters to be
369             passed to the constructor.
370              
371             Here's an example excerpted from the C<config> command:
372              
373             sub options {
374             return qw(
375             get
376             unset
377             list
378             global
379             system
380             config-file=s
381             );
382             }
383              
384             This will result in hash keys with the same names as each option except for
385             C<config-file=s>, which will be named C<config_file>.
386              
387             =head3 C<configure>
388              
389             my $params = App::Sqitch::Command->configure($config, $options);
390              
391             Takes two arguments, an L<App::Sqitch::Config> object and the hash of
392             command-line options as specified by C<options>. The returned hash should be
393             the result of munging these two objects into a hash reference of parameters to
394             be passed to the command subclass constructor.
395              
396             By default, this method converts dashes to underscores in command-line options
397             keys, and then merges the configuration values with the options, with the
398             command-line options taking priority. You may wish to override this method to
399             do something different.
400              
401             =head3 C<class_for>
402              
403             my $subclass = App::Sqitch::Command->subclass_for($sqitch, $cmd_name);
404              
405             This method attempts to load the subclass of App::Sqitch::Commmand that
406             corresponds to the command name. Returns C<undef> and sends errors to the
407             C<debug> method of the <$sqitch> object if no such subclass can
408             be loaded.
409              
410             =head2 Constructors
411              
412             =head3 C<load>
413              
414             my $cmd = App::Sqitch::Command->load( \%params );
415              
416             A factory method for instantiating Sqitch commands. It loads the subclass for
417             the specified command and calls C<create> to instantiate and return an
418             instance of the subclass. Sends error messages to the C<debug> method of the
419             C<sqitch> parameter and throws an exception if the subclass does not exist or
420             cannot be loaded. Supported parameters are:
421              
422             =over
423              
424             =item C<sqitch>
425              
426             The App::Sqitch object driving the whole thing.
427              
428             =item C<config>
429              
430             An L<App::Sqitch::Config> representing the current application configuration
431             state.
432              
433             =item C<command>
434              
435             The name of the command to be executed.
436              
437             =item C<args>
438              
439             An array reference of command-line arguments passed to the command.
440              
441             =back
442              
443             =head3 C<create>
444              
445             my $pkg = App::Sqitch::Command->class_for( $sqitch, $cmd_name )
446             or die "No such command $cmd_name";
447             my $cmd = $pkg->create({
448             sqitch => $sqitch,
449             config => $config,
450             args => \@ARGV,
451             });
452              
453             Creates and returns a new object for a subclass of App::Sqitch::Command. It
454             parses options from the C<args> parameter, calls C<configure> to merge
455             configuration with the options, and finally calls C<new> with the resulting
456             hash. Supported parameters are the same as for C<load> except for the
457             C<command> parameter, which will be ignored.
458              
459             =head3 C<new>
460              
461             my $cmd = App::Sqitch::Command->new(%params);
462              
463             Instantiates and returns a App::Sqitch::Command object. This method is not
464             designed to be overridden by subclasses; they should implement
465             L<C<BUILDARGS>|Moo::Manual::Construction/BUILDARGS> or
466             L<C<BUILD>|Moo::Manual::Construction/BUILD>, instead.
467              
468             =head2 Accessors
469              
470             =head3 C<sqitch>
471              
472             my $sqitch = $cmd->sqitch;
473              
474             Returns the L<App::Sqitch> object that instantiated the command. Commands may
475             access its properties in order to manage global state.
476              
477             =head2 Overridable Instance Methods
478              
479             These methods should be overridden by all subclasses.
480              
481             =head3 C<execute>
482              
483             $cmd->execute;
484              
485             Executes the command. This is the method that does the work of the command.
486             Must be overridden in all subclasses. Dies if the method is not overridden for
487             the object on which it is called, or if it is called against a base
488             App::Sqitch::Command object.
489              
490             =head3 C<command>
491              
492             my $command = $cmd->command;
493              
494             The name of the command. Defaults to the last part of the package name, so as
495             a rule you should not need to override it, since it is that string that Sqitch
496             uses to find the command class.
497              
498             =head2 Utility Instance Methods
499              
500             These methods are mainly provided as utilities for the command subclasses to
501             use.
502              
503             =head3 C<default_target>
504              
505             my $target = $cmd->default_target;
506              
507             This method returns the default target. It should only be used by commands
508             that don't use a C<parse_args()> to find and load a target.
509              
510             This method should always return a target option, never C<undef>. If the
511             C<core.engine> configuration option has been set, then the target will support
512             that engine. In the latter case, if C<engine.$engine.target> is set, that
513             value will be used. Otherwise, the returned target will have a URI of C<db:>
514             and no associated engine; the C<engine> method will throw an exception. This
515             behavior should be fine for commands that don't need to load the engine.
516              
517             =head3 C<parse_args>
518              
519             my ($name1, $name2, $targets, $changes) = $cmd->parse_args(
520             names => \@names,
521             target => $target_name,
522             args => \@args
523             );
524              
525             Examines each argument to determine whether it's a known change spec or
526             identifies a target or engine. Unrecognized arguments will replace false
527             values in the C<names> array reference. Any remaining unknown arguments will
528             trigger an error.
529              
530             Returns a list consisting all the desired names, followed by an array
531             reference of target objects and an array reference of change specs.
532              
533             This method is useful for commands that take a number of arguments where the
534             order may be mixed.
535              
536             The supported parameters are:
537              
538             =over
539              
540             =item C<args>
541              
542             An array reference of the command arguments.
543              
544             =item C<target>
545              
546             The name of a target, if any. Useful for commands that offer their own
547             C<--target> option. This target will be the default target, and the first
548             returned in the targets array.
549              
550             =item C<names>
551              
552             An array reference of names. If any is false, its place will be taken by an
553             otherwise unrecognized argument. The number of values in this array reference
554             determines the number of values returned as names in the return values. Such
555             values may still be false or undefined; it's up to the caller to decide what
556             to do about that.
557              
558             =item C<all>
559              
560             In the event that no targets are recognized (or changes that implicitly
561             recognize the default target), if this parameter is true, then all known
562             targets from the configuration will be returned.
563              
564             =item C<no_changes>
565              
566             If true, the parser will not check to see if any argument corresponds to a
567             change. The last value returned will be C<undef> instead of the usual array
568             reference. Any argument that might have been recognized as a change will
569             instead be included in either the C<targets> array -- if it's recognized as a
570             target -- or used to set names to return. Any remaining are considered
571             unknown arguments and will result in an exception.
572              
573             =back
574              
575             If a target parameter is passed, it will always be instantiated and returned
576             as the first item in the "target" array, and arguments recognized as changes
577             in the plan associated with that target will be returned as changes.
578              
579             If no target is passed or appears in the arguments, a default target will be
580             instantiated based on the command-line options and configuration. Unlike the
581             target returned by C<default_target>, this target B<must> have an associated
582             engine specified by the configuration. This is on the assumption that it will
583             be used by commands that require an engine to do their work. Of course, any
584             changes must be recognized from the plan associated with this target.
585              
586             Changes are only recognized if they're found in the plan of the target that
587             precedes them. If no target precedes them, the target specified by the
588             C<target> parameter or the default target will be searched. Such changes can
589             be specified in any way documented in L<sqitchchanges>.
590              
591             Targets may be recognized by any one of these types of arguments:
592              
593             =over
594              
595             =item * Target Name
596              
597             =item * Database URI
598              
599             =item * Engine Name
600              
601             =item * Plan File
602              
603             =back
604              
605             In the case of plan files, C<parse_args()> will return the first target it
606             finds for that plan file, even if multiple targets use the same plan file. The
607             order of precedence for this determination is the default project target,
608             followed by named targets, then engine targets.
609              
610             =head3 C<target_params>
611              
612             my $target = App::Sqitch::Target->new( $cmd->target_params );
613              
614             Returns a list of parameters suitable for passing to the C<new> or
615             C<all_targets> constructors of App::Sqitch::Target.
616              
617             =head3 C<run>
618              
619             $cmd->run('echo hello');
620              
621             Runs a system command and waits for it to finish. Throws an exception on
622             error.
623              
624             =head3 C<capture>
625              
626             my @files = $cmd->capture(qw(ls -lah));
627              
628             Runs a system command and captures its output to C<STDOUT>. Returns the output
629             lines in list context and the concatenation of the lines in scalar context.
630             Throws an exception on error.
631              
632             =head3 C<probe>
633              
634             my $git_version = $cmd->capture(qw(git --version));
635              
636             Like C<capture>, but returns just the C<chomp>ed first line of output.
637              
638             =head3 C<verbosity>
639              
640             my $verbosity = $cmd->verbosity;
641              
642             Returns the verbosity level.
643              
644             =head3 C<trace>
645              
646             Send trace information to C<STDOUT> if the verbosity level is 3 or higher.
647             Trace messages will have C<trace: > prefixed to every line. If it's lower than
648             3, nothing will be output.
649              
650             =head3 C<debug>
651              
652             $cmd->debug('Found snuggle in the crib.');
653              
654             Send debug information to C<STDOUT> if the verbosity level is 2 or higher.
655             Debug messages will have C<debug: > prefixed to every line. If it's lower than
656             2, nothing will be output.
657              
658             =head3 C<info>
659              
660             $cmd->info('Nothing to deploy (up-to-date)');
661              
662             Send informational message to C<STDOUT> if the verbosity level is 1 or higher,
663             which, by default, it is. Should be used for normal messages the user would
664             normally want to see. If verbosity is lower than 1, nothing will be output.
665              
666             =head3 C<comment>
667              
668             $cmd->comment('On database flipr_test');
669              
670             Send comments to C<STDOUT> if the verbosity level is 1 or higher, which, by
671             default, it is. Comments have C<# > prefixed to every line. If verbosity is
672             lower than 1, nothing will be output.
673              
674             =head3 C<emit>
675              
676             $cmd->emit('core.editor=emacs');
677              
678             Send a message to C<STDOUT>, without regard to the verbosity. Should be used
679             only if the user explicitly asks for output, such as for
680             C<sqitch config --get core.editor>.
681              
682             =head3 C<vent>
683              
684             $cmd->vent('That was a misage.');
685              
686             Send a message to C<STDERR>, without regard to the verbosity. Should be used
687             only for error messages to be printed before exiting with an error, such as
688             when reverting failed changes.
689              
690             =head3 C<page>
691              
692             $sqitch->page('Search results:');
693              
694             Like C<emit()>, but sends the output to a pager handle rather than C<STDOUT>.
695             Unless there is no TTY (such as when output is being piped elsewhere), in
696             which case it I<is> sent to C<STDOUT>. Meant to be used to send a lot of data
697             to the user at once, such as when display the results of searching the event
698             log:
699              
700             $iter = $engine->search_events;
701             while ( my $change = $iter->() ) {
702             $cmd->page(join ' - ', @{ $change }{ qw(change_id event change) });
703             }
704              
705             =head3 C<warn>
706              
707             $cmd->warn('Could not find nerble; using nobble instead.');
708              
709             Send a warning messages to C<STDERR>. Warnings will have C<warning: > prefixed
710             to every line. Use if something unexpected happened but you can recover from
711             it.
712              
713             =head3 C<usage>
714              
715             $cmd->usage('Missing "value" argument');
716              
717             Sends the specified message to C<STDERR>, followed by the usage sections of
718             the command's documentation. Those sections may be named "Name", "Synopsis",
719             or "Options". Any or all of these will be shown. The doc used to display them
720             will be the first found of:
721              
722             =over
723              
724             =item C<sqitch-$command-usage>
725              
726             =item C<sqitch-$command>
727              
728             =item C<sqitch>
729              
730             =item C<App::Sqitch::Command::$command>
731              
732             =item C<App::Sqitch::Command>
733              
734             =back
735              
736             For an ideal usage messages, C<sqitch-$command-usage.pod> should be created by
737             all command subclasses.
738              
739             =head1 See Also
740              
741             =over
742              
743             =item L<sqitch>
744              
745             The Sqitch command-line client.
746              
747             =back
748              
749             =head1 Author
750              
751             David E. Wheeler <david@justatheory.com>
752              
753             =head1 License
754              
755             Copyright (c) 2012-2022 iovation Inc., David E. Wheeler
756              
757             Permission is hereby granted, free of charge, to any person obtaining a copy
758             of this software and associated documentation files (the "Software"), to deal
759             in the Software without restriction, including without limitation the rights
760             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
761             copies of the Software, and to permit persons to whom the Software is
762             furnished to do so, subject to the following conditions:
763              
764             The above copyright notice and this permission notice shall be included in all
765             copies or substantial portions of the Software.
766              
767             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
768             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
769             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
770             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
771             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
773             SOFTWARE.
774              
775             =cut