I was trying to figure out a mechanism to somehow format all modules in a distro (Text::Template::Simple) automatically to have a single version number instead of varying versions among files. I'm not so sure if this is the best way, but I chose to manually modify the files to update the versions in them. First, I had to subclass Module::Build to alter the `Build dist` action. However, M::B has an awkward interface for subclassing. One needs to pass the sublass code as a string into the subclass() method. Weirdo :p But since I didn't like this interface for subclassing and I wanted to use the syntax checking/coloring of my Komodo Edit, I've decided to load the content from an external file:
my $class = Module::Build->subclass(
class => 'MBSubclass',
code => raw_subclass(),
);
sub raw_subclass {
my $file = File::Spec->catfile( 'tools', 'Build.pm' );
my $FH = IO::File->new;
$FH->open( $file, 'r' ) or die "Can not open($file): $!";
my $rv = do { local $/; <$FH> };
close $FH;
return $rv;
}
And here is the subclass (note that there is no package declaration since M::B adds this part automatically afterwards):
use strict;
use vars qw( $VERSION );
use warnings;
use File::Find;
use constant RE_VERSION_LINE => qr{
\A \$VERSION \s+ = \s+ ["'] (.+?) ['"] ; (.+?) \z
}xms;
use constant VTEMP => q{$VERSION = '%s';};
$VERSION = '0.10';
sub ACTION_dist {
my $self = shift;
warn sprintf(
"RUNNING 'dist' Action from subclass %s v%s\n",
ref($self),
$VERSION
);
my @modules;
find {
wanted => sub {
my $file = $_;
return if $file !~ m{ \. pm \z }xms;
push @modules, $file;
warn "FOUND Module: $file\n";
},
no_chdir => 1,
}, "lib";
$self->_change_versions( \@modules );
$self->SUPER::ACTION_dist( @_ );
}
sub _change_versions {
my $self = shift;
my $files = shift;
my $dver = $self->dist_version;
warn "DISTRO Version: $dver\n";
foreach my $mod ( @{ $files } ) {
warn "PROCESSING $mod\n";
my $new = $mod . '.new';
open my $RO_FH, '<:raw', $mod or die "Can not open file($mod): $!";
open my $W_FH , '>:raw', $new or die "Can not open file($new): $!";
my $changed;
while ( my $line = readline $RO_FH ) {
if ( ! $changed && ( $line =~ RE_VERSION_LINE ) ) {
my $oldv = $1;
my $remainder = $2;
warn "CHANGED Version from $oldv to $dver\n";
printf $W_FH VTEMP . $remainder, $dver;
$changed++;
next;
}
print $W_FH $line;
}
close $RO_FH or die "Can not close file($mod): $!";
close $W_FH or die "Can not close file($new): $!";
unlink($mod) || die "Can not remove original module($mod): $!";
rename( $new, $mod ) || die "Can not rename( $new, $mod ): $!";
warn "RENAME Successful!\n";
}
return;
}
It's really straightforward. Find the *.pm and them create a modified copy that has the distro's version and replace the original with the new one and resume `dist` process :)
I am not sure it makes sense unless the module can't stand on its own to share the version from the main application but I would love to hear what others have to say.
Re:Perhaps Crosspost on Perlmonks
Burak on 2008-10-21T21:12:36
Well, it looks like this was discussed at least once:)
http://www.nntp.perl.org/group/perl.module.build/2007/04/msg642.html
Anyway, I bet (since this is not something new) there is already some stuff related to this on PerlMonks, but I'm too lazy to search right now:)
As for my decision, Text::Template::Simple and all it's sub modules are actually a single monolithic thing splitted into separate files to ease managing:) And it was really a single .pm some time back...