From 8221480eec2d017394bdb65c63c11b8d9c96e068 Mon Sep 17 00:00:00 2001 From: espie Date: Sun, 1 Aug 2010 10:03:24 +0000 Subject: [PATCH] fix the qt 4.5 -> 4.6 update issue. since we usually deal with directories in a global way, replacing a directory with something else didn't work. the fix is to record removed directories in Vstat in a "lazy" way: we only test these objects for existence if we add something else at the same location. Since this happens rarely, we can afford to perform the whole SharedItems dance twice... --- usr.sbin/pkg_add/OpenBSD/Delete.pm | 6 +-- usr.sbin/pkg_add/OpenBSD/PkgAdd.pm | 3 +- usr.sbin/pkg_add/OpenBSD/SharedItems.pm | 54 ++++++++++++++++++++----- usr.sbin/pkg_add/OpenBSD/UpdateSet.pm | 16 +++++++- usr.sbin/pkg_add/OpenBSD/Vstat.pm | 36 ++++++++++++++++- 5 files changed, 98 insertions(+), 17 deletions(-) diff --git a/usr.sbin/pkg_add/OpenBSD/Delete.pm b/usr.sbin/pkg_add/OpenBSD/Delete.pm index 32c40f8a5c0..77644983efb 100644 --- a/usr.sbin/pkg_add/OpenBSD/Delete.pm +++ b/usr.sbin/pkg_add/OpenBSD/Delete.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: Delete.pm,v 1.107 2010/07/25 05:20:34 espie Exp $ +# $OpenBSD: Delete.pm,v 1.108 2010/08/01 10:03:24 espie Exp $ # # Copyright (c) 2003-2007 Marc Espie # @@ -311,9 +311,9 @@ sub prepare_for_deletion { my ($self, $state, $pkgname) = @_; my $fname = $state->{destdir}.$self->fullname; -# $state->vstat->remove_directory($fname); + $state->vstat->remove_directory($fname, $self); return unless $self->{noshadow}; - $state->{noshadow}->{$state->{destdir}.$self->fullname} = 1; + $state->{noshadow}{$fname} = 1; } sub delete diff --git a/usr.sbin/pkg_add/OpenBSD/PkgAdd.pm b/usr.sbin/pkg_add/OpenBSD/PkgAdd.pm index 97e762f9cd9..8fa5f2db23f 100644 --- a/usr.sbin/pkg_add/OpenBSD/PkgAdd.pm +++ b/usr.sbin/pkg_add/OpenBSD/PkgAdd.pm @@ -1,7 +1,7 @@ #! /usr/bin/perl # ex:ts=8 sw=4: -# $OpenBSD: PkgAdd.pm,v 1.10 2010/07/30 10:06:44 espie Exp $ +# $OpenBSD: PkgAdd.pm,v 1.11 2010/08/01 10:03:24 espie Exp $ # # Copyright (c) 2003-2010 Marc Espie # @@ -656,6 +656,7 @@ sub delete_old_packages } OpenBSD::PkgCfl::unregister($o->plist, $state); }); + $set->cleanup_old_shared($state); # Here there should be code to handle old libs } diff --git a/usr.sbin/pkg_add/OpenBSD/SharedItems.pm b/usr.sbin/pkg_add/OpenBSD/SharedItems.pm index fd1df6afc24..fb0cf7e81d5 100644 --- a/usr.sbin/pkg_add/OpenBSD/SharedItems.pm +++ b/usr.sbin/pkg_add/OpenBSD/SharedItems.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: SharedItems.pm,v 1.26 2010/06/30 10:51:04 espie Exp $ +# $OpenBSD: SharedItems.pm,v 1.27 2010/08/01 10:03:24 espie Exp $ # # Copyright (c) 2004-2006 Marc Espie # @@ -34,13 +34,53 @@ sub find_items_in_installed_packages sub { my $e = shift; my $plist = OpenBSD::PackingList->from_installation($e, - \&OpenBSD::PackingList::SharedItemsOnly) or next; + \&OpenBSD::PackingList::SharedItemsOnly) or return; return if !defined $plist; $plist->record_shared($db, $e); }); return $db; } +sub check_shared +{ + my ($set, $o) = @_; + if (!defined $set->{db}) { + $set->{db} = OpenBSD::SharedItemsRecorder->new; + for my $pkg (installed_packages()) { + next if $set->{older}{$pkg}; + my $plist = OpenBSD::PackingList->from_installation($pkg, + \&OpenBSD::PackingList::SharedItemsOnly) or next; + next if !defined $plist; + $plist->record_shared($set->{db}, $pkg); + } + } + if (defined $set->{db}{dirs}{$o->fullname}) { + return 1; + } else { + push(@{$set->{old_shared}{$o->fullname}}, $o); + return 0; + } +} + +sub wipe_directory +{ + my ($state, $h, $d) = @_; + + my $realname = $state->{destdir}.$d; + + for my $i (@{$h->{$d}}) { + $state->log->set_context($i->{pkgname}); + $i->cleanup($state); + } + if (!rmdir $realname) { + $state->log("Error deleting directory #1: #2", + $realname, $!) + unless $state->{dirs_okay}->{$d}; + return 0; + } + return 1; +} + sub cleanup { my ($recorder, $state) = @_; @@ -68,15 +108,7 @@ sub cleanup $i->reload($state); } } else { - for my $i (@{$h->{$d}}) { - $state->log->set_context($i->{pkgname}); - $i->cleanup($state); - } - if (!rmdir $realname) { - $state->log("Error deleting directory #1: #2", - $realname, $!) - unless $state->{dirs_okay}->{$d}; - } + wipe_directory($state, $h, $d); } $done++; } diff --git a/usr.sbin/pkg_add/OpenBSD/UpdateSet.pm b/usr.sbin/pkg_add/OpenBSD/UpdateSet.pm index 38ee050d89f..22eb42cd3dc 100644 --- a/usr.sbin/pkg_add/OpenBSD/UpdateSet.pm +++ b/usr.sbin/pkg_add/OpenBSD/UpdateSet.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: UpdateSet.pm,v 1.61 2010/07/11 07:27:25 espie Exp $ +# $OpenBSD: UpdateSet.pm,v 1.62 2010/08/01 10:03:24 espie Exp $ # # Copyright (c) 2007-2010 Marc Espie # @@ -286,6 +286,8 @@ sub validate_plists $state->{problems} = 0; delete $state->{overflow}; + $state->{current_set} = $self; + for my $o ($self->older_to_do) { require OpenBSD::Delete; OpenBSD::Delete::validate_plist($o->{plist}, $state); @@ -321,6 +323,18 @@ sub validate_plists } } +sub cleanup_old_shared +{ + my ($set, $state) = @_; + my $h = $set->{old_shared}; + + for my $d (sort {$b cmp $a} keys %$h) { + OpenBSD::SharedItems::wipe_directory($state, $h, $d) || + $state->fatal("Can't continue"); + delete $state->{recorder}{dirs}{$d}; + } +} + sub create_new { my ($class, $pkgname) = @_; diff --git a/usr.sbin/pkg_add/OpenBSD/Vstat.pm b/usr.sbin/pkg_add/OpenBSD/Vstat.pm index b977317badf..a88b0801ec1 100644 --- a/usr.sbin/pkg_add/OpenBSD/Vstat.pm +++ b/usr.sbin/pkg_add/OpenBSD/Vstat.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: Vstat.pm,v 1.61 2010/06/30 10:51:04 espie Exp $ +# $OpenBSD: Vstat.pm,v 1.62 2010/08/01 10:03:24 espie Exp $ # # Copyright (c) 2003-2007 Marc Espie # @@ -59,6 +59,7 @@ sub none } } + { package OpenBSD::Vstat::Object::None; our @ISA = qw(OpenBSD::Vstat::Object); @@ -77,6 +78,28 @@ sub new } } +{ +package OpenBSD::Vstat::Object::Directory; +our @ISA = qw(OpenBSD::Vstat::Object); + +sub new +{ + my ($class, $fname, $set, $o) = @_; + bless { name => $fname, set => $set, o => $o }, $class; +} + +# XXX directories don't do anything until you test for their presence. +# which only happens if you want to replace a directory with a file. +sub exists +{ + my $self = shift; + require OpenBSD::SharedItems; + + return OpenBSD::SharedItems::check_shared($self->{set}, $self->{o}); +} + +} + package OpenBSD::Vstat; use File::Basename; use OpenBSD::Paths; @@ -187,6 +210,17 @@ sub remove_first return defined($size) ? $self->account_for($name, -$size) : undef; } +# since directories may become files during updates, we may have to remove +# them early, so we need to record them: store exactly as much info as needed +# for SharedItems. +sub remove_directory +{ + my ($self, $name, $o) = @_; + $self->{v}[0]->{$name} = OpenBSD::Vstat::Object::Directory->new($name, + $self->{state}->{current_set}, $o); +} + + sub tally { my $self = shift; -- 2.20.1