File Coverage

blib/lib/App/Git/Workflow/Pom.pm
Criterion Covered Total %
statement 98 110 89.0
branch 21 36 58.3
condition 24 43 55.8
subroutine 16 16 100.0
pod 4 4 100.0
total 163 209 77.9


line stmt bran cond sub pod time code
1             package App::Git::Workflow::Pom;
2              
3             # Created on: 2014-08-06 19:04:05
4             # Create by: Ivan Wills
5             # $Id$
6             # $Revision$, $HeadURL$, $Date$
7             # $Revision$, $Source$, $Date$
8              
9 6     6   117396 use strict;
  6         15  
  6         187  
10 6     6   32 use warnings;
  6         12  
  6         144  
11 6     6   914 use version;
  6         4088  
  6         31  
12 6     6   432 use Carp qw/carp croak cluck confess longmess/;
  6         14  
  6         417  
13 6     6   2306 use Data::Dumper qw/Dumper/;
  6         25374  
  6         378  
14 6     6   1139 use English qw/ -no_match_vars /;
  6         5557  
  6         36  
15 6     6   4749 use XML::Tiny;
  6         9433  
  6         299  
16 6     6   2138 use App::Git::Workflow::Repository qw//;
  6         17  
  6         144  
17 6     6   2335 use App::Git::Workflow;
  6         19  
  6         306  
18 6     6   48 use base qw/App::Git::Workflow/;
  6         13  
  6         6950  
19              
20             our $VERSION = version->new(1.1.16);
21              
22             sub new {
23 20     20 1 56 my $class = shift;
24 20         111 my $self = App::Git::Workflow->new(@_);
25 20         46 bless $self, $class;
26              
27 20         48 return $self;
28             }
29              
30             sub _alphanum_sort {
31 2     2   5 my $A = $a;
32 2         15 $A =~ s/(\d+)/sprintf "%014i", $1/egxms;
  6         33  
33 2         5 my $B = $b;
34 2         7 $B =~ s/(\d+)/sprintf "%014i", $1/egxms;
  6         22  
35              
36 2         11 return $A cmp $B;
37             }
38              
39             sub _max_age {
40 4     4   10 my ($self) = @_;
41             return $self->{MAX_AGE} ||= 60 * 60 * 24 * (
42             $ENV{GIT_WORKFLOW_MAX_AGE}
43 4   50     38 || $self->git->config('workflow.max-age')
      33        
44             || 120
45             );
46             }
47              
48             sub get_pom_versions {
49 4     4 1 17 my ($self, $pom, $match, $skip) = @_;
50 4         44 my @branches = $self->branches('both');
51 4         21 my $settings = $self->settings();
52 4         8 my %versions;
53 4         5 my $count = 0;
54 4         16 my $max_age = $self->_max_age;
55 4 50 33     19 my $run = !$settings->{max_age} || $settings->{max_age} == $max_age ? 0 : 1;
56              
57 4   66     18 while (!%versions && $run < 10) {
58             BRANCH:
59 4         24 for my $branch (sort @branches) {
60 11   100     588 $settings->{pom_versions}{$branch} ||= {};
61 11         21 my $saved = $settings->{pom_versions}{$branch};
62              
63             # skip branches marked as OLD
64 11 50 33     39 next BRANCH if !$run && $saved->{old};
65 11 50 33     24 next BRANCH if $match && $branch !~ /$match/;
66 11 50 33     23 next BRANCH if $skip && $skip =~ /$skip/;
67              
68 11 100       15 my $current = eval { $self->commit_details($branch) } or next;
  11         48  
69              
70             # Skip any branches that are over $MAX_AGE old
71 8 50       54 if ( $current->{time} < time - $max_age ) {
72 0         0 $saved->{old} = 1;
73 0 0       0 $self->save_settings() if $count++ % 20 == 0;
74 0         0 next BRANCH;
75             }
76              
77 8         16 delete $saved->{old};
78              
79             # used saved version if it exists.
80 8 100 66     74 if ( $saved && $saved->{time} && $saved->{time} == $current->{time} ) {
      66        
81 2         9 $versions{$saved->{numerical}}{$branch} = $saved->{version};
82 2         9 next BRANCH;
83             }
84              
85 6         10 my $xml = eval { $self->git->show("$branch:$pom"); };
  6         16  
86              
87 6 50       15 next BRANCH if !$xml;
88 6         13 chomp $xml;
89 6 50       13 next BRANCH if !$xml;
90              
91 6         25 $branch =~ s{^origin/}{}xms;
92              
93 6         10 my $numerical = my $version = eval { $self->pom_version($xml, $pom) };
  6         18  
94              
95             # make sure we get a valid version
96 6 50 33     42 if ( $@ || !defined $numerical ) {
97 0         0 next BRANCH;
98             }
99              
100             # remove snapshots from the end
101 6         26 $numerical =~ s/-SNAPSHOT$//xms;
102             # remove any extranious text from the front
103 6         15 $numerical =~ s/^\D+//xms;
104              
105 6         18 $versions{$numerical}{$branch} = $version;
106             $settings->{pom_versions}{$branch} = {
107             numerical => $numerical,
108             version => $version,
109             time => $current->{time},
110 6         26 };
111 6 100       36 $self->save_settings() if $count++ % 50 == 0;
112             }
113 4         704 $run++;
114             }
115              
116 4         20 $self->save_settings();
117              
118 4         68 return \%versions;
119             }
120              
121             sub pom_version {
122 12     12 1 1362 my ($self, $xml, $pom) = @_;
123              
124 12 50 66     54 if ( $pom && $pom =~ /[.]json$/ ) {
125 0         0 require JSON;
126 0         0 my $json = eval { JSON::decode_json($xml) }
127 0 0       0 or do { warn "Could not read $xml as json : $@\n"; };
  0         0  
128 0         0 return $json->{version};
129             }
130 12 50 66     42 if ( $pom && $pom =~ /[.]ya?ml$/ ) {
131 0         0 require YAML;
132 0         0 my $json = YAML::Load($xml);
133 0         0 return $json->{version};
134             }
135              
136 12 100 100     182 my $doc = XML::Tiny::parsefile( $xml !~ /\n/ && -f $xml ? $xml : '_TINY_XML_STRING_' . $xml);
137              
138 12         7732 for my $elem (@{ $doc->[0]{content} }) {
  12         33  
139 20 100       84 next if $elem->{name} ne 'version';
140              
141 11         72 return $elem->{content}[0]{content};
142             }
143              
144 1         13 return;
145             }
146              
147             sub next_pom_version {
148 3     3 1 10 my ($self, $pom, $versions) = @_;
149 3   66     12 $versions ||= $self->get_pom_versions($pom);
150              
151             # sanity check
152 3 50       9 die "No POM versions found!" if !%$versions;
153              
154 3         7 my ($max) = reverse sort _alphanum_sort keys %{$versions};
  3         23  
155 3         14 my ($primary, $secondary) = split /[.]/, $max;
156 3         8 $secondary++;
157              
158 3         21 return "$primary.$secondary.0-SNAPSHOT";
159             }
160              
161             1;
162              
163             __END__
164              
165             =head1 NAME
166              
167             App::Git::Workflow::Pom - Tools for maven POM files with git
168              
169             =head1 VERSION
170              
171             This documentation refers to App::Git::Workflow::Pom version 1.1.16
172              
173             =head1 SYNOPSIS
174              
175             use App::Git::Workflow::Pom qw/get_pom_versions pom_version next_pom_version/;
176              
177             # get all branch POM versions
178             my $versions = $pom->get_pom_versions("pom.xml");
179             # {
180             # 1.0 => { "some_branch" => "1.0.0-SNAPSHOT" },
181             # ...
182             # }
183              
184             # extract the version from the POM
185             my $version = $pom->pom_version("pom.xml");
186              
187             # find the next unused POM version.
188             my $next = $pom->next_pom_version("pom.xml");
189              
190             =head1 DESCRIPTION
191              
192             This library provides tools for looking at POM files in different branches.
193              
194             =head1 SUBROUTINES/METHODS
195              
196             =over 4
197              
198             =item C<new (%params)>
199              
200             Create a new C<App::Git::Workflow::Pom> object
201              
202             =item C<get_pom_versions ($pom_file)>
203              
204             Find all POM versions used in all branches.
205              
206             =item C<pom_version ($xml_text_or_file)>
207              
208             Extract the version number from C$xml_text_or_file>
209              
210             =item C<next_pom_version ($pom, $versions)>
211              
212             Find the next available POM version number.
213              
214             =back
215              
216             =head1 DIAGNOSTICS
217              
218             =head1 CONFIGURATION AND ENVIRONMENT
219              
220             =head1 DEPENDENCIES
221              
222             =head1 INCOMPATIBILITIES
223              
224             =head1 BUGS AND LIMITATIONS
225              
226             There are no known bugs in this module.
227              
228             Please report problems to Ivan Wills (ivan.wills@gmail.com).
229              
230             Patches are welcome.
231              
232             =head1 AUTHOR
233              
234             Ivan Wills - (ivan.wills@gmail.com)
235              
236             =head1 LICENSE AND COPYRIGHT
237              
238             Copyright (c) 2014 Ivan Wills (14 Mullion Close, Hornsby Heights, NSW Australia 2077).
239             All rights reserved.
240              
241             This module is free software; you can redistribute it and/or modify it under
242             the same terms as Perl itself. See L<perlartistic>. This program is
243             distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
244             without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
245             PARTICULAR PURPOSE.
246              
247             =cut