| OLD | NEW |
| (Empty) |
| 1 # Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org> | |
| 2 # Copyright © 2012 Guillem Jover <guillem@debian.org> | |
| 3 # | |
| 4 # This program is free software; you may redistribute it and/or modify | |
| 5 # it under the terms of the GNU General Public License as published by | |
| 6 # the Free Software Foundation; either version 2 of the License, or | |
| 7 # (at your option) any later version. | |
| 8 # | |
| 9 # This is distributed in the hope that it will be useful, | |
| 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 # GNU General Public License for more details. | |
| 13 # | |
| 14 # You should have received a copy of the GNU General Public License | |
| 15 # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| 16 ######################################################################### | |
| 17 # Several parts are inspired by lib/Dep.pm from lintian (same license) | |
| 18 # | |
| 19 # Copyright © 1998 Richard Braakman | |
| 20 # Portions Copyright © 1999 Darren Benham | |
| 21 # Portions Copyright © 2000 Sean 'Shaleh' Perry | |
| 22 # Portions Copyright © 2004 Frank Lichtenheld | |
| 23 # Portions Copyright © 2006 Russ Allbery | |
| 24 | |
| 25 package Dpkg::Deps; | |
| 26 | |
| 27 =encoding utf8 | |
| 28 | |
| 29 =head1 NAME | |
| 30 | |
| 31 Dpkg::Deps - parse and manipulate dependencies of Debian packages | |
| 32 | |
| 33 =head1 DESCRIPTION | |
| 34 | |
| 35 The Dpkg::Deps module provides objects implementing various types of | |
| 36 dependencies. | |
| 37 | |
| 38 The most important function is deps_parse(), it turns a dependency line in | |
| 39 a set of Dpkg::Deps::{Simple,AND,OR,Union} objects depending on the case. | |
| 40 | |
| 41 =head1 FUNCTIONS | |
| 42 | |
| 43 All the deps_* functions are exported by default. | |
| 44 | |
| 45 =over 4 | |
| 46 | |
| 47 =cut | |
| 48 | |
| 49 use strict; | |
| 50 use warnings; | |
| 51 | |
| 52 our $VERSION = '1.02'; | |
| 53 | |
| 54 use Dpkg::Version; | |
| 55 use Dpkg::Arch qw(get_host_arch get_build_arch); | |
| 56 use Dpkg::BuildProfiles qw(get_build_profiles); | |
| 57 use Dpkg::ErrorHandling; | |
| 58 use Dpkg::Gettext; | |
| 59 | |
| 60 use Exporter qw(import); | |
| 61 our @EXPORT = qw(deps_concat deps_parse deps_eval_implication deps_compare); | |
| 62 | |
| 63 =item deps_eval_implication($rel_p, $v_p, $rel_q, $v_q) | |
| 64 | |
| 65 ($rel_p, $v_p) and ($rel_q, $v_q) express two dependencies as (relation, | |
| 66 version). The relation variable can have the following values that are | |
| 67 exported by Dpkg::Version: REL_EQ, REL_LT, REL_LE, REL_GT, REL_GT. | |
| 68 | |
| 69 This functions returns 1 if the "p" dependency implies the "q" | |
| 70 dependency. It returns 0 if the "p" dependency implies that "q" is | |
| 71 not satisfied. It returns undef when there's no implication. | |
| 72 | |
| 73 The $v_p and $v_q parameter should be Dpkg::Version objects. | |
| 74 | |
| 75 =cut | |
| 76 | |
| 77 sub deps_eval_implication { | |
| 78 my ($rel_p, $v_p, $rel_q, $v_q) = @_; | |
| 79 | |
| 80 # If versions are not valid, we can't decide of any implication | |
| 81 return unless defined($v_p) and $v_p->is_valid(); | |
| 82 return unless defined($v_q) and $v_q->is_valid(); | |
| 83 | |
| 84 # q wants an exact version, so p must provide that exact version. p | |
| 85 # disproves q if q's version is outside the range enforced by p. | |
| 86 if ($rel_q eq REL_EQ) { | |
| 87 if ($rel_p eq REL_LT) { | |
| 88 return ($v_p <= $v_q) ? 0 : undef; | |
| 89 } elsif ($rel_p eq REL_LE) { | |
| 90 return ($v_p < $v_q) ? 0 : undef; | |
| 91 } elsif ($rel_p eq REL_GT) { | |
| 92 return ($v_p >= $v_q) ? 0 : undef; | |
| 93 } elsif ($rel_p eq REL_GE) { | |
| 94 return ($v_p > $v_q) ? 0 : undef; | |
| 95 } elsif ($rel_p eq REL_EQ) { | |
| 96 return ($v_p == $v_q); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 # A greater than clause may disprove a less than clause. An equal | |
| 101 # cause might as well. Otherwise, if | |
| 102 # p's clause is <<, <=, or =, the version must be <= q's to imply q. | |
| 103 if ($rel_q eq REL_LE) { | |
| 104 if ($rel_p eq REL_GT) { | |
| 105 return ($v_p >= $v_q) ? 0 : undef; | |
| 106 } elsif ($rel_p eq REL_GE) { | |
| 107 return ($v_p > $v_q) ? 0 : undef; | |
| 108 } elsif ($rel_p eq REL_EQ) { | |
| 109 return ($v_p <= $v_q) ? 1 : 0; | |
| 110 } else { # <<, <= | |
| 111 return ($v_p <= $v_q) ? 1 : undef; | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 # Similar, but << is stronger than <= so p's version must be << q's | |
| 116 # version if the p relation is <= or =. | |
| 117 if ($rel_q eq REL_LT) { | |
| 118 if ($rel_p eq REL_GT or $rel_p eq REL_GE) { | |
| 119 return ($v_p >= $v_p) ? 0 : undef; | |
| 120 } elsif ($rel_p eq REL_LT) { | |
| 121 return ($v_p <= $v_q) ? 1 : undef; | |
| 122 } elsif ($rel_p eq REL_EQ) { | |
| 123 return ($v_p < $v_q) ? 1 : 0; | |
| 124 } else { # <<, <= | |
| 125 return ($v_p < $v_q) ? 1 : undef; | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 # Same logic as above, only inverted. | |
| 130 if ($rel_q eq REL_GE) { | |
| 131 if ($rel_p eq REL_LT) { | |
| 132 return ($v_p <= $v_q) ? 0 : undef; | |
| 133 } elsif ($rel_p eq REL_LE) { | |
| 134 return ($v_p < $v_q) ? 0 : undef; | |
| 135 } elsif ($rel_p eq REL_EQ) { | |
| 136 return ($v_p >= $v_q) ? 1 : 0; | |
| 137 } else { # >>, >= | |
| 138 return ($v_p >= $v_q) ? 1 : undef; | |
| 139 } | |
| 140 } | |
| 141 if ($rel_q eq REL_GT) { | |
| 142 if ($rel_p eq REL_LT or $rel_p eq REL_LE) { | |
| 143 return ($v_p <= $v_q) ? 0 : undef; | |
| 144 } elsif ($rel_p eq REL_GT) { | |
| 145 return ($v_p >= $v_q) ? 1 : undef; | |
| 146 } elsif ($rel_p eq REL_EQ) { | |
| 147 return ($v_p > $v_q) ? 1 : 0; | |
| 148 } else { | |
| 149 return ($v_p > $v_q) ? 1 : undef; | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 return; | |
| 154 } | |
| 155 | |
| 156 =item my $dep = deps_concat(@dep_list) | |
| 157 | |
| 158 This function concatenates multiple dependency lines into a single line, | |
| 159 joining them with ", " if appropriate, and always returning a valid string. | |
| 160 | |
| 161 =cut | |
| 162 | |
| 163 sub deps_concat { | |
| 164 my (@dep_list) = @_; | |
| 165 | |
| 166 return join(', ', grep { defined $_ } @dep_list); | |
| 167 } | |
| 168 | |
| 169 =item my $dep = deps_parse($line, %options) | |
| 170 | |
| 171 This function parses the dependency line and returns an object, either a | |
| 172 Dpkg::Deps::AND or a Dpkg::Deps::Union. Various options can alter the | |
| 173 behaviour of that function. | |
| 174 | |
| 175 =over 4 | |
| 176 | |
| 177 =item use_arch (defaults to 1) | |
| 178 | |
| 179 Take into account the architecture restriction part of the dependencies. | |
| 180 Set to 0 to completely ignore that information. | |
| 181 | |
| 182 =item host_arch (defaults to the current architecture) | |
| 183 | |
| 184 Define the host architecture. By default it uses | |
| 185 Dpkg::Arch::get_host_arch() to identify the proper architecture. | |
| 186 | |
| 187 =item build_arch (defaults to the current architecture) | |
| 188 | |
| 189 Define the build architecture. By default it uses | |
| 190 Dpkg::Arch::get_build_arch() to identify the proper architecture. | |
| 191 | |
| 192 =item reduce_arch (defaults to 0) | |
| 193 | |
| 194 If set to 1, ignore dependencies that do not concern the current host | |
| 195 architecture. This implicitely strips off the architecture restriction | |
| 196 list so that the resulting dependencies are directly applicable to the | |
| 197 current architecture. | |
| 198 | |
| 199 =item use_profiles (defaults to 1) | |
| 200 | |
| 201 Take into account the profile restriction part of the dependencies. Set | |
| 202 to 0 to completely ignore that information. | |
| 203 | |
| 204 =item build_profiles (defaults to no profile) | |
| 205 | |
| 206 Define the active build profiles. By default no profile is defined. | |
| 207 | |
| 208 =item reduce_profiles (defaults to 0) | |
| 209 | |
| 210 If set to 1, ignore dependencies that do not concern the current build | |
| 211 profile. This implicitly strips off the profile restriction list so | |
| 212 that the resulting dependencies are directly applicable to the current | |
| 213 profiles. | |
| 214 | |
| 215 =item reduce_restrictions (defaults to 0) | |
| 216 | |
| 217 If set to 1, ignore dependencies that do not concern the current set of | |
| 218 restrictions. This implicitly strips off any restriction list so that the | |
| 219 resulting dependencies are directly applicable to the current restriction. | |
| 220 This currently implies C<reduce_arch> and C<reduce_profiles>, and overrides | |
| 221 them if set. | |
| 222 | |
| 223 =item union (defaults to 0) | |
| 224 | |
| 225 If set to 1, returns a Dpkg::Deps::Union instead of a Dpkg::Deps::AND. Use | |
| 226 this when parsing non-dependency fields like Conflicts. | |
| 227 | |
| 228 =item build_dep (defaults to 0) | |
| 229 | |
| 230 If set to 1, allow build-dep only arch qualifiers, that is “:native”. | |
| 231 This should be set whenever working with build-deps. | |
| 232 | |
| 233 =back | |
| 234 | |
| 235 =cut | |
| 236 | |
| 237 sub deps_parse { | |
| 238 my $dep_line = shift; | |
| 239 my %options = (@_); | |
| 240 $options{use_arch} = 1 if not exists $options{use_arch}; | |
| 241 $options{reduce_arch} = 0 if not exists $options{reduce_arch}; | |
| 242 $options{host_arch} = get_host_arch() if not exists $options{host_arch}; | |
| 243 $options{build_arch} = get_build_arch() if not exists $options{build_arch}; | |
| 244 $options{use_profiles} = 1 if not exists $options{use_profiles}; | |
| 245 $options{reduce_profiles} = 0 if not exists $options{reduce_profiles}; | |
| 246 $options{build_profiles} = [ get_build_profiles() ] | |
| 247 if not exists $options{build_profiles}; | |
| 248 $options{reduce_restrictions} = 0 if not exists $options{reduce_restrictions
}; | |
| 249 $options{union} = 0 if not exists $options{union}; | |
| 250 $options{build_dep} = 0 if not exists $options{build_dep}; | |
| 251 | |
| 252 if ($options{reduce_restrictions}) { | |
| 253 $options{reduce_arch} = 1; | |
| 254 $options{reduce_profiles} = 1; | |
| 255 } | |
| 256 | |
| 257 # Strip trailing/leading spaces | |
| 258 $dep_line =~ s/^\s+//; | |
| 259 $dep_line =~ s/\s+$//; | |
| 260 | |
| 261 my @dep_list; | |
| 262 foreach my $dep_and (split(/\s*,\s*/m, $dep_line)) { | |
| 263 my @or_list = (); | |
| 264 foreach my $dep_or (split(/\s*\|\s*/m, $dep_and)) { | |
| 265 my $dep_simple = Dpkg::Deps::Simple->new($dep_or, host_arch => | |
| 266 $options{host_arch}, | |
| 267 build_arch => | |
| 268 $options{build_arch}, | |
| 269 build_dep => | |
| 270 $options{build_dep}); | |
| 271 if (not defined $dep_simple->{package}) { | |
| 272 warning(_g("can't parse dependency %s"), $dep_or); | |
| 273 return; | |
| 274 } | |
| 275 $dep_simple->{arches} = undef if not $options{use_arch}; | |
| 276 if ($options{reduce_arch}) { | |
| 277 $dep_simple->reduce_arch($options{host_arch}); | |
| 278 next if not $dep_simple->arch_is_concerned($options{host_arch}); | |
| 279 } | |
| 280 $dep_simple->{restrictions} = undef if not $options{use_profiles}; | |
| 281 if ($options{reduce_profiles}) { | |
| 282 $dep_simple->reduce_profiles($options{build_profiles}); | |
| 283 next if not $dep_simple->profile_is_concerned($options{build_pro
files}); | |
| 284 } | |
| 285 push @or_list, $dep_simple; | |
| 286 } | |
| 287 next if not @or_list; | |
| 288 if (scalar @or_list == 1) { | |
| 289 push @dep_list, $or_list[0]; | |
| 290 } else { | |
| 291 my $dep_or = Dpkg::Deps::OR->new(); | |
| 292 $dep_or->add($_) foreach (@or_list); | |
| 293 push @dep_list, $dep_or; | |
| 294 } | |
| 295 } | |
| 296 my $dep_and; | |
| 297 if ($options{union}) { | |
| 298 $dep_and = Dpkg::Deps::Union->new(); | |
| 299 } else { | |
| 300 $dep_and = Dpkg::Deps::AND->new(); | |
| 301 } | |
| 302 foreach my $dep (@dep_list) { | |
| 303 if ($options{union} and not $dep->isa('Dpkg::Deps::Simple')) { | |
| 304 warning(_g('an union dependency can only contain simple dependencies
')); | |
| 305 return; | |
| 306 } | |
| 307 $dep_and->add($dep); | |
| 308 } | |
| 309 return $dep_and; | |
| 310 } | |
| 311 | |
| 312 =item deps_compare($a, $b) | |
| 313 | |
| 314 Implements a comparison operator between two dependency objects. | |
| 315 This function is mainly used to implement the sort() method. | |
| 316 | |
| 317 =back | |
| 318 | |
| 319 =cut | |
| 320 | |
| 321 my %relation_ordering = ( | |
| 322 undef => 0, | |
| 323 REL_GE() => 1, | |
| 324 REL_GT() => 2, | |
| 325 REL_EQ() => 3, | |
| 326 REL_LT() => 4, | |
| 327 REL_LE() => 5, | |
| 328 ); | |
| 329 | |
| 330 sub deps_compare { | |
| 331 my ($a, $b) = @_; | |
| 332 return -1 if $a->is_empty(); | |
| 333 return 1 if $b->is_empty(); | |
| 334 while ($a->isa('Dpkg::Deps::Multiple')) { | |
| 335 return -1 if $a->is_empty(); | |
| 336 my @deps = $a->get_deps(); | |
| 337 $a = $deps[0]; | |
| 338 } | |
| 339 while ($b->isa('Dpkg::Deps::Multiple')) { | |
| 340 return 1 if $b->is_empty(); | |
| 341 my @deps = $b->get_deps(); | |
| 342 $b = $deps[0]; | |
| 343 } | |
| 344 my $ar = defined($a->{relation}) ? $a->{relation} : 'undef'; | |
| 345 my $br = defined($b->{relation}) ? $b->{relation} : 'undef'; | |
| 346 return (($a->{package} cmp $b->{package}) || | |
| 347 ($relation_ordering{$ar} <=> $relation_ordering{$br}) || | |
| 348 ($a->{version} cmp $b->{version})); | |
| 349 } | |
| 350 | |
| 351 | |
| 352 package Dpkg::Deps::Simple; | |
| 353 | |
| 354 =head1 OBJECTS - Dpkg::Deps::* | |
| 355 | |
| 356 There are several kind of dependencies. A Dpkg::Deps::Simple dependency | |
| 357 represents a single dependency statement (it relates to one package only). | |
| 358 Dpkg::Deps::Multiple dependencies are built on top of this object | |
| 359 and combine several dependencies in a different manners. Dpkg::Deps::AND | |
| 360 represents the logical "AND" between dependencies while Dpkg::Deps::OR | |
| 361 represents the logical "OR". Dpkg::Deps::Multiple objects can contain | |
| 362 Dpkg::Deps::Simple object as well as other Dpkg::Deps::Multiple objects. | |
| 363 | |
| 364 In practice, the code is only meant to handle the realistic cases which, | |
| 365 given Debian's dependencies structure, imply those restrictions: AND can | |
| 366 contain Simple or OR objects, OR can only contain Simple objects. | |
| 367 | |
| 368 Dpkg::Deps::KnownFacts is a special object that is used while evaluating | |
| 369 dependencies and while trying to simplify them. It represents a set of | |
| 370 installed packages along with the virtual packages that they might | |
| 371 provide. | |
| 372 | |
| 373 =head2 COMMON FUNCTIONS | |
| 374 | |
| 375 =over 4 | |
| 376 | |
| 377 =item $dep->is_empty() | |
| 378 | |
| 379 Returns true if the dependency is empty and doesn't contain any useful | |
| 380 information. This is true when a Dpkg::Deps::Simple object has not yet | |
| 381 been initialized or when a (descendant of) Dpkg::Deps::Multiple contains | |
| 382 an empty list of dependencies. | |
| 383 | |
| 384 =item $dep->get_deps() | |
| 385 | |
| 386 Returns a list of sub-dependencies. For Dpkg::Deps::Simple it returns | |
| 387 itself. | |
| 388 | |
| 389 =item $dep->output([$fh]) | |
| 390 | |
| 391 =item "$dep" | |
| 392 | |
| 393 Returns a string representing the dependency. If $fh is set, it prints | |
| 394 the string to the filehandle. | |
| 395 | |
| 396 =item $dep->implies($other_dep) | |
| 397 | |
| 398 Returns 1 when $dep implies $other_dep. Returns 0 when $dep implies | |
| 399 NOT($other_dep). Returns undef when there's no implication. $dep and | |
| 400 $other_dep do not need to be of the same type. | |
| 401 | |
| 402 =item $dep->sort() | |
| 403 | |
| 404 Sorts alphabetically the internal list of dependencies. It's a no-op for | |
| 405 Dpkg::Deps::Simple objects. | |
| 406 | |
| 407 =item $dep->arch_is_concerned($arch) | |
| 408 | |
| 409 Returns true if the dependency applies to the indicated architecture. For | |
| 410 multiple dependencies, it returns true if at least one of the | |
| 411 sub-dependencies apply to this architecture. | |
| 412 | |
| 413 =item $dep->reduce_arch($arch) | |
| 414 | |
| 415 Simplifies the dependency to contain only information relevant to the given | |
| 416 architecture. A Dpkg::Deps::Simple object can be left empty after this | |
| 417 operation. For Dpkg::Deps::Multiple objects, the non-relevant | |
| 418 sub-dependencies are simply removed. | |
| 419 | |
| 420 This trims off the architecture restriction list of Dpkg::Deps::Simple | |
| 421 objects. | |
| 422 | |
| 423 =item $dep->get_evaluation($facts) | |
| 424 | |
| 425 Evaluates the dependency given a list of installed packages and a list of | |
| 426 virtual packages provided. Those lists are part of the | |
| 427 Dpkg::Deps::KnownFacts object given as parameters. | |
| 428 | |
| 429 Returns 1 when it's true, 0 when it's false, undef when some information | |
| 430 is lacking to conclude. | |
| 431 | |
| 432 =item $dep->simplify_deps($facts, @assumed_deps) | |
| 433 | |
| 434 Simplifies the dependency as much as possible given the list of facts (see | |
| 435 object Dpkg::Deps::KnownFacts) and a list of other dependencies that are | |
| 436 known to be true. | |
| 437 | |
| 438 =item $dep->has_arch_restriction() | |
| 439 | |
| 440 For a simple dependency, returns the package name if the dependency | |
| 441 applies only to a subset of architectures. For multiple dependencies, it | |
| 442 returns the list of package names that have such a restriction. | |
| 443 | |
| 444 =item $dep->reset() | |
| 445 | |
| 446 Clears any dependency information stored in $dep so that $dep->is_empty() | |
| 447 returns true. | |
| 448 | |
| 449 =back | |
| 450 | |
| 451 =head2 Dpkg::Deps::Simple | |
| 452 | |
| 453 Such an object has four interesting properties: | |
| 454 | |
| 455 =over 4 | |
| 456 | |
| 457 =item package | |
| 458 | |
| 459 The package name (can be undef if the dependency has not been initialized | |
| 460 or if the simplification of the dependency lead to its removal). | |
| 461 | |
| 462 =item relation | |
| 463 | |
| 464 The relational operator: "=", "<<", "<=", ">=" or ">>". It can be | |
| 465 undefined if the dependency had no version restriction. In that case the | |
| 466 following field is also undefined. | |
| 467 | |
| 468 =item version | |
| 469 | |
| 470 The version. | |
| 471 | |
| 472 =item arches | |
| 473 | |
| 474 The list of architectures where this dependency is applicable. It's | |
| 475 undefined when there's no restriction, otherwise it's an | |
| 476 array ref. It can contain an exclusion list, in that case each | |
| 477 architecture is prefixed with an exclamation mark. | |
| 478 | |
| 479 =item archqual | |
| 480 | |
| 481 The arch qualifier of the dependency (can be undef if there's none). | |
| 482 In the dependency "python:any (>= 2.6)", the arch qualifier is "any". | |
| 483 | |
| 484 =back | |
| 485 | |
| 486 =head3 METHODS | |
| 487 | |
| 488 =over 4 | |
| 489 | |
| 490 =item $simple_dep->parse_string('dpkg-dev (>= 1.14.8) [!hurd-i386]') | |
| 491 | |
| 492 Parses the dependency and modifies internal properties to match the parsed | |
| 493 dependency. | |
| 494 | |
| 495 =item $simple_dep->merge_union($other_dep) | |
| 496 | |
| 497 Returns true if $simple_dep could be modified to represent the union of | |
| 498 both dependencies. Otherwise returns false. | |
| 499 | |
| 500 =back | |
| 501 | |
| 502 =cut | |
| 503 | |
| 504 use strict; | |
| 505 use warnings; | |
| 506 | |
| 507 use Carp; | |
| 508 | |
| 509 use Dpkg::Arch qw(debarch_is); | |
| 510 use Dpkg::Version; | |
| 511 use Dpkg::ErrorHandling; | |
| 512 use Dpkg::Gettext; | |
| 513 use Dpkg::Util qw(:list); | |
| 514 | |
| 515 use parent qw(Dpkg::Interface::Storable); | |
| 516 | |
| 517 sub new { | |
| 518 my ($this, $arg, %opts) = @_; | |
| 519 my $class = ref($this) || $this; | |
| 520 my $self = {}; | |
| 521 bless $self, $class; | |
| 522 $self->reset(); | |
| 523 $self->{host_arch} = $opts{host_arch} || Dpkg::Arch::get_host_arch(); | |
| 524 $self->{build_arch} = $opts{build_arch} || Dpkg::Arch::get_build_arch(); | |
| 525 $self->{build_dep} = $opts{build_dep} || 0; | |
| 526 $self->parse_string($arg) if defined($arg); | |
| 527 return $self; | |
| 528 } | |
| 529 | |
| 530 sub reset { | |
| 531 my ($self) = @_; | |
| 532 $self->{package} = undef; | |
| 533 $self->{relation} = undef; | |
| 534 $self->{version} = undef; | |
| 535 $self->{arches} = undef; | |
| 536 $self->{archqual} = undef; | |
| 537 $self->{restrictions} = undef; | |
| 538 } | |
| 539 | |
| 540 sub parse { | |
| 541 my ($self, $fh, $desc) = @_; | |
| 542 my $line = <$fh>; | |
| 543 chomp($line); | |
| 544 return $self->parse_string($line); | |
| 545 } | |
| 546 | |
| 547 sub parse_string { | |
| 548 my ($self, $dep) = @_; | |
| 549 return if not $dep =~ | |
| 550 m{^\s* # skip leading whitespace | |
| 551 ([a-zA-Z0-9][a-zA-Z0-9+.-]*) # package name | |
| 552 (?: # start of optional part | |
| 553 : # colon for architecture | |
| 554 ([a-zA-Z0-9][a-zA-Z0-9-]*) # architecture name | |
| 555 )? # end of optional part | |
| 556 (?: # start of optional part | |
| 557 \s* \( # open parenthesis for version part | |
| 558 \s* (<<|<=|=|>=|>>|<|>) # relation part | |
| 559 \s* (.*?) # do not attempt to parse version | |
| 560 \s* \) # closing parenthesis | |
| 561 )? # end of optional part | |
| 562 (?: # start of optional architecture | |
| 563 \s* \[ # open bracket for architecture | |
| 564 \s* (.*?) # don't parse architectures now | |
| 565 \s* \] # closing bracket | |
| 566 )? # end of optional architecture | |
| 567 (?: # start of optional restriction | |
| 568 \s* < # open bracket for restriction | |
| 569 \s* (.*?) # don't parse restrictions now | |
| 570 \s* > # closing bracket | |
| 571 )? # end of optional restriction | |
| 572 \s*$ # trailing spaces at end | |
| 573 }x; | |
| 574 if (defined($2)) { | |
| 575 return if $2 eq 'native' and not $self->{build_dep}; | |
| 576 $self->{archqual} = $2; | |
| 577 } | |
| 578 $self->{package} = $1; | |
| 579 $self->{relation} = version_normalize_relation($3) if defined($3); | |
| 580 if (defined($4)) { | |
| 581 $self->{version} = Dpkg::Version->new($4); | |
| 582 } | |
| 583 if (defined($5)) { | |
| 584 $self->{arches} = [ split(/\s+/, $5) ]; | |
| 585 } | |
| 586 if (defined($6)) { | |
| 587 $self->{restrictions} = [ map { lc } split /\s+/, $6 ]; | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 sub output { | |
| 592 my ($self, $fh) = @_; | |
| 593 my $res = $self->{package}; | |
| 594 if (defined($self->{archqual})) { | |
| 595 $res .= ':' . $self->{archqual}; | |
| 596 } | |
| 597 if (defined($self->{relation})) { | |
| 598 $res .= ' (' . $self->{relation} . ' ' . $self->{version} . ')'; | |
| 599 } | |
| 600 if (defined($self->{arches})) { | |
| 601 $res .= ' [' . join(' ', @{$self->{arches}}) . ']'; | |
| 602 } | |
| 603 if (defined($self->{restrictions})) { | |
| 604 $res .= ' <' . join(' ', @{$self->{restrictions}}) . '>'; | |
| 605 } | |
| 606 if (defined($fh)) { | |
| 607 print { $fh } $res; | |
| 608 } | |
| 609 return $res; | |
| 610 } | |
| 611 | |
| 612 # _arch_is_superset(\@p, \@q) | |
| 613 # | |
| 614 # Returns true if the arch list @p is a superset of arch list @q. | |
| 615 # The arguments can also be undef in case there's no explicit architecture | |
| 616 # restriction. | |
| 617 sub _arch_is_superset { | |
| 618 my ($p, $q) = @_; | |
| 619 my $p_arch_neg = defined($p) && $p->[0] =~ /^!/; | |
| 620 my $q_arch_neg = defined($q) && $q->[0] =~ /^!/; | |
| 621 | |
| 622 # If "p" has no arches, it is a superset of q and we should fall through | |
| 623 # to the version check. | |
| 624 if (not defined $p) { | |
| 625 return 1; | |
| 626 } | |
| 627 | |
| 628 # If q has no arches, it is a superset of p and there are no useful | |
| 629 # implications. | |
| 630 elsif (not defined $q) { | |
| 631 return 0; | |
| 632 } | |
| 633 | |
| 634 # Both have arches. If neither are negated, we know nothing useful | |
| 635 # unless q is a subset of p. | |
| 636 elsif (not $p_arch_neg and not $q_arch_neg) { | |
| 637 my %p_arches = map { $_ => 1 } @{$p}; | |
| 638 my $subset = 1; | |
| 639 for my $arch (@{$q}) { | |
| 640 $subset = 0 unless $p_arches{$arch}; | |
| 641 } | |
| 642 return 0 unless $subset; | |
| 643 } | |
| 644 | |
| 645 # If both are negated, we know nothing useful unless p is a subset of | |
| 646 # q (and therefore has fewer things excluded, and therefore is more | |
| 647 # general). | |
| 648 elsif ($p_arch_neg and $q_arch_neg) { | |
| 649 my %q_arches = map { $_ => 1 } @{$q}; | |
| 650 my $subset = 1; | |
| 651 for my $arch (@{$p}) { | |
| 652 $subset = 0 unless $q_arches{$arch}; | |
| 653 } | |
| 654 return 0 unless $subset; | |
| 655 } | |
| 656 | |
| 657 # If q is negated and p isn't, we'd need to know the full list of | |
| 658 # arches to know if there's any relationship, so bail. | |
| 659 elsif (not $p_arch_neg and $q_arch_neg) { | |
| 660 return 0; | |
| 661 } | |
| 662 | |
| 663 # If p is negated and q isn't, q is a subset of p if none of the | |
| 664 # negated arches in p are present in q. | |
| 665 elsif ($p_arch_neg and not $q_arch_neg) { | |
| 666 my %q_arches = map { $_ => 1 } @{$q}; | |
| 667 my $subset = 1; | |
| 668 for my $arch (@{$p}) { | |
| 669 $subset = 0 if $q_arches{substr($arch, 1)}; | |
| 670 } | |
| 671 return 0 unless $subset; | |
| 672 } | |
| 673 return 1; | |
| 674 } | |
| 675 | |
| 676 # _arch_qualifier_allows_implication($p, $q) | |
| 677 # | |
| 678 # Returns true if the arch qualifier $p and $q are compatible with the | |
| 679 # implication $p -> $q, false otherwise. $p/$q can be | |
| 680 # undef/"any"/"native" or an architecture string. | |
| 681 sub _arch_qualifier_allows_implication { | |
| 682 my ($p, $q) = @_; | |
| 683 if (defined $p and $p eq 'any') { | |
| 684 return 1 if defined $q and $q eq 'any'; | |
| 685 return 0; | |
| 686 } elsif (defined $p and $p eq 'native') { | |
| 687 return 1 if defined $q and ($q eq 'any' or $q eq 'native'); | |
| 688 return 0; | |
| 689 } elsif (defined $p) { | |
| 690 return 1 if defined $q and ($p eq $q or $q eq 'any'); | |
| 691 return 0; | |
| 692 } else { | |
| 693 return 0 if defined $q and $q ne 'any' and $q ne 'native'; | |
| 694 return 1; | |
| 695 } | |
| 696 } | |
| 697 | |
| 698 # Returns true if the dependency in parameter can deduced from the current | |
| 699 # dependency. Returns false if it can be negated. Returns undef if nothing | |
| 700 # can be concluded. | |
| 701 sub implies { | |
| 702 my ($self, $o) = @_; | |
| 703 if ($o->isa('Dpkg::Deps::Simple')) { | |
| 704 # An implication is only possible on the same package | |
| 705 return if $self->{package} ne $o->{package}; | |
| 706 | |
| 707 # Our architecture set must be a superset of the architectures for | |
| 708 # o, otherwise we can't conclude anything. | |
| 709 return unless _arch_is_superset($self->{arches}, $o->{arches}); | |
| 710 | |
| 711 # The arch qualifier must not forbid an implication | |
| 712 return unless _arch_qualifier_allows_implication($self->{archqual}, | |
| 713 $o->{archqual}); | |
| 714 | |
| 715 # If o has no version clause, then our dependency is stronger | |
| 716 return 1 if not defined $o->{relation}; | |
| 717 # If o has a version clause, we must also have one, otherwise there | |
| 718 # can't be an implication | |
| 719 return if not defined $self->{relation}; | |
| 720 | |
| 721 return Dpkg::Deps::deps_eval_implication($self->{relation}, | |
| 722 $self->{version}, $o->{relation}, $o->{version}); | |
| 723 | |
| 724 } elsif ($o->isa('Dpkg::Deps::AND')) { | |
| 725 # TRUE: Need to imply all individual elements | |
| 726 # FALSE: Need to NOT imply at least one individual element | |
| 727 my $res = 1; | |
| 728 foreach my $dep ($o->get_deps()) { | |
| 729 my $implication = $self->implies($dep); | |
| 730 unless (defined($implication) && $implication == 1) { | |
| 731 $res = $implication; | |
| 732 last if defined $res; | |
| 733 } | |
| 734 } | |
| 735 return $res; | |
| 736 } elsif ($o->isa('Dpkg::Deps::OR')) { | |
| 737 # TRUE: Need to imply at least one individual element | |
| 738 # FALSE: Need to not apply all individual elements | |
| 739 # UNDEF: The rest | |
| 740 my $res = undef; | |
| 741 foreach my $dep ($o->get_deps()) { | |
| 742 my $implication = $self->implies($dep); | |
| 743 if (defined($implication)) { | |
| 744 if (not defined $res) { | |
| 745 $res = $implication; | |
| 746 } else { | |
| 747 if ($implication) { | |
| 748 $res = 1; | |
| 749 } else { | |
| 750 $res = 0; | |
| 751 } | |
| 752 } | |
| 753 last if defined($res) && $res == 1; | |
| 754 } | |
| 755 } | |
| 756 return $res; | |
| 757 } else { | |
| 758 croak 'Dpkg::Deps::Simple cannot evaluate implication with a ' . | |
| 759 ref($o); | |
| 760 } | |
| 761 } | |
| 762 | |
| 763 sub get_deps { | |
| 764 my $self = shift; | |
| 765 return $self; | |
| 766 } | |
| 767 | |
| 768 sub sort { | |
| 769 # Nothing to sort | |
| 770 } | |
| 771 | |
| 772 sub arch_is_concerned { | |
| 773 my ($self, $host_arch) = @_; | |
| 774 | |
| 775 return 0 if not defined $self->{package}; # Empty dep | |
| 776 return 1 if not defined $self->{arches}; # Dep without arch spec | |
| 777 | |
| 778 my $seen_arch = 0; | |
| 779 foreach my $arch (@{$self->{arches}}) { | |
| 780 $arch=lc($arch); | |
| 781 | |
| 782 if ($arch =~ /^!/) { | |
| 783 my $not_arch = $arch; | |
| 784 $not_arch =~ s/^!//; | |
| 785 | |
| 786 if (debarch_is($host_arch, $not_arch)) { | |
| 787 $seen_arch = 0; | |
| 788 last; | |
| 789 } else { | |
| 790 # !arch includes by default all other arches | |
| 791 # unless they also appear in a !otherarch | |
| 792 $seen_arch = 1; | |
| 793 } | |
| 794 } elsif (debarch_is($host_arch, $arch)) { | |
| 795 $seen_arch = 1; | |
| 796 last; | |
| 797 } | |
| 798 } | |
| 799 return $seen_arch; | |
| 800 } | |
| 801 | |
| 802 sub reduce_arch { | |
| 803 my ($self, $host_arch) = @_; | |
| 804 if (not $self->arch_is_concerned($host_arch)) { | |
| 805 $self->reset(); | |
| 806 } else { | |
| 807 $self->{arches} = undef; | |
| 808 } | |
| 809 } | |
| 810 | |
| 811 sub has_arch_restriction { | |
| 812 my ($self) = @_; | |
| 813 if (defined $self->{arches}) { | |
| 814 return $self->{package}; | |
| 815 } else { | |
| 816 return (); | |
| 817 } | |
| 818 } | |
| 819 | |
| 820 sub profile_is_concerned { | |
| 821 my ($self, $build_profiles) = @_; | |
| 822 | |
| 823 return 0 if not defined $self->{package}; # Empty dep | |
| 824 return 1 if not defined $self->{restrictions}; # Dep without restrictions | |
| 825 | |
| 826 my $seen_profile = 0; | |
| 827 foreach my $restriction (@{$self->{restrictions}}) { | |
| 828 # Determine if this restriction is negated, and within the "profile" | |
| 829 # namespace, otherwise it does not concern this check. | |
| 830 next if $restriction !~ m/^(!)?profile\.(.*)/; | |
| 831 | |
| 832 my $negated = defined $1 && $1 eq '!'; | |
| 833 my $profile = $2; | |
| 834 | |
| 835 # Determine if the restriction matches any of the specified profiles. | |
| 836 my $found = any { $_ eq $profile } @{$build_profiles}; | |
| 837 | |
| 838 if ($negated) { | |
| 839 if ($found) { | |
| 840 $seen_profile = 0; | |
| 841 last; | |
| 842 } else { | |
| 843 # "!profile.this" includes by default all other profiles | |
| 844 # unless they also appear in a "!profile.other". | |
| 845 $seen_profile = 1; | |
| 846 } | |
| 847 } elsif ($found) { | |
| 848 $seen_profile = 1; | |
| 849 last; | |
| 850 } | |
| 851 } | |
| 852 return $seen_profile; | |
| 853 } | |
| 854 | |
| 855 sub reduce_profiles { | |
| 856 my ($self, $build_profiles) = @_; | |
| 857 | |
| 858 if (not $self->profile_is_concerned($build_profiles)) { | |
| 859 $self->reset(); | |
| 860 } else { | |
| 861 $self->{restrictions} = undef; | |
| 862 } | |
| 863 } | |
| 864 | |
| 865 sub get_evaluation { | |
| 866 my ($self, $facts) = @_; | |
| 867 return if not defined $self->{package}; | |
| 868 return $facts->_evaluate_simple_dep($self); | |
| 869 } | |
| 870 | |
| 871 sub simplify_deps { | |
| 872 my ($self, $facts) = @_; | |
| 873 my $eval = $self->get_evaluation($facts); | |
| 874 $self->reset() if defined $eval and $eval == 1; | |
| 875 } | |
| 876 | |
| 877 sub is_empty { | |
| 878 my $self = shift; | |
| 879 return not defined $self->{package}; | |
| 880 } | |
| 881 | |
| 882 sub merge_union { | |
| 883 my ($self, $o) = @_; | |
| 884 return 0 if not $o->isa('Dpkg::Deps::Simple'); | |
| 885 return 0 if $self->is_empty() or $o->is_empty(); | |
| 886 return 0 if $self->{package} ne $o->{package}; | |
| 887 return 0 if defined $self->{arches} or defined $o->{arches}; | |
| 888 | |
| 889 if (not defined $o->{relation} and defined $self->{relation}) { | |
| 890 # Union is the non-versioned dependency | |
| 891 $self->{relation} = undef; | |
| 892 $self->{version} = undef; | |
| 893 return 1; | |
| 894 } | |
| 895 | |
| 896 my $implication = $self->implies($o); | |
| 897 my $rev_implication = $o->implies($self); | |
| 898 if (defined($implication)) { | |
| 899 if ($implication) { | |
| 900 $self->{relation} = $o->{relation}; | |
| 901 $self->{version} = $o->{version}; | |
| 902 return 1; | |
| 903 } else { | |
| 904 return 0; | |
| 905 } | |
| 906 } | |
| 907 if (defined($rev_implication)) { | |
| 908 if ($rev_implication) { | |
| 909 # Already merged... | |
| 910 return 1; | |
| 911 } else { | |
| 912 return 0; | |
| 913 } | |
| 914 } | |
| 915 return 0; | |
| 916 } | |
| 917 | |
| 918 package Dpkg::Deps::Multiple; | |
| 919 | |
| 920 =head2 Dpkg::Deps::Multiple | |
| 921 | |
| 922 This is the base class for Dpkg::Deps::{AND,OR,Union}. It implements | |
| 923 the following methods: | |
| 924 | |
| 925 =over 4 | |
| 926 | |
| 927 =item $mul->add($dep) | |
| 928 | |
| 929 Adds a new dependency object at the end of the list. | |
| 930 | |
| 931 =back | |
| 932 | |
| 933 =cut | |
| 934 | |
| 935 use strict; | |
| 936 use warnings; | |
| 937 | |
| 938 use Carp; | |
| 939 | |
| 940 use Dpkg::ErrorHandling; | |
| 941 | |
| 942 use parent qw(Dpkg::Interface::Storable); | |
| 943 | |
| 944 sub new { | |
| 945 my $this = shift; | |
| 946 my $class = ref($this) || $this; | |
| 947 my $self = { list => [ @_ ] }; | |
| 948 bless $self, $class; | |
| 949 return $self; | |
| 950 } | |
| 951 | |
| 952 sub reset { | |
| 953 my ($self) = @_; | |
| 954 $self->{list} = []; | |
| 955 } | |
| 956 | |
| 957 sub add { | |
| 958 my $self = shift; | |
| 959 push @{$self->{list}}, @_; | |
| 960 } | |
| 961 | |
| 962 sub get_deps { | |
| 963 my $self = shift; | |
| 964 return grep { not $_->is_empty() } @{$self->{list}}; | |
| 965 } | |
| 966 | |
| 967 sub sort { | |
| 968 my $self = shift; | |
| 969 my @res = (); | |
| 970 @res = sort { Dpkg::Deps::deps_compare($a, $b) } @{$self->{list}}; | |
| 971 $self->{list} = [ @res ]; | |
| 972 } | |
| 973 | |
| 974 sub arch_is_concerned { | |
| 975 my ($self, $host_arch) = @_; | |
| 976 my $res = 0; | |
| 977 foreach my $dep (@{$self->{list}}) { | |
| 978 $res = 1 if $dep->arch_is_concerned($host_arch); | |
| 979 } | |
| 980 return $res; | |
| 981 } | |
| 982 | |
| 983 sub reduce_arch { | |
| 984 my ($self, $host_arch) = @_; | |
| 985 my @new; | |
| 986 foreach my $dep (@{$self->{list}}) { | |
| 987 $dep->reduce_arch($host_arch); | |
| 988 push @new, $dep if $dep->arch_is_concerned($host_arch); | |
| 989 } | |
| 990 $self->{list} = [ @new ]; | |
| 991 } | |
| 992 | |
| 993 sub has_arch_restriction { | |
| 994 my ($self) = @_; | |
| 995 my @res; | |
| 996 foreach my $dep (@{$self->{list}}) { | |
| 997 push @res, $dep->has_arch_restriction(); | |
| 998 } | |
| 999 return @res; | |
| 1000 } | |
| 1001 | |
| 1002 | |
| 1003 sub is_empty { | |
| 1004 my $self = shift; | |
| 1005 return scalar @{$self->{list}} == 0; | |
| 1006 } | |
| 1007 | |
| 1008 sub merge_union { | |
| 1009 croak 'method merge_union() is only valid for Dpkg::Deps::Simple'; | |
| 1010 } | |
| 1011 | |
| 1012 package Dpkg::Deps::AND; | |
| 1013 | |
| 1014 =head2 Dpkg::Deps::AND | |
| 1015 | |
| 1016 This object represents a list of dependencies who must be met at the same | |
| 1017 time. | |
| 1018 | |
| 1019 =over 4 | |
| 1020 | |
| 1021 =item $and->output([$fh]) | |
| 1022 | |
| 1023 The output method uses ", " to join the list of sub-dependencies. | |
| 1024 | |
| 1025 =back | |
| 1026 | |
| 1027 =cut | |
| 1028 | |
| 1029 use strict; | |
| 1030 use warnings; | |
| 1031 | |
| 1032 use parent -norequire, qw(Dpkg::Deps::Multiple); | |
| 1033 | |
| 1034 sub output { | |
| 1035 my ($self, $fh) = @_; | |
| 1036 my $res = join(', ', map { $_->output() } grep { not $_->is_empty() } $self-
>get_deps()); | |
| 1037 if (defined($fh)) { | |
| 1038 print { $fh } $res; | |
| 1039 } | |
| 1040 return $res; | |
| 1041 } | |
| 1042 | |
| 1043 sub implies { | |
| 1044 my ($self, $o) = @_; | |
| 1045 # If any individual member can imply $o or NOT $o, we're fine | |
| 1046 foreach my $dep ($self->get_deps()) { | |
| 1047 my $implication = $dep->implies($o); | |
| 1048 return 1 if defined($implication) && $implication == 1; | |
| 1049 return 0 if defined($implication) && $implication == 0; | |
| 1050 } | |
| 1051 # If o is an AND, we might have an implication, if we find an | |
| 1052 # implication within us for each predicate in o | |
| 1053 if ($o->isa('Dpkg::Deps::AND')) { | |
| 1054 my $subset = 1; | |
| 1055 foreach my $odep ($o->get_deps()) { | |
| 1056 my $found = 0; | |
| 1057 foreach my $dep ($self->get_deps()) { | |
| 1058 $found = 1 if $dep->implies($odep); | |
| 1059 } | |
| 1060 $subset = 0 if not $found; | |
| 1061 } | |
| 1062 return 1 if $subset; | |
| 1063 } | |
| 1064 return; | |
| 1065 } | |
| 1066 | |
| 1067 sub get_evaluation { | |
| 1068 my ($self, $facts) = @_; | |
| 1069 # Return 1 only if all members evaluates to true | |
| 1070 # Return 0 if at least one member evaluates to false | |
| 1071 # Return undef otherwise | |
| 1072 my $result = 1; | |
| 1073 foreach my $dep ($self->get_deps()) { | |
| 1074 my $eval = $dep->get_evaluation($facts); | |
| 1075 if (not defined $eval) { | |
| 1076 $result = undef; | |
| 1077 } elsif ($eval == 0) { | |
| 1078 $result = 0; | |
| 1079 last; | |
| 1080 } elsif ($eval == 1) { | |
| 1081 # Still possible | |
| 1082 } | |
| 1083 } | |
| 1084 return $result; | |
| 1085 } | |
| 1086 | |
| 1087 sub simplify_deps { | |
| 1088 my ($self, $facts, @knowndeps) = @_; | |
| 1089 my @new; | |
| 1090 | |
| 1091 WHILELOOP: | |
| 1092 while (@{$self->{list}}) { | |
| 1093 my $dep = shift @{$self->{list}}; | |
| 1094 my $eval = $dep->get_evaluation($facts); | |
| 1095 next if defined($eval) and $eval == 1; | |
| 1096 foreach my $odep (@knowndeps, @new) { | |
| 1097 next WHILELOOP if $odep->implies($dep); | |
| 1098 } | |
| 1099 # When a dependency is implied by another dependency that | |
| 1100 # follows, then invert them | |
| 1101 # "a | b, c, a" becomes "a, c" and not "c, a" | |
| 1102 my $i = 0; | |
| 1103 foreach my $odep (@{$self->{list}}) { | |
| 1104 if (defined $odep and $odep->implies($dep)) { | |
| 1105 splice @{$self->{list}}, $i, 1; | |
| 1106 unshift @{$self->{list}}, $odep; | |
| 1107 next WHILELOOP; | |
| 1108 } | |
| 1109 $i++; | |
| 1110 } | |
| 1111 push @new, $dep; | |
| 1112 } | |
| 1113 $self->{list} = [ @new ]; | |
| 1114 } | |
| 1115 | |
| 1116 | |
| 1117 package Dpkg::Deps::OR; | |
| 1118 | |
| 1119 =head2 Dpkg::Deps::OR | |
| 1120 | |
| 1121 This object represents a list of dependencies of which only one must be met | |
| 1122 for the dependency to be true. | |
| 1123 | |
| 1124 =over 4 | |
| 1125 | |
| 1126 =item $or->output([$fh]) | |
| 1127 | |
| 1128 The output method uses " | " to join the list of sub-dependencies. | |
| 1129 | |
| 1130 =back | |
| 1131 | |
| 1132 =cut | |
| 1133 | |
| 1134 use strict; | |
| 1135 use warnings; | |
| 1136 | |
| 1137 use parent -norequire, qw(Dpkg::Deps::Multiple); | |
| 1138 | |
| 1139 sub output { | |
| 1140 my ($self, $fh) = @_; | |
| 1141 my $res = join(' | ', map { $_->output() } grep { not $_->is_empty() } $self
->get_deps()); | |
| 1142 if (defined($fh)) { | |
| 1143 print { $fh } $res; | |
| 1144 } | |
| 1145 return $res; | |
| 1146 } | |
| 1147 | |
| 1148 sub implies { | |
| 1149 my ($self, $o) = @_; | |
| 1150 | |
| 1151 # Special case for AND with a single member, replace it by its member | |
| 1152 if ($o->isa('Dpkg::Deps::AND')) { | |
| 1153 my @subdeps = $o->get_deps(); | |
| 1154 if (scalar(@subdeps) == 1) { | |
| 1155 $o = $subdeps[0]; | |
| 1156 } | |
| 1157 } | |
| 1158 | |
| 1159 # In general, an OR dependency can't imply anything except if each | |
| 1160 # of its member implies a member in the other OR dependency | |
| 1161 if ($o->isa('Dpkg::Deps::OR')) { | |
| 1162 my $subset = 1; | |
| 1163 foreach my $dep ($self->get_deps()) { | |
| 1164 my $found = 0; | |
| 1165 foreach my $odep ($o->get_deps()) { | |
| 1166 $found = 1 if $dep->implies($odep); | |
| 1167 } | |
| 1168 $subset = 0 if not $found; | |
| 1169 } | |
| 1170 return 1 if $subset; | |
| 1171 } | |
| 1172 return; | |
| 1173 } | |
| 1174 | |
| 1175 sub get_evaluation { | |
| 1176 my ($self, $facts) = @_; | |
| 1177 # Returns false if all members evaluates to 0 | |
| 1178 # Returns true if at least one member evaluates to true | |
| 1179 # Returns undef otherwise | |
| 1180 my $result = 0; | |
| 1181 foreach my $dep ($self->get_deps()) { | |
| 1182 my $eval = $dep->get_evaluation($facts); | |
| 1183 if (not defined $eval) { | |
| 1184 $result = undef; | |
| 1185 } elsif ($eval == 1) { | |
| 1186 $result = 1; | |
| 1187 last; | |
| 1188 } elsif ($eval == 0) { | |
| 1189 # Still possible to have a false evaluation | |
| 1190 } | |
| 1191 } | |
| 1192 return $result; | |
| 1193 } | |
| 1194 | |
| 1195 sub simplify_deps { | |
| 1196 my ($self, $facts) = @_; | |
| 1197 my @new; | |
| 1198 | |
| 1199 WHILELOOP: | |
| 1200 while (@{$self->{list}}) { | |
| 1201 my $dep = shift @{$self->{list}}; | |
| 1202 my $eval = $dep->get_evaluation($facts); | |
| 1203 if (defined($eval) and $eval == 1) { | |
| 1204 $self->{list} = []; | |
| 1205 return; | |
| 1206 } | |
| 1207 foreach my $odep (@new, @{$self->{list}}) { | |
| 1208 next WHILELOOP if $odep->implies($dep); | |
| 1209 } | |
| 1210 push @new, $dep; | |
| 1211 } | |
| 1212 $self->{list} = [ @new ]; | |
| 1213 } | |
| 1214 | |
| 1215 package Dpkg::Deps::Union; | |
| 1216 | |
| 1217 =head2 Dpkg::Deps::Union | |
| 1218 | |
| 1219 This object represents a list of relationships. | |
| 1220 | |
| 1221 =over 4 | |
| 1222 | |
| 1223 =item $union->output([$fh]) | |
| 1224 | |
| 1225 The output method uses ", " to join the list of relationships. | |
| 1226 | |
| 1227 =item $union->implies($other_dep) | |
| 1228 | |
| 1229 =item $union->get_evaluation($other_dep) | |
| 1230 | |
| 1231 Those methods are not meaningful for this object and always return undef. | |
| 1232 | |
| 1233 =item $union->simplify_deps($facts) | |
| 1234 | |
| 1235 The simplication is done to generate an union of all the relationships. | |
| 1236 It uses $simple_dep->merge_union($other_dep) to get its job done. | |
| 1237 | |
| 1238 =back | |
| 1239 | |
| 1240 =cut | |
| 1241 | |
| 1242 use strict; | |
| 1243 use warnings; | |
| 1244 | |
| 1245 use parent -norequire, qw(Dpkg::Deps::Multiple); | |
| 1246 | |
| 1247 sub output { | |
| 1248 my ($self, $fh) = @_; | |
| 1249 my $res = join(', ', map { $_->output() } grep { not $_->is_empty() } $self-
>get_deps()); | |
| 1250 if (defined($fh)) { | |
| 1251 print { $fh } $res; | |
| 1252 } | |
| 1253 return $res; | |
| 1254 } | |
| 1255 | |
| 1256 sub implies { | |
| 1257 # Implication test are not useful on Union | |
| 1258 return; | |
| 1259 } | |
| 1260 | |
| 1261 sub get_evaluation { | |
| 1262 # Evaluation are not useful on Union | |
| 1263 return; | |
| 1264 } | |
| 1265 | |
| 1266 sub simplify_deps { | |
| 1267 my ($self, $facts) = @_; | |
| 1268 my @new; | |
| 1269 | |
| 1270 WHILELOOP: | |
| 1271 while (@{$self->{list}}) { | |
| 1272 my $odep = shift @{$self->{list}}; | |
| 1273 foreach my $dep (@new) { | |
| 1274 next WHILELOOP if $dep->merge_union($odep); | |
| 1275 } | |
| 1276 push @new, $odep; | |
| 1277 } | |
| 1278 $self->{list} = [ @new ]; | |
| 1279 } | |
| 1280 | |
| 1281 package Dpkg::Deps::KnownFacts; | |
| 1282 | |
| 1283 =head2 Dpkg::Deps::KnownFacts | |
| 1284 | |
| 1285 This object represents a list of installed packages and a list of virtual | |
| 1286 packages provided (by the set of installed packages). | |
| 1287 | |
| 1288 =over 4 | |
| 1289 | |
| 1290 =item my $facts = Dpkg::Deps::KnownFacts->new(); | |
| 1291 | |
| 1292 Creates a new object. | |
| 1293 | |
| 1294 =cut | |
| 1295 | |
| 1296 use strict; | |
| 1297 use warnings; | |
| 1298 | |
| 1299 use Dpkg::Version; | |
| 1300 | |
| 1301 sub new { | |
| 1302 my $this = shift; | |
| 1303 my $class = ref($this) || $this; | |
| 1304 my $self = { | |
| 1305 pkg => {}, | |
| 1306 virtualpkg => {}, | |
| 1307 }; | |
| 1308 bless $self, $class; | |
| 1309 return $self; | |
| 1310 } | |
| 1311 | |
| 1312 =item $facts->add_installed_package($package, $version, $arch, $multiarch) | |
| 1313 | |
| 1314 Records that the given version of the package is installed. If | |
| 1315 $version/$arch is undefined we know that the package is installed but we | |
| 1316 don't know which version/architecture it is. $multiarch is the Multi-Arch | |
| 1317 field of the package. If $multiarch is undef, it will be equivalent to | |
| 1318 "Multi-Arch: no". | |
| 1319 | |
| 1320 Note that $multiarch is only used if $arch is provided. | |
| 1321 | |
| 1322 =cut | |
| 1323 | |
| 1324 sub add_installed_package { | |
| 1325 my ($self, $pkg, $ver, $arch, $multiarch) = @_; | |
| 1326 my $p = { | |
| 1327 package => $pkg, | |
| 1328 version => $ver, | |
| 1329 architecture => $arch, | |
| 1330 multiarch => $multiarch || 'no', | |
| 1331 }; | |
| 1332 $self->{pkg}{"$pkg:$arch"} = $p if defined $arch; | |
| 1333 push @{$self->{pkg}{$pkg}}, $p; | |
| 1334 } | |
| 1335 | |
| 1336 =item $facts->add_provided_package($virtual, $relation, $version, $by) | |
| 1337 | |
| 1338 Records that the "$by" package provides the $virtual package. $relation | |
| 1339 and $version correspond to the associated relation given in the Provides | |
| 1340 field. This might be used in the future for versioned provides. | |
| 1341 | |
| 1342 =cut | |
| 1343 | |
| 1344 sub add_provided_package { | |
| 1345 my ($self, $pkg, $rel, $ver, $by) = @_; | |
| 1346 if (not exists $self->{virtualpkg}{$pkg}) { | |
| 1347 $self->{virtualpkg}{$pkg} = []; | |
| 1348 } | |
| 1349 push @{$self->{virtualpkg}{$pkg}}, [ $by, $rel, $ver ]; | |
| 1350 } | |
| 1351 | |
| 1352 =item my ($check, $param) = $facts->check_package($package) | |
| 1353 | |
| 1354 $check is one when the package is found. For a real package, $param | |
| 1355 contains the version. For a virtual package, $param contains an array | |
| 1356 reference containing the list of packages that provide it (each package is | |
| 1357 listed as [ $provider, $relation, $version ]). | |
| 1358 | |
| 1359 This function is obsolete and should not be used. Dpkg::Deps::KnownFacts | |
| 1360 is only meant to be filled with data and then passed to Dpkg::Deps | |
| 1361 methods where appropriate, but it should not be directly queried. | |
| 1362 | |
| 1363 =back | |
| 1364 | |
| 1365 =cut | |
| 1366 | |
| 1367 sub check_package { | |
| 1368 my ($self, $pkg) = @_; | |
| 1369 if (exists $self->{pkg}{$pkg}) { | |
| 1370 return (1, $self->{pkg}{$pkg}[0]{version}); | |
| 1371 } | |
| 1372 if (exists $self->{virtualpkg}{$pkg}) { | |
| 1373 return (1, $self->{virtualpkg}{$pkg}); | |
| 1374 } | |
| 1375 return (0, undef); | |
| 1376 } | |
| 1377 | |
| 1378 ## The functions below are private to Dpkg::Deps | |
| 1379 | |
| 1380 sub _find_package { | |
| 1381 my ($self, $dep, $lackinfos) = @_; | |
| 1382 my ($pkg, $archqual) = ($dep->{package}, $dep->{archqual}); | |
| 1383 return if not exists $self->{pkg}{$pkg}; | |
| 1384 my $host_arch = $dep->{host_arch}; | |
| 1385 my $build_arch = $dep->{build_arch}; | |
| 1386 foreach my $p (@{$self->{pkg}{$pkg}}) { | |
| 1387 my $a = $p->{architecture}; | |
| 1388 my $ma = $p->{multiarch}; | |
| 1389 if (not defined $a) { | |
| 1390 $$lackinfos = 1; | |
| 1391 next; | |
| 1392 } | |
| 1393 if (not defined $archqual) { | |
| 1394 return $p if $ma eq 'foreign'; | |
| 1395 return $p if $a eq $host_arch or $a eq 'all'; | |
| 1396 } elsif ($archqual eq 'any') { | |
| 1397 return $p if $ma eq 'allowed'; | |
| 1398 } elsif ($archqual eq 'native') { | |
| 1399 return $p if $a eq $build_arch and $ma ne 'foreign'; | |
| 1400 } else { | |
| 1401 return $p if $a eq $archqual; | |
| 1402 } | |
| 1403 } | |
| 1404 return; | |
| 1405 } | |
| 1406 | |
| 1407 sub _find_virtual_packages { | |
| 1408 my ($self, $pkg) = @_; | |
| 1409 return () if not exists $self->{virtualpkg}{$pkg}; | |
| 1410 return @{$self->{virtualpkg}{$pkg}}; | |
| 1411 } | |
| 1412 | |
| 1413 sub _evaluate_simple_dep { | |
| 1414 my ($self, $dep) = @_; | |
| 1415 my ($lackinfos, $pkg) = (0, $dep->{package}); | |
| 1416 my $p = $self->_find_package($dep, \$lackinfos); | |
| 1417 if ($p) { | |
| 1418 if (defined $dep->{relation}) { | |
| 1419 if (defined $p->{version}) { | |
| 1420 return 1 if version_compare_relation($p->{version}, | |
| 1421 $dep->{relation}, $dep->{version}); | |
| 1422 } else { | |
| 1423 $lackinfos = 1; | |
| 1424 } | |
| 1425 } else { | |
| 1426 return 1; | |
| 1427 } | |
| 1428 } | |
| 1429 foreach my $virtpkg ($self->_find_virtual_packages($pkg)) { | |
| 1430 # XXX: Adapt when versioned provides are allowed | |
| 1431 next if defined $virtpkg->[1]; | |
| 1432 next if defined $dep->{relation}; # Provides don't satisfy versioned dep
s | |
| 1433 return 1; | |
| 1434 } | |
| 1435 return if $lackinfos; | |
| 1436 return 0; | |
| 1437 } | |
| 1438 | |
| 1439 =head1 CHANGES | |
| 1440 | |
| 1441 =head2 Version 1.02 | |
| 1442 | |
| 1443 =over | |
| 1444 | |
| 1445 =item * Add new Dpkg::deps_concat() function. | |
| 1446 | |
| 1447 =back | |
| 1448 | |
| 1449 =head2 Version 1.01 | |
| 1450 | |
| 1451 =over | |
| 1452 | |
| 1453 =item * Add new $dep->reset() method that all dependency objects support. | |
| 1454 | |
| 1455 =item * Dpkg::Deps::Simple now recognizes the arch qualifier "any" and | |
| 1456 stores it in the "archqual" property when present. | |
| 1457 | |
| 1458 =item * Dpkg::Deps::KnownFacts->add_installed_package() now accepts 2 | |
| 1459 supplementary parameters ($arch and $multiarch). | |
| 1460 | |
| 1461 =item * Dpkg::Deps::KnownFacts->check_package() is obsolete, it should | |
| 1462 not have been part of the public API. | |
| 1463 | |
| 1464 =back | |
| 1465 | |
| 1466 =cut | |
| 1467 | |
| 1468 1; | |
| OLD | NEW |