File Coverage

blib/lib/only/matching.pm
Criterion Covered Total %
statement 70 73 95.8
branch 12 16 75.0
condition 8 12 66.6
subroutine 18 18 100.0
pod n/a
total 108 119 90.7


line stmt bran cond sub pod time code
1             package only::matching;
2              
3             =pod
4              
5             =head1 NAME
6              
7             only::matching - Check that two Perl files are version-locked
8              
9             =head1 SYNOPSIS
10              
11             At the start of your application's main module...
12              
13             package Foo;
14            
15             use strict;
16             use vars qw{$VERSION};
17             BEGIN {
18             $VERSION = '1.00';
19             }
20              
21             # ...code...
22              
23             And at the top of your front-end script that loads the module...
24              
25             #!/usr/bin/perl
26            
27             use strict;
28             use vars qw{$VERSION};
29             BEGIN {
30             $VERSION = '1.00';
31             }
32            
33             # Load our matching module
34             use only::matching 'Foo';
35            
36             # ...code...
37              
38             =head1 DESCRIPTION
39              
40             The L module provides a great deal of interesting and rich
41             functionality, allowing you to install multiple copies of modules
42             and limit the version of a module you load to various arbitrary
43             patterns.
44              
45             However, installing it creates some additional directories to your
46             library tree for the multi-version support, and you have to be
47             explicit about the versions you want to be compatible with.
48              
49             This means for the case where you have a script and a module
50             and it is important that no matter what happens with system paths
51             or @INC paths, the script B loads the matching module,
52             you need to change the code each revision to refer to the new
53             version, or you have to do something like...
54              
55             use only 'Foo' => $VERSION;
56              
57             Like L, B is a task-specific version
58             of L for the specific case of having version-locked script
59             to module loading.
60              
61             Instead of the above, you say...
62              
63             use only::matching 'Foo';
64              
65             ... and you are guaranteed to get the correctly matching module
66             version.
67              
68             Because it only needs such limited and specific functionality
69             B also removes the multiversion support and is
70             contained entirely in one small .pm file, to make bundling it a
71             little easier as well.
72              
73             =head2 Providing Params
74              
75             The syntax for B is the same as for L,
76             except without the version number string.
77              
78             Thus to load a module with default imports:
79              
80             # These are equivalent
81             use Foo;
82             use only::matching 'Foo';
83              
84             To load a module passing params
85              
86             # These are also equivalent
87             use Foo => 'bar', 'baz';
88             use only::matching Foo => 'bar', 'baz';
89              
90             To load a module explicitly without calling import
91              
92             # And these are equivalent
93             use Foo ();
94             use only::matching 'Foo', [];
95              
96             Other than this, there's very little that you need to know.
97              
98             =cut
99              
100 2     2   2491 use 5.005;
  2         6  
  2         69  
101 2     2   12 use strict;
  2         4  
  2         61  
102 2     2   19 use Carp ();
  2         3  
  2         36  
103 2     2   9 use vars qw{$VERSION};
  2         3  
  2         125  
104             BEGIN {
105 2     2   800 $VERSION = '0.02';
106             }
107              
108             sub import {
109 12     12   16329 my $class = shift;
110              
111             # What are we loading
112 12         24 my($mod, @imports) = @_;
113 12 100       67 @imports = () unless @imports;
114              
115             # What called us
116 12         27 my $pkg = caller();
117              
118 12         35 SCOPE: {
119             # eval sometimes interferes with $!
120 12         15 local ($!);
121              
122 12 50 66     91 if ( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) {
  1 100 66     3  
      66        
123             # probably a version check. Perl needs to see the bare number
124             # for it to work with non-Exporter based modules.
125 0         0 eval <<"END_PERL";
126             package $pkg;
127             use $mod $imports[0];
128             END_PERL
129              
130             } elsif ( @imports == 1 and ref($imports[0]) eq 'ARRAY' and @{$imports[0]} == 0 ) {
131             # Called with [], which turns into "use module ();"
132 1     1   46 eval <<"END_PERL";
  1         5  
  1         12  
  1         9  
133             package $pkg;
134             use $mod ();
135             END_PERL
136              
137             } else {
138             # Just a regular call, pass on imports
139 11     1   872 eval <<"END_PERL";
  1     1   646  
  1     1   163  
  1     1   7  
  1     1   6  
  1     1   1  
  1     1   5  
  1     1   5  
  1     1   2  
  1     1   3  
  1     1   6  
  1         2  
  1         5  
  1         14  
  1         3  
  1         11  
  1         9  
  1         4  
  1         10  
  1         7  
  1         2  
  1         32  
  1         6  
  1         2  
  1         5  
  1         6  
  1         2  
  1         5  
  1         5  
  1         1  
  1         4  
  1         7  
  1         3  
  1         4  
140             package $pkg;
141             use $mod \@imports;
142             END_PERL
143             }
144             }
145              
146             # Rethrow any errors
147 12 50       203 Carp::croak($@) if $@;
148              
149             # Get the versions of caller and module via official channels
150 12         170 my $pkg_version = $pkg->VERSION;
151 7         70 my $mod_version = $mod->VERSION;
152              
153             # Check that both exist and are the same thing.
154             # Since they should be IDENTICAL, check with BOTH of == and eq
155 7 100       30 unless ( defined $pkg_version ) {
156 1         189 Carp::croak("Calling package $pkg does not have a version");
157             }
158 6 50       16 unless ( defined $mod_version ) {
159 0         0 Carp::croak("$mod does not have a version");
160             }
161 6 50       17 unless ( ref($pkg_version) eq ref($mod_version) ) {
162 0         0 Carp::croak("Caller $pkg and module $mod version ref type mismatch");
163             }
164 6         23 local $^W = 0;
165 6 100 66     31 unless ( $pkg_version eq $mod_version and $pkg_version == $mod_version ) {
166 3         1469 Carp::croak("$mod version $mod_version does not match caller $pkg $pkg_version");
167             }
168              
169             # Looks good
170 3         26 return 1;
171             }
172              
173             1;
174              
175             =pod
176              
177             =head1 SUPPORT
178              
179             This module is stored in an Open Repository at the following address.
180              
181             L
182              
183             Write access to the repository is made available automatically to any
184             published CPAN author, and to most other volunteers on request.
185              
186             If you are able to submit your bug report in the form of new (failing)
187             unit tests, or can apply your fix directly instead of submitting a patch,
188             you are B encouraged to do so as the author currently maintains
189             over 100 modules and it can take some time to deal with non-Critcal bug
190             reports or patches.
191              
192             This will guarentee that your issue will be addressed in the next
193             release of the module.
194              
195             If you cannot provide a direct test or fix, or don't have time to do so,
196             then regular bug reports are still accepted and appreciated via the CPAN
197             bug tracker.
198              
199             L
200              
201             For other issues, for commercial enhancement or support, or to have your
202             write access enabled for the repository, contact the author at the email
203             address above.
204              
205             =head1 AUTHORS
206              
207             Adam Kennedy Eadamk@cpan.orgE
208              
209             =head1 SEE ALSO
210              
211             L, L
212              
213             =head1 COPYRIGHT
214              
215             Copyright 2006 Adam Kennedy.
216              
217             This program is free software; you can redistribute
218             it and/or modify it under the same terms as Perl itself.
219              
220             The full text of the license can be found in the
221             LICENSE file included with this module.
222              
223             =cut