1d15f7ce5Sespie# ex:ts=8 sw=4:
2*fb75580aSespie# $OpenBSD: CollisionReport.pm,v 1.47 2018/02/27 22:46:53 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
18d15f7ce5Sespieuse strict;
19d15f7ce5Sespieuse warnings;
20d15f7ce5Sespie
2116d0b37eSespiepackage OpenBSD::PackingElement;
2216d0b37eSespiesub handle_collisions
2316d0b37eSespie{
2416d0b37eSespie}
2516d0b37eSespie
2616d0b37eSespiepackage OpenBSD::PackingElement::FileBase;
2716d0b37eSespiesub handle_collisions
2816d0b37eSespie{
2916d0b37eSespie	my ($self, $todo, $pkg, $bypkg) = @_;
3016d0b37eSespie	my $name = $self->fullname;
3116d0b37eSespie	if (defined $todo->{$name}) {
3216d0b37eSespie		push(@{$bypkg->{$pkg}}, $name);
3316d0b37eSespie		delete $todo->{$name};
3416d0b37eSespie	}
3516d0b37eSespie}
3616d0b37eSespie
37d15f7ce5Sespiepackage OpenBSD::CollisionReport;
38d15f7ce5Sespieuse OpenBSD::PackingList;
39d15f7ce5Sespieuse OpenBSD::PackageInfo;
40d15f7ce5Sespie
412818ea65Sespiesub find_collisions
42d15f7ce5Sespie{
430f0116c3Sespie	my ($todo, $state) = @_;
44e74b30b0Sespie	my $verbose = $state->verbose >= 3;
45d15f7ce5Sespie	my $bypkg = {};
462818ea65Sespie	for my $name (keys %$todo) {
47b6ce8483Sespie		my $pkg = $state->vstat->value($state->{destdir}.$name);
48b6ce8483Sespie		if (defined $pkg) {
498eeac59fSespie			push(@{$bypkg->{$pkg}}, $name);
502818ea65Sespie			delete $todo->{$name};
518eeac59fSespie		}
528eeac59fSespie	}
53d15f7ce5Sespie
542818ea65Sespie
552818ea65Sespie	if (!%$todo) {
562818ea65Sespie		return $bypkg;
572818ea65Sespie	}
58d15f7ce5Sespie	for my $pkg (installed_packages()) {
597e83eca3Sespie		$state->say("Looking for collisions in #1", $pkg) if $verbose;
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
68b5c9b1b8Sespiesub collision_report
692818ea65Sespie{
70b5c9b1b8Sespie	my ($list, $state, $set) = @_;
712818ea65Sespie
72d17dc12fSespie	my $destdir = $state->{destdir};
73d17dc12fSespie
74a409537dSespie	if ($state->defines('removecollisions')) {
752818ea65Sespie		require OpenBSD::Error;
762818ea65Sespie		for my $f (@$list) {
77d17dc12fSespie			$state->unlink(1, $destdir.$f->fullname);
788eeac59fSespie		}
792818ea65Sespie		return;
802818ea65Sespie	}
81700d29cbSespie	my %todo = map {($_->fullname, $_->{d})} @$list;
8245571e80Sespie	my %extra = map {($_->fullname, $_->{newly_found})} @$list;
832818ea65Sespie	my $clueless_bat;
842818ea65Sespie	my $clueless_bat2;
852818ea65Sespie	my $found = 0;
862818ea65Sespie
87b5c9b1b8Sespie	$state->errsay("Collision in #1: the following files already exist",
88b5c9b1b8Sespie	    $set->print);
89a409537dSespie	if (!$state->defines('dontfindcollisions')) {
900f0116c3Sespie		my $bypkg = find_collisions(\%todo, $state);
91d15f7ce5Sespie		for my $pkg (sort keys %$bypkg) {
92d15f7ce5Sespie		    for my $item (sort @{$bypkg->{$pkg}}) {
932818ea65Sespie		    	$found++;
940f753b04Sespie			$state->errsay("\t#1 (#2 and #3)", $item, $pkg,
950f753b04Sespie			    $extra{$item});
9645571e80Sespie		    }
97cc24e6f2Sespie		    if ($pkg =~ m/^(?:partial\-|borked\.\d+$)/o) {
98eefd3b46Sespie			$clueless_bat = $pkg;
99eefd3b46Sespie		    }
100eb9d5597Sespie		    if ($pkg =~ m/^\.libs\d*-*$/o) {
1011c9bf27fSespie			$clueless_bat2 = $pkg;
1021c9bf27fSespie		    }
103d15f7ce5Sespie		}
1042818ea65Sespie	}
1050b2ea41eSespie	if (%todo) {
1060b2ea41eSespie
107d15f7ce5Sespie		for my $item (sort keys %todo) {
108700d29cbSespie			my $old = $todo{$item};
1090f753b04Sespie		    $state->errprint("\t#1 from #2", $item, $extra{$item});
110b6ce8483Sespie		    if (defined $old && -f $destdir.$item) {
111700d29cbSespie			    my $d = $old->new($destdir.$item);
112b6ce8483Sespie
113700d29cbSespie			    if ($d->equals($old)) {
114b6ce8483Sespie				    $state->errsay(" (same checksum)");
1150b2ea41eSespie			    } else {
116b6ce8483Sespie				    $state->errsay(" (different checksum)");
1170b2ea41eSespie			    }
118eefd3b46Sespie		    } else {
119b0dfb814Sespie			    $state->errsay;
1200b2ea41eSespie		    }
121d15f7ce5Sespie	    	}
122d15f7ce5Sespie	}
123a96a2504Sespie	if (defined $clueless_bat) {
1247e83eca3Sespie		$state->errprint("The package name #1 suggests that a former installation\n".
1257e83eca3Sespie		    "of a similar package got interrupted.  It is likely that\n".
1267e83eca3Sespie		    "\tpkg_delete #1\n".
1277e83eca3Sespie		    "will solve the problem\n", $clueless_bat);
128eefd3b46Sespie	}
129a96a2504Sespie	if (defined $clueless_bat2) {
1307e83eca3Sespie		$state->errprint("The package name #1 suggests remaining libraries\n".
1317e83eca3Sespie		    "from a former package update.  It is likely that\n".
1327e83eca3Sespie		    "\tpkg_delete #1\n".
1337e83eca3Sespie		    "will solve the problem\n", $clueless_bat2);
1341c9bf27fSespie	}
1352818ea65Sespie	my $dorepair = 0;
1362818ea65Sespie	if ($found == 0) {
137eb8b7390Sespie		$dorepair = $state->defines('repair') ||
138*fb75580aSespie		    $state->confirm_defaults_to_no(
139*fb75580aSespie		    "It seems to be a missing package registration\nRepair");
1402818ea65Sespie	}
1412818ea65Sespie	if ($dorepair == 1) {
1422818ea65Sespie		for my $f (@$list) {
1432818ea65Sespie
144e74b30b0Sespie			if ($state->unlink($state->verbose >= 2,
145d17dc12fSespie			    $destdir.$f->fullname)) {
1462818ea65Sespie				$state->{problems}--;
1472818ea65Sespie			} else {
1482818ea65Sespie				return;
1492818ea65Sespie			}
1502818ea65Sespie		}
1512818ea65Sespie		$state->{repairdependencies} = 1;
1522818ea65Sespie	}
153eefd3b46Sespie}
154d15f7ce5Sespie
155d15f7ce5Sespie1;
156