File Coverage

blib/lib/PerlReq/Utils.pm
Criterion Covered Total %
statement 9 83 10.8
branch 0 36 0.0
condition 0 12 0.0
subroutine 3 13 23.0
pod 10 10 100.0
total 22 154 14.2


line stmt bran cond sub pod time code
1             package PerlReq::Utils;
2              
3             =head1 NAME
4              
5             PerlReq::Utils - auxiliary routines for L, L and L
6              
7             =head1 DESCRIPTION
8              
9             This module provides the following convenience functions:
10              
11             =over
12              
13             =cut
14              
15             require Exporter;
16             @ISA = qw(Exporter);
17             @EXPORT = qw(argv explode inc path2mod mod2path path2dep mod2dep sv_version verf verf_perl);
18              
19 1     1   8 use strict;
  1         1  
  1         400  
20              
21             =item B
22              
23             Convert file path to module name, e.g. I -> I.
24              
25             =cut
26              
27             sub path2mod ($) {
28 0     0 1   local $_ = shift;
29 0           s/\//::/g;
30 0           s/\.pm$//;
31 0           return $_;
32             }
33              
34             =item B
35              
36             Convert module name to file path, e.g. I -> I.
37              
38             =cut
39              
40             sub mod2path ($) {
41 0     0 1   local $_ = shift;
42 0           s/::/\//g;
43 0           return $_ . ".pm";
44             }
45              
46             =item B
47              
48             Convert file path to conventional dependency name,
49             e.g. I -> I.
50             Note that this differs from RedHat conventional form I.
51              
52             =cut
53              
54             sub path2dep ($) {
55 0     0 1   my $path = shift;
56 0           return "perl($path)";
57             }
58              
59             =item B
60              
61             Convert module name to conventional dependency name,
62             e.g. I -> I.
63             Note that this differs from RedHat conventional form I.
64              
65             =cut
66              
67             sub mod2dep ($) {
68 0     0 1   my $mod = shift;
69 0           return path2dep(mod2path($mod));
70             }
71              
72             =item B
73              
74             Format module version number, e.g. I<2.12> -> I<2.120>. Currently
75             truncated to 3 digits after decimal point, except for all zeroes, e.g.
76             I<2.000> -> I<2.0>.
77              
78             Update. The algorithm has been amended in almost compatible way
79             so that versions do not lose precision when truncated. Now we allow
80             one more I<.ddd> series at the end, but I<.000> is still truncated
81             by default, e.g. I<2.123> -> I<2.123>, I<2.123456> -> I<2.123.456>.
82              
83             =cut
84              
85             sub verf ($) {
86 0     0 1   my $v = shift;
87 0           $v = sprintf "%.6f", $v;
88 0 0 0       $v =~ s/[.]000000$/.0/ ||
      0        
89             $v =~ s/000$// ||
90             $v =~ s/(\d\d\d)$/.$1/ && $v =~ s/[.]000[.]/.0./;
91 0           return $v;
92             }
93              
94             =item B
95              
96             Format Perl version number, e.g. I<5.005_03> -> I<1:5.5.30>.
97              
98             =cut
99              
100             sub verf_perl ($) {
101 0     0 1   my $v = shift;
102 0           my $major = int($v);
103 0           my $minor = ($v * 1000) % ($major * 1000);
104 0           my $micro = ($v * 1000 * 1000) % ($minor * 1000 + $major * 1000 * 1000);
105 0           return "1:$major.$minor.$micro";
106             }
107              
108             =item B
109              
110             Extract version number from B::SV object. v-strings converted to floats
111             according to Perl rules, e.g. I<1.2.3> -> I<1.002003>.
112              
113             =cut
114              
115             sub sv_version ($) {
116 0     0 1   my $sv = shift;
117 0 0         if ($$sv == ${B::sv_yes()}) {
  0            
118             # very special case: (0==0) -> 1
119 0           return 1;
120             }
121 0 0         if ($sv->can("FLAGS")) {
122 1     1   6 use B qw(SVf_IOK SVf_NOK);
  1         2  
  1         389  
123 0 0         if ($sv->FLAGS & SVf_IOK) {
124 0           return $sv->int_value;
125             }
126 0 0         if ($sv->FLAGS & SVf_NOK) {
127 0           return $sv->NV;
128             }
129             }
130 0 0         if ($sv->can("MAGIC")) {
131 0           for (my $mg = $sv->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
132 0 0         next if $mg->TYPE ne "V";
133 0           my @v = $mg->PTR =~ /(\d+)/g;
134 0           return $v[0] + $v[1] / 1000 + $v[2] / 1000 / 1000;
135             }
136             }
137             # handle version objects
138 0           my $vobj = ${$sv->object_2svref};
  0            
139 0           my $vnum;
140 0 0 0       if (ref($vobj) eq "version") {
    0          
141 0           $vnum = $vobj->numify;
142 0           $vnum =~ s/_//g;
143 0           return 0 + $vnum;
144             }
145             elsif ($sv->can("PV") and $sv->PV =~ /^[v.]?\d/) {
146             # upgrade quoted-string version to version object
147 0           require version;
148 0           $vobj = eval { version->parse($sv->PV) };
  0            
149 0 0         if ($@) {
150 0           warn $@;
151 0           return undef;
152             }
153 0           $vnum = $vobj->numify;
154 0           $vnum =~ s/_//g;
155 0           return 0 + $vnum;
156             }
157 0           return undef;
158             }
159              
160             =item B
161              
162             Obtain a list of files passed on the command line. When command line
163             is empty, obtain a list of files from standard input, one file per line.
164             Die when file list is empty. Check that each file exists, or die
165             otherwise. Canonicalize each filename with C
166             function (which makes no checks against the filesystem).
167              
168             =cut
169              
170 1     1   915 use File::Spec::Functions qw(rel2abs);
  1         743  
  1         384  
171             sub argv {
172 0 0   0 1   my @f = @ARGV ? @ARGV : grep length, map { chomp; $_ } <>;
  0            
  0            
173 0 0         die "$0: no files\n" unless @f;
174 0 0         return map { -f $_ ? rel2abs($_) : die "$0: $_: $!\n" } @f;
  0            
175             }
176              
177             =item B
178              
179             Obtain a list of Perl library paths from C<@INC> variable, except for
180             current directory. The RPM_PERL_LIB_PATH environment variable, if set,
181             is treated as a list of paths, seprarated by colons; put these paths
182             in front of the list. Canonicalize each path in the list.
183              
184             Finally, the RPM_BUILD_ROOT environment variable, if set, is treated as
185             installation root directory; each element of the list is then prefixed
186             with canonicalized RPM_BUILD_ROOT path and new values are put in front
187             of the list.
188              
189             After all, only existent directories are returned.
190              
191             =cut
192              
193             my @inc;
194             sub inc {
195 0 0   0 1   return @inc if @inc;
196 0   0       my $root = $ENV{RPM_BUILD_ROOT}; $root &&= rel2abs($root);
  0            
197 0           unshift @inc, map rel2abs($_), grep $_ ne ".", @INC;
198 0           unshift @inc, map rel2abs($_), $ENV{RPM_PERL_LIB_PATH} =~ /([^:\s]+)/g;
199 0 0         unshift @inc, map "$root$_", @inc if $root;
200 0           return @inc = grep -d, @inc;
201             }
202              
203             =item B
204              
205             Split given filename into its prefix (which is a valid Perl library
206             path, according to the inc() function above) and basename. Return empty
207             list if filename does not match any prefix.
208              
209             =cut
210              
211             sub explode ($) {
212 0     0 1   my $fname = shift;
213 0           my ($prefix) = sort { length($b) <=> length($a) }
  0            
214 0           grep { index($fname, $_) == 0 } inc();
215 0 0         return unless $prefix;
216 0           my $delim = substr $fname, length($prefix), 1;
217 0 0         return unless $delim eq "/";
218 0           my $basename = substr $fname, length($prefix) + 1;
219 0 0         return unless $basename;
220 0           return ($prefix, $basename);
221             }
222              
223             1;
224              
225             __END__