File Coverage

blib/lib/App/Sqitch/Command/tag.pm
Criterion Covered Total %
statement 62 62 100.0
branch 8 10 80.0
condition n/a
subroutine 12 12 100.0
pod 1 1 100.0
total 83 85 97.6


line stmt bran cond sub pod time code
1             package App::Sqitch::Command::tag;
2              
3 3     3   992 use 5.010;
  3         12  
4 3     3   18 use strict;
  3         7  
  3         72  
5 3     3   16 use warnings;
  3         8  
  3         112  
6 3     3   18 use utf8;
  3         7  
  3         27  
7 3     3   88 use Moo;
  3         4  
  3         21  
8 3     3   1561 use App::Sqitch::X qw(hurl);
  3         8  
  3         28  
9 3     3   934 use Types::Standard qw(Str ArrayRef Maybe Bool);
  3         18  
  3         37  
10 3     3   3485 use Locale::TextDomain qw(App-Sqitch);
  3         8  
  3         42  
11 3     3   593 use List::Util qw(first);
  3         18  
  3         176  
12 3     3   20 use namespace::autoclean;
  3         6  
  3         21  
13              
14             extends 'App::Sqitch::Command';
15             with 'App::Sqitch::Role::ContextCommand';
16              
17             our $VERSION = 'v1.4.0'; # VERSION
18              
19             has tag_name => (
20             is => 'ro',
21             isa => Maybe[Str],
22             );
23              
24             has change_name => (
25             is => 'ro',
26             isa => Maybe[Str],
27             );
28              
29             has all => (
30             is => 'ro',
31             isa => Bool,
32             default => 0
33             );
34              
35             has note => (
36             is => 'ro',
37             isa => ArrayRef[Str],
38             default => sub { [] },
39             );
40              
41             sub options {
42             return qw(
43             tag-name|tag|t=s
44             change-name|change|c=s
45             all|a!
46             note|n|m=s@
47             );
48             }
49              
50             sub configure {
51             my ( $class, $config, $opt ) = @_;
52             # Just keep options.
53             return $opt;
54             }
55              
56             sub execute {
57 12     12 1 8169 my $self = shift;
58 12         95 my ($name, $change, $targets) = $self->parse_args(
59             names => [$self->tag_name, $self->change_name],
60             all => $self->all,
61             args => \@_,
62             no_changes => 1,
63             );
64              
65 11 100       198 if (defined $name) {
66 8         13 my $note = join "\n\n" => @{ $self->note };
  8         31  
67 8         17 my (%seen, @plans, @tags);
68 8         12 for my $target (@{ $targets }) {
  8         16  
69 11 100       374 next if $seen{$target->plan_file}++;
70 9         3698 my $plan = $target->plan;
71 9         1263 push @tags => $plan->tag(
72             name => $name,
73             change => $change,
74             note => $note,
75             );
76 9         19 push @plans => $plan;
77             }
78              
79             # Make sure we have a note.
80 8         186 $note = $tags[0]->request_note(for => __ 'tag');
81              
82             # We good, write the plan files back out.
83 8         78 for my $plan (@plans) {
84 9         251 my $tag = shift @tags;
85 9         167 $tag->note($note);
86 9         179 $plan->write_to( $plan->file );
87 9         65 $self->info(__x(
88             'Tagged "{change}" with {tag} in {file}',
89             change => $tag->change->format_name,
90             tag => $tag->format_name,
91             file => $plan->file,
92             ));
93             }
94             } else {
95             # Check for missing name.
96 3 100       13 if (@_) {
97 1 50   1   9 if (my $target = first { my $n = $_->name; first { $_ eq $n } @_ } @{ $targets }) {
  1         5  
  1         12  
  1         7  
  1         8  
98             # Name conflicts with a target.
99 1         7 hurl tag => __x(
100             'Name "{name}" identifies a target; use "--tag {name}" to use it for the tag name',
101             name => $target->name,
102             );
103             }
104             }
105              
106             # Show unique tags.
107 2         3 my %seen;
108 2         4 for my $target (@{ $targets }) {
  2         8  
109 2         42 my $plan = $target->plan;
110 2         342 for my $tag ($plan->tags) {
111 3         57 my $name = $tag->format_name;
112 3 50       61 $self->info($name) unless $seen{$name}++;
113             }
114             }
115             }
116              
117 10         1894 return $self;
118             }
119              
120             1;
121              
122             __END__
123              
124             =head1 Name
125              
126             App::Sqitch::Command::tag - Add or list tags in Sqitch plans
127              
128             =head1 Synopsis
129              
130             my $cmd = App::Sqitch::Command::tag->new(%params);
131             $cmd->execute;
132              
133             =head1 Description
134              
135             Tags a Sqitch change. The tag will be added to the last change in the plan.
136              
137             =head1 Interface
138              
139             =head2 Attributes
140              
141             =head3 C<tag_name>
142              
143             The name of the tag to add.
144              
145             =head3 C<change_name>
146              
147             The name of the change to tag.
148              
149             =head3 C<all>
150              
151             Boolean indicating whether or not to run the command against all plans in the
152             project.
153              
154             =head3 C<note>
155              
156             Text of the tag note.
157              
158             =head2 Instance Methods
159              
160             =head3 C<execute>
161              
162             $tag->execute($command);
163              
164             Executes the C<tag> command.
165              
166             =head1 See Also
167              
168             =over
169              
170             =item L<sqitch-tag>
171              
172             Documentation for the C<tag> command to the Sqitch command-line client.
173              
174             =item L<sqitch>
175              
176             The Sqitch command-line client.
177              
178             =back
179              
180             =head1 Author
181              
182             David E. Wheeler <david@justatheory.com>
183              
184             =head1 License
185              
186             Copyright (c) 2012-2023 iovation Inc., David E. Wheeler
187              
188             Permission is hereby granted, free of charge, to any person obtaining a copy
189             of this software and associated documentation files (the "Software"), to deal
190             in the Software without restriction, including without limitation the rights
191             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
192             copies of the Software, and to permit persons to whom the Software is
193             furnished to do so, subject to the following conditions:
194              
195             The above copyright notice and this permission notice shall be included in all
196             copies or substantial portions of the Software.
197              
198             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
199             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
200             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
202             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
203             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
204             SOFTWARE.
205              
206             =cut