File Coverage

blib/lib/Group/Git/Cmd/SinceRelease.pm
Criterion Covered Total %
statement 27 72 37.5
branch 0 40 0.0
condition 0 3 0.0
subroutine 9 12 75.0
pod 2 2 100.0
total 38 129 29.4


line stmt bran cond sub pod time code
1             package Group::Git::Cmd::SinceRelease;
2              
3             # Created on: 2013-05-20 09:03:03
4             # Create by: Ivan Wills
5             # $Id$
6             # $Revision$, $HeadURL$, $Date$
7             # $Revision$, $Source$, $Date$
8              
9 1     1   68910 use strict;
  1         3  
  1         27  
10 1     1   6 use warnings;
  1         1  
  1         22  
11 1     1   454 use version;
  1         1882  
  1         5  
12 1     1   585 use Moose::Role;
  1         467391  
  1         5  
13 1     1   5682 use Carp;
  1         3  
  1         83  
14 1     1   776 use Data::Dumper qw/Dumper/;
  1         6854  
  1         70  
15 1     1   517 use English qw/ -no_match_vars /;
  1         3582  
  1         5  
16 1     1   854 use File::chdir;
  1         3074  
  1         95  
17 1     1   551 use Getopt::Alt;
  1         264909  
  1         6  
18              
19             our $VERSION = version->new('0.0.12');
20              
21             my $opt = Getopt::Alt->new(
22             {
23             helper => 1,
24             help => __PACKAGE__,
25             default => {
26             min => 1,
27             },
28             },
29             [
30             'min|min-commits|m=i',
31             'name|n',
32             'no_release|no-release',
33             'latest|latest-tag',
34             'released|r',
35             'verbose|v+',
36             'quiet|q!',
37             ]
38             );
39              
40             sub _num_sort {
41 0     0     my $A = $a;
42 0           $A =~ s/^v(\d)/$1/;
43 0           my $B = $b;
44 0           $B =~ s/^v(\d)/$1/;
45              
46 0 0 0       if ( $A =~ /^\d+[.]\d+[.]\d+$/ && $B =~ /^\d+[.]\d+[.]\d+$/ ) {
47 0           my @A = split /[.]/, $A;
48 0           my @B = split /[.]/, $B;
49 0 0         my $max = @A > @B ? @A : @B;
50              
51 0           for my $i ( 0 .. $max - 1 ) {
52 0 0         return $A[$i] <=> $B[$i] if $A[$i] <=> $B[$i];
53             }
54 0           return 0;
55             }
56              
57 0 0         $A =~ s/((0+)\d+)/sprintf "%03d", $2 eq '00' ? $1 : $2 eq '0' ? $1 * 10 : $1 * 100/egxms;
  0 0          
58 0 0         $B =~ s/((0+)\d+)/sprintf "%03d", $2 eq '00' ? $1 : $2 eq '0' ? $1 * 10 : $1 * 100/egxms;
  0 0          
59 0           $A cmp $B;
60             }
61              
62             sub since_release_start {
63 0     0 1   $opt->process;
64 0           return;
65             }
66              
67             sub since_release {
68 0     0 1   my ($self, $name) = @_;
69              
70 0 0         return unless -d $name;
71              
72 0           local $CWD = $name;
73              
74             # find the newest tag and count newer commits
75 0           my @tags = sort _num_sort grep {/^v?\d+(?:[.]\d+)*$/} map {/(.*)$/; $1} `git tag | sort -n`;
  0            
  0            
  0            
76 0 0         if ($opt->opt->no_release) {
    0          
77 0 0         return "Never released" if !@tags;
78 0           return;
79             }
80             elsif (!@tags) {
81 0           return;
82             }
83              
84 0 0         if ( $opt->opt->latest ) {
85 0           return $tags[-1];
86             }
87              
88 0           my ($sha, $time, @rest) = split /\s+/, `git log -n 1 --format=format:'%H %at' $tags[-1]`;
89              
90 0 0         if (!$sha) {
91 0           warn "$name\ngit log -n 1 --format=format:'%H %at' $tags[-1]\n\n";
92 0           warn join ' ', $sha, $time, @rest;
93 0           return;
94             }
95              
96 0 0         my $format = @ARGV ? join(' ', @ARGV) : '--format=format:" %s"';
97 0           my @logged = `git log -n 100 $format $sha..HEAD`;
98              
99 0 0         if ($opt->opt->released) {
100 0 0         return "Released!" if !@logged;
101 0           return;
102             }
103              
104 0 0         return if @logged < $opt->opt->min;
105 0 0         my $text = $opt->opt->quiet ? '' : "Commits since last release ($tags[-1])";
106 0 0         $text .= $opt->opt->name ? " ($tags[-1]): " : ': ';
107              
108 0 0         return $text . ($opt->opt->verbose ? "\n" . join '', @logged : scalar @logged);
109             }
110              
111             1;
112              
113             __END__
114              
115             =head1 NAME
116              
117             Group::Git::Cmd::SinceRelease - Gets the number of commits each repository is ahead of the last release
118              
119             =head1 VERSION
120              
121             This documentation refers to Group::Git::Cmd::SinceRelease version 0.0.12
122              
123             =head1 SYNOPSIS
124              
125             group-git since-release [(-m|--min-commits) n] [-n|--name]
126             group-git since-release --no-release
127             group-git since-release (-r|--released)
128             group-git since-release [options]
129              
130             Options:
131             -m --min-commits[=]int
132             Set the minimum number of commits to be found since the
133             last release (ie tag) before the results are shown.
134             (Default 1)
135             -n --name Show the last release's name (ignored if --quiet used)
136             --no-release
137             Show only repositories that have never been released (no tags)
138             -r --released Show repositories that are currently released.
139             -q --quiet Just show the number of commits since the last release
140             -v --verbose Show all repository results.
141             --help Show this documentation
142             --man Show full documentation
143              
144             =head1 DESCRIPTION
145              
146             The C<since-release> command reports the statuses of repositories relative to
147             their last release. Usually reporting the number of releases since the last
148             release but with the C<--released> option shows only with no new commits since
149             the last release. Also with the C<--no-release> option only repositories with
150             no tagged releases are reported.
151              
152             =head1 SUBROUTINES/METHODS
153              
154             =head2 C<since_release_start ()>
155              
156             Initializes command line parameters.
157              
158             =head2 C<since_release ($name)>
159              
160             Calculates the number of commits since the last release (via the newest tag)
161              
162             =head1 DESCRIPTION
163              
164             =head1 SUBROUTINES/METHODS
165              
166             =head2 C<tag ($name)>
167              
168             Does the work of finding tags
169              
170             =head1 DIAGNOSTICS
171              
172             =head1 CONFIGURATION AND ENVIRONMENT
173              
174             =head1 DEPENDENCIES
175              
176             =head1 INCOMPATIBILITIES
177              
178             =head1 BUGS AND LIMITATIONS
179              
180             There are no known bugs in this module.
181              
182             Please report problems to Ivan Wills (ivan.wills@gmail.com).
183              
184             Patches are welcome.
185              
186             =head1 AUTHOR
187              
188             Ivan Wills - (ivan.wills@gmail.com)
189              
190             =head1 LICENSE AND COPYRIGHT
191              
192             Copyright (c) 2015 Ivan Wills (14 Mullion Close, Hornsby Heights, NSW Australia 2077).
193             All rights reserved.
194              
195             This module is free software; you can redistribute it and/or modify it under
196             the same terms as Perl itself. See L<perlartistic>. This program is
197             distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
198             without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
199             PARTICULAR PURPOSE.
200              
201             =cut