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