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