1d15f7ce5Sespie# ex:ts=8 sw=4:
2*d17dc12fSespie# $OpenBSD: CollisionReport.pm,v 1.25 2009/11/14 21:04:02 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
21d15f7ce5Sespiepackage OpenBSD::CollisionReport;
22d15f7ce5Sespieuse OpenBSD::PackingList;
23d15f7ce5Sespieuse OpenBSD::PackageInfo;
248eeac59fSespieuse OpenBSD::Vstat;
25d15f7ce5Sespie
262818ea65Sespiesub find_collisions
27d15f7ce5Sespie{
280f0116c3Sespie	my ($todo, $state) = @_;
290f0116c3Sespie	my $verbose = $state->{verbose};
30d15f7ce5Sespie	my $bypkg = {};
312818ea65Sespie	for my $name (keys %$todo) {
328eeac59fSespie		my $p = OpenBSD::Vstat::vexists $name;
338eeac59fSespie		if (ref $p) {
348eeac59fSespie			my $pkg = $$p;
358eeac59fSespie			push(@{$bypkg->{$pkg}}, $name);
362818ea65Sespie			delete $todo->{$name};
378eeac59fSespie		}
388eeac59fSespie	}
39d15f7ce5Sespie
402818ea65Sespie
412818ea65Sespie	if (!%$todo) {
422818ea65Sespie		return $bypkg;
432818ea65Sespie	}
44d15f7ce5Sespie	for my $pkg (installed_packages()) {
45662ab648Sespie		$state->say("Looking for collisions in $pkg") if $verbose;
46d15f7ce5Sespie		my $plist = OpenBSD::PackingList->from_installation($pkg,
47d15f7ce5Sespie		    \&OpenBSD::PackingList::FilesOnly);
488ee98284Sespie		next if !defined $plist;
49d15f7ce5Sespie		for my $item (@{$plist->{items}}) {
50f04afe28Sespie			next unless $item->IsFile;
51f04afe28Sespie			my $name = $item->fullname;
522818ea65Sespie			if (defined $todo->{$name}) {
53d15f7ce5Sespie				push(@{$bypkg->{$pkg}}, $name);
542818ea65Sespie				delete $todo->{$name};
55d15f7ce5Sespie			}
56d15f7ce5Sespie		}
57d15f7ce5Sespie	}
582818ea65Sespie	return $bypkg;
59d15f7ce5Sespie}
602818ea65Sespie
612818ea65Sespiesub collision_report($$)
622818ea65Sespie{
632818ea65Sespie	my ($list, $state) = @_;
642818ea65Sespie
65*d17dc12fSespie	my $destdir = $state->{destdir};
66*d17dc12fSespie
672818ea65Sespie	if ($state->{defines}->{removecollisions}) {
682818ea65Sespie		require OpenBSD::Error;
692818ea65Sespie		for my $f (@$list) {
70*d17dc12fSespie			$state->unlink(1, $destdir.$f->fullname);
718eeac59fSespie		}
722818ea65Sespie		return;
732818ea65Sespie	}
74700d29cbSespie	my %todo = map {($_->fullname, $_->{d})} @$list;
752818ea65Sespie	my $clueless_bat;
762818ea65Sespie	my $clueless_bat2;
772818ea65Sespie	my $found = 0;
782818ea65Sespie
79662ab648Sespie	$state->say("Collision: the following files already exist");
802818ea65Sespie	if (!$state->{defines}->{dontfindcollisions}) {
810f0116c3Sespie		my $bypkg = find_collisions(\%todo, $state);
82d15f7ce5Sespie		for my $pkg (sort keys %$bypkg) {
83d15f7ce5Sespie		    for my $item (sort @{$bypkg->{$pkg}}) {
842818ea65Sespie		    	$found++;
85662ab648Sespie			$state->say("\t$item ($pkg)");
86d15f7ce5Sespie		    }
87cc24e6f2Sespie		    if ($pkg =~ m/^(?:partial\-|borked\.\d+$)/o) {
88eefd3b46Sespie			$clueless_bat = $pkg;
89eefd3b46Sespie		    }
90eb9d5597Sespie		    if ($pkg =~ m/^\.libs\d*-*$/o) {
911c9bf27fSespie			$clueless_bat2 = $pkg;
921c9bf27fSespie		    }
93d15f7ce5Sespie		}
942818ea65Sespie	}
950b2ea41eSespie	if (%todo) {
960b2ea41eSespie
97d15f7ce5Sespie		for my $item (sort keys %todo) {
98eefd3b46Sespie		    if (defined $todo{$item}) {
99700d29cbSespie			    my $old = $todo{$item};
100700d29cbSespie			    my $d = $old->new($destdir.$item);
101700d29cbSespie			    if ($d->equals($old)) {
102662ab648Sespie				$state->say("\t$item (same checksum)");
1030b2ea41eSespie			    } else {
104662ab648Sespie				$state->say("\t$item (different checksum)");
1050b2ea41eSespie			    }
106eefd3b46Sespie		    } else {
107662ab648Sespie			    $state->say("\t$item");
1080b2ea41eSespie		    }
109d15f7ce5Sespie	    	}
110d15f7ce5Sespie	}
111a96a2504Sespie	if (defined $clueless_bat) {
112662ab648Sespie		$state->print("The package name $clueless_bat suggests that a former installation\n",
113662ab648Sespie		    "of a similar package got interrupted.  It is likely that\n",
114662ab648Sespie		    "\tpkg_delete $clueless_bat\n",
115662ab648Sespie		    "will solve the problem\n");
116eefd3b46Sespie	}
117a96a2504Sespie	if (defined $clueless_bat2) {
118662ab648Sespie		$state->print("The package name $clueless_bat2 suggests remaining libraries\n",
119662ab648Sespie		    "from a former package update.  It is likely that\n",
120662ab648Sespie		    "\tpkg_delete $clueless_bat2\n".
121662ab648Sespie		    "will solve the problem\n");
1221c9bf27fSespie	}
1232818ea65Sespie	my $dorepair = 0;
1242818ea65Sespie	if ($found == 0) {
1252818ea65Sespie		if ($state->{defines}->{repair}) {
1262818ea65Sespie			$dorepair = 1;
1272818ea65Sespie		} elsif ($state->{interactive}) {
1282818ea65Sespie			require OpenBSD::Interactive;
1292818ea65Sespie			if (OpenBSD::Interactive::confirm(
1302818ea65Sespie	    "It seems to be a missing package registration\nRepair", 1, 0)) {
1312818ea65Sespie				$dorepair = 1;
1322818ea65Sespie			}
1332818ea65Sespie		}
1342818ea65Sespie	}
1352818ea65Sespie	if ($dorepair == 1) {
1362818ea65Sespie		for my $f (@$list) {
1372818ea65Sespie
138b5458979Sespie			if ($state->unlink($state->{verbose},
139*d17dc12fSespie			    $destdir.$f->fullname)) {
1402818ea65Sespie				$state->{problems}--;
1412818ea65Sespie			} else {
1422818ea65Sespie				return;
1432818ea65Sespie			}
1442818ea65Sespie		}
1452818ea65Sespie		$state->{repairdependencies} = 1;
1462818ea65Sespie	}
147eefd3b46Sespie}
148d15f7ce5Sespie
149d15f7ce5Sespie1;
150