4 use warnings FATAL => 'all';
6 use Getopt::Long qw(:config gnu_getopt);
11 "force" => \my $force,
12 'n|dry-run' => \my $dry_run,
13 ) or die("Error in command line arguments\n");
15 my $old_version = shift
16 or die "no old version provided!\n";
18 my ($new_decimal, $new_vstring) = bump_version($old_version, $bump);
20 warn "Bumping $old_version -> $new_decimal" . ($new_decimal ne $new_vstring ? " ($new_vstring)" : '') . "\n";
24 |lib[/\\].*\.(?:pod|pm)
41 if (system "git diff --quiet --cached HEAD") {
42 die "Staged changes!\n";
44 for (`git ls-files`) {
47 unless /^$file_match$/;
48 $files{$_} = `git show HEAD:"$_"`;
55 my $fn = File::Spec->abs2rel($_, '.');
56 if (-d && $fn !~ /^$dir_match$/) {
57 $File::Find::prune = 1;
63 unless $fn =~ /^$file_match$/;
65 or die "can't open $fn: $!";
66 $files{$fn} = do { local $/; <$fh> };
73 (^.* \$VERSION \s* = \s* )
74 (['"]?) v?([0-9]+(?:[._][0-9]+)*) \2
83 (^.* ['"]?version['"] \s* => \s* )
84 (['"]?) v?([0-9]+(?:[._][0-9]+)*) \2
94 for my $file (sort keys %files) {
96 my $content = $files{$file};
98 my $re = $file eq 'Makefile.PL' ? $MAKE_RE : $FILE_RE;
99 my @lines = split /\r?\n/, $content;
100 for my $ln (0 .. $#lines) {
101 my $line = $lines[$ln];
102 if ($lines[$ln] =~ $re) {
103 die "unable to bump version number in $file from $old_version, found $3\n"
104 if !$force && $3 ne $old_version;
105 my $comment = ($5 ? $5 . $new_vstring : '');
106 my $new_line = "$1'$new_decimal'$4$comment$6";
107 $file_diff .= <<"END_DIFF";
108 @@ -@{[ $ln ]},3 +@{[ $ln ]},3 @@
117 $patch .= <<"END_HEADER" . $file_diff;
123 } or $dry_run ? warn($@) : die($@);
130 my ($fh, $file) = File::Temp::tempfile( "bump-version-XXXXXX", TMPDIR => 1 );
131 print { $fh } $patch;
133 system qw(git --no-pager apply --apply --stat), $file
137 system qw(git apply --cached), $file
140 my $message = "Bumping version to $new_decimal";
141 system qw(git commit -m), $message
147 my $dotted = $version =~ s/^v//;
148 my @parts = split /\./, $version;
149 if (!$dotted && @parts == 2) {
150 my $dec = pop @parts;
152 $dec .= "0" x ((- length $dec) % 3);
153 push @parts, $dec =~ /(\d{1,3})/g;
160 my ($version, $new) = @_;
162 my %bump_part = (major => 0, minor => 1, bugfix => 2, last => -1);
163 my $bump_this = $bump_part{$new||'last'};
168 if (defined $bump_this) {
169 if ($version =~ /^v/ || ($version =~ tr/.//) > 1) {
170 my $v = $version =~ /^(v)/ ? $1 : '';
171 my @parts = version_parts($version);
174 $parts[$_] = 0 for $bump_this+1 .. $#parts;
175 $parts[$_] = 0 for $#parts+1 .. $bump_this;
176 $parts[$bump_this]++;
179 $new_decimal = $new_vstring = $v . join '.', @parts;
182 my $alpha_pos = index($version, '_');
184 $version =~ s/^(\d+)\.//;
186 push @parts, $version =~ /(\d{1,3})/g;
187 my $format = '%i.'.join '', map { '%0'.length($_).'i' } @parts[1 .. $#parts];
188 $parts[$bump_this]++;
189 $parts[$_] = 0 for (($bump_this < 0 ? @parts : 0)+$bump_this+1 .. $#parts);
190 $new_decimal = sprintf $format, @parts;
191 substr $new_decimal, $alpha_pos, 0, '_'
193 $new_vstring = join '.', version_parts($new_decimal);
196 elsif ($new =~ /^v?[0-9]+(?:[._][0-9]+)*$/) {
198 $new_vstring = join('.', version_parts($new_decimal));
201 die "no idea which part to bump - $new means nothing to me"
203 return ($new_decimal, $new_vstring);