John Peacock wrote:
I have a couple of distros[1][2] that contain child modules that implement
specific feature (and hence have no life outside of the parent distribution).
Consequently, I want them to always report the same $VERSION as the parent
module.  However, if I use a block like this[1]:

    use base qw(SVN::Notify::Mirror);
    $VERSION = $SVN::Notify::Mirror::VERSION;

this works fine when actually *running* the code, but META.yml comes up with ''
(which resolves to undef as far as CPAN is concerned).  Then I tried to do this:
[...]
Is this too risky a patch to apply to Module::Build?  As it turns out, the
change is not needed except to build META.yml (i.e. I can apply that locally and
it isn't needed to build/test on an unpatched M::B).  Is there some other way I
can skin this particular cat?

I'm not sure I've really understood you, but I have a package (http://search.cpan.org/~sendu/bioperl-1.5.2_102/) where all the modules take their version from one of the modules in the package. I get my generated META.yml file to include the correct version for each module by using a ModuleBuild subclass I call ModuleBuildBioperl, where I override find_dist_packages(). Yes, I wish I didn't have to duplicate all that code in my subclass. Perhaps someone can think of a generalized and optional way of enabling the same effect.


## Build.PL
my $build = ModuleBuildBioperl->new(
    module_name         => 'Bio',
    dist_name           => 'bioperl',
    dist_version_from   => 'Bio/Root/Version.pm',


## ModuleBuildBioperl

# like the Module::Build version, except that we always get version from
# dist_version
sub find_dist_packages {
    my $self = shift;

    # Only packages in .pm files are candidates for inclusion here.
    # Only include things in the MANIFEST, not things in developer's
    # private stock.

my $manifest = $self->_read_manifest('MANIFEST') or die "Can't find dist packages without a MANIFEST file - run 'manifest' action first";

    # Localize
my %dist_files = map { $self->localize_file_path($_) => $_ } keys %$manifest;

my @pm_files = grep {exists $dist_files{$_}} keys %{ $self->find_pm_files };

    my $actual_version = $self->dist_version;

    # First, we enumerate all packages & versions,
    # seperating into primary & alternative candidates
    my( %prime, %alt );
    foreach my $file (@pm_files) {
        next if $dist_files{$file} =~ m{^t/};  # Skip things in t/

        my @path = split( /\//, $dist_files{$file} );
        (my $prime_package = join( '::', @path[1..$#path] )) =~ s/\.pm$//;

        my $pm_info = Module::Build::ModuleInfo->new_from_file( $file );

        foreach my $package ( $pm_info->packages_inside ) {
next if $package eq 'main'; # main can appear numerous times, ignore next if grep /^_/, split( /::/, $package ); # private package, ignore

            my $version = $pm_info->version( $package );
            if ($version && $version != $actual_version) {
$self->log_warn("Package $package had version $version!\n");
            }
            $version = $actual_version;

            if ( $package eq $prime_package ) {
                if ( exists( $prime{$package} ) ) {
                    # M::B::ModuleInfo will handle this conflict
die "Unexpected conflict in '$package'; multiple versions found.\n";
                }
                else {
                    $prime{$package}{file} = $dist_files{$file};
$prime{$package}{version} = $version if defined( $version );
                }
            }
            else {
push( @{$alt{$package}}, { file => $dist_files{$file}, version => $version } );
            }
        }
    }

# Then we iterate over all the packages found above, identifying conflicts
    # and selecting the "best" candidate for recording the file & version
    # for each package.
    foreach my $package ( keys( %alt ) ) {
        my $result = $self->_resolve_module_versions( $alt{$package} );

        if ( exists( $prime{$package} ) ) { # primary package selected
            if ( $result->{err} ) {
# Use the selected primary package, but there are conflicting # errors amoung multiple alternative packages that need to be
                 # reported
$self->log_warn("Found conflicting versions for package '$package'\n" . " $prime{$package}{file} ($prime{$package}{version})\n" . $result->{err});
            }
            elsif ( defined( $result->{version} ) ) {
                # There is a primary package selected, and exactly one
                # alternative package

if ( exists( $prime{$package}{version} ) && defined( $prime{$package}{version} ) ) { # Unless the version of the primary package agrees with the
                    # version of the alternative package, report a conflict
if ( $self->compare_versions( $prime{$package}{version}, '!=', $result->{version} ) ) { $self->log_warn("Found conflicting versions for package '$package'\n" . " $prime{$package}{file} ($prime{$package}{version})\n" . " $result->{file} ($result->{version})\n");
                    }
                }
                else {
# The prime package selected has no version so, we choose to
                  # use any alternative package that does have a version
                  $prime{$package}{file}    = $result->{file};
                  $prime{$package}{version} = $result->{version};
                }
            }
            else {
                # no alt package found with a version, but we have a prime
                # package so we use it whether it has a version or not
            }
        }
        else { # No primary package was selected, use the best alternative
            if ( $result->{err} ) {
$self->log_warn("Found conflicting versions for package '$package'\n" . $result->{err});
            }

            # Despite possible conflicting versions, we choose to record
            # something rather than nothing
            $prime{$package}{file}    = $result->{file};
$prime{$package}{version} = $result->{version} if defined( $result->{version} );
        }
    }

    # Stringify versions
    for (grep exists $_->{version}, values %prime) {
        $_->{version} = $_->{version}->stringify if ref($_->{version});
    }

    return \%prime;
}

Reply via email to