AutoReloader

 view release on metacpan or  search on metacpan

lib/AutoReloader.pm  view on Meta::CPAN

=item checksub ($coderef)

set the checking subroutine. Class and object method. This subroutine will be
invoked with a subroutines source filename (full path) every time the sub for
which it is configured - but only if check for that subroutine is true -, and
should return some value special to that file.
Default is 'sub { (stat $_[0]) [9] }', i.e. mtime.

=back

=head1 SEE ALSO

 AutoLoader, AutoSplit, DBIx::VersionedSubs

=head1 BUGS

AutoReloader subroutines are always reported as __ANON__ (e.g. with Carp::cluck),
even if they are assigned to a symbol table entry. Which might not be a bug.

There might be others.

=head1 Author

 shmem <shmem@cpan.org>

=head1 CREDITS

Many thanks to thospel, Corion, diotalevi, tye and chromatic (these are their
http://perlmonks.org nicks) for review and most valuable hints.

=head1 COPYRIGHT

Copyright 2007 - 2021 by shmem <shmem@cpan.org>

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut

package AutoReloader;

use strict;
use warnings;
use Scalar::Util;
use File::Spec;

our $VERSION   = 0.03;

use vars qw($Debug %AL);
$Debug = 0;

sub new {
    my $class  = shift;
    my $caller = caller;
    my $sub    = gensub ($caller,@_);

    bless $sub, $class;
}

sub auto {
    shift if __PACKAGE__ || $_[0] eq (caller(0))[0];
    $AL {'auto'} = shift if @_;
    $AL {'auto'};
}

sub check {
    my $self = shift;
    if(ref($self)) {
        ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'check'} }
	    = shift if @_;
        ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'check'} };
    }
    else {
        $AL {'check'}  = shift;
        $AL {'check'};
    }
}

sub checksub {
    my $self = shift;
    if(ref($self)) {
        ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'checksub'} }
	    = shift if @_;
	${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'checksub'} };
    }
    else {
        $AL {'checksub'} = shift if @_;
        $AL {'checksub'};
    }
}
sub suffix {
    shift if __PACKAGE__ || $_[0] eq (caller(0))[0];
    $AL {'suffix'} = shift if @_;
    $AL {'suffix'};
} 
# default check subroutine
checksub ( __PACKAGE__, sub { (stat $_[0]) [9] } );
# default is not checking
check    ( __PACKAGE__,  0);

# gensub - returns an anonymous subroutine.
# Parameters:
# if one:  filename (full path)
# if more: package, filename [, checkfuncref [, auto ]]

sub gensub {
    my $package = scalar(@_) == 1 ? caller : shift;
    my $file    = shift;
    my $chkfunc = shift || $AL {'checksub'};
    my $auto    = shift || $AL {'auto'} || 'auto';
    my $function;

    {
        ($function = pop (@{[ File::Spec->splitpath($file) ]}) ) =~ s/\..*//;
        
        $file .= $AL {'suffix'} || '.al' unless $file =~ /\.\w+$/;
        unless (-e $file) {
	    my ($filename, $seen);
	    {
		$filename = File::Spec -> catfile ($auto, $package, $file);
		foreach my $d ('.',@INC) { # check current working dir first
		    my $f = File::Spec -> catfile ($d,$filename);
		    if (-e $f) {
			$file = $f;
			last;
		    }
		}
		last if $seen;
		unless (-e $file) {
		    # redo the search with a truncated filename
		    $file =~ s/(\w{12,})(\.\w+)$/substr($1,0,11).$2/e;
		    $seen++;
		    redo;
		}
	    } 
	    die
	      "Can't locate function file '$filename' for package '$package'\n"
		unless -e $file;
	}
    }

    if (my $addr = $AL {'Inc'} -> {"$package\::$function"} ) {
        return $AL {Sub} -> {$addr} -> {'outer'};
    }
    else {
        # file not known yet
        my $inner;
        my $h        = {};
        my $cr       = $chkfunc -> ($file);
        my $subname  = "$package\::$function";

        $h = {



( run in 2.604 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )