Deps.pm 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. # Copyright 2007 Raphael Hertzog <hertzog@debian.org>
  2. #
  3. # This program is free software; you may redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2, or (at your option)
  6. # any later version.
  7. #
  8. # This is distributed in the hope that it will be useful, but without
  9. # any warranty; without even the implied warranty of merchantability or
  10. # fitness for a particular purpose. See the GNU General Public License
  11. # for more details.
  12. #
  13. # A copy of the GNU General Public License is available as
  14. # /usr/share/common-licenses/GPL in the Debian GNU/Linux distribution
  15. # or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html.
  16. # You can also obtain it by writing to the Free Software Foundation, Inc.,
  17. # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  18. #########################################################################
  19. # Several parts are inspired by lib/Dep.pm from lintian (same license)
  20. #
  21. # Copyright (C) 1998 Richard Braakman
  22. # Portions Copyright (C) 1999 Darren Benham
  23. # Portions Copyright (C) 2000 Sean 'Shaleh' Perry
  24. # Portions Copyright (C) 2004 Frank Lichtenheld
  25. # Portions Copyright (C) 2006 Russ Allbery
  26. package Dpkg::Deps;
  27. use strict;
  28. use warnings;
  29. use Dpkg::Version qw(compare_versions);
  30. use Dpkg::Arch qw(get_host_arch);
  31. use Dpkg::ErrorHandling qw(warning);
  32. use Dpkg::Gettext;
  33. our @ISA = qw(Exporter);
  34. our @EXPORT_OK = qw(@pkg_dep_fields @src_dep_fields %dep_field_type);
  35. # Some generic variables
  36. our @pkg_dep_fields = qw(Pre-Depends Depends Recommends Suggests Enhances
  37. Conflicts Breaks Replaces Provides);
  38. our @src_dep_fields = qw(Build-Depends Build-Depends-Indep
  39. Build-Conflicts Build-Conflicts-Indep);
  40. our %dep_field_type = (
  41. 'Pre-Depends' => 'normal',
  42. 'Depends' => 'normal',
  43. 'Recommends' => 'normal',
  44. 'Suggests' => 'normal',
  45. 'Enhances' => 'union',
  46. 'Conflicts' => 'union',
  47. 'Breaks' => 'union',
  48. 'Replaces' => 'union',
  49. 'Provides' => 'union',
  50. 'Build-Depends' => 'normal',
  51. 'Build-Depends-Indep' => 'normal',
  52. 'Build-Conflicts' => 'union',
  53. 'Build-Conflicts-Indep' => 'union',
  54. );
  55. # Some factorized function
  56. # Returns true if the arch list $p is a superset of arch list $q
  57. sub arch_is_superset {
  58. my ($p, $q) = @_;
  59. my $p_arch_neg = defined($p) && $p->[0] =~ /^!/;
  60. my $q_arch_neg = defined($q) && $q->[0] =~ /^!/;
  61. # If "a" has no arches, it is a superset of q and we should fall through
  62. # to the version check.
  63. if (not defined $p) {
  64. return 1;
  65. }
  66. # If q has no arches, it is a superset of p and there are no useful
  67. # implications.
  68. elsif (not defined $q) {
  69. return 0;
  70. }
  71. # Both have arches. If neither are negated, we know nothing useful
  72. # unless q is a subset of p.
  73. elsif (not $p_arch_neg and not $q_arch_neg) {
  74. my %p_arches = map { $_ => 1 } @{$p};
  75. my $subset = 1;
  76. for my $arch (@{$q}) {
  77. $subset = 0 unless $p_arches{$arch};
  78. }
  79. return 0 unless $subset;
  80. }
  81. # If both are negated, we know nothing useful unless p is a subset of
  82. # q (and therefore has fewer things excluded, and therefore is more
  83. # general).
  84. elsif ($p_arch_neg and $q_arch_neg) {
  85. my %q_arches = map { $_ => 1 } @{$q};
  86. my $subset = 1;
  87. for my $arch (@{$p}) {
  88. $subset = 0 unless $q_arches{$arch};
  89. }
  90. return 0 unless $subset;
  91. }
  92. # If q is negated and p isn't, we'd need to know the full list of
  93. # arches to know if there's any relationship, so bail.
  94. elsif (not $p_arch_neg and $q_arch_neg) {
  95. return 0;
  96. }
  97. # If p is negated and q isn't, q is a subset of p if none of the
  98. # negated arches in p are present in q.
  99. elsif ($p_arch_neg and not $q_arch_neg) {
  100. my %q_arches = map { $_ => 1 } @{$q};
  101. my $subset = 1;
  102. for my $arch (@{$p}) {
  103. $subset = 0 if $q_arches{substr($arch, 1)};
  104. }
  105. return 0 unless $subset;
  106. }
  107. return 1;
  108. }
  109. sub version_implies {
  110. my ($rel_p, $v_p, $rel_q, $v_q) = @_;
  111. # q wants an exact version, so p must provide that exact version. p
  112. # disproves q if q's version is outside the range enforced by p.
  113. if ($rel_q eq '=') {
  114. if ($rel_p eq '<<') {
  115. return compare_versions($v_p, '<=', $v_q) ? 0 : undef;
  116. } elsif ($rel_p eq '<=') {
  117. return compare_versions($v_p, '<<', $v_q) ? 0 : undef;
  118. } elsif ($rel_p eq '>>') {
  119. return compare_versions($v_p, '>=', $v_q) ? 0 : undef;
  120. } elsif ($rel_p eq '>=') {
  121. return compare_versions($v_p, '>>', $v_q) ? 0 : undef;
  122. } elsif ($rel_p eq '=') {
  123. return compare_versions($v_p, '=', $v_q);
  124. }
  125. }
  126. # A greater than clause may disprove a less than clause. An equal
  127. # cause might as well. Otherwise, if
  128. # p's clause is <<, <=, or =, the version must be <= q's to imply q.
  129. if ($rel_q eq '<=') {
  130. if ($rel_p eq '>>') {
  131. return compare_versions($v_p, '>=', $v_q) ? 0 : undef;
  132. } elsif ($rel_p eq '>=') {
  133. return compare_versions($v_p, '>>', $v_q) ? 0 : undef;
  134. } elsif ($rel_p eq '=') {
  135. return compare_versions($v_p, '<=', $v_q) ? 1 : 0;
  136. } else { # <<, <=
  137. return compare_versions($v_p, '<=', $v_q) ? 1 : undef;
  138. }
  139. }
  140. # Similar, but << is stronger than <= so p's version must be << q's
  141. # version if the p relation is <= or =.
  142. if ($rel_q eq '<<') {
  143. if ($rel_p eq '>>' or $rel_p eq '>=') {
  144. return compare_versions($v_p, '>=', $v_p) ? 0 : undef;
  145. } elsif ($rel_p eq '<<') {
  146. return compare_versions($v_p, '<=', $v_q) ? 1 : undef;
  147. } elsif ($rel_p eq '=') {
  148. return compare_versions($v_p, '<<', $v_q) ? 1 : 0;
  149. } else { # <<, <=
  150. return compare_versions($v_p, '<<', $v_q) ? 1 : undef;
  151. }
  152. }
  153. # Same logic as above, only inverted.
  154. if ($rel_q eq '>=') {
  155. if ($rel_p eq '<<') {
  156. return compare_versions($v_p, '<=', $v_q) ? 0 : undef;
  157. } elsif ($rel_p eq '<=') {
  158. return compare_versions($v_p, '<<', $v_q) ? 0 : undef;
  159. } elsif ($rel_p eq '=') {
  160. return compare_versions($v_p, '>=', $v_q) ? 1 : 0;
  161. } else { # >>, >=
  162. return compare_versions($v_p, '>=', $v_q) ? 1 : undef;
  163. }
  164. }
  165. if ($rel_q eq '>>') {
  166. if ($rel_p eq '<<' or $rel_p eq '<=') {
  167. return compare_versions($v_p, '<=', $v_q) ? 0 : undef;
  168. } elsif ($rel_p eq '>>') {
  169. return compare_versions($v_p, '>=', $v_q) ? 1 : undef;
  170. } elsif ($rel_p eq '=') {
  171. return compare_versions($v_p, '>>', $v_q) ? 1 : 0;
  172. } else {
  173. return compare_versions($v_p, '>>', $v_q) ? 1 : undef;
  174. }
  175. }
  176. return undef;
  177. }
  178. sub parse {
  179. my $dep_line = shift;
  180. my %options = (@_);
  181. $options{use_arch} = 1 if not exists $options{use_arch};
  182. $options{reduce_arch} = 0 if not exists $options{reduce_arch};
  183. $options{host_arch} = get_host_arch() if not exists $options{host_arch};
  184. $options{union} = 0 if not exists $options{union};
  185. my @dep_list;
  186. foreach my $dep_and (split(/\s*,\s*/m, $dep_line)) {
  187. my @or_list = ();
  188. foreach my $dep_or (split(/\s*\|\s*/m, $dep_and)) {
  189. my $dep_simple = Dpkg::Deps::Simple->new($dep_or);
  190. if (not defined $dep_simple->{package}) {
  191. warning(sprintf(_g("can't parse dependency %s"), $dep_and));
  192. return undef;
  193. }
  194. $dep_simple->{arches} = undef if not $options{use_arch};
  195. if ($options{reduce_arch}) {
  196. $dep_simple->reduce_arch($options{host_arch});
  197. next if not $dep_simple->arch_is_concerned($options{host_arch});
  198. }
  199. push @or_list, $dep_simple;
  200. }
  201. next if not @or_list;
  202. if (scalar @or_list == 1) {
  203. push @dep_list, $or_list[0];
  204. } else {
  205. my $dep_or = Dpkg::Deps::OR->new();
  206. $dep_or->add($_) foreach (@or_list);
  207. push @dep_list, $dep_or;
  208. }
  209. }
  210. return undef if not @dep_list;
  211. my $dep_and;
  212. if ($options{union}) {
  213. $dep_and = Dpkg::Deps::Union->new();
  214. } else {
  215. $dep_and = Dpkg::Deps::AND->new();
  216. }
  217. $dep_and->add($_) foreach (@dep_list);
  218. return $dep_and;
  219. }
  220. package Dpkg::Deps::Simple;
  221. use strict;
  222. use warnings;
  223. use Dpkg::Arch qw(debarch_is);
  224. use Dpkg::Version qw(compare_versions);
  225. use Dpkg::ErrorHandling qw(internerr);
  226. use Dpkg::Gettext;
  227. sub new {
  228. my ($this, $arg) = @_;
  229. my $class = ref($this) || $this;
  230. my $self = {
  231. 'package' => undef,
  232. 'relation' => undef,
  233. 'version' => undef,
  234. 'arches' => undef,
  235. };
  236. bless $self, $class;
  237. $self->parse($arg) if defined($arg);
  238. return $self;
  239. }
  240. sub parse {
  241. my ($self, $dep) = @_;
  242. return if not $dep =~
  243. /^\s* # skip leading whitespace
  244. ([a-zA-Z0-9][a-zA-Z0-9+.-]*) # package name
  245. (?: # start of optional part
  246. \s* \( # open parenthesis for version part
  247. \s* (<<|<=|=|>=|>>|<|>) # relation part
  248. \s* (.*?) # do not attempt to parse version
  249. \s* \) # closing parenthesis
  250. )? # end of optional part
  251. (?: # start of optional architecture
  252. \s* \[ # open bracket for architecture
  253. \s* (.*?) # don't parse architectures now
  254. \s* \] # closing bracket
  255. )? # end of optional architecture
  256. \s*$ # trailing spaces at end
  257. /mx;
  258. $self->{package} = $1;
  259. $self->{relation} = $2;
  260. $self->{version} = $3;
  261. if (defined($4)) {
  262. $self->{arches} = [ split(/\s+/, $4) ];
  263. }
  264. # Standardize relation field
  265. if (defined($self->{relation})) {
  266. $self->{relation} = '<<' if ($self->{relation} eq '<');
  267. $self->{relation} = '>>' if ($self->{relation} eq '>');
  268. }
  269. }
  270. sub dump {
  271. my $self = shift;
  272. my $res = $self->{package};
  273. if (defined($self->{relation})) {
  274. $res .= " (" . $self->{relation} . " " . $self->{version} . ")";
  275. }
  276. if (defined($self->{'arches'})) {
  277. $res .= " [" . join(" ", @{$self->{arches}}) . "]";
  278. }
  279. return $res;
  280. }
  281. # Returns true if the dependency in parameter can deduced from the current
  282. # dependency. Returns false if it can be negated. Returns undef if nothing
  283. # can be concluded.
  284. sub implies {
  285. my ($self, $o) = @_;
  286. if ($o->isa('Dpkg::Deps::Simple')) {
  287. # An implication is only possible on the same package
  288. return undef if $self->{package} ne $o->{package};
  289. # Our architecture set must be a superset of the architectures for
  290. # o, otherwise we can't conclude anything.
  291. return undef unless Dpkg::Deps::arch_is_superset($self->{arches}, $o->{arches});
  292. # If o has no version clause, then our dependency is stronger
  293. return 1 if not defined $o->{relation};
  294. # If o has a version clause, we must also have one, otherwise there
  295. # can't be an implication
  296. return undef if not defined $self->{relation};
  297. return Dpkg::Deps::version_implies($self->{relation}, $self->{version},
  298. $o->{relation}, $o->{version});
  299. } elsif ($o->isa('Dpkg::Deps::AND')) {
  300. # TRUE: Need to imply all individual elements
  301. # FALSE: Need to NOT imply at least one individual element
  302. my $res = 1;
  303. foreach my $dep ($o->get_deps()) {
  304. my $implication = $self->implies($dep);
  305. unless (defined($implication) && $implication == 1) {
  306. $res = $implication;
  307. last if defined $res;
  308. }
  309. }
  310. return $res;
  311. } elsif ($o->isa('Dpkg::Deps::OR')) {
  312. # TRUE: Need to imply at least one individual element
  313. # FALSE: Need to not apply all individual elements
  314. # UNDEF: The rest
  315. my $res = undef;
  316. foreach my $dep ($o->get_deps()) {
  317. my $implication = $self->implies($dep);
  318. if (defined($implication)) {
  319. if (not defined $res) {
  320. $res = $implication;
  321. } else {
  322. if ($implication) {
  323. $res = 1;
  324. } else {
  325. $res = 0;
  326. }
  327. }
  328. last if defined($res) && $res == 1;
  329. }
  330. }
  331. return $res;
  332. } else {
  333. internerr(sprintf(_g("Dpkg::Deps::Simple can't evaluate implication with a %s!"), ref($o)));
  334. }
  335. }
  336. sub get_deps {
  337. my $self = shift;
  338. return $self;
  339. }
  340. sub sort {
  341. # Nothing to sort
  342. }
  343. sub arch_is_concerned {
  344. my ($self, $host_arch) = @_;
  345. return 0 if not defined $self->{package}; # Empty dep
  346. return 1 if not defined $self->{arches}; # Dep without arch spec
  347. my $seen_arch = 0;
  348. foreach my $arch (@{$self->{arches}}) {
  349. $arch=lc($arch);
  350. if ($arch =~ /^!/) {
  351. my $not_arch = $arch;
  352. $not_arch =~ s/^!//;
  353. if (debarch_is($host_arch, $not_arch)) {
  354. $seen_arch = 0;
  355. last;
  356. } else {
  357. # !arch includes by default all other arches
  358. # unless they also appear in a !otherarch
  359. $seen_arch = 1;
  360. }
  361. } elsif (debarch_is($host_arch, $arch)) {
  362. $seen_arch = 1;
  363. last;
  364. }
  365. }
  366. return $seen_arch;
  367. }
  368. sub reduce_arch {
  369. my ($self, $host_arch) = @_;
  370. if (not $self->arch_is_concerned($host_arch)) {
  371. $self->{package} = undef;
  372. $self->{relation} = undef;
  373. $self->{version} = undef;
  374. $self->{arches} = undef;
  375. } else {
  376. $self->{arches} = undef;
  377. }
  378. }
  379. sub get_evaluation {
  380. my ($self, $facts) = @_;
  381. return undef if not defined $self->{package};
  382. my ($check, $param) = $facts->check_package($self->{package});
  383. if ($check) {
  384. if (defined $self->{relation}) {
  385. if (ref($param)) {
  386. # Provided packages
  387. # XXX: Once support for versioned provides is in place,
  388. # this part must be adapted
  389. return 0;
  390. } else {
  391. if (defined($param)) {
  392. if (compare_versions($param, $self->{relation}, $self->{version})) {
  393. return 1;
  394. } else {
  395. return 0;
  396. }
  397. } else {
  398. return undef;
  399. }
  400. }
  401. } else {
  402. return 1;
  403. }
  404. }
  405. return undef;
  406. }
  407. sub simplify_deps {
  408. my ($self, $facts) = @_;
  409. my $eval = $self->get_evaluation($facts);
  410. if (defined($eval) and $eval == 1) {
  411. $self->{package} = undef;
  412. $self->{relation} = undef;
  413. $self->{version} = undef;
  414. $self->{arches} = undef;
  415. }
  416. }
  417. sub is_empty {
  418. my $self = shift;
  419. return not defined $self->{package};
  420. }
  421. sub merge_union {
  422. my ($self, $o) = @_;
  423. return 0 if not $o->isa('Dpkg::Deps::Simple');
  424. return 0 if $self->is_empty() or $o->is_empty();
  425. return 0 if $self->{package} ne $o->{package};
  426. return 0 if defined $self->{arches} or defined $o->{arches};
  427. if (not defined $o->{relation} and defined $self->{relation}) {
  428. # Union is the non-versioned dependency
  429. $self->{relation} = undef;
  430. $self->{version} = undef;
  431. return 1;
  432. }
  433. my $implication = $self->implies($o);
  434. my $rev_implication = $o->implies($self);
  435. if (defined($implication)) {
  436. if ($implication) {
  437. $self->{relation} = $o->{relation};
  438. $self->{version} = $o->{version};
  439. return 1;
  440. } else {
  441. return 0;
  442. }
  443. }
  444. if (defined($rev_implication)) {
  445. if ($rev_implication) {
  446. # Already merged...
  447. return 1;
  448. } else {
  449. return 0;
  450. }
  451. }
  452. return 0;
  453. }
  454. package Dpkg::Deps::Multiple;
  455. use strict;
  456. use warnings;
  457. use Dpkg::ErrorHandling qw(internerr);
  458. sub new {
  459. my $this = shift;
  460. my $class = ref($this) || $this;
  461. my $self = { 'list' => [ @_ ] };
  462. bless $self, $class;
  463. return $self;
  464. }
  465. sub add {
  466. my $self = shift;
  467. push @{$self->{list}}, @_;
  468. }
  469. sub get_deps {
  470. my $self = shift;
  471. return @{$self->{list}};
  472. }
  473. sub sort {
  474. my $self = shift;
  475. my @res = ();
  476. @res = sort { $a->dump() cmp $b->dump() } @{$self->{list}};
  477. $self->{list} = [ @res ];
  478. }
  479. sub arch_is_concerned {
  480. my ($self, $host_arch) = @_;
  481. my $res = 0;
  482. foreach my $dep (@{$self->{list}}) {
  483. $res = 1 if $dep->arch_is_concerned($host_arch);
  484. }
  485. return $res;
  486. }
  487. sub reduce_arch {
  488. my ($self, $host_arch) = @_;
  489. my @new;
  490. foreach my $dep (@{$self->{list}}) {
  491. $dep->reduce_arch($host_arch);
  492. push @new, $dep if $dep->arch_is_concerned($host_arch);
  493. }
  494. $self->{list} = [ @new ];
  495. }
  496. sub is_empty {
  497. my $self = shift;
  498. return scalar @{$self->{list}} == 0;
  499. }
  500. sub merge_union {
  501. internerr("The method merge_union() is only valid for Dpkg::Deps::Simple");
  502. }
  503. package Dpkg::Deps::AND;
  504. use strict;
  505. use warnings;
  506. our @ISA = qw(Dpkg::Deps::Multiple);
  507. sub dump {
  508. my $self = shift;
  509. return join(", ", map { $_->dump() } grep { not $_->is_empty() } $self->get_deps());
  510. }
  511. sub implies {
  512. my ($self, $o) = @_;
  513. # If any individual member can imply $o or NOT $o, we're fine
  514. foreach my $dep ($self->get_deps()) {
  515. my $implication = $dep->implies($o);
  516. return 1 if defined($implication) && $implication == 1;
  517. return 0 if defined($implication) && $implication == 0;
  518. }
  519. # If o is an AND, we might have an implication, if we find an
  520. # implication within us for each predicate in o
  521. if ($o->isa('Dpkg::Deps::AND')) {
  522. my $subset = 1;
  523. foreach my $odep ($o->get_deps()) {
  524. my $found = 0;
  525. foreach my $dep ($self->get_deps()) {
  526. $found = 1 if $dep->implies($odep);
  527. }
  528. $subset = 0 if not $found;
  529. }
  530. return 1 if $subset;
  531. }
  532. return undef;
  533. }
  534. sub get_evaluation {
  535. my ($self, $facts) = @_;
  536. my $result = 1;
  537. foreach my $dep ($self->get_deps()) {
  538. my $eval = $dep->get_evaluation($facts);
  539. if (not defined $eval) {
  540. $result = undef;
  541. last;
  542. } elsif ($eval == 0) {
  543. $result = 0;
  544. last;
  545. } elsif ($eval == 1) {
  546. # Still possible
  547. }
  548. }
  549. return $result;
  550. }
  551. sub simplify_deps {
  552. my ($self, $facts, @knowndeps) = @_;
  553. my @new;
  554. WHILELOOP:
  555. while (@{$self->{list}}) {
  556. my $dep = shift @{$self->{list}};
  557. my $eval = $dep->get_evaluation($facts);
  558. next if defined($eval) and $eval == 1;
  559. foreach my $odep (@knowndeps, @new, @{$self->{list}}) {
  560. next WHILELOOP if $odep->implies($dep);
  561. }
  562. push @new, $dep;
  563. }
  564. $self->{list} = [ @new ];
  565. }
  566. package Dpkg::Deps::OR;
  567. use strict;
  568. use warnings;
  569. our @ISA = qw(Dpkg::Deps::Multiple);
  570. sub dump {
  571. my $self = shift;
  572. return join(" | ", map { $_->dump() } grep { not $_->is_empty() } $self->get_deps());
  573. }
  574. sub implies {
  575. my ($self, $o) = @_;
  576. # Special case for AND with a single member, replace it by its member
  577. if ($o->isa('Dpkg::Deps::AND')) {
  578. my @subdeps = $o->get_deps();
  579. if (scalar(@subdeps) == 1) {
  580. $o = $subdeps[0];
  581. }
  582. }
  583. # In general, an OR dependency can't imply anything except if each
  584. # of its member implies a member in the other OR dependency
  585. if ($o->isa('Dpkg::Deps::OR')) {
  586. my $subset = 1;
  587. foreach my $dep ($self->get_deps()) {
  588. my $found = 0;
  589. foreach my $odep ($o->get_deps()) {
  590. $found = 1 if $dep->implies($odep);
  591. }
  592. $subset = 0 if not $found;
  593. }
  594. return 1 if $subset;
  595. }
  596. return undef;
  597. }
  598. sub get_evaluation {
  599. my ($self, $facts) = @_;
  600. my $result = 0;
  601. foreach my $dep ($self->get_deps()) {
  602. my $eval = $dep->get_evaluation($facts);
  603. if (not defined $eval) {
  604. $result = undef;
  605. last;
  606. } elsif ($eval == 1) {
  607. $result = 1;
  608. last;
  609. } elsif ($eval == 0) {
  610. # Still possible to have a false evaluation
  611. }
  612. }
  613. return $result;
  614. }
  615. sub simplify_deps {
  616. my ($self, $facts) = @_;
  617. my @new;
  618. WHILELOOP:
  619. while (@{$self->{list}}) {
  620. my $dep = shift @{$self->{list}};
  621. my $eval = $dep->get_evaluation($facts);
  622. if (defined($eval) and $eval == 1) {
  623. $self->{list} = [];
  624. return;
  625. }
  626. foreach my $odep (@new, @{$self->{list}}) {
  627. next WHILELOOP if $odep->implies($dep);
  628. }
  629. push @new, $dep;
  630. }
  631. $self->{list} = [ @new ];
  632. }
  633. package Dpkg::Deps::Union;
  634. use strict;
  635. use warnings;
  636. our @ISA = qw(Dpkg::Deps::Multiple);
  637. sub dump {
  638. my $self = shift;
  639. return join(", ", map { $_->dump() } grep { not $_->is_empty() } $self->get_deps());
  640. }
  641. sub implies {
  642. # Implication test are not useful on Union
  643. return undef;
  644. }
  645. sub get_evaluation {
  646. # Evaluation are not useful on Union
  647. return undef;
  648. }
  649. sub simplify_deps {
  650. my ($self, $facts) = @_;
  651. my @new;
  652. WHILELOOP:
  653. while (@{$self->{list}}) {
  654. my $dep = shift @{$self->{list}};
  655. foreach my $odep (@new) {
  656. next WHILELOOP if $dep->merge_union($odep);
  657. }
  658. push @new, $dep;
  659. }
  660. $self->{list} = [ @new ];
  661. }
  662. package Dpkg::Deps::KnownFacts;
  663. use strict;
  664. use warnings;
  665. sub new {
  666. my $this = shift;
  667. my $class = ref($this) || $this;
  668. my $self = { 'pkg' => {}, 'virtualpkg' => {} };
  669. bless $self, $class;
  670. return $self;
  671. }
  672. sub add_installed_package {
  673. my ($self, $pkg, $ver) = @_;
  674. $self->{pkg}{$pkg} = $ver;
  675. }
  676. sub add_provided_package {
  677. my ($self, $pkg, $rel, $ver, $by) = @_;
  678. if (not exists $self->{virtualpkg}{$pkg}) {
  679. $self->{virtualpkg}{$pkg} = [];
  680. }
  681. push @{$self->{virtualpkg}{$pkg}}, [ $by, $rel, $ver ];
  682. }
  683. sub check_package {
  684. my ($self, $pkg) = @_;
  685. if (exists $self->{pkg}{$pkg}) {
  686. return (1, $self->{pkg}{$pkg});
  687. }
  688. if (exists $self->{virtualpkg}{$pkg}) {
  689. return (1, $self->{virtualpkg}{$pkg});
  690. }
  691. return (0, undef);
  692. }
  693. 1;