File Coverage

blib/lib/lib/relative.pm
Criterion Covered Total %
statement 23 23 100.0
branch 3 4 75.0
condition n/a
subroutine 7 7 100.0
pod n/a
total 33 34 97.0


line stmt bran cond sub pod time code
1             package lib::relative;
2              
3 1     1   72567 use strict;
  1         12  
  1         24  
4 1     1   5 use warnings;
  1         1  
  1         21  
5 1     1   3 use Cwd ();
  1         2  
  1         10  
6 1     1   4 use File::Basename ();
  1         2  
  1         10  
7 1     1   3 use File::Spec ();
  1         2  
  1         19  
8 1     1   352 use lib ();
  1         515  
  1         118  
9              
10             our $VERSION = '1.001';
11              
12             sub import {
13 3     3   1817 my ($class, @paths) = @_;
14 3         10 my $file = (caller)[1];
15 3 50       233 my $dir = -e $file ? File::Basename::dirname(Cwd::abs_path $file) : Cwd::getcwd;
16 3 100       9 lib->import(map { File::Spec->file_name_is_absolute($_) ? $_ : File::Spec->catdir($dir, $_) } @paths);
  3         42  
17             }
18              
19             1;
20              
21             =head1 NAME
22              
23             lib::relative - Add paths relative to the current file to @INC
24              
25             =head1 SYNOPSIS
26              
27             # Path is relative to this file, not current working directory
28             use lib::relative 'path/to/lib';
29             use lib::relative '../../lib';
30            
31             # Add two lib paths, as in lib.pm
32             use lib::relative 'foo', 'bar';
33            
34             # Absolute paths are passed through unchanged
35             use lib::relative 'foo/baz', '/path/to/lib';
36            
37             # Equivalent code using core modules
38             use Cwd ();
39             use File::Basename ();
40             use File::Spec ();
41             use lib File::Spec->catdir(File::Basename::dirname(Cwd::abs_path __FILE__), 'path/to/lib');
42              
43             =head1 DESCRIPTION
44              
45             Adding a path to L<@INC|perlvar/"@INC"> to load modules from a local directory
46             may seem simple, but has a few common pitfalls to be aware of. Directly adding
47             a relative path to C<@INC> means that any later code that changes the current
48             working directory will change where modules are loaded from. This applies to
49             the C<.> path that used to be in C<@INC> by default until perl 5.26.0, or a
50             relative path added in code like C, and may be a
51             vulnerability if such a location is not supposed to be writable. Additionally,
52             the commonly used L module relies on interpreter state and the path to
53             the original script invoked by the perl interpreter, sometimes requiring
54             workarounds in uncommon cases like generated or embedded code. This module
55             proposes a more straightforward method: take a path relative to the
56             L, absolutize it, and add it to
57             C<@INC>.
58              
59             If this module is already available to be loaded, it can be used as with
60             L.pm, passing relative paths, which will be absolutized relative to the
61             current file then passed on to L. Multiple arguments will be separately
62             absolutized, and absolute paths will be passed on unchanged.
63              
64             For cases where this module cannot be loaded beforehand, the last section of
65             the L can be copy-pasted into a file to perform the same task.
66              
67             =head1 CAVEATS
68              
69             Due to C<__FILE__> possibly being a path relative to the current working
70             directory, be sure to use C or the equivalent code from
71             L as early as possible in the file. If a C occurs before
72             this code, it will add the incorrect directory path.
73              
74             All file paths are expected to be in a format appropriate to the current
75             operating system, e.g. C<..\\foo\\bar> on Windows. L can
76             be used to form directory paths portably.
77              
78             =head1 BUGS
79              
80             Report any issues on the public bugtracker.
81              
82             =head1 AUTHOR
83              
84             Dan Book
85              
86             =head1 COPYRIGHT AND LICENSE
87              
88             This software is Copyright (c) 2017 by Dan Book.
89              
90             This is free software, licensed under:
91              
92             The Artistic License 2.0 (GPL Compatible)
93              
94             =head1 SEE ALSO
95              
96             L, L, L