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