File Coverage

lib/Dist/Zilla/Util/Git/Tags.pm
Criterion Covered Total %
statement 8 10 80.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 12 14 85.7


line stmt bran cond sub pod time code
1 1     1   6629 use strict;
  1         2  
  1         37  
2 1     1   5 use warnings;
  1         1  
  1         65  
3              
4             package Dist::Zilla::Util::Git::Tags;
5             BEGIN {
6 1     1   27 $Dist::Zilla::Util::Git::Tags::AUTHORITY = 'cpan:KENTNL';
7             }
8             {
9             $Dist::Zilla::Util::Git::Tags::VERSION = '0.004000';
10             }
11              
12             # ABSTRACT: Extract all tags from a repository
13              
14 1     1   2076 use Moose;
  0            
  0            
15             with 'Dist::Zilla::UtilRole::MaybeGit';
16              
17              
18              
19             has 'refs' => ( isa => Object =>, is => ro =>, lazy_build => 1 );
20              
21             sub _build_refs {
22             my ($self) = @_;
23             require Dist::Zilla::Util::Git::Refs;
24             return Dist::Zilla::Util::Git::Refs->new( git => $self->git );
25             }
26              
27             sub _to_tag {
28             my ( $self, $ref ) = @_;
29             require Dist::Zilla::Util::Git::Tags::Tag;
30             return Dist::Zilla::Util::Git::Tags::Tag->new_from_Ref($ref);
31             }
32              
33             sub _to_tags {
34             my ( $self, @refs ) = @_;
35             return map { $self->_to_tag($_) } @refs;
36             }
37              
38             # There's 2 types of results that come back from git ls-remote
39             #
40             # tags, and heavy tags ( usually annotations )
41             #
42             # puretags look like
43             #
44             # abffab foo # pointer to the commit
45             #
46             # While heavy tags come in pairs
47             #
48             # fabfab foo # heavy tag pointer
49             # abffab foo^{} # pointer to the actual commit
50             #
51             # However, we don't really care about the second half of the latter kind.
52             #
53             sub _grep_commit_pointers {
54             my ( $self, @refs ) = @_;
55             my (@out);
56             for my $ref (@refs) {
57             next if $ref->name =~ /[^][{][}]\z/msx;
58             push @out, $ref;
59             }
60             return @out;
61             }
62              
63              
64             sub tags {
65             my ($self) = @_;
66             return $self->get_tag(q[**]);
67             }
68              
69              
70             sub get_tag {
71             my ( $self, $name ) = @_;
72             return $self->_to_tags( $self->_grep_commit_pointers( $self->refs->get_ref( 'refs/tags/' . $name ) ) );
73             }
74              
75              
76             sub tag_sha1_map {
77             my ($self) = @_;
78              
79             my %hash;
80             for my $tag ( $self->tags ) {
81             my $sha1 = $tag->sha1;
82             if ( not exists $hash{$sha1} ) {
83             $hash{$sha1} = [];
84             }
85             push @{ $hash{$sha1} }, $tag;
86             }
87             return \%hash;
88             }
89              
90              
91             sub tags_for_rev {
92             my ( $self, $rev ) = @_;
93             my (@shas) = $self->git->rev_parse($rev);
94             if ( scalar @shas != 1 ) {
95             require Carp;
96             Carp::croak("Could not resolve a SHA1 from rev $rev");
97             }
98             my ($sha) = shift @shas;
99             my $map = $self->tag_sha1_map;
100             return unless exists $map->{$sha};
101             return @{ $map->{$sha} };
102             }
103              
104             __PACKAGE__->meta->make_immutable;
105             no Moose;
106              
107             1;
108              
109             __END__
110              
111             =pod
112              
113             =encoding UTF-8
114              
115             =head1 NAME
116              
117             Dist::Zilla::Util::Git::Tags - Extract all tags from a repository
118              
119             =head1 VERSION
120              
121             version 0.004000
122              
123             =head1 SYNOPSIS
124              
125             This tool basically gives a more useful interface around
126              
127             git tag
128              
129             Namely, each tag returned is a tag object, and you can view tag properties with it.
130              
131             use Dist::Zilla::Util::Git::Tags;
132              
133             my $tags_finder = Dist::Zilla::Util::Git::Tags->new(
134             zilla => $self->zilla
135             );
136              
137             for my $tag ( $tags_finder->tags ) {
138             printf "%s - %s\n", $tag->name, $tag->sha1;
139             }
140              
141             =head1 METHODS
142              
143             =head2 C<tags>
144              
145             A C<List> of L<< C<::Tags::Tag> objects|Dist::Zilla::Util::Git::Tags::Tag >>
146              
147             my @tags = $tag_finder->tags();
148              
149             =head2 C<get_tag>
150              
151             my ($first_matching) = $tags->get_tag('1.000');
152             my (@all_matching) = $tags->get_tag('1.*');
153              
154             Note: This can easily return multiple values.
155              
156             For instance, C<tags> is implemented as
157              
158             my ( @tags ) = $branches->get_tag('*');
159              
160             Mostly, because the underlying mechanism is implemented in terms of L<< C<fnmatch(3)>|fnmatch(3) >>
161              
162             If the tag does not exist, or no tag match the expression, C<< get_tag >> will return an empty list.
163              
164             So in the top example, C<match> is C<undef> if C<1.000> does not exist.
165              
166             =head2 C<tag_sha1_map>
167              
168             A C<HashRef> of C<< sha1 => [ L<< tag|Dist::Zilla::Util::Git::Tags::Tag >>, L<< tag|Dist::Zilla::Util::Git::Tags::Tag >> ] >> entries.
169              
170             my $hash = $tag_finder->tag_sha1_map();
171              
172             =head2 C<tags_for_rev>
173              
174             A C<List> of L<< C<::Tags::Tag> objects|Dist::Zilla::Util::Git::Tags::Tag >> that point to the given C<SHA1>.
175              
176             $tag_finder->tags_for_rev( $sha1_or_commitish_etc );
177              
178             =head1 ATTRIBUTES
179              
180             =head2 C<refs>
181              
182             A Dist::Zilla::Util::Git::Refs instance, auto-built if not specified.
183              
184             =head1 AUTHOR
185              
186             Kent Fredric <kentfredric@gmail.com>
187              
188             =head1 COPYRIGHT AND LICENSE
189              
190             This software is copyright (c) 2013 by Kent Fredric <kentfredric@gmail.com>.
191              
192             This is free software; you can redistribute it and/or modify it under
193             the same terms as the Perl 5 programming language system itself.
194              
195             =cut