1d15f7ce5Sespie# ex:ts=8 sw=4:
2*039cbdaaSespie# $OpenBSD: CollisionReport.pm,v 1.49 2023/06/13 09:07:17 espie Exp $
3d15f7ce5Sespie#
41144937fSespie# Copyright (c) 2003-2006 Marc Espie <espie@openbsd.org>
5d15f7ce5Sespie#
6d15f7ce5Sespie# Permission to use, copy, modify, and distribute this software for any
7d15f7ce5Sespie# purpose with or without fee is hereby granted, provided that the above
8d15f7ce5Sespie# copyright notice and this permission notice appear in all copies.
9d15f7ce5Sespie#
10d15f7ce5Sespie# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11d15f7ce5Sespie# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d15f7ce5Sespie# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13d15f7ce5Sespie# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d15f7ce5Sespie# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d15f7ce5Sespie# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d15f7ce5Sespie# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
170fbefeddSespie
18*039cbdaaSespieuse v5.36;
19d15f7ce5Sespie
2016d0b37eSespiepackage OpenBSD::PackingElement;
21*039cbdaaSespiesub handle_collisions($, $, $, $)
2216d0b37eSespie{
2316d0b37eSespie}
2416d0b37eSespie
2516d0b37eSespiepackage OpenBSD::PackingElement::FileBase;
26*039cbdaaSespiesub handle_collisions($self, $todo, $pkg, $bypkg)
2716d0b37eSespie{
2816d0b37eSespie	my $name = $self->fullname;
2916d0b37eSespie	if (defined $todo->{$name}) {
3016d0b37eSespie		push(@{$bypkg->{$pkg}}, $name);
3116d0b37eSespie		delete $todo->{$name};
3216d0b37eSespie	}
3316d0b37eSespie}
3416d0b37eSespie
35d15f7ce5Sespiepackage OpenBSD::CollisionReport;
36d15f7ce5Sespieuse OpenBSD::PackingList;
37d15f7ce5Sespieuse OpenBSD::PackageInfo;
38d15f7ce5Sespie
39*039cbdaaSespiesub find_collisions($todo, $state)
40d15f7ce5Sespie{
41e74b30b0Sespie	my $verbose = $state->verbose >= 3;
42d15f7ce5Sespie	my $bypkg = {};
432818ea65Sespie	for my $name (keys %$todo) {
44b6ce8483Sespie		my $pkg = $state->vstat->value($state->{destdir}.$name);
45b6ce8483Sespie		if (defined $pkg) {
468eeac59fSespie			push(@{$bypkg->{$pkg}}, $name);
472818ea65Sespie			delete $todo->{$name};
488eeac59fSespie		}
498eeac59fSespie	}
50d15f7ce5Sespie
512818ea65Sespie
522818ea65Sespie	if (!%$todo) {
532818ea65Sespie		return $bypkg;
542818ea65Sespie	}
55d15f7ce5Sespie	for my $pkg (installed_packages()) {
567e83eca3Sespie		$state->say("Looking for collisions in #1", $pkg) if $verbose;
57af4e06d4Sespie		# XXX in -n mode, some stuff is not really there
58af4e06d4Sespie		# avoid warnings
59af4e06d4Sespie		next unless -d installed_info($pkg);
60d15f7ce5Sespie		my $plist = OpenBSD::PackingList->from_installation($pkg,
61d15f7ce5Sespie		    \&OpenBSD::PackingList::FilesOnly);
628ee98284Sespie		next if !defined $plist;
6316d0b37eSespie		$plist->handle_collisions($todo, $pkg, $bypkg);
64d15f7ce5Sespie	}
652818ea65Sespie	return $bypkg;
66d15f7ce5Sespie}
672818ea65Sespie
68*039cbdaaSespiesub collision_report($list, $state, $set)
692818ea65Sespie{
70d17dc12fSespie	my $destdir = $state->{destdir};
71d17dc12fSespie
72a409537dSespie	if ($state->defines('removecollisions')) {
732818ea65Sespie		require OpenBSD::Error;
742818ea65Sespie		for my $f (@$list) {
75d17dc12fSespie			$state->unlink(1, $destdir.$f->fullname);
768eeac59fSespie		}
772818ea65Sespie		return;
782818ea65Sespie	}
79700d29cbSespie	my %todo = map {($_->fullname, $_->{d})} @$list;
8045571e80Sespie	my %extra = map {($_->fullname, $_->{newly_found})} @$list;
812818ea65Sespie	my $clueless_bat;
822818ea65Sespie	my $clueless_bat2;
832818ea65Sespie	my $found = 0;
842818ea65Sespie
85b5c9b1b8Sespie	$state->errsay("Collision in #1: the following files already exist",
86b5c9b1b8Sespie	    $set->print);
87a409537dSespie	if (!$state->defines('dontfindcollisions')) {
880f0116c3Sespie		my $bypkg = find_collisions(\%todo, $state);
89d15f7ce5Sespie		for my $pkg (sort keys %$bypkg) {
90d15f7ce5Sespie		    for my $item (sort @{$bypkg->{$pkg}}) {
912818ea65Sespie		    	$found++;
920f753b04Sespie			$state->errsay("\t#1 (#2 and #3)", $item, $pkg,
930f753b04Sespie			    $extra{$item});
9445571e80Sespie		    }
95cc24e6f2Sespie		    if ($pkg =~ m/^(?:partial\-|borked\.\d+$)/o) {
96eefd3b46Sespie			$clueless_bat = $pkg;
97eefd3b46Sespie		    }
98eb9d5597Sespie		    if ($pkg =~ m/^\.libs\d*-*$/o) {
991c9bf27fSespie			$clueless_bat2 = $pkg;
1001c9bf27fSespie		    }
101d15f7ce5Sespie		}
1022818ea65Sespie	}
1030b2ea41eSespie	if (%todo) {
1040b2ea41eSespie
105d15f7ce5Sespie		for my $item (sort keys %todo) {
106700d29cbSespie			my $old = $todo{$item};
1070f753b04Sespie		    $state->errprint("\t#1 from #2", $item, $extra{$item});
108b6ce8483Sespie		    if (defined $old && -f $destdir.$item) {
109700d29cbSespie			    my $d = $old->new($destdir.$item);
110b6ce8483Sespie
111700d29cbSespie			    if ($d->equals($old)) {
112b6ce8483Sespie				    $state->errsay(" (same checksum)");
1130b2ea41eSespie			    } else {
114b6ce8483Sespie				    $state->errsay(" (different checksum)");
1150b2ea41eSespie			    }
116eefd3b46Sespie		    } else {
117b0dfb814Sespie			    $state->errsay;
1180b2ea41eSespie		    }
119d15f7ce5Sespie	    	}
120d15f7ce5Sespie	}
121a96a2504Sespie	if (defined $clueless_bat) {
1227e83eca3Sespie		$state->errprint("The package name #1 suggests that a former installation\n".
1237e83eca3Sespie		    "of a similar package got interrupted.  It is likely that\n".
1247e83eca3Sespie		    "\tpkg_delete #1\n".
1257e83eca3Sespie		    "will solve the problem\n", $clueless_bat);
126eefd3b46Sespie	}
127a96a2504Sespie	if (defined $clueless_bat2) {
1287e83eca3Sespie		$state->errprint("The package name #1 suggests remaining libraries\n".
1297e83eca3Sespie		    "from a former package update.  It is likely that\n".
1307e83eca3Sespie		    "\tpkg_delete #1\n".
1317e83eca3Sespie		    "will solve the problem\n", $clueless_bat2);
1321c9bf27fSespie	}
1332818ea65Sespie	my $dorepair = 0;
1342818ea65Sespie	if ($found == 0) {
135eb8b7390Sespie		$dorepair = $state->defines('repair') ||
136fb75580aSespie		    $state->confirm_defaults_to_no(
137fb75580aSespie		    "It seems to be a missing package registration\nRepair");
1382818ea65Sespie	}
1392818ea65Sespie	if ($dorepair == 1) {
1402818ea65Sespie		for my $f (@$list) {
1412818ea65Sespie
142e74b30b0Sespie			if ($state->unlink($state->verbose >= 2,
143d17dc12fSespie			    $destdir.$f->fullname)) {
1442818ea65Sespie				$state->{problems}--;
1452818ea65Sespie			} else {
1462818ea65Sespie				return;
1472818ea65Sespie			}
1482818ea65Sespie		}
1492818ea65Sespie		$state->{repairdependencies} = 1;
1502818ea65Sespie	}
151eefd3b46Sespie}
152d15f7ce5Sespie
153d15f7ce5Sespie1;
154