NAME

Array::Sticky::INC - lock your @INC hooks in place

SYNOPSIS

Let's say you've written a module which hides the existence of certain modules:

package Module::Hider;

my %hidden;
my $set_up_already;

sub hider {
    my ($module) = pop();
    $module =~ s{/}{::}g;
    $module =~ s{\.pm$}{};

    return undef if exists $hidden{$module};
}

sub import {
    my ($class, @to_hide) = @_;

    @hidden{@to_hide} = @to_hide;
    if (! $set_up_already++) {
        # this works until some other piece of code issues a
        #     use lib '/somewhere';
        # or
        #     unshift @INC, '/over';
        # or
        #     $INC[0] = '/the-rainbow';
        unshift @INC, \&hider;
    }
}

1;

To hide a module using this Module::Hider, you'd write:

use Module::Hider qw(strict warnings LWP::UserAgent);

Now any code which is running with that in place would encounter errors attempting to load strict.pm, warnings.pm, and LWP/UserAgent.pm.

Hiding modules is pretty nice; see Devel::Hide for a stronger treatment of why you might care to do so.

But there is one downside to the "stick a coderef in @INC" trick: if any piece of code manually updates @INC to steal the primary spot away from your coderef, then your coderef may be rendered ineffective.

This module provides a simple interface to tie @INC in a way that you specify so that attempts to manipulate @INC succeed in a way that you choose.

Now you may write Module::Hider like this:

package Module::Hider;

use Array::Sticky::INC;

my %hidden;
my $set_up_already;

sub hider {
    my ($module) = pop();
    $module =~ s{/}{::}g;
    $module =~ s{\.pm$}{};

    return undef if exists $hidden{$module};
}

sub import {
    my ($class, @to_hide) = @_;

    @hidden{@to_hide} = @to_hide;
    if (! $set_up_already++) {
        unshift @INC, \&hider;
        Array::Sticky::INC->make_sticky;
    }
}

1;

RECIPES

This module only makes the foremost element of @INC sticky. If you need to make different elements of @INC sticky, then use Array::Sticky:

Making the tail of @INC sticky

If you're using like The::Net or Acme::Intraweb to automatically install modules that you're missing, then you might want to lock their behaviors to the end of @INC:

package My::The::Net;

use The::Net;
use Array::Sticky;

sub import {
    tie @INC, 'Array::Sticky', body => [@INC], tail => [shift @INC];
}

SEE ALSO

  • Devel::INC::Sorted solves this same problem slightly differently.

  • 'perldoc -f require' and 'perldoc perltie' talk about code hooks in @INC, and tied arrays, respectively

  • Acme::Intraweb - places a coderef at the tail of @INC

  • The::Net - places a coderef at the tail of @INC

  • Devel::Hide - places a coderef at the head of @INC

  • Test::Without::Module - places a coderef at the head of @INC

BUGS AND LIMITATIONS

If you do something like:

local @INC = @INC;
unshift @INC, '/some/path';

then this module won't be able to preserve your hooks at the head of @INC.

Please report bugs on this project's Github Issues page: http://github.com/belden/perl-array-sticky/issues.

CONTRIBUTING

The repository for this software is freely available on this project's Github page: http://github.com/belden/perl-array-sticky. You may fork it there and submit pull requests in the standard fashion.

COPYRIGHT AND LICENSE

(c) 2013 by Belden Lyman

This library is free software: you may redistribute it and/or modify it under the same terms as Perl itself; either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.

}

1;

__END__ =pod

NAME

Devel::TraceINC - Trace who is loading which perl modules

VERSION

version 1.100850

SYNOPSIS

$ perl -MDevel::TraceINC t/01_my_test.t
Test/More.pm loaded from package main, file t/01_my_test.t, line 6
Test/Builder/Module.pm loaded from package Test::More, file /usr/local/svn/perl/Test/More.pm, line 22
Test/Builder.pm loaded from package Test::Builder::Module, file /usr/local/svn/perl/Test/Builder/Module.pm, line 3
Exporter/Heavy.pm loaded from package Exporter, file /System/Library/Perl/5.8.6/Exporter.pm, line 17
...

DESCRIPTION

I had a situation where a program was loading a module but I couldn't find where in the code it was loaded. It turned out that I loaded some module, which loaded another module, which loaded the module in question. To be able to track down who loads what, I wrote Devel::TraceINC.

Just use() the module and it will print a warning every time a module is searched for in @INC, i.e., loaded.

INSTALLATION

See perlmodinstall for information and options on installing Perl modules.

BUGS AND LIMITATIONS

No bugs have been reported.

Please report any bugs or feature requests through the web interface at http://rt.cpan.org/Public/Dist/Display.html?Name=Devel-TraceINC.

AVAILABILITY

The latest version of this module is available from the Comprehensive Perl Archive Network (CPAN). Visit http://www.perl.com/CPAN/ to find a CPAN site near you, or see http://search.cpan.org/dist/Devel-TraceINC/.

The development version lives at http://github.com/marcelgrunauer/Devel-TraceINC/. Instead of sending patches, please fork this project using the standard git and github infrastructure.

AUTHOR

Marcel Gruenauer <marcel@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2007 by Marcel Gruenauer.

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