1 package Fedora
::Rebuild
::RPM
;
6 use RPM
::VersionCompare
;
9 use version
0.77; our $VERSION = version
->declare("v0.12.1");
11 # FLAGS defined in <rpm/rpmds.h> in enum rpmsenseFlags_e:
19 # Return string representation of dependency FLAG qualifier (LESS|EQUAL, ...).
20 # ANY is represented as an asterisk. Higher bits of flag are ignored.
21 # XXX This is not a method.
26 if ($flag & LESS
) { $text .= '<'; }
27 if ($flag & GREATER
) { $text .= '>'; }
28 if ($flag & EQUAL
) { $text .= '='; }
29 if ($text eq '') { $text = '*'; }
34 # Add $needles dependecies into $stash dependecies. The $stash will be
35 # modified. It does not compact overlapping dependencies because provides and
36 # requires have opposite ordering. It removes identical dependencies only.
37 # The added dependency is not copied deeply. All references remain unchaged.
38 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
39 # XXX: This is not a method.
41 my ($stash, $needles) = @_;
42 for my $needle (keys %{$needles}) {
43 if (exists $$stash{$needle}) {
44 my @subneedles = @
{$$needles{$needle}};
45 my @substraws = @
{$$stash{$needle}};
46 NEEDLE
: for (my $n = 0; $n <= $#subneedles; $n++) {
47 STRAW
: for (my $s = 0; $s <= $#substraws; $s++) {
48 if ($subneedles[$n][0] eq $substraws[$s][0] &&
49 $subneedles[$n][1] eq $substraws[$s][1]) {
53 push @
{$$stash{$needle}}, $subneedles[$n];
56 $$stash{$needle} = $$needles{$needle};
61 # Check whether a required version constrain (flag, version) is fulfilled by
62 # a provided version constrain (flag, version). Return true or false (even in parser error).
63 # XXX: FLAG cannot be LESS|GREATER. Not implemented.
64 # XXX: This is not a method.
65 sub version_is_satisfied
{
66 my ($rflag, $rversion, $pflag, $pversion) = @_;
68 if (($rflag & (LESS
|GREATER
|EQUAL
)) == ANY
||
69 ($pflag & (LESS
|GREATER
|EQUAL
)) == ANY
) {
73 my $order = RPM
::VersionCompare
::labelCompare
($rversion, $pversion);
74 if (!defined $order) {
79 # Satisfaction matrix:
81 # (labelCompare($rversion,$pversion) = $order) == 0:
91 if (($rflag & EQUAL
) && ($pflag & EQUAL
)) { return 1; }
92 if (($rflag & LESS
) && ($pflag & LESS
)) { return 1; }
93 if (($rflag & GREATER
) && ($pflag & GREATER
)) { return 1; }
96 # (labelCompare($rversion,$pversion) = $order) > 0:
106 if (($rflag & LESS
) || ($pflag & GREATER
)) { return 1; }
109 # (labelCompare($rversion,$pversion) = $order) < 0:
119 if (($rflag & GREATER
) || ($pflag & LESS
)) { return 1; }
126 # Check whether a requires tripplet (name, flag, version) is fulfilled by
127 # hash of provides. Return true or false (even in parser error).
128 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
129 # XXX: FLAG cannot be LESS|GREATER. Not implemented.
130 # XXX: This is not a method.
132 my ($rname, $rflag, $rversion, $provides) = @_;
134 if (! (exists $$provides{$rname})) {
138 for my $provide (@
{$$provides{$rname}}) {
139 my $pflag = $$provide[0];
140 my $pversion = $$provide[1];
142 if (version_is_satisfied
($rflag, $rversion, $pflag, $pversion)) {
151 has
'name' => (is
=> 'ro', isa
=> 'Str', required
=> 1);
154 # Load local RPM package and return the Header object and package ENVR
159 if (!eval { $headers = RPM2
->open_package($self->name); }) {
160 $@
= "Could not load RPM package `" . $self->name . "': ". $@
;
164 my $envr = $headers->as_nvre;
165 if (! defined $envr) {
166 $@
= "Could not get ENVR of RPM package`" . $self->name . "'";
170 return ($headers, $envr);
174 # Destile provides from local RPM package.
175 # Return reference to hash of provides and ENVR string of the package in this
177 # In case of failure, return undef and set $@.
178 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
182 my ($headers, $envr) = $self->open_package();
183 if (! defined $headers || ! defined $envr) {
187 my @names = $headers->tag('PROVIDENAME');
188 my @flags = $headers->tag('PROVIDEFLAGS');
189 my @versions = $headers->tag('PROVIDEVERSION');
190 if (!($#names == $#flags) && ($#names == $#versions)) {
191 $@
= "Inconsistent number of provides names, flags, and versions in `"
192 . $self->name . "' RPM package";
198 my $name = shift @names,
199 my $flag = shift @flags,
200 defined(my $version = shift @versions)
202 # ???: Filter some higher flag bits?
203 if (!exists $provides{$name}) { $provides{$name} = []; }
204 push @
{$provides{$name}}, [$flag, $version];
207 return (\
%provides, $envr);
211 # Destile requires from local RPM package.
212 # Return reference to hash of requires or in case of failure, return undef
214 # Hash format is { NAME1 => [ [FLAG1, VERSION1], [FLAG2, VERSION2] ] }.
218 my ($headers, $envr) = $self->open_package();
219 if (! defined $headers || ! defined $envr) {
223 my @names = $headers->tag('REQUIRENAME');
224 my @flags = $headers->tag('REQUIREFLAGS');
225 my @versions = $headers->tag('REQUIREVERSION');
226 if (!($#names == $#flags) && ($#names == $#versions)) {
227 $@
= "Inconsistent number of requires names, flags, and versions in `"
228 . $self->name . "' RPM package";
234 my $name = shift @names,
235 my $flag = shift @flags,
236 defined(my $version = shift @versions)
238 # ???: Filter some higher flag bits?
239 if (!exists $requires{$name}) { $requires{$name} = []; }
240 push @
{$requires{$name}}, [$flag, $version];
243 return (\
%requires, $envr);