| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  | use 5.010; | 
| 3 | 50 |  |  | 50 |  | 2050 | use strict; | 
|  | 50 |  |  |  |  | 162 |  | 
| 4 | 50 |  |  | 50 |  | 258 | use warnings; | 
|  | 50 |  |  |  |  | 114 |  | 
|  | 50 |  |  |  |  | 993 |  | 
| 5 | 50 |  |  | 50 |  | 1175 | use utf8; | 
|  | 50 |  |  |  |  | 171 |  | 
|  | 50 |  |  |  |  | 1637 |  | 
| 6 | 50 |  |  | 50 |  | 299 | use Try::Tiny; | 
|  | 50 |  |  |  |  | 83 |  | 
|  | 50 |  |  |  |  | 333 |  | 
| 7 | 50 |  |  | 50 |  | 1265 | use Locale::TextDomain qw(App-Sqitch); | 
|  | 50 |  |  |  |  | 84 |  | 
|  | 50 |  |  |  |  | 2967 |  | 
| 8 | 50 |  |  | 50 |  | 365 | use App::Sqitch::X qw(hurl); | 
|  | 50 |  |  |  |  | 88 |  | 
|  | 50 |  |  |  |  | 577 |  | 
| 9 | 50 |  |  | 50 |  | 9316 | use Hash::Merge 'merge'; | 
|  | 50 |  |  |  |  | 99 |  | 
|  | 50 |  |  |  |  | 467 |  | 
| 10 | 50 |  |  | 50 |  | 14551 | use File::Path qw(make_path); | 
|  | 50 |  |  |  |  | 93 |  | 
|  | 50 |  |  |  |  | 2742 |  | 
| 11 | 50 |  |  | 50 |  | 296 | use Moo; | 
|  | 50 |  |  |  |  | 90 |  | 
|  | 50 |  |  |  |  | 2051 |  | 
| 12 | 50 |  |  | 50 |  | 292 | use App::Sqitch::Types qw(Sqitch Target); | 
|  | 50 |  |  |  |  | 136 |  | 
|  | 50 |  |  |  |  | 360 |  | 
| 13 | 50 |  |  | 50 |  | 19795 |  | 
|  | 50 |  |  |  |  | 101 |  | 
|  | 50 |  |  |  |  | 410 |  | 
| 14 |  |  |  |  |  |  | our $VERSION = 'v1.3.1'; # VERSION | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | use constant ENGINES => qw( | 
| 17 | 50 |  |  |  |  | 96766 | pg | 
| 18 |  |  |  |  |  |  | sqlite | 
| 19 |  |  |  |  |  |  | mysql | 
| 20 |  |  |  |  |  |  | oracle | 
| 21 |  |  |  |  |  |  | firebird | 
| 22 |  |  |  |  |  |  | vertica | 
| 23 |  |  |  |  |  |  | exasol | 
| 24 |  |  |  |  |  |  | snowflake | 
| 25 |  |  |  |  |  |  | ); | 
| 26 | 50 |  |  | 50 |  | 36170 |  | 
|  | 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 | 19871 | my $pkg = quotemeta __PACKAGE__; | 
| 83 | 256 | 100 |  |  |  | 736 | $class =~ s/^$pkg\:://; | 
| 84 | 253 |  |  |  |  | 441 | $class =~ s/_/-/g; | 
| 85 | 253 |  |  |  |  | 1876 | return $class; | 
| 86 | 253 |  |  |  |  | 689 | } | 
| 87 | 253 |  |  |  |  | 1153 |  | 
| 88 |  |  |  |  |  |  | my ( $class, $sqitch, $cmd ) = @_; | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | $cmd =~ s/-/_/g; | 
| 91 | 65 |  |  | 65 | 1 | 1075 |  | 
| 92 |  |  |  |  |  |  | # Load the command class. | 
| 93 | 65 |  |  |  |  | 224 | my $pkg = __PACKAGE__ . "::$cmd"; | 
| 94 |  |  |  |  |  |  | eval "require $pkg; 1" or do { | 
| 95 |  |  |  |  |  |  | # Emit the original error for debugging. | 
| 96 | 65 |  |  |  |  | 244 | $sqitch->debug($@); | 
| 97 | 65 | 100 |  |  |  | 4692 | return undef; | 
| 98 |  |  |  |  |  |  | }; | 
| 99 | 9 |  |  |  |  | 379 | return $pkg; | 
| 100 | 4 |  |  |  |  | 229 | } | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 56 |  |  |  |  | 368 | 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 | 53666 | ident   => 'command', | 
| 107 |  |  |  |  |  |  | exitval => 1, | 
| 108 | 39 | 100 |  |  |  | 207 | message => __x( | 
| 109 | 38 | 100 |  |  |  | 161 | '"{command}" is not a valid command', | 
| 110 |  |  |  |  |  |  | command => $cmd, | 
| 111 |  |  |  |  |  |  | ), | 
| 112 |  |  |  |  |  |  | }; | 
| 113 |  |  |  |  |  |  | $pkg->create($p); | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | my ( $class, $p ) = @_; | 
| 117 | 35 |  |  |  |  | 256 |  | 
| 118 |  |  |  |  |  |  | # Merge the command-line options and configuration parameters | 
| 119 |  |  |  |  |  |  | my $params = $class->configure( | 
| 120 |  |  |  |  |  |  | $p->{config}, | 
| 121 | 44 |  |  | 44 | 1 | 1615 | $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 |  |  |  |  | 264 | } | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | my ( $class, $config, $options ) = @_; | 
| 130 | 44 |  |  |  |  | 2108 |  | 
| 131 | 44 |  |  |  |  | 713 | return Hash::Merge->new->merge( | 
| 132 |  |  |  |  |  |  | $options, | 
| 133 |  |  |  |  |  |  | $config->get_section( section => $class->command ), | 
| 134 |  |  |  |  |  |  | ); | 
| 135 | 93 |  |  | 93 | 1 | 19889 | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 93 |  |  |  |  | 609 | return; | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | my ( $class, $args ) = @_; | 
| 141 |  |  |  |  |  |  | return {} unless $args && @{$args}; | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | my %opts; | 
| 144 | 7 |  |  | 7 | 1 | 42 | Getopt::Long::Configure(qw(bundling no_pass_through)); | 
| 145 |  |  |  |  |  |  | Getopt::Long::GetOptionsFromArray( $args, \%opts, $class->options ) | 
| 146 |  |  |  |  |  |  | or $class->usage; | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 49 |  |  | 49 |  | 3391 | # Convert dashes to underscores. | 
| 149 | 49 | 100 | 100 |  |  | 567 | for my $k (keys %opts) { | 
|  | 20 |  |  |  |  | 84 |  | 
| 150 |  |  |  |  |  |  | next unless ( my $nk = $k ) =~ s/-/_/g; | 
| 151 | 16 |  |  |  |  | 33 | $opts{$nk} = delete $opts{$k}; | 
| 152 | 16 |  |  |  |  | 79 | } | 
| 153 | 16 | 100 |  |  |  | 884 |  | 
| 154 |  |  |  |  |  |  | return \%opts; | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 16 |  |  |  |  | 5888 | require File::Basename; | 
| 158 | 10 | 100 |  |  |  | 52 | File::Basename::basename($0); | 
| 159 | 2 |  |  |  |  | 10 | } | 
| 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 |  | 40 | my $find_pod = sub { | 
| 167 | 11 |  |  |  |  | 483 | 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 |  | 43733 | ||  $find_pod->($bn) | 
| 172 | 8 |  |  |  |  | 40 | ||  $find_pod->('sqitch') | 
| 173 | 8 |  |  |  |  | 60 | ||  $find_pod->(ref $self || $self) | 
| 174 | 8 |  |  |  |  | 29 | ||  $find_pod->(__PACKAGE__); | 
| 175 | 8 |  |  |  |  | 35 | Pod::Usage::pod2usage( | 
| 176 |  |  |  |  |  |  | '-verbose'  => 99, | 
| 177 | 26 |  |  | 26 |  | 18700 | '-sections' => '(?i:(Usage|Synopsis|Options))', | 
| 178 | 8 |  |  |  |  | 52 | '-exitval'  => 2, | 
| 179 | 8 |  | 33 |  |  | 61 | %params, | 
|  |  |  | 66 |  |  |  |  | 
| 180 |  |  |  |  |  |  | ); | 
| 181 |  |  |  |  |  |  | } | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | my $self = shift; | 
| 184 |  |  |  |  |  |  | hurl( | 
| 185 | 8 |  |  |  |  | 87 | '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 | 87 | my $upod = _bn . '-' . $self->command . '-usage'; | 
| 195 | 2 | 100 |  |  |  | 11 | $self->_pod2usage( | 
| 196 |  |  |  |  |  |  | '-input' => Pod::Find::pod_where( { '-inc' => 1 }, $upod ) || undef, | 
| 197 |  |  |  |  |  |  | '-message' => join '', @_ | 
| 198 |  |  |  |  |  |  | ); | 
| 199 |  |  |  |  |  |  | } | 
| 200 | 1 |  |  |  |  | 7 |  | 
| 201 |  |  |  |  |  |  | return (sqitch => shift->sqitch); | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 3 |  |  | 3 | 1 | 86531 | my ($self, %p) = @_; | 
| 205 | 3 |  |  |  |  | 31 | my $config = $self->sqitch->config; | 
| 206 | 3 |  |  |  |  | 12 | my @params = $self->target_params; | 
| 207 | 3 |  | 50 |  |  | 2651 |  | 
| 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 | 2303 | # 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 | 47791 | }; | 
| 219 | 177 |  |  |  |  | 4327 |  | 
| 220 | 177 |  |  |  |  | 3661 | # Set up the default results. | 
| 221 |  |  |  |  |  |  | my (%seen, %target_for); | 
| 222 |  |  |  |  |  |  | my %rec = map { $_ => [] } qw(targets unknown); | 
| 223 | 177 |  |  |  |  | 1607 | $rec{changes} = [] unless $p{no_changes}; | 
| 224 | 177 |  |  |  |  | 325 | if ($p{target}) { | 
| 225 |  |  |  |  |  |  | push @{ $rec{targets} } => $target; | 
| 226 |  |  |  |  |  |  | $seen{$target->name}++; | 
| 227 | 177 |  |  | 177 |  | 12005 | } | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 4 | 100 |  | 4 |  | 5806 | # Iterate over the args to look for changes, engines, plans, or targets. | 
| 230 | 3 |  |  |  |  | 9 | my %engines = map { $_ => 1 } ENGINES; | 
| 231 | 3 |  |  |  |  | 11 | for my $arg (@{ $p{args} }) { | 
| 232 | 177 |  |  |  |  | 1571 | if ( !$p{no_changes} && $target && -e $target->plan_file && $target->plan->contains($arg) ) { | 
| 233 |  |  |  |  |  |  | # A change. | 
| 234 |  |  |  |  |  |  | push @{ $rec{changes} } => $arg; | 
| 235 | 176 |  |  |  |  | 16263 | } elsif ($config->get( key => "target.$arg.uri") || URI->new($arg)->isa('URI::db')) { | 
| 236 | 176 |  |  |  |  | 430 | # A target. Instantiate and keep for subsequente change searches. | 
|  | 352 |  |  |  |  | 1021 |  | 
| 237 | 176 | 100 |  |  |  | 752 | $target = App::Sqitch::Target->new( @params, name => $arg ); | 
| 238 | 176 | 100 |  |  |  | 637 | push @{ $rec{targets} } => $target unless $seen{$target->name}++; | 
| 239 | 44 |  |  |  |  | 71 | } elsif ($engines{$arg}) { | 
|  | 44 |  |  |  |  | 112 |  | 
| 240 | 44 |  |  |  |  | 166 | # 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 |  |  |  |  | 487 | } elsif (-e $arg) { | 
|  | 1408 |  |  |  |  | 2817 |  | 
| 245 | 176 |  |  |  |  | 338 | # Maybe it's a plan file? | 
|  | 176 |  |  |  |  | 501 |  | 
| 246 | 191 | 100 | 100 |  |  | 4073 | %target_for = map { | 
|  |  | 100 | 100 |  |  |  |  | 
|  |  | 100 | 100 |  |  |  |  | 
|  |  | 100 | 100 |  |  |  |  | 
| 247 |  |  |  |  |  |  | $_->plan_file => $_ | 
| 248 | 47 |  |  |  |  | 87 | } reverse App::Sqitch::Target->all_targets(@params) unless %target_for; | 
|  | 47 |  |  |  |  | 223 |  | 
| 249 |  |  |  |  |  |  | if ($target_for{$arg}) { | 
| 250 |  |  |  |  |  |  | # It *is* a plan file. | 
| 251 | 39 |  |  |  |  | 10792 | $target = $target_for{$arg}; | 
| 252 | 38 | 50 |  |  |  | 3684 | push @{ $rec{targets} } => $target unless $seen{$target->name}++; | 
|  | 38 |  |  |  |  | 1046 |  | 
| 253 |  |  |  |  |  |  | } else { | 
| 254 |  |  |  |  |  |  | # Nah, who knows. | 
| 255 | 21 |  | 66 |  |  | 4298 | push @{ $rec{unknown} } => $arg; | 
| 256 | 21 |  |  |  |  | 2887 | } | 
| 257 | 21 | 50 |  |  |  | 1896 | } else { | 
|  | 21 |  |  |  |  | 567 |  | 
| 258 |  |  |  |  |  |  | # Who knows? | 
| 259 |  |  |  |  |  |  | push @{ $rec{unknown} } => $arg; | 
| 260 |  |  |  |  |  |  | } | 
| 261 | 7 | 50 |  |  |  | 1887 | } | 
|  | 14 |  |  |  |  | 2403 |  | 
| 262 |  |  |  |  |  |  |  | 
| 263 | 7 | 100 |  |  |  | 2576 | # Replace missing names with unknown values. | 
| 264 |  |  |  |  |  |  | my @names = map { $_ || shift @{ $rec{unknown} } } @{ $p{names} || [] }; | 
| 265 | 6 |  |  |  |  | 104 |  | 
| 266 | 6 | 50 |  |  |  | 163 | # Die on unknowns. | 
|  | 6 |  |  |  |  | 297 |  | 
| 267 |  |  |  |  |  |  | if (my @unknown = @{ $rec{unknown} } ) { | 
| 268 |  |  |  |  |  |  | hurl $self->command => __nx( | 
| 269 | 1 |  |  |  |  | 3 | 'Unknown argument "{arg}"', | 
|  | 1 |  |  |  |  | 7 |  | 
| 270 |  |  |  |  |  |  | 'Unknown arguments: {arg}', | 
| 271 |  |  |  |  |  |  | scalar @unknown, | 
| 272 |  |  |  |  |  |  | arg => join ', ', @unknown | 
| 273 | 77 |  |  |  |  | 15165 | ); | 
|  | 77 |  |  |  |  | 566 |  | 
| 274 |  |  |  |  |  |  | } | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | # Figure out what targets to access. Use default unless --all. | 
| 277 |  |  |  |  |  |  | my @targets = @{ $rec{targets} }; | 
| 278 | 175 | 100 |  |  |  | 900 | if ($p{all}) { | 
|  | 65 | 100 |  |  |  | 171 |  | 
|  | 58 |  |  |  |  | 198 |  | 
|  | 175 |  |  |  |  | 859 |  | 
| 279 |  |  |  |  |  |  | # Got --all. | 
| 280 |  |  |  |  |  |  | hurl $self->command => __( | 
| 281 | 175 | 100 |  |  |  | 346 | 'Cannot specify both --all and engine, target, or plan arugments' | 
|  | 175 |  |  |  |  | 539 |  | 
| 282 | 21 |  |  |  |  | 117 | ) 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 |  |  |  |  | 247 | die $deftarget_err if $deftarget_err; | 
|  | 154 |  |  |  |  | 356 |  | 
| 292 | 154 | 100 |  |  |  | 666 | ($target) | 
|  |  | 100 |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | } | 
| 294 | 12 | 100 |  |  |  | 96 | } | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | return (@names, \@targets, $rec{changes}); | 
| 297 | 8 |  |  |  |  | 68 | } | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | my ( $self, $dir ) = @_; | 
| 300 | 64 |  |  |  |  | 316 | $self->debug( '    ', __x 'Created {file}', file => $dir ) | 
| 301 |  |  |  |  |  |  | if make_path $dir, { error => \my $err }; | 
| 302 |  |  |  |  |  |  |  | 
| 303 | 64 | 100 |  |  |  | 1489 | my $diag = shift @{ $err } or return $self; | 
| 304 |  |  |  |  |  |  |  | 
| 305 | 60 | 100 |  |  |  | 7136 | my ( $path, $msg ) = %{ $diag }; | 
| 306 | 59 |  |  |  |  | 153 | hurl $self->command => __x( | 
| 307 |  |  |  |  |  |  | 'Error creating {path}: {error}', | 
| 308 |  |  |  |  |  |  | path  => $path, | 
| 309 |  |  |  |  |  |  | error => $msg, | 
| 310 | 149 |  |  |  |  | 1284 | ) if $path; | 
| 311 |  |  |  |  |  |  | hurl $self->command => $msg; | 
| 312 |  |  |  |  |  |  | } | 
| 313 |  |  |  |  |  |  |  | 
| 314 | 162 |  |  | 162 |  | 89784 | 1; | 
| 315 | 162 | 100 |  |  |  | 7623 |  | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | =head1 Name | 
| 318 | 162 | 100 |  |  |  | 35505 |  | 
|  | 162 |  |  |  |  | 595 |  | 
| 319 |  |  |  |  |  |  | App::Sqitch::Command - Sqitch Command support | 
| 320 | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 6 |  | 
| 321 | 2 | 100 |  |  |  | 9 | =head1 Synopsis | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | my $cmd = App::Sqitch::Command->load( deploy => \%params ); | 
| 324 |  |  |  |  |  |  | $cmd->run; | 
| 325 |  |  |  |  |  |  |  | 
| 326 | 1 |  |  |  |  | 5 | =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 |