File Coverage

blib/lib/PPI/App/ppi_copyright.pm
Criterion Covered Total %
statement 31 145 21.3
branch 0 44 0.0
condition 0 15 0.0
subroutine 11 20 55.0
pod 0 5 0.0
total 42 229 18.3


line stmt bran cond sub pod time code
1             package PPI::App::ppi_copyright;
2              
3 1     1   1462 use 5.006;
  1         4  
  1         32  
4 1     1   6 use strict;
  1         1  
  1         33  
5 1     1   6 use warnings;
  1         2  
  1         32  
6 1     1   5 use version ();
  1         2  
  1         12  
7 1     1   6 use File::Spec ();
  1         2  
  1         11  
8 1     1   5 use Getopt::Long ();
  1         2  
  1         11  
9 1     1   4 use PPI::Document ();
  1         3  
  1         12  
10 1     1   5 use File::Find::Rule ();
  1         1  
  1         17  
11 1     1   4 use File::Find::Rule::Perl ();
  1         2  
  1         22  
12              
13 1     1   27 use vars qw{$VERSION};
  1         2  
  1         58  
14             BEGIN {
15 1     1   1396 $VERSION = '0.14';
16             }
17              
18              
19              
20              
21              
22             #####################################################################
23             # Main Functions
24              
25             sub main {
26 0     0 0   my $cmd = shift @_;
27 0 0         return usage(@_) unless defined $cmd;
28 0 0         return show(@_) if $cmd eq 'show';
29 0 0         return change(@_) if $cmd eq 'change';
30 0           return error("Unknown command '$cmd'");
31             }
32              
33             sub error {
34 0     0 0   my $msg = shift;
35 0           chomp $msg;
36 0           print "\n";
37 0           print " $msg\n";
38 0           print "\n";
39 0           return 255;
40             }
41              
42              
43              
44              
45              
46             #####################################################################
47             # Command Functions
48              
49             sub usage {
50 0     0 0   print "\n";
51 0           print "ppi_version $VERSION - Copyright 2006 - 2009 Adam Kennedy.\n";
52 0           print "Usage:\n";
53 0           print " ppi_version show\n";
54 0           print " ppi_version change 0.02_03 0.54\n";
55 0           print "\n";
56 0           return 0;
57             }
58              
59             sub show {
60             # Capture the author
61 0     0 0   @ARGV = @_;
62 0           my $AUTHOR = '';
63 0           Getopt::Long::GetOptions(
64             'author=s' => \$AUTHOR,
65             );
66 0 0         if ( $AUTHOR ) {
67 0           $AUTHOR = quotemeta $AUTHOR;
68             }
69              
70             # Find all modules and scripts below the current directory
71 0           my @files = File::Find::Rule->perl_file->in( File::Spec->curdir );
72 0           print "Found " . scalar(@files) . " file(s)\n";
73              
74 0           my $count = 0;
75 0           foreach my $file ( @files ) {
76 0           print "$file...";
77 0           my $document = PPI::Document->new($file);
78 0 0         unless ( $document ) {
79 0           print " failed to parse file\n";
80 0           next;
81             }
82              
83             # Does the document contain a simple version number
84 0           my $elements = $document->find( \&_wanted );
85              
86             # Filter by author if applicable
87 0 0 0       if ( $elements and $AUTHOR ) {
88 0           @$elements = grep {
89 0           $_->{content} =~ /$AUTHOR/
90             } @$elements;
91             }
92              
93             # Find anything?
94 0 0 0       unless ( $elements and @$elements ) {
95 0           print " no copyright\n";
96 0           next;
97             }
98              
99 0 0         if ( @$elements ) {
100             # Print the raw copyright lines
101 0           print "\n";
102 0           print "\n";
103 0           foreach my $element ( @$elements ) {
104 0           my $pod = $element->content;
105 0           print map {
106 0           " $_\n"
107             } grep {
108 0           /Copyright/
109             } split /\n/, $pod;
110             }
111 0           print "\n";
112 0           $count++;
113             }
114             }
115              
116 0           print "Found " . scalar($count) . " copyright(s)\n";
117 0           print "Done.\n";
118 0           return 0;
119             }
120              
121             sub change {
122             # Capture the author
123 0     0 0   @ARGV = @_;
124 0           my $AUTHOR = '';
125 0           Getopt::Long::GetOptions(
126             'author=s' => \$AUTHOR,
127             );
128 0 0         if ( $AUTHOR ) {
129 0           $AUTHOR = quotemeta $AUTHOR;
130             }
131              
132             # Find all modules and scripts below the current directory
133 0           my @files = File::Find::Rule->perl_file->in( File::Spec->curdir );
134 0           print "Found " . scalar(@files) . " file(s)\n";
135              
136 0           my $count = 0;
137 0           foreach my $file ( @files ) {
138 0           print "$file...";
139 0 0         if ( ! -w $file ) {
140 0           print " no write permission\n";
141 0           next;
142             }
143 0           my $rv = _change_file( $file, $AUTHOR );
144 0 0         if ( $rv ) {
    0          
145 0           print " updated\n";
146 0           $count++;
147             } elsif ( defined $rv ) {
148 0           print " skipped\n";
149             } else {
150 0           print " failed to parse file\n";
151             }
152             }
153              
154 0           print "Updated " . scalar($count) . " file(s)\n";
155 0           print "Done.\n";
156 0           return 0;
157             }
158              
159              
160              
161              
162              
163              
164             #####################################################################
165             # Support Functions
166              
167             sub _change_file {
168 0     0     my $file = shift;
169              
170             # Parse the file
171 0           my $document = PPI::Document->new($file);
172 0 0         unless ( $document ) {
173 0           error("Failed to parse $file");
174             }
175              
176             # Apply the changes
177 0           my $rv = _change_document( $document, $_[0] );
178 0 0         unless ( defined $rv ) {
179 0           error("$file contains more than one \$VERSION assignment");
180             }
181 0 0         unless ( $rv ) {
182 0           return '';
183             }
184              
185             # Save the updated version
186 0 0         unless ( $document->save($file) ) {
187 0           error("PPI::Document save failed");
188             }
189              
190 0           return 1;
191             }
192              
193             sub _change_document {
194 0     0     my $document = shift;
195 0           my $AUTHOR = shift;
196              
197             # Does the document contain an element
198 0           my $elements = $document->find( \&_wanted );
199 0 0 0       if ( $elements and $AUTHOR ) {
200 0           @$elements = grep {
201 0           $_->{content} =~ /$AUTHOR/
202             } @$elements;
203             }
204 0 0 0       unless ( $elements and @$elements ) {
205 0           return '';
206             }
207              
208 0           my $pattern = qr/\b(copyright\s+\d{4}(?:\s*-\s*\d{4}))/i;
209 0           foreach my $element ( @$elements ) {
210 0           $element->{content} =~ s/$pattern/_change($1)/eg;
  0            
211             }
212              
213 0           return 1;
214             }
215              
216             # Locate a version number token
217             sub _wanted {
218             return !! (
219 0   0 0     $_[1]->isa('PPI::Token::Pod')
220             and
221             $_[1]->content =~ /\bCopyright\b/
222             );
223             }
224              
225             sub _change {
226 0     0     my $copyright = shift;
227 0           my $thisyear = (localtime time)[5] + 1900;
228 0           my @year = $copyright =~ m/(\d{4})/g;
229              
230 0 0         if ( @year == 1 ) {
231             # Handle the single year format
232 0 0         if ( $year[0] == $thisyear ) {
233             # No change
234 0           return $copyright;
235             } else {
236             # Convert from single year to multiple year
237 0           $copyright =~ s/(\d{4})/$1 - $thisyear/;
238 0           return $copyright;
239             }
240             }
241              
242 0 0         if ( @year == 2 ) {
243             # Handle the range format
244 0 0         if ( $year[1] == $thisyear ) {
245             # No change
246 0           return $copyright;
247             } else {
248             # Change the second year to the current one
249 0           $copyright =~ s/$year[1]/$thisyear/;
250 0           return $copyright;
251             }
252             }
253              
254             # huh?
255 0           die "Invalid or unknown copyright line $copyright";
256             }
257              
258             1;