File Coverage

blib/lib/App/Sqitch/Command/engine.pm
Criterion Covered Total %
statement 145 145 100.0
branch 30 34 88.2
condition 8 13 61.5
subroutine 28 28 100.0
pod 3 3 100.0
total 214 223 95.9


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