Blame lib/inc/latest/private.pm

Packit 4fdfb4
use strict;
Packit 4fdfb4
use warnings;
Packit 4fdfb4
Packit 4fdfb4
package inc::latest::private;
Packit 4fdfb4
# ABSTRACT: private implementation for inc::latest
Packit 4fdfb4
Packit 4fdfb4
our $VERSION = '0.500';
Packit 4fdfb4
Packit 4fdfb4
use File::Spec;
Packit 4fdfb4
use IO::File;
Packit 4fdfb4
Packit 4fdfb4
# must ultimately "goto" the import routine of the module to be loaded
Packit 4fdfb4
# so that the calling package is correct when $mod->import() runs.
Packit 4fdfb4
sub import {
Packit 4fdfb4
    my ( $package, $mod, @args ) = @_;
Packit 4fdfb4
    my $file = $package->_mod2path($mod);
Packit 4fdfb4
Packit 4fdfb4
    if ( $INC{$file} ) {
Packit 4fdfb4
        # Already loaded, but let _load_module handle import args
Packit 4fdfb4
        goto \&_load_module;
Packit 4fdfb4
    }
Packit 4fdfb4
Packit 4fdfb4
    # A bundled copy must be present
Packit 4fdfb4
    my ( $bundled, $bundled_dir ) = $package->_search_bundled($file)
Packit 4fdfb4
      or die "No bundled copy of $mod found";
Packit 4fdfb4
Packit 4fdfb4
    my $from_inc = $package->_search_INC($file);
Packit 4fdfb4
    unless ($from_inc) {
Packit 4fdfb4
        # Only bundled is available
Packit 4fdfb4
        unshift( @INC, $bundled_dir );
Packit 4fdfb4
        goto \&_load_module;
Packit 4fdfb4
    }
Packit 4fdfb4
Packit 4fdfb4
    if ( _version($from_inc) >= _version($bundled) ) {
Packit 4fdfb4
        # Ignore the bundled copy
Packit 4fdfb4
        goto \&_load_module;
Packit 4fdfb4
    }
Packit 4fdfb4
Packit 4fdfb4
    # Load the bundled copy
Packit 4fdfb4
    unshift( @INC, $bundled_dir );
Packit 4fdfb4
    goto \&_load_module;
Packit 4fdfb4
}
Packit 4fdfb4
Packit 4fdfb4
sub _version {
Packit 4fdfb4
    require ExtUtils::MakeMaker;
Packit 4fdfb4
    return ExtUtils::MM->parse_version(shift);
Packit 4fdfb4
}
Packit 4fdfb4
Packit 4fdfb4
# use "goto" for import to preserve caller
Packit 4fdfb4
sub _load_module {
Packit 4fdfb4
    my $package = shift; # remaining @_ is ready for goto
Packit 4fdfb4
    my ( $mod, @args ) = @_;
Packit 4fdfb4
    eval "require $mod; 1" or die $@;
Packit 4fdfb4
    if ( my $import = $mod->can('import') ) {
Packit 4fdfb4
        goto $import;
Packit 4fdfb4
    }
Packit 4fdfb4
    return 1;
Packit 4fdfb4
}
Packit 4fdfb4
Packit 4fdfb4
sub _search_bundled {
Packit 4fdfb4
    my ( $self, $file ) = @_;
Packit 4fdfb4
Packit 4fdfb4
    my $mypath = 'inc';
Packit 4fdfb4
Packit 4fdfb4
    local *DH; # Maintain 5.005 compatibility
Packit 4fdfb4
    opendir DH, $mypath or die "Can't open directory $mypath: $!";
Packit 4fdfb4
Packit 4fdfb4
    while ( defined( my $e = readdir DH ) ) {
Packit 4fdfb4
        next unless $e =~ /^inc_/;
Packit 4fdfb4
        my $try = File::Spec->catfile( $mypath, $e, $file );
Packit 4fdfb4
Packit 4fdfb4
        return ( $try, File::Spec->catdir( $mypath, $e ) ) if -e $try;
Packit 4fdfb4
    }
Packit 4fdfb4
    return;
Packit 4fdfb4
}
Packit 4fdfb4
Packit 4fdfb4
# Look for the given path in @INC.
Packit 4fdfb4
sub _search_INC {
Packit 4fdfb4
    # TODO: doesn't handle coderefs or arrayrefs or objects in @INC, but
Packit 4fdfb4
    # it probably should
Packit 4fdfb4
    my ( $self, $file ) = @_;
Packit 4fdfb4
Packit 4fdfb4
    foreach my $dir (@INC) {
Packit 4fdfb4
        next if ref $dir;
Packit 4fdfb4
        my $try = File::Spec->catfile( $dir, $file );
Packit 4fdfb4
        return $try if -e $try;
Packit 4fdfb4
    }
Packit 4fdfb4
Packit 4fdfb4
    return;
Packit 4fdfb4
}
Packit 4fdfb4
Packit 4fdfb4
# Translate a module name into a directory/file.pm to search for in @INC
Packit 4fdfb4
sub _mod2path {
Packit 4fdfb4
    my ( $self, $mod ) = @_;
Packit 4fdfb4
    my @parts = split /::/, $mod;
Packit 4fdfb4
    $parts[-1] .= '.pm';
Packit 4fdfb4
    return $parts[0] if @parts == 1;
Packit 4fdfb4
    return File::Spec->catfile(@parts);
Packit 4fdfb4
}
Packit 4fdfb4
Packit 4fdfb4
1;
Packit 4fdfb4
Packit 4fdfb4
Packit 4fdfb4
# vim: ts=4 sts=4 sw=4 tw=75 et:
Packit 4fdfb4
Packit 4fdfb4
__END__
Packit 4fdfb4
Packit 4fdfb4
=pod
Packit 4fdfb4
Packit 4fdfb4
=encoding UTF-8
Packit 4fdfb4
Packit 4fdfb4
=head1 NAME
Packit 4fdfb4
Packit 4fdfb4
inc::latest::private - private implementation for inc::latest
Packit 4fdfb4
Packit 4fdfb4
=head1 VERSION
Packit 4fdfb4
Packit 4fdfb4
version 0.500
Packit 4fdfb4
Packit 4fdfb4
=head1 DESCRIPTION
Packit 4fdfb4
Packit 4fdfb4
This module has the private methods used to find and load bundled modules.
Packit 4fdfb4
It should not be used directly.
Packit 4fdfb4
Packit 4fdfb4
=head1 AUTHORS
Packit 4fdfb4
Packit 4fdfb4
=over 4
Packit 4fdfb4
Packit 4fdfb4
=item *
Packit 4fdfb4
Packit 4fdfb4
David Golden <dagolden@cpan.org>
Packit 4fdfb4
Packit 4fdfb4
=item *
Packit 4fdfb4
Packit 4fdfb4
Eric Wilhelm <ewilhelm@cpan.org>
Packit 4fdfb4
Packit 4fdfb4
=back
Packit 4fdfb4
Packit 4fdfb4
=head1 COPYRIGHT AND LICENSE
Packit 4fdfb4
Packit 4fdfb4
This software is Copyright (c) 2009 by David Golden.
Packit 4fdfb4
Packit 4fdfb4
This is free software, licensed under:
Packit 4fdfb4
Packit 4fdfb4
  The Apache License, Version 2.0, January 2004
Packit 4fdfb4
Packit 4fdfb4
=cut