File Coverage

blib/lib/App/Sqitch/Command/target.pm
Criterion Covered Total %
statement 143 143 100.0
branch 30 32 93.7
condition 10 10 100.0
subroutine 28 28 100.0
pod 8 8 100.0
total 219 221 99.1


line stmt bran cond sub pod time code
1              
2             use 5.010;
3 2     2   1040 use strict;
  2         7  
4 2     2   16 use warnings;
  2         9  
  2         65  
5 2     2   17 use utf8;
  2         7  
  2         121  
6 2     2   14 use Moo;
  2         6  
  2         37  
7 2     2   55 use Types::Standard qw(Str Int HashRef);
  2         6  
  2         19  
8 2     2   959 use Locale::TextDomain qw(App-Sqitch);
  2         5  
  2         48  
9 2     2   2588 use App::Sqitch::X qw(hurl);
  2         5  
  2         37  
10 2     2   629 use URI::db;
  2         5  
  2         25  
11 2     2   1309 use Try::Tiny;
  2         15186  
  2         67  
12 2     2   12 use Path::Class qw(file dir);
  2         4  
  2         157  
13 2     2   12 use List::Util qw(max);
  2         8  
  2         144  
14 2     2   11 use namespace::autoclean;
  2         5  
  2         170  
15 2     2   12 use constant extra_target_keys => qw(uri);
  2         5  
  2         141  
16 2     2   207  
  2         6  
  2         3867  
17             extends 'App::Sqitch::Command';
18             with 'App::Sqitch::Role::TargetConfigCommand';
19              
20             our $VERSION = 'v1.3.0'; # VERSION
21              
22             # No config; target config is actually targets.
23             return {};
24             }
25              
26             my ( $self, $action ) = (shift, shift);
27             $action ||= 'list';
28             $action =~ s/-/_/g;
29 15     15 1 14497 my $meth = $self->can($action) or $self->usage(__x(
30 15   100     51 'Unknown action "{action}"',
31 15         30 action => $action,
32 15 100       79 ));
33             return $self->$meth(@_);
34             }
35              
36 14         40 my $self = shift;
37             my $sqitch = $self->sqitch;
38             my %targets = $sqitch->config->get_regexp(key => qr/^target[.][^.]+[.]uri$/);
39              
40 3     3 1 3147 # Make it verbose if --verbose was passed at all.
41 3         23 my $format = $sqitch->options->{verbosity} ? "%1\$s\t%2\$s" : '%1$s';
42 3         93 for my $key (sort keys %targets) {
43             my ($target) = $key =~ /target[.]([^.]+)/;
44             $sqitch->emit(sprintf $format, $target, $targets{$key});
45 3 100       901 }
46 3         23  
47 12         125 return $self;
48 12         86 }
49              
50             my ($self, $name, $uri) = @_;
51 3         43 $self->usage unless $name && $uri;
52              
53             my $key = "target.$name";
54             my $config = $self->sqitch->config;
55 8     8 1 13686  
56 8 100 100     107 hurl target => __x(
57             'Target "{target}" already exists',
58 6         24 target => $name
59 6         222 ) if $config->get( key => "$key.uri");
60              
61 6 100       135 # Put together the URI and other config variables.
62             my $vars = $self->config_params($key);
63             unshift @{ $vars } => {
64             key => "$key.uri",
65             value => URI::db->new($uri, 'db:')->as_string,
66             };
67 5         690  
68 5         13 # Make it so.
  5         88  
69             $config->group_set( $config->local_file, $vars );
70             my $target = $self->config_target(name => $name);
71             $self->write_plan(target => $target);
72             $self->make_directories_for( $target );
73             return $self;
74 5         1716 }
75 5         42888  
76 5         1262 my ($self, $target) = @_;
77 5         52 $self->usage unless $target;
78 5         114  
79             my $key = "target.$target";
80             my $config = $self->sqitch->config;
81             my $props = $self->properties;
82 5     5 1 8811  
83 5 100       39 hurl target => __x(
84             'Missing Target "{target}"; use "{command}" to add it',
85 4         10 target => $target,
86 4         129 command => "add $target " . ($props->{uri} || '$uri'),
87 4         68 ) unless $config->get( key => "target.$target.uri");
88              
89             # Make it so.
90             $config->group_set( $config->local_file, $self->config_params($key) );
91             $self->make_directories_for( $self->config_target(name => $target) );
92 4 100 100     36 }
93              
94             my ($self, $name) = @_;
95             $self->usage unless $name;
96 2         307 if ( my @deps = $self->_dependencies($name) ) {
97 2         39382 hurl target => __x(
98             q{Cannot rename target "{target}" because it's referenced by: {engines}},
99             target => $name,
100 2     2 1 7 engines => join ', ', @deps
101             );
102 5     5 1 6473 }
103 5 100       38 $self->_rename($name);
104 4 100       32 }
105 1         22  
106             my ($self, $old, $new) = @_;
107             $self->usage unless $old && $new;
108             if ( my @deps = $self->_dependencies($old) ) {
109             hurl target => __x(
110             q{Cannot rename target "{target}" because it's referenced by: {engines}},
111 3         20 target => $old,
112             engines => join ', ', @deps
113             );
114             }
115 6     6 1 51406 $self->_rename($old, $new);
116 6 100 100     62 }
117 4 100       31  
118 1         30 my ($self, $name) = @_;
119             my %depends = $self->sqitch->config->get_regexp(
120             key => qr/^(?:core|engine[.][^.]+)[.]target$/
121             );
122             return grep { $depends{$_} eq $name } sort keys %depends;
123             }
124 3         24  
125             my ($self, $old, $new) = @_;
126             my $config = $self->sqitch->config;
127              
128 8     8   26 try {
129 8         252 $config->rename_section(
130             from => "target.$old",
131             ($new ? (to => "target.$new") : ()),
132 8         1696 filename => $config->local_file,
  12         79  
133             );
134             } catch {
135             die $_ unless /No such section/;
136 6     6   19 hurl target => __x(
137 6         359 'Unknown target "{target}"',
138             target => $old,
139             );
140 6 100   6   620 };
141             try {
142             $config->rename_section(
143             from => "target.$old.variables",
144             ($new ? (to => "target.$new.variables") : ()),
145             filename => $config->local_file,
146 2 50   2   6363 );
147 2         38 } catch {
148             die $_ unless /No such section/;
149             };
150             return $self;
151 6         189 }
152              
153 4 100   4   213 my ($self, @names) = @_;
154             return $self->list unless @names;
155             my $sqitch = $self->sqitch;
156             my $config = $sqitch->config;
157              
158             my %label_for = (
159 2 50   2   6201 uri => __('URI'),
160 4         15785 registry => __('Registry'),
161 4         6813 client => __('Client'),
162             top_dir => __('Top Directory'),
163             plan_file => __('Plan File'),
164             extension => __('Extension'),
165 6     6 1 21123 revert => ' ' . __ 'Revert',
166 6 100       43 deploy => ' ' . __ 'Deploy',
167 5         27 verify => ' ' . __ 'Verify',
168 5         129 reworked => ' ' . __ 'Reworked',
169             );
170 5         58  
171             my $len = max map { length } values %label_for;
172             $_ .= ': ' . ' ' x ($len - length $_) for values %label_for;
173              
174             # Header labels.
175             $label_for{script_dirs} = __('Script Directories') . ':';
176             $label_for{reworked_dirs} = __('Reworked Script Directories') . ':';
177             $label_for{variables} = __('Variables') . ':';
178             $label_for{no_variables} = __('No Variables');
179              
180             require App::Sqitch::Target;
181             for my $name (@names) {
182             my $target = App::Sqitch::Target->new(
183 5         1244 $self->target_params,
  50         119  
184 5         61 name => $name,
185             );
186             $self->emit("* $name");
187 5         25 $self->emit(' ', $label_for{uri}, $target->uri->as_string);
188 5         160 $self->emit(' ', $label_for{registry}, $target->registry);
189 5         144 $self->emit(' ', $label_for{client}, $target->client);
190 5         144 $self->emit(' ', $label_for{top_dir}, $target->top_dir);
191             $self->emit(' ', $label_for{plan_file}, $target->plan_file);
192 5         143 $self->emit(' ', $label_for{extension}, $target->extension);
193 5         18 $self->emit(' ', $label_for{script_dirs});
194 7         136 $self->emit(' ', $label_for{deploy}, $target->deploy_dir);
195             $self->emit(' ', $label_for{revert}, $target->revert_dir);
196             $self->emit(' ', $label_for{verify}, $target->verify_dir);
197             $self->emit(' ', $label_for{reworked_dirs});
198 7         778 $self->emit(' ', $label_for{reworked}, $target->reworked_dir);
199 7         244 $self->emit(' ', $label_for{deploy}, $target->reworked_deploy_dir);
200 7         429 $self->emit(' ', $label_for{revert}, $target->reworked_revert_dir);
201 7         1175 $self->emit(' ', $label_for{verify}, $target->reworked_verify_dir);
202 7         959 my $vars = $target->variables;
203 7         2394 if (%{ $vars }) {
204 7         1800 my $len = max map { length } keys %{ $vars };
205 7         1869 $self->emit(' ', $label_for{variables});
206 7         258 $self->emit(" $_: " . (' ' x ($len - length $_)) . $vars->{$_})
207 7         1488 for sort { lc $a cmp lc $b } keys %{ $vars };
208 7         1270 } else {
209 7         1211 $self->emit(' ', $label_for{no_variables});
210 7         250 }
211 7         710 }
212 7         1221  
213 7         1297 return $self;
214 7         1277 }
215 7 100       176  
  7         16  
216 1         2 1;
  3         8  
  1         4  
217 1         37  
218              
219 1         31 =head1 Name
  3         33  
  1         19  
220              
221 6         97 App::Sqitch::Command::target - Add, modify, or list Sqitch target databases
222              
223             =head1 Synopsis
224              
225 5         388 my $cmd = App::Sqitch::Command::target->new(%params);
226             $cmd->execute;
227              
228             =head1 Description
229              
230             Manages Sqitch targets, which are stored in the local configuration file.
231              
232             =head1 Interface
233              
234             =head3 Class Methods
235              
236             =head3 C<extra_target_keys>
237              
238             Returns a list of additional option keys to be specified via options.
239              
240             =head2 Instance Methods
241              
242             =head2 Attributes
243              
244             =head3 C<properties>
245              
246             Hash of property values to set.
247              
248             =head3 C<verbose>
249              
250             Verbosity.
251              
252             =head3 C<execute>
253              
254             $target->execute($command);
255              
256             Executes the C<target> command.
257              
258             =head3 C<add>
259              
260             Implements the C<add> action.
261              
262             =head3 C<alter>
263              
264             Implements the C<alter> action.
265              
266             =head3 C<list>
267              
268             Implements the C<list> action.
269              
270             =head3 C<remove>
271              
272             =head3 C<rm>
273              
274             Implements the C<remove> action.
275              
276             =head3 C<rename>
277              
278             Implements the C<rename> action.
279              
280             =head3 C<show>
281              
282             Implements the C<show> action.
283              
284             =head1 See Also
285              
286             =over
287              
288             =item L<sqitch-target>
289              
290             Documentation for the C<target> command to the Sqitch command-line client.
291              
292             =item L<sqitch>
293              
294             The Sqitch command-line client.
295              
296             =back
297              
298             =head1 Author
299              
300             David E. Wheeler <david@justatheory.com>
301              
302             =head1 License
303              
304             Copyright (c) 2012-2022 iovation Inc., David E. Wheeler
305              
306             Permission is hereby granted, free of charge, to any person obtaining a copy
307             of this software and associated documentation files (the "Software"), to deal
308             in the Software without restriction, including without limitation the rights
309             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
310             copies of the Software, and to permit persons to whom the Software is
311             furnished to do so, subject to the following conditions:
312              
313             The above copyright notice and this permission notice shall be included in all
314             copies or substantial portions of the Software.
315              
316             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
317             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
318             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
319             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
320             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
321             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
322             SOFTWARE.
323              
324             =cut