File Coverage

blib/lib/Real/Handy.pm
Criterion Covered Total %
statement 98 191 51.3
branch 32 106 30.1
condition 5 15 33.3
subroutine 8 17 47.0
pod 0 10 0.0
total 143 339 42.1


line stmt bran cond sub pod time code
1             package Real::Handy;
2             our $VERSION = '0.24';
3             my $warnings =
4             "\x54\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x15"
5             ^ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00";
6              
7             sub clean_namespace;
8             my %clean_namespace;
9             my @autouse;
10             my %autouse;
11             my $utf8 = 0x00800000;
12             set_autouse( __PACKAGE__ . '=clean_namespace' );
13 0 0   0 0 0 sub set_utf8 { $utf8 = $_[0] ? 0x00800000 : 0 };
14             our $SKIP_CONFIG;
15             1 if $DB::single;
16             sub import{
17 1     1   11 my $self = shift;
18 1         3 my $caller = caller;
19 1         4 my @caller = caller;
20 1         2 do {
21 1         1 my $fixpackage = $caller;
22 1 50       5 if ( $fixpackage ne 'main' ){
23 0         0 $fixpackage=~s/::/\//g;
24 0         0 $fixpackage=~s/\.pm|\z/.pm/;
25 0         0 $INC{ $fixpackage } = $caller[1];
26             }
27             };
28            
29 1 50       10 $SKIP_CONFIG || do {
30 1         3 $SKIP_CONFIG = 1;
31 1         3 _require_config(@_);
32 1         2 1;
33             };
34 1         7 $self->customize_module( $caller, \@_ );
35 1 50       7 if ( $autouse{ $caller } ){
36             # delete ${ $caller . "::" }{AUTOLOAD};
37             }
38 1         3 for my $module ( @autouse ) {
39 1         3 my $state = $autouse{$module};
40 1 50       5 if ( $state->{var} ) {
41 0         0 for ( @{ $state->{var} } ) {
  0         0  
42 0         0 my $sym = substr($_,0,1);
43 0         0 my $symname = $module . "::" . substr($_,1);
44 0 0       0 my $ref = $sym eq '%' ? \%{$symname} : undef;
  0         0  
45 0         0 *{ $caller . "::" . substr($_,1) } = $ref;
  0         0  
46             }
47             }
48 1 50       4 if ( $module eq $caller ) { # Fix: remain own methods untouched
49 0         0 next;
50             }
51 1 50       4 if ( $state->{sub} ) {
52 1         2 for ( @{ $state->{sub} } ) {
  1         3  
53 1         9 *{ $caller . "::" . $_ } = \&{ $module . "::" . $_ };
  1         6  
  1         5  
54 1         7 $clean_namespace{$caller}{$_} = 1;
55             }
56             }
57             }
58 1 50       6 if ( $] >= 5.016){
59 1         11 require feature;
60 1         20 @_ = ();
61 1         4 @_ = qw(feature say switch);
62 1         144 goto &feature::import;
63             }
64             }
65             sub bn{
66 5     5 0 8 my $dd = shift;
67 5         7 my $dev = shift;
68 5         5 my $inode = shift;
69 5 50       239 opendir my $f, $dd or die "Can't open dd";
70 5         339 while( my $g = readdir $f ){
71 31         645 my $stat = [ lstat "$dd/$g" ];
72 31 100       171 next if $stat->[1] != $inode;
73 5 50       12 next if $stat->[0] != $dev;
74 5 50       11 next if $g eq '.';
75 5 50       11 next if $g eq '..';
76 5 100       81 return "$dd/$g" if $dd ne '/';
77 1         67 return "/$g";
78             }
79 0         0 return;
80             }
81 0     0   0 sub _croak{ require Carp ; Carp->import; goto &croak; };
  0         0  
  0         0  
82             sub der{
83 6     6 0 10 my $dd = shift;
84 6   50     21 my $limit = shift // 16;
85 6 50       129 _croak "not a directory" unless -d $dd;
86 6 50       14 _croak "limit exceed" unless $limit;
87 6         140 my @st = lstat $dd;
88 6         88 my @rt = lstat '/';
89 6 100 66     36 return '/' if $st[0] == $rt[0] && $st[1] == $rt[1];
90 5         21 my @limit = split '/', $dd;
91 5         30 my $before = der( $dd . '/' . '..' );
92 5         17 return bn( $before, $st[0], $st[1] );
93             }
94              
95              
96             sub inc_remove{
97 0     0 0 0 @INC = grep $_[0] ne $_, @INC;
98 0 0       0 @INC = grep $_[1] ne $_, @INC if $_[1];
99             }
100              
101             sub _require_config{
102             # set my @INC
103 1     1   1 my $workspace;
104 1         2 my $ourdir = __FILE__;
105 1         26 $ourdir=~s/\/[^\/]+\/*\z// for 1..2;
106 1         4 $ourabs = der( $ourdir );
107 1 50       6 if ( $ourabs ){
108 1 50       24 if ( -f "$ourabs/handy.pl" ){
109 0 0       0 if ( $ourabs=~s#/lib\z## ){
110 0         0 inc_remove( $ourdir );
111 0         0 set_workspace( $ourabs );
112 0         0 return;
113             }
114             }
115             }
116 1         2 my @PWD;
117 1 50       5 if ( @_ ) {
118 0         0 push @PWD, @_;
119             };
120 1         8 for ( map "$_", grep $_, $a = $ENV{'DOCUMENT_ROOT'} ){
121 0 0       0 last unless $_;
122 0         0 s#\w+/?\z##;
123 0         0 push @PWD, $_;
124             };
125 1         2 local($a,$b);
126 1         8 for ( grep $_, $b = $ENV{PWD}, @PWD, $0, $a = $ENV{project} ){
127 2 50       14 if (m#(/home/sites/[-\.\w]+|/home/\w+)#){
128 0         0 my $candidate = substr $_, 0, $+[0];
129 0 0       0 if ( -f "$candidate/config/site.pl" ){
130 0         0 $workspace = $candidate ;
131 0         0 last ;
132             }
133             }
134             }
135 1 50       4 if ( !$workspace ){
136 1         32 warn "Can't load proper config ( ENV{project} = '$ENV{project}'";
137 1         4 return;
138             }
139 0         0 set_workspace( $workspace );
140             }
141              
142             sub set_workspace{
143 0     0 0 0 my $location = shift;
144 0 0       0 $location = shift if UNIVERSAL::isa( $location, 'Real::Handy' );
145 0 0       0 return unless -d $location;
146 0         0 for ( $Real::Handy::Workname = $Real::Handy::Workspace = $location){
147 0         0 s/\/+\z//;
148 0         0 s/.*\///;
149             };
150 0         0 my $l = "$location/lib";
151 0 0       0 if ( ref $INC[0] ){
152 0 0       0 splice @INC, 1,0,($l) if -d $l;
153             }
154             else {
155 0 0       0 unshift @INC, $l if -d $l;
156             }
157 0         0 my ( $c ) = grep -f -s $_, "$location/lib/handy.pl", "$location/config/site.pl";
158 0 0 0     0 require $c if -f $c && -s $c;
159             };
160              
161              
162             sub customize_module{
163 1     1 0 3 my $self = shift;
164 1         3 my $caller = shift;
165             # strict refs, subs, vars, utf8
166 1         4 $^H |= ( 0x00000002 | 0x00000200 | 0x00000400 | $utf8 );
167 1         12 ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ $warnings;
168 1 50   0   3 *{ $caller . '::CLASS' } = sub () { $caller; } unless exists &{ $caller . '::CLASS' };
  1         7  
  0         0  
  1         16  
169 1         15 $^H{ $_ } = 1 for qw/feature_say feature_switch feature_state/;
170             }
171             my %cleanup_autoload;
172             sub cleanup_autoload{
173 7     7 0 121800 my $s = $cleanup_autoload{ $_[1] };
174 7 50       31 $s->() if $s;
175 7         12877 undef;
176             }
177             unshift @INC, \&cleanup_autoload;
178             sub set_autoload {
179 1     1 0 2 my ( $module ) = @_;
180              
181              
182 1         3 my $require = "require $module; ";
183              
184 1         6 s/::/\//g for (my $pm = $module . ".pm");
185             my $cleanup = sub {
186 0     0   0 delete ${ $module . "::" }{AUTOLOAD};
  0         0  
187 0         0 delete $cleanup_autoload{ $pm };
188             # print STDERR "Cleanup $module<=>$pm\n";
189 1         5 };
190 1         6 $cleanup_autoload{ $pm } = $cleanup;
191              
192 1 50 33     10 if ( !$INC{$pm} || $INC{$pm} eq 'Stub' ) {
193 0         0 *{ $module . "::AUTOLOAD" } = sub {
194 0     0   0 our $AUTOLOAD;
195 0 0       0 return if $AUTOLOAD =~ m/\bDESTROY\z/;
196 0         0 my $autoload = $AUTOLOAD;
197             {
198 0         0 delete ${ $module . "::" }{AUTOLOAD};
  0         0  
  0         0  
199 0         0 delete $cleanup_autoload{ $pm };
200 0 0       0 return if caller() eq $module;
201 0 0 0     0 delete $INC{$pm} if ($INC{$pm}||'') eq 'Stub';
202 0         0 eval $require;
203 0 0       0 die $@ if $@;
204             };
205 0 0       0 goto &$autoload if exists &$autoload;
206 0 0       0 if ( UNIVERSAL::isa( $_[0], $module ) ) {
207 0         0 my $sub;
208 0         0 s/.*::// for my $subname = $autoload;
209 0         0 $sub = UNIVERSAL::can( $_[0], $subname );
210 0 0       0 goto &$sub if $sub;
211 0         0 $sub = UNIVERSAL::can( $_[0], 'AUTOLOAD' );
212 0 0       0 if ($sub) {
213 0         0 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
214 0         0 return $_[0]->$subname( @_[ 1 .. $#_ ] );
215             }
216             }
217 0         0 require Carp;
218 0         0 local $Carp::CarpLevel = 1;
219 0         0 Carp::croak("Undefined procedure $autoload called");
220 0         0 };
221             }
222             }
223             sub set_autouse{
224 1     1 0 6 while (@_) {
225 1 50       5 if ($_[0]=~m/\n/){
226 0         0 push @_, split " ", $_[0];
227 0         0 next;
228             }
229 1         9 my ( $module, $param ) = split "=", $_[0], 2;
230              
231 1         2 my $state = $autouse{ $module };
232 1 50       4 if ( ! $state ){
233 1         3 $state = $autouse{ $module } = {};
234 1         3 push @autouse, $module;
235 1         3 set_autoload( $module );
236             }
237 1 50       5 if ($param) {
238 1   50     4 my @all_import = split ",", $param || '';
239 1         5 my @var_import = grep m/^[%\@\$]/, @all_import;
240 1         4 my @sub_import = grep m/^\w/, @all_import;
241 1 50       5 if ( @var_import ){
242 0         0 $state->{var} = \@var_import;
243             }
244 1 50       3 if (@sub_import){
245 1         41 $state->{sub} = \@sub_import;
246             }
247             }
248             }
249             continue {
250 1         4 shift @_;
251             }
252             }
253             sub clean_namespace {
254 0     0 0   my $caller = caller;
255 0 0         if (ref $_[0]){
256 0           $caller = ${ shift() }[0];
  0            
257             }
258 0 0         return 1 if caller eq __PACKAGE__;
259 0           my $x = delete $clean_namespace{ $caller };
260 0           my @x;
261 0 0         @x = keys %$x if $x;
262 0           push @x, 'clean_namespace';
263 0           push @x, @_;
264              
265 0           for (@x) {
266 0 0         next unless m/^\w+\z/;
267 0           delete ${ $caller . '::' }{$_};
  0            
268             }
269 0           'yes!';
270             }
271             sub unimport{
272 0     0     $^H ^= $^H & 0x00000002;
273             }
274             # load site define options
275             # Prevent Real::Handy loading twice
276             $INC{'Real/Handy.pm'} ||= 'S';
277             1;
278              
279             # Preloaded methods go here.
280             __END__