1 |
package MGATools::rpmsrate; |
2 |
|
3 |
use strict; |
4 |
use MDK::Common; |
5 |
|
6 |
require Exporter; |
7 |
use URPM; |
8 |
our @ISA = qw(Exporter); |
9 |
our @EXPORT = qw(cleanrpmsrate); |
10 |
|
11 |
=head1 NAME |
12 |
|
13 |
Mageia rpmsrate tools |
14 |
|
15 |
=head1 SYNOPSYS |
16 |
|
17 |
require MGATools::rpmsrate; |
18 |
|
19 |
=head1 DESCRIPTION |
20 |
|
21 |
<MGATools::rpmsrate> includes Mageia rpmsrate tools. |
22 |
|
23 |
=head1 COPYRIGHT |
24 |
|
25 |
Copyright (C) 2000,2001,2002,2003,2004 Mandriva <warly@mandriva.com> |
26 |
|
27 |
This program is free software; you can redistribute it and/or modify |
28 |
it under the terms of the GNU General Public License as published by |
29 |
the Free Software Foundation; either version 2, or (at your option) |
30 |
any later version. |
31 |
|
32 |
This program is distributed in the hope that it will be useful, |
33 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
34 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
35 |
GNU General Public License for more details. |
36 |
|
37 |
You should have received a copy of the GNU General Public License |
38 |
along with this program; if not, write to the Free Software |
39 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
40 |
|
41 |
=cut |
42 |
|
43 |
# must preread to get locale guessed packages |
44 |
sub preread_rpmsrate { |
45 |
my ($rpmsrate, $norpmsrate) = @_; |
46 |
my (@rpmsrate, %potloc); |
47 |
foreach (cat_or_die($rpmsrate)) { |
48 |
chomp; |
49 |
s/#.*//; |
50 |
#s/\s*$//; |
51 |
if (/^(\s*)$/) { |
52 |
push @rpmsrate, [ '', 0, '', [] ]; |
53 |
next; |
54 |
} |
55 |
if (/^(\S+)(.*)$/) { |
56 |
push @rpmsrate, [ 0, 0, $1, [], $2 ]; |
57 |
next; |
58 |
} |
59 |
if (/^(\s*)([1-5])?(\s?[0-9A-Z_]+)$/) { |
60 |
push @rpmsrate, [ $1, $2, $3, [] ]; |
61 |
next; |
62 |
} |
63 |
my ($indent, $r, $flags, $data) = /^(\s*)([1-5])?(\s*(?:(?:(?:!\s*)?[0-9A-Z_]+(?:"[^"]*")?(?:\s+(?:\|\|\s+)?)*)+\s+)|\s*)(.*)$/; |
64 |
# postfix is just used not to break the diff when checking if the result is correct |
65 |
my ($postfix) = $data =~ /(\s*)$/; |
66 |
my (@data, $i); |
67 |
foreach ([$data =~ /(?:^|\s)(\S+)-(?:\S+)\s+\1-(?:\S+)(?:\s|$)/g], [split ' ', $data]) { |
68 |
$data[$i++] = [ @$norpmsrate ? any { my $r = $_; any { $r =~ /$_/ } @$norpmsrate ? @{[]} : $r } @$_ : @$_ ]; |
69 |
} |
70 |
$potloc{$_} = [] foreach @{$data[0]}; |
71 |
push @rpmsrate, [ $indent,$r, $flags, $data[1], $postfix ]; |
72 |
} |
73 |
(\@rpmsrate, \%potloc); |
74 |
} |
75 |
|
76 |
sub lookup_pkg { |
77 |
my ($key, $fullpath, $urpm2, $o_urpm) = @_; |
78 |
|
79 |
# try to lookup package in urpm first (if we got an $urpm and if media were parsed): |
80 |
return $o_urpm->{rpm}{$o_urpm->{rpmkey}{key}{$key}} if ref($o_urpm); |
81 |
|
82 |
# if package is not urpmi' synthesis, try to parse it directly: |
83 |
my $id = $urpm2->parse_rpm($fullpath); |
84 |
return $urpm2->{depslist}[$id]; |
85 |
} |
86 |
|
87 |
sub check_if_expandable { |
88 |
my ($key, $raw, $fullpath, $potloc, $locale, $localized_pkg, $urpm2, $o_urpm) = @_; |
89 |
my ($pg, $loc) = $raw =~ /^(.*)-([^-+]+)$/; |
90 |
return if !$pg || !$loc; |
91 |
return if !$potloc->{$pg}; |
92 |
|
93 |
my $pkg = lookup_pkg($key, $fullpath, $urpm2, $o_urpm); |
94 |
|
95 |
# still nothing? bailout: |
96 |
if (!$pkg) { |
97 |
print "ERROR cleanrpmsrate: parse_rpm $fullpath ($key) failed\n"; |
98 |
next; |
99 |
} |
100 |
|
101 |
# some i18n packages does not require the same locale, e.g. kde-i18n-nb and nn requires locales-no |
102 |
# if (grep { s/locales-// && $loc =~ /^$_(_|$)/ } @{$header{REQUIRENAME}}) { |
103 |
if (any { /^locales-...?$/ } $pkg->requires) { |
104 |
push @{$locale->{$pg}}, $loc; |
105 |
$localized_pkg->{"$pg-$loc"} = 1; |
106 |
} |
107 |
} |
108 |
|
109 |
# function copied from Mkcd::Tools |
110 |
sub cleanrpmsrate { |
111 |
my ($rpmsrate_file, $output, $norpmsrate, $reprpms, $o_urpm) = @_; |
112 |
$norpmsrate ||= []; |
113 |
|
114 |
my ($rpmsrate, $potloc) = preread_rpmsrate($rpmsrate_file, $norpmsrate); |
115 |
|
116 |
my (%rpms, $text, %rate, %section, %keyword, %locale, %localized_pkg); |
117 |
my @plain_flags = qw(INSTALL LIVE); |
118 |
my $kernel_like = "((?:(?:NVIDIA_)?kernel|NVIDIA_nforce|cm2020).*)"; |
119 |
my $dkms_like = '(.*)([-_])kernel-([0-9]+(?:\.[0-9]+){2,3}-\w+-[0-9]+(?:.[^.]+){0,2}\.?mga\d+)(.*)'; |
120 |
my $rpmsrate_dkms_like = "(.*[-_]kernel)(.*)"; |
121 |
my $urpm2 = URPM->new; |
122 |
|
123 |
foreach my $dir (keys %$reprpms) { |
124 |
foreach (@{$reprpms->{$dir}}) { |
125 |
my $rpm = "$_.rpm"; |
126 |
my $key = $_; |
127 |
s/-[^-]+-[^-]+\.[^.]+$// or next; |
128 |
any { $rpm =~ /$_/ } @$norpmsrate and next; |
129 |
|
130 |
if (/(.*?)([_-]*[\d._]+)(-.*)?-devel$/ || /^$kernel_like(-[^.]+(?:\.[^.]+){3,6}\.?mga\d+)$/) { |
131 |
if (!$rpms{"$1$3"} || URPM::ranges_overlap("== $2", "> $rpms{'$1$3'}")) { |
132 |
$rpms{"$1$3"} = [ $2, $1, $3 ]; |
133 |
} |
134 |
if (/^$kernel_like-(\d+\.\d+)(.*)/) { |
135 |
$rpms{"$1-$2"} = [ $3, "$1-$2" ]; |
136 |
} |
137 |
} elsif (/^$dkms_like$/) { |
138 |
my $vname = "$1$2kernel$4"; |
139 |
if (!$rpms{$vname}) { |
140 |
$rpms{$vname} = [ $3, $vname ]; |
141 |
} elsif (URPM::ranges_overlap("== $3", "> $rpms{$vname}[0]")) { |
142 |
$rpms{$vname} = [ $3, $vname ]; |
143 |
} |
144 |
} else { |
145 |
check_if_expandable($key, $_, "$dir/$rpm", $potloc, \%locale, \%localized_pkg, $urpm2, $o_urpm); |
146 |
} |
147 |
} |
148 |
} |
149 |
|
150 |
my (%done, @flags, @tree_rate, $prev_level); |
151 |
foreach (@$rpmsrate) { |
152 |
if (!$_->[0]) { |
153 |
$text .= "$_->[2]$_->[4]\n"; |
154 |
@flags = $_->[2] if $_->[2]; |
155 |
next; |
156 |
} |
157 |
|
158 |
my ($indent, $r, $flags, $data, $postfix) = @$_; |
159 |
my $level = (length $indent)/2 - 1; |
160 |
my $rate; |
161 |
if ($r) { |
162 |
#print "tree_rate[$level] = $r\n"; |
163 |
$rate = $r; |
164 |
$tree_rate[$level] = $r; |
165 |
} else { |
166 |
if (@$data) { |
167 |
if ($level > $prev_level) { |
168 |
$level--; |
169 |
} else { |
170 |
# fix a syntax error in rpmsrate such as |
171 |
# A |
172 |
# 1 toto |
173 |
# B tata <--- |
174 |
# 4 titi |
175 |
@$data = (); |
176 |
} |
177 |
} |
178 |
$rate = $tree_rate[$level]; |
179 |
} |
180 |
|
181 |
$prev_level = $level; |
182 |
@flags = @flags[0 .. $level]; |
183 |
push @flags, split(' ', $flags); |
184 |
#push @flags, grep { s/\s//; !/(\|\||[A-Z_]+"[^"]+")/ } split(' ', $flags); |
185 |
|
186 |
if (!@$data) { |
187 |
$text .= "$indent$r$flags$postfix\n"; |
188 |
next; |
189 |
} |
190 |
|
191 |
my @k; |
192 |
my $flat_path = join ' ', @flags; |
193 |
foreach (@$data) { |
194 |
my $c = $_; |
195 |
next if ref $done{$_} && any { $flat_path eq $_ } @{$done{$_}}; |
196 |
|
197 |
my $is_plain_flag = member($flags[0], @plain_flags); |
198 |
|
199 |
die "FATAL: too complicated flags for duplicate entry $c ($flat_path and " . join ',', @{$done{$_}} |
200 |
if !$is_plain_flag && @flags > 1 && any { |
201 |
my ($f) = $flat_path =~ /^[^ ]+ (.*)/; |
202 |
!/^[^ ]+ (.*)/ || $1 ne $f; |
203 |
} @{$done{$_}}; |
204 |
|
205 |
my ($name) = /(.*)-[^-]+/; |
206 |
my ($e, $do); |
207 |
|
208 |
if (!$is_plain_flag) { |
209 |
my ($a, $b); |
210 |
if ((s/(-devel)// ? ($b = "-devel") : /^$kernel_like/) && |
211 |
($rpms{$_} || (defined $rpms{"lib$_"} and $a = "lib") || (defined $rpms{"lib64$_"} and $a = "lib64") |
212 |
|| (s/^lib(.*?)[_-]*[\d._]*(-.*)?$/$1$2/g && defined $rpms{"lib64$_"} and $a = 'lib64'))) { |
213 |
warn ">> looking at $c\n"; |
214 |
$e = $rpms{"$a$_"}[1] . $rpms{"$a$_"}[0] . $rpms{"$a$_"}[2] . $b; |
215 |
$do = 1; |
216 |
} elsif (/^$rpmsrate_dkms_like$/ && $rpms{"$1$2"}) { |
217 |
$e = "$1-" . $rpms{"$1$2"}[0] . $2; |
218 |
$do = 1; |
219 |
} |
220 |
|
221 |
} |
222 |
|
223 |
if ($do) { |
224 |
$keyword{$c} = $e; |
225 |
if (!ref $done{$e} || $is_plain_flag && !(any { $flat_path eq $_ } @{$done{$e}}) || $flat_path =~ /DRIVER|HW/) { |
226 |
push @{$done{$e}}, $flat_path; |
227 |
push @k, $e; |
228 |
} |
229 |
} |
230 |
|
231 |
# process localized packages (eg: man-pages-XX, hunspell-XX, firefox-XX, ...) |
232 |
if ($locale{$name} && $localized_pkg{$c}) { |
233 |
foreach (sort @{$locale{$name}}) { |
234 |
next if member($flat_path, @{$done{"$name-$_"}}); |
235 |
push @{$done{"$name-$_"}}, $flat_path; |
236 |
push @k , "$name-$_"; |
237 |
} |
238 |
next; |
239 |
} |
240 |
push @k, $c; |
241 |
push @{$done{$c}}, $flat_path; |
242 |
} |
243 |
|
244 |
$text .= "$indent$r$flags@k$postfix\n" if @k; |
245 |
@rate{@k} = ($rate) x @k; |
246 |
my $path; |
247 |
foreach (@flags) { |
248 |
$path .= $path ? "/$_" : $_; |
249 |
push @{$section{$path}}, @k; |
250 |
} |
251 |
} |
252 |
|
253 |
if (%rpms || $output || %locale) { |
254 |
if (%$reprpms || $output) { |
255 |
$output ||= $rpmsrate_file; |
256 |
if (open my $A, ">$output") { |
257 |
print $A $text; |
258 |
} else { |
259 |
warn "ERROR cleanrpmsrate: cannot open $rpmsrate_file for writing\n"; |
260 |
print $text; |
261 |
} |
262 |
} |
263 |
} |
264 |
|
265 |
[\%rate, \%section, \%keyword]; |
266 |
} |
267 |
|
268 |
1 |
269 |
|