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