1# ex:ts=8 sw=4: 2# $OpenBSD: PkgCfl.pm,v 1.27 2009/06/06 10:53:38 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, $pkg) = @_; 29 my $l = []; 30 my $pkgname = $plist->pkgname; 31 if (!defined $pkgname) { 32 print STDERR "No pkgname in packing-list for $pkg\n"; 33 return; 34 } 35 my $stem = OpenBSD::PackageName::splitstem($pkgname); 36 37 unless (defined $plist->{'no-default-conflict'}) { 38 push(@$l, OpenBSD::Search::PkgSpec->new("$stem-*|partial-$stem-*")); 39 } else { 40 push(@$l, OpenBSD::Search::Exact->new("$pkgname|partial-$pkgname")); 41 } 42 push(@$l, OpenBSD::Search::PkgSpec->new(".libs-$stem-*")); 43 if (defined $plist->{conflict}) { 44 for my $cfl (@{$plist->{conflict}}) { 45 push(@$l, OpenBSD::Search::PkgSpec->new($cfl->name)); 46 } 47 } 48 bless $l, $class; 49} 50 51sub conflicts_with 52{ 53 my ($self, @pkgnames) = @_; 54 my @l = (); 55 for my $cfl (@$self) { 56 push(@l, $cfl->filter(@pkgnames)); 57 } 58 return @l; 59} 60 61sub register($$) 62{ 63 my ($plist, $state) = @_; 64 if (!defined $plist->{conflicts}) { 65 $plist->{conflicts} = OpenBSD::PkgCfl->make_conflict_list($plist); 66 } 67 $state->{conflict_list}->{$plist->pkgname} = $plist->{conflicts}; 68} 69 70sub unregister($$) 71{ 72 my ($plist, $state) = @_; 73 delete $state->{conflict_list}->{$plist->pkgname}; 74} 75 76sub fill_conflict_lists($) 77{ 78 my $state = shift; 79 for my $pkg (installed_packages()) { 80 my $plist = OpenBSD::PackingList->from_installation($pkg, 81 \&OpenBSD::PackingList::ConflictOnly); 82 next unless defined $plist; 83 $plist->{conflicts} = OpenBSD::PkgCfl->make_conflict_list($plist, $pkg); 84 register($plist, $state); 85 } 86} 87 88sub find($$) 89{ 90 my ($pkgname, $state) = @_; 91 my @bad = (); 92 if (is_installed $pkgname) { 93 push(@bad, $pkgname); 94 } 95 if (!defined $state->{conflict_list}) { 96 $state->{conflict_list} = {}; 97 fill_conflict_lists($state); 98 } 99 while (my ($name, $l) = each %{$state->{conflict_list}}) { 100 next if $name eq $pkgname; 101 if (!defined $l) { 102 die "Error: $name has no definition"; 103 } 104 if ($l->conflicts_with($pkgname)) { 105 push(@bad, $name); 106 } 107 } 108 return @bad; 109} 110 111sub find_all 112{ 113 my ($plist, $state) = @_; 114 my $pkgname = $plist->pkgname; 115 116 my $l = OpenBSD::PkgCfl->make_conflict_list($plist); 117 $plist->{conflicts} = $l; 118 my @first = $l->conflicts_with(installed_packages()); 119 # XXX optimization 120 if (@first > 0 && !$state->{allow_replacing}) { 121 return @first; 122 } 123 124 my @conflicts = find($pkgname, $state); 125 return (@conflicts, @first); 126} 127 1281; 129