#!/usr/bin/perl -w use strict; use File::Copy; use Getopt::Std; my $VERSION = '0.01'; my %o = ( b => 0, # backup touched files h => 0, # usage help p => 0, # zero padding r => 0, # release section s => '.', # user defined separator t => 0, # trim off trailing zero revisions ); getopts('bhp:r:s:t', \%o); # Show the usage help (with the given file list, if there are any). if ($o{h}) { my @f = @_ ? @_ : 'file1 [file2 .. fileN]'; print "Usage: $0 [-h] [-b] [-p N] [-r N] [-s STRING] [-t N] @f\n"; } else { # Handle each provided file. for my $f (@ARGV) { # Skip the argument, if we can't open it as a text file. unless (open PM, $f) { warn "Can't open $f: $!\n"; next; } # Open the module file (with the proc id appeneded) for writing. open NEW, ">$f.$$" or die "Can't write $f.$$: $!\n"; # Look for a version string. while () { # Skip commented or CVS revision lines. if (!/^#/ && !/\$Revision:\s/ && /VERSION\s*=\s*.*?([\d\w.\-]+)/ ) { # Save the original version string. my $old = $1; # Grab the non-separator parts. my @version = split /[._\-]/, $old; # Grab the separators. my @separators = grep {$_} split /[^._\-]+/, $old; # Initialize any needed version parts to zero and # separators to a dot. for (0 .. $o{r}) { $version[$_] = 0 unless $version[$_]; $separators[$_] = $o{s} unless $separators[$_] || $_ == $o{r}; } # Strip off any non-numeric prefix (usually just 'v'). my ($prefix, $version) = $version[$o{r}] =~ /^([^\d.]*)(.+)$/; # Increment the version part specified by the # revision flag. $version[$o{r}] = sprintf '%s%0'.$o{p}.'s', $prefix, ++$version; # "Zero out" succeeding version sections following # the incremented one. for ($o{r} + 1 .. @version - 1) { $version[$_] = 0 x length $version[$_]; } # Reconstitute our version string. This algorithm is # like a join() with a dynamic separator expression # given that @version is always one element bigger # than @separators. my $new = ''; for (0 .. @version - 1) { $new .= $version[$_]; $new .= $separators[$_] if defined $separators[$_]; } # Remove trailing zero revisions if asked to. $new =~ s/^(.+?)[0._]+$/$1/ if $o{t}; # Replace the old version string with the new one. s/$old/$new/; # Feedback: It does a body good. print "$f: $old -> $new\n"; } # Write the line out to the new file. print NEW $_; } close NEW or die "Can't close $f.$$: $!\n"; close PM or die "Can't close $f: $!\n"; # XXX debugging: unlink "$f.$$"; # Keep a backup, if asked to. # copy $f, "$f.bak" if $o{b}; # Move the new file over the original. # move "$f.$$", $f; } } exit; __END__ =head1 NAME version_incrementer - increment a perl file version string =head1 DESCRIPTION This program finds the file version variable, and increments it based on the command line switches described in the C section. =head1 OPTIONS =over 4 =item -b NUMBER Backup touched files. Defaults to 0. =item -h NUMBER Show the usage help. Defaults to 0. =item -p NUMBER Amount of left justified "zero padding" of the revision increment. * Currently, this option does not force a revision section to have less places, only more. That is, with a setting of -p3 -r1, the following is the case: "1.2.3", "1.02.3", and "1.002.3" are all incremented to "1.003.3", yet "1.0002.3" will be incremented to "1.0003.3". This may change in a future release, after I think about it for a while. : ) =item -r NUMBER Revision section. Defaults to 0. This probably requires a bit of elucidation. In a version string like, "v1.2.003_04-a", the C are as follows: "1" is section 0 (the default), "2" is section 1, "003" is section 2, "04" is section 3, "a" is section 4, and the initial "v" is optional. =item -s STRING The separator to use for new revision sections. Defaults to a period (.). Common separators that are also recognized by this program are the underscore character (_) and the hyphen (-). This option can be used to specify that double or triple zeros (00 or 000) are to be treated as separators as well, for instance. =item -t NUMBER trim off trailing zero revisions. Defaults to 0. =back =head1 README This program finds the file version variable, and increments it based on flags that specify the revision section of the version string to update, the amount of "zero padding" to use, whether to trim trailing zero revision sections, and whether to keep a backup of the original touched file. Please see the DESCRIPTION section for details. Note that this program does I make use of C objects. =head1 USAGE Generally: inc_ver [-h] [-b] [-p N] [-r N] [-s STRING] [-t N] file1 [file2 .. fileN] Specifically: inc_ver lib/foo/Module.pm lib/bar/Module.pm lib/baz/Module.pm inc_ver lib/foo/Module.pm # 0 -> 1 # 0.0 -> 1.0 # 1.01 -> 2.00 inc_ver -r1 lib/foo/Module.pm # 1 -> 1.1 # 1.0 -> 1.1 # 1.01 -> 1.02 # 1.01.0 -> 1.02.0 # 1.01.1 -> 1.02.0 inc_ver -r2 lib/foo/Module.pm # 1 -> 1.0.1 # 1.0 -> 1.0.1 # 1.02 -> 1.02.1 # 1.02.0 -> 1.02.1 # 1.02.1 -> 1.02.2 # 1.02.0.0 -> 1.02.1.0 # 1.02.0.5 -> 1.02.1.0 inc_ver -p1 -r1 lib/foo/Module.pm # 1 -> 1.01 # 1.0 -> 1.01 # 1.01 -> 1.02 # 1.001 -> 1.02 inc_ver -r1 -t lib/foo/Module.pm # 0.1.2 -> 0.2 # 0.01.02 -> 0.02 inc_ver -r2 -s_ lib/foo/Module.pm # 1 -> 1_0_1 # 1.0 -> 1.0_1 =head1 PREREQUISITES This script requires the C pragma, the C and C modules (which are all in the core perl distribution). =head1 OSNAMES Any =head1 SCRIPT CATEGORIES Module/Maintenance =head1 TO DO Figure out how to split on a user defined separator. Get Barry Slaymaker to integrate this into C. : ) Either that or make a C module. =head1 AUTHOR Gene Boggs Egene@cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2003 by Gene Boggs This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut