allow quotes around version in Makefile.PL
[p5sagit/Distar.git] / helpers / bump-version
CommitLineData
8ab5ea70 1#!/usr/bin/env perl
2
3use strict;
4use warnings FATAL => 'all';
5use File::Find;
ece2756d 6use Getopt::Long qw(:config gnu_compat);
7use File::Temp ();
8
9GetOptions(
10 "git" => \my $git,
11) or die("Error in command line arguments\n");
12
13my ($old_version, $bump) = @ARGV;
14my ($new_decimal, $new_vstring) = bump_version($old_version, $bump);
15
16warn "Bumping $old_version -> $new_decimal\n";
17
343f5d00 18my $file_match = qr{^(?:
19 Makefile\.PL
20 |lib[/\\].*\.(?:pod|pm)
21 |bin[/\\].*
22 |script[/\\].*
23)$}x;
24
ece2756d 25my %files;
26if ($git) {
176acdb4 27 if (system "git diff --quiet --cached HEAD") {
ece2756d 28 die "Staged changes!\n";
29 }
30 for (`git ls-files`) {
31 chomp;
32 next
343f5d00 33 unless /$file_match/;
ece2756d 34 $files{$_} = `git show HEAD:"$_"`;
35 }
36}
37else {
38 find({
39 no_chdir => 1,
40 wanted => sub {
41 next
42 unless -f;
43 next
343f5d00 44 unless /(?:\.[\/\\])?$file_match/;
ece2756d 45 open my $fh, '<', $_
46 or die "can't open $_: $!";
47 $files{$_} = do { local $/; <$fh> };
48 close $fh;
49 },
343f5d00 50 }, '.');
ece2756d 51}
52
53my $FILE_RE = qr{
54 (^.* \$VERSION \s* = \s* )
55 (['"]?) v?([0-9]+(?:[._][0-9]+)*) \2
56 ( \s*; )
57 (?:
58 (\s*\#\s*)
59 v?[.0-9]+
60 )?
61 (.*)$
62}x;
63my $MAKE_RE = qr{
22de1c6a 64 (^.* ['"]?version['"] \s* => \s* )
ece2756d 65 (['"]?) v?([0-9]+(?:[._][0-9]+)*) \2
66 ( \s*, )
67 (?:
68 (\s*\#\s*)
69 v?[.0-9]+
70 )?
71 (.*)$
72}x;
73
74my $patch = '';
75for my $file (sort keys %files) {
76 my $content = $files{$file};
77 my $file_diff = '';
78 my $re = $file eq 'Makefile.PL' ? $MAKE_RE : $FILE_RE;
79 my @lines = split /\r?\n/, $content;
80 for my $ln (0 .. $#lines) {
81 my $line = $lines[$ln];
82 if ($lines[$ln] =~ $re) {
83 die "unable to bump version number in $file from $old_version, found $3\n"
84 if $3 ne $old_version;
85 my $comment = ($5 ? $5 . $new_vstring : '');
86 my $new_line = "$1'$new_decimal'$4$comment$6";
87 $file_diff .= <<"END_DIFF";
88@@ -@{[ $ln ]},3 +@{[ $ln ]},3 @@
89 $lines[$ln-1]
90-$lines[$ln]
91+$new_line
92 $lines[$ln+1]
93END_DIFF
94 }
95 }
96 if ($file_diff) {
97 $patch .= <<"END_HEADER" . $file_diff;
98--- a/$file
99+++ b/$file
100END_HEADER
101 }
102}
103
104my ($fh, $file) = File::Temp::tempfile( "bump-version-XXXXXX", TMPDIR => 1 );
105print { $fh } $patch;
106close $fh;
413a726c 107system qw(git --no-pager apply --apply --stat), $file
ece2756d 108 and exit 1;
109
110if ($git) {
111 system qw(git apply --cached), $file
112 and exit 1;
113
114 my $message = "Bumping version to $new_decimal";
115 system qw(git commit -m), $message
116 and exit 1;
117}
8ab5ea70 118
119sub version_parts {
576656c4 120 my $version = shift;
121 my $dotted = $version =~ s/^v//;
122 my @parts = split /\./, $version;
123 if (!$dotted && @parts == 2) {
8ab5ea70 124 my $dec = pop @parts;
576656c4 125 $dec =~ s/_//g;
47ac0560 126 $dec .= "0" x ((- length $dec) % 3);
8ab5ea70 127 push @parts, $dec =~ /(\d{1,3})/g;
128 }
129 $_ += 0 for @parts;
8ab5ea70 130 return @parts;
131}
132
ece2756d 133sub bump_version {
150fcad0 134 my ($version, $new) = @_;
8ab5ea70 135
150fcad0 136 my %bump_part = (major => 0, minor => 1, bugfix => 2, last => -1);
137 my $bump_this = $bump_part{$new||'last'};
576656c4 138
ece2756d 139 my $new_vstring;
140 my $new_decimal;
8ab5ea70 141
ece2756d 142 if (defined $bump_this) {
150fcad0 143 if ($version =~ /^v/ || ($version =~ tr/.//) > 1) {
144 my @parts = version_parts($version);
145 $parts[$bump_this]++;
146 $parts[$_] = 0 for (($bump_this < 0 ? @parts : 0)+$bump_this+1 .. $#parts);
147 $_ += 0
148 for @parts;
149 $new_vstring = join '.', @parts;
150 my $format = '%i.'. join '', map { '%03i' } @parts[1 .. $#parts];
151 $new_decimal = sprintf $format, @parts;
152 }
153 else {
154 my $alpha_pos = index($version, '_');
155 $version =~ s/_//g;
156 $version =~ s/^(\d+)\.//;
157 my @parts = $1;
158 push @parts, $version =~ /(\d{1,3})/g;
159 my $format = '%i.'.join '', map { '%0'.length($_).'i' } @parts[1 .. $#parts];
160 $parts[$bump_this]++;
161 $parts[$_] = 0 for (($bump_this < 0 ? @parts : 0)+$bump_this+1 .. $#parts);
162 $new_decimal = sprintf $format, @parts;
163 substr $new_decimal, $alpha_pos, 0, '_'
164 if $alpha_pos != -1;
165 $new_vstring = join '.', version_parts($new_decimal);
166 }
ece2756d 167 }
168 elsif ($new =~ /^v?[0-9]+(?:[._][0-9]+)*$/) {
169 $new_decimal = $new;
170 $new_vstring = join('.', version_parts($new_decimal));
171 }
172 else {
173 die "no idea which part to bump - $new means nothing to me"
174 }
175 return ($new_decimal, $new_vstring);
a4c19845 176}
177