1 package Fedora
::Rebuild
::RPM
;
7 use RPM
::VersionCompare
;
10 use version
0.77; our $VERSION = version
->declare("v0.8.0");
12 # FLAGS defined in <rpm/rpmds.h> in enum rpmsenseFlags_e:
20 # Return string representation of dependency FLAG qualifier (LESS|EQUAL, ...).
21 # ANY is represented as an asterisk. Higher bits of flag are ignored.
22 # XXX This is not a method.
27 if ($flag & LESS
) { $text .= '<'; }
28 if ($flag & GREATER
) { $text .= '>'; }
29 if ($flag & EQUAL
) { $text .= '='; }
30 if ($text eq '') { $text = '*'; }
35 # Add $needles dependecies into $stash dependecies. The $stash will be
36 # modified. It does not compact overlapping dependencies because provides and
37 # requires have opposite ordering. It removes identical dependencies only.
38 # The added dependency is not copied deeply. All references remain unchaged.
39 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
40 # XXX: This is not a method.
42 my ($stash, $needles) = @_;
43 for my $needle (keys %{$needles}) {
44 if (exists $$stash{$needle}) {
45 my @subneedles = @
{$$needles{$needle}};
46 my @substraws = @
{$$stash{$needle}};
47 NEEDLE
: for (my $n = 0; $n <= $#subneedles; $n++) {
48 STRAW
: for (my $s = 0; $s <= $#substraws; $s++) {
49 if ($subneedles[$n][0] eq $substraws[$s][0] &&
50 $subneedles[$n][1] eq $substraws[$s][1]) {
54 push @
{$$stash{$needle}}, $subneedles[$n];
57 $$stash{$needle} = $$needles{$needle};
62 # Check whether a requires tripplet (name, flag, version) is fulfilled by
63 # hash of provides. Return true or false (even in parser error).
64 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
65 # XXX: FLAG cannot be LESS|GREATER. Not implemented.
66 # XXX: This is not a method.
68 my ($rname, $rflag, $rversion, $provides) = @_;
70 if (! (exists $$provides{$rname})) {
74 for my $provide (@
{$$provides{$rname}}) {
75 my $pflag = $$provide[0];
76 my $pversion = $$provide[1];
78 if (($rflag & (LESS
|GREATER
|EQUAL
)) == ANY
||
79 ($pflag & (LESS
|GREATER
|EQUAL
)) == ANY
) {
83 my $order = RPM
::VersionCompare
::labelCompare
($rversion, $pversion);
84 if (!defined $order) {
89 # Satisfaction matrix:
91 # (labelCompare($rversion,$pversion) = $order) == 0:
101 if (($rflag & EQUAL
) && ($pflag & EQUAL
)) { return 1; }
102 if (($rflag & LESS
) && ($pflag & LESS
)) { return 1; }
103 if (($rflag & GREATER
) && ($pflag & GREATER
)) { return 1; }
106 # (labelCompare($rversion,$pversion) = $order) > 0:
116 if (($rflag & LESS
) || ($pflag & GREATER
)) { return 1; }
119 # (labelCompare($rversion,$pversion) = $order) < 0:
129 if (($rflag & GREATER
) || ($pflag & LESS
)) { return 1; }
137 has
'name' => (is
=> 'ro', isa
=> 'Str', required
=> 1);
140 # Load local RPM package and return the Header object and package ENVR
145 if (!eval { $headers = RPM2
->open_package($self->name); }) {
146 $@
= "Could not load RPM package `" . $self->name . "': ". $@
;
150 my $envr = $headers->as_nvre;
151 if (! defined $envr) {
152 $@
= "Could not get ENVR of RPM package`" . $self->name . "'";
156 return ($headers, $envr);
160 # Destile provides from local RPM package.
161 # Return reference to hash of provides and ENVR string of the package in this
163 # In case of failure, return undef and set $@.
164 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
168 my ($headers, $envr) = $self->open_package();
169 if (! defined $headers || ! defined $envr) {
173 my @names = $headers->tag('PROVIDENAME');
174 my @flags = $headers->tag('PROVIDEFLAGS');
175 my @versions = $headers->tag('PROVIDEVERSION');
176 if (!($#names == $#flags) && ($#names == $#versions)) {
177 $@
= "Inconsistent number of provides names, flags, and versions in `"
178 . $self->name . "' RPM package";
184 my $name = shift @names,
185 my $flag = shift @flags,
186 defined(my $version = shift @versions)
188 # ???: Filter some higher flag bits?
189 if (!exists $provides{$name}) { $provides{$name} = []; }
190 push @
{$provides{$name}}, [$flag, $version];
193 return (\
%provides, $envr);
197 # Destile requires from local RPM package.
198 # Return reference to hash of requires or in case of failure, return undef
200 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
204 my ($headers, $envr) = $self->open_package();
205 if (! defined $headers || ! defined $envr) {
209 my @names = $headers->tag('REQUIRENAME');
210 my @flags = $headers->tag('REQUIREFLAGS');
211 my @versions = $headers->tag('REQUIREVERSION');
212 if (!($#names == $#flags) && ($#names == $#versions)) {
213 $@
= "Inconsistent number of requires names, flags, and versions in `"
214 . $self->name . "' RPM package";
220 my $name = shift @names,
221 my $flag = shift @flags,
222 defined(my $version = shift @versions)
224 # ???: Filter some higher flag bits?
225 if (!exists $requires{$name}) { $requires{$name} = []; }
226 push @
{$requires{$name}}, [$flag, $version];
229 return (\
%requires, $envr);