1# ex:ts=8 sw=4: 2# $OpenBSD: PkgCfl.pm,v 1.37 2011/07/02 12:12:58 espie Exp $ 3# 4# Copyright (c) 2003-2005 Marc Espie <espie@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use strict; 19use warnings; 20 21package OpenBSD::PkgCfl; 22use OpenBSD::PackageName; 23use OpenBSD::Search; 24use OpenBSD::PackageInfo; 25 26sub make_conflict_list 27{ 28 my ($class, $plist) = @_; 29 my $l = []; 30 my $pkgname = $plist->pkgname; 31 my $stem = OpenBSD::PackageName::splitstem($pkgname); 32 33 unless (defined $plist->{'no-default-conflict'}) { 34 push(@$l, OpenBSD::Search::PkgSpec->new("$stem-*|partial-$stem-*")); 35 } else { 36 push(@$l, OpenBSD::Search::Exact->new("$pkgname|partial-$pkgname")); 37 } 38 if (defined $plist->{conflict}) { 39 for my $cfl (@{$plist->{conflict}}) { 40 push(@$l, $cfl->spec); 41 } 42 } 43 bless $l, $class; 44} 45 46sub conflicts_with 47{ 48 my ($self, @pkgnames) = @_; 49 my @libs = grep {/^\.libs\d*\-/} @pkgnames; 50 @pkgnames = grep {!/^\.libs\d*\-/} @pkgnames; 51 if (wantarray) { 52 my @l = (); 53 for my $cfl (@$self) { 54 push(@l, $cfl->filter(@pkgnames)); 55 push(@l, $cfl->filter_libs(@libs)); 56 } 57 return @l; 58 } else { 59 for my $cfl (@$self) { 60 if ($cfl->filter(@pkgnames)) { 61 return 1; 62 } 63 if ($cfl->filter_libs(@libs)) { 64 return 1; 65 } 66 } 67 return 0; 68 } 69} 70 71sub register($$) 72{ 73 my ($plist, $state) = @_; 74 75 $state->{conflict_list}->{$plist->pkgname} = $plist->conflict_list; 76} 77 78sub unregister($$) 79{ 80 my ($plist, $state) = @_; 81 delete $state->{conflict_list}->{$plist->pkgname}; 82} 83 84sub fill_conflict_lists($) 85{ 86 my $state = shift; 87 for my $pkg (installed_packages()) { 88 my $plist = OpenBSD::PackingList->from_installation($pkg, 89 \&OpenBSD::PackingList::ConflictOnly); 90 next unless defined $plist; 91 if (!defined $plist->pkgname) { 92 print STDERR "No pkgname in packing-list for $pkg\n"; 93 next; 94 } 95 register($plist, $state); 96 } 97} 98 99sub find($$) 100{ 101 my ($pkgname, $state) = @_; 102 my @bad = (); 103 if (is_installed $pkgname) { 104 push(@bad, $pkgname); 105 } 106 if (!defined $state->{conflict_list}) { 107 fill_conflict_lists($state); 108 } 109 while (my ($name, $l) = each %{$state->{conflict_list}}) { 110 next if $name eq $pkgname; 111 if (!defined $l) { 112 die "Error: $name has no definition"; 113 } 114 if ($l->conflicts_with($pkgname)) { 115 push(@bad, $name); 116 } 117 } 118 return @bad; 119} 120 121sub find_all 122{ 123 my ($plist, $state) = @_; 124 125 my @first = $plist->conflict_list->conflicts_with(installed_packages()); 126 # XXX optimization 127 if (@first > 0 && !$state->{allow_replacing}) { 128 return @first; 129 } 130 131 my @conflicts = find($plist->pkgname, $state); 132 return (@conflicts, @first); 133} 134 1351; 136