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 |