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   1072 use strict;
  2         7  
4 2     2   13 use warnings;
  2         8  
  2         63  
5 2     2   14 use utf8;
  2         8  
  2         75  
6 2     2   10 use Moo;
  2         4  
  2         34  
7 2     2   109 use Types::Standard qw(Str Int HashRef);
  2         4  
  2         23  
8 2     2   1018 use Locale::TextDomain qw(App-Sqitch);
  2         6  
  2         60  
9 2     2   2276 use App::Sqitch::X qw(hurl);
  2         4  
  2         36  
10 2     2   618 use Try::Tiny;
  2         9  
  2         36  
11 2     2   790 use URI::db;
  2         8  
  2         171  
12 2     2   538 use Path::Class qw(file dir);
  2         15252  
  2         80  
13 2     2   14 use List::Util qw(max first);
  2         5  
  2         169  
14 2     2   13 use namespace::autoclean;
  2         4  
  2         214  
15 2     2   15 use constant extra_target_keys => qw(target);
  2         5  
  2         142  
16 2     2   238  
  2         4  
  2         3977  
17             extends 'App::Sqitch::Command';
18             with 'App::Sqitch::Role::TargetConfigCommand';
19              
20             our $VERSION = 'v1.3.0'; # VERSION
21              
22             my $engine = shift;
23             hurl engine => __x(
24 11     11   27 'Unknown engine "{engine}"', engine => $engine
25             ) unless first { $engine eq $_ } App::Sqitch::Command::ENGINES;
26             }
27 11 100   47   170  
  47         110  
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 20481 'Unknown action "{action}"',
37 21   100     71 action => $action,
38 21         57 ));
39 21 100       105  
40             return $self->$meth(@_);
41             }
42              
43             my $self = shift;
44 20         56 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   3034 # Make it verbose if --verbose was passed at all.
49 3         23 my $format = $sqitch->options->{verbosity} ? "%1\$s\t%2\$s" : '%1$s';
50 3         19 for my $key (sort keys %engines) {
51 3         103 my ($engine) = $key =~ /engine[.]([^.]+)/;
52             $sqitch->emit(sprintf $format, $engine, $engines{$key})
53             }
54 3 100       931  
55 3         24 return $self;
56 10         98 }
57 10         69  
58             my ($self, $engine, $name) = @_;
59             my $target = $self->properties->{target} || $name || return;
60 3         34  
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   3857 hurl engine => __x(
65 10   100     82 'Cannot assign URI using engine "{new}" to engine "{old}"',
66             new => $uri->canonical_engine,
67 8 100       72 old => $engine,
68             ) if $uri->canonical_engine ne $engine;
69 7         81 return $uri->as_string;
70 7 100       5368 }
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         301 'Unknown target "{target}"',
76             target => $target
77             );
78             }
79 1 50       30  
80 1         199 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   11614 hurl engine => __x(
88 6 100       22 'Engine "{engine}" already exists',
89 5         31 engine => $engine
90             ) if $config->get( key => "$key.target");
91 5         32  
92 5         158 # Set up the target and other config variables.
93             my $vars = $self->config_params($key);
94 5 100       81 unshift @{ $vars } => {
95             key => "$key.target",
96             value => $self->_target($engine, $target) || "db:$engine:",
97             };
98              
99             # Make it so.
100 4         507 $config->group_set( $config->local_file, $vars );
101 4   66     7 $target = $self->config_target(
  4         24  
102             name => $target,
103             engine => $engine,
104             );
105             $self->write_plan(target => $target);
106             $self->make_directories_for($target);
107 3         199 }
108 3         32671  
109             my ($self, $engine) = @_;
110             $self->usage unless $engine;
111             _chk_engine $engine;
112 3         669  
113 3         17 my $key = "engine.$engine";
114             my $config = $self->sqitch->config;
115             my $props = $self->properties;
116              
117 7     7 1 26744 hurl engine => __x(
118 7 100       31 'Missing Engine "{engine}"; use "{command}" to add it',
119 6         38 engine => $engine,
120             command => "add $engine " . ($props->{target} || "db:$engine:"),
121 5         33 ) unless $config->get( key => "engine.$engine.target");
122 5         180  
123 5         63 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     44  
129             # Make it so.
130             $config->group_set( $config->local_file, $self->config_params($key) );
131 3 100       452 $self->make_directories_for( $self->config_target( engine => $engine) );
132 2 50       24 }
133              
134             my ($self, $engine) = @_;
135             $self->usage unless $engine;
136              
137             my $config = $self->sqitch->config;
138 2         236 try {
139 2         32889 $config->rename_section(
140             from => "engine.$engine",
141             filename => $config->local_file,
142 2     2 1 6 );
143             } catch {
144 4     4   5549 die $_ unless /No such section/;
145 4 100       27 hurl engine => __x(
146             'Unknown engine "{engine}"',
147 3         95 engine => $engine,
148             );
149 3     3   304 };
150             try {
151             $config->rename_section(
152             from => "engine.$engine.variables",
153             filename => $config->local_file,
154 1 50   1   2708 );
155 1         11 } catch {
156             die $_ unless /No such section/;
157             };
158             return $self;
159 3         94 }
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   2249 # Set up labels.
167 2         6240 my %label_for = (
168 2         2808 target => __ 'Target',
169             registry => __ 'Registry',
170             client => __ 'Client',
171             top_dir => __ 'Top Directory',
172 3     3   6075 plan_file => __ 'Plan File',
173 3 100       57 extension => __ 'Extension',
174 2         25 revert => ' ' . __ 'Revert',
175 2         49 deploy => ' ' . __ 'Deploy',
176             verify => ' ' . __ 'Verify',
177             reworked => ' ' . __ 'Reworked',
178 2         23 );
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         556 my $target = App::Sqitch::Target->new(
  20         56  
192 2         34 $self->target_params,
193             name => $config->get(key => "engine.$engine.target") || "db:$engine",
194             );
195 2         18  
196 2         70 $self->emit("* $engine");
197 2         61 $self->emit(' ', $label_for{target}, $target->target);
198 2         57 $self->emit(' ', $label_for{registry}, $target->registry);
199             $self->emit(' ', $label_for{client}, $target->client);
200 2         68 $self->emit(' ', $label_for{top_dir}, $target->top_dir);
201 2         14 $self->emit(' ', $label_for{plan_file}, $target->plan_file);
202 4   33     123 $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         475 $self->emit(' ', $label_for{reworked_dirs});
208 4         149 $self->emit(' ', $label_for{reworked}, $target->reworked_dir);
209 4         174 $self->emit(' ', $label_for{deploy}, $target->reworked_deploy_dir);
210 4         459 $self->emit(' ', $label_for{revert}, $target->reworked_revert_dir);
211 4         941 $self->emit(' ', $label_for{verify}, $target->reworked_verify_dir);
212 4         1368 my $vars = $target->variables;
213 4         688 if (%{ $vars }) {
214 4         1019 my $len = max map { length } keys %{ $vars };
215 4         153 $self->emit(' ', $label_for{variables});
216 4         884 $self->emit(" $_: " . (' ' x ($len - length $_)) . $vars->{$_})
217 4         718 for sort { lc $a cmp lc $b } keys %{ $vars };
218 4         667 } else {
219 4         170 $self->emit(' ', $label_for{no_variables});
220 4         382 }
221 4         700 }
222 4         724  
223 4         726 return $self;
224 4 100       114 }
  4         9  
225 1         3  
  3         11  
  1         3  
226 1         17 1;
227              
228 1         31  
  3         35  
  1         17  
229             =head1 Name
230 3         47  
231             App::Sqitch::Command::engine - Add, modify, or list Sqitch database engines
232              
233             =head1 Synopsis
234 2         180  
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