xref: /openbsd/usr.sbin/pkg_add/OpenBSD/PkgCfl.pm (revision 404b540a)
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