1# ex:ts=8 sw=4: 2# $OpenBSD: UpdateSet.pm,v 1.4 2009/04/19 14:58:32 espie Exp $ 3# 4# Copyright (c) 2007 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 18package OpenBSD::SharedItemsRecorder; 19sub new 20{ 21 my $class = shift; 22 return bless {}, $class; 23} 24 25sub is_empty 26{ 27 my $self = shift; 28 return !(defined $self->{dirs} or defined $self->{users} or 29 defined $self->{groups}); 30} 31 32sub cleanup 33{ 34 my ($self, $state) = @_; 35 return if $self->is_empty or $state->{not}; 36 37 require OpenBSD::SharedItems; 38 OpenBSD::SharedItems::cleanup($self, $state); 39} 40 41package OpenBSD::pkg_foo::State; 42use OpenBSD::Error; 43our @ISA=(qw(OpenBSD::Error)); 44 45sub progress 46{ 47 my $self = shift; 48 return $self->{progressmeter}; 49} 50 51sub setup_progressmeter 52{ 53 my ($self, $opt_x) = @_; 54 if (!$opt_x && !$self->{beverbose}) { 55 require OpenBSD::ProgressMeter; 56 $self->{progressmeter} = OpenBSD::ProgressMeter->new; 57 } else { 58 $self->{progressmeter} = bless {}, "OpenBSD::StubProgress"; 59 } 60} 61 62sub check_root 63{ 64 my $state = shift; 65 if ($< && !$state->{defines}->{nonroot}) { 66 if ($state->{not}) { 67 Warn "$0 should be run as root\n"; 68 } else { 69 Fatal "$0 must be run as root"; 70 } 71 } 72} 73 74package OpenBSD::StubProgress; 75sub clear {} 76 77sub show {} 78 79sub message {} 80 81sub next {} 82 83sub set_header {} 84 85# fairly non-descriptive name. Used to store various package information 86# during installs and updates. 87package OpenBSD::Handle; 88 89use constant { 90 BAD_PACKAGE => 1, 91 CANT_INSTALL => 2, 92 ALREADY_INSTALLED => 3, 93 NOT_FOUND => 4 94}; 95 96sub new 97{ 98 my $class = shift; 99 return bless {}, $class; 100} 101 102sub set_error 103{ 104 my ($self, $error) = @_; 105 $self->{error} = $error; 106} 107 108sub has_error 109{ 110 my ($self, $error) = @_; 111 if (!defined $self->{error}) { 112 return undef; 113 } 114 if (defined $error) { 115 return $self->{error} eq $error; 116 } 117 return $self->{error}; 118} 119 120sub create_old 121{ 122 123 my ($class, $pkgname, $state) = @_; 124 my $self= $class->new; 125 $self->{pkgname} = $pkgname; 126 127 require OpenBSD::PackageRepository::Installed; 128 129 my $location = OpenBSD::PackageRepository::Installed->new->find($pkgname, $state->{arch}); 130 if (!defined $location) { 131 $self->set_error(NOT_FOUND); 132 } else { 133 $self->{location} = $location; 134 my $plist = $location->plist; 135 if (!defined $plist) { 136 $self->set_error(BAD_PACKAGE); 137 } else { 138 $self->{plist} = $plist; 139 } 140 } 141 return $self; 142} 143 144sub create_new 145{ 146 my ($class, $pkg) = @_; 147 my $handle = $class->new; 148 $handle->{pkgname} = $pkg; 149 $handle->{tweaked} = 0; 150 return $handle; 151} 152 153sub from_location 154{ 155 my ($class, $location) = @_; 156 my $handle = $class->new; 157 $handle->{pkgname} = $location->name; 158 $handle->{location} = $location; 159 $handle->{tweaked} = 0; 160 return $handle; 161} 162 163package OpenBSD::UpdateSet; 164sub new 165{ 166 my $class = shift; 167 return bless {newer => [], older => []}, $class; 168} 169 170sub add_newer 171{ 172 my ($self, @handles) = @_; 173 push(@{$self->{newer}}, @handles); 174} 175 176sub add_older 177{ 178 my ($self, @handles) = @_; 179 push(@{$self->{older}}, @handles); 180} 181 182sub newer 183{ 184 my $self =shift; 185 return @{$self->{newer}}; 186} 187 188sub older 189{ 190 my $self = shift; 191 return @{$self->{older}}; 192} 193 194sub older_to_do 195{ 196 my $self = shift; 197 # XXX in `combined' updates, some dependencies may remove extra 198 # packages, so we do a double-take on the list of packages we 199 # are actually replacing... for now, until we merge update sets. 200 require OpenBSD::PackageInfo; 201 my @l = (); 202 for my $h ($self->older) { 203 if (OpenBSD::PackageInfo::is_installed($h->{pkgname})) { 204 push(@l, $h); 205 } 206 } 207 return @l; 208} 209 210sub print 211{ 212 my $self = shift; 213 my @l = (); 214 if (defined $self->{newer}) { 215 push(@l, "installing", map {$_->{pkgname}} $self->newer); 216 } 217 if (defined $self->{older} && @{$self->{older}} > 0) { 218 push(@l, "deinstalling", map {$_->{pkgname}} $self->older); 219 } 220 return join(' ', @l); 221} 222 223sub validate_plists 224{ 225 my ($self, $state) = @_; 226 $state->{problems} = 0; 227 228 for my $o ($self->older_to_do) { 229 require OpenBSD::Delete; 230 OpenBSD::Delete::validate_plist($o->{plist}, $state); 231 } 232 $state->{colliding} = []; 233 for my $n ($self->newer) { 234 require OpenBSD::Add; 235 OpenBSD::Add::validate_plist($n->{plist}, $state); 236 } 237 if (@{$state->{colliding}} > 0) { 238 require OpenBSD::CollisionReport; 239 240 OpenBSD::CollisionReport::collision_report($state->{colliding}, $state); 241 } 242 if (defined $state->{overflow}) { 243 OpenBSD::Vstat::tally(); 244 } 245 if ($state->{problems}) { 246 require OpenBSD::Error; 247 OpenBSD::Error::Fatal "fatal issues in ", $self->print; 248 } 249 OpenBSD::Vstat::synchronize(); 250} 251 252sub compute_size 253{ 254 my ($self, $state) = @_; 255 for my $h ($self->older_to_do, $self->newer) { 256 $h->{totsize} = $h->{plist}->compute_size; 257 } 258} 259 260# temporary shortcut 261sub handle 262{ 263 my $self = shift; 264 if (defined $self->{newer}) { 265 return $self->{newer}[0]; 266 } else { 267 return undef; 268 } 269} 270 271# temporary creator 272sub create_new 273{ 274 my ($class, $pkgname) = @_; 275 my $set = $class->new; 276 $set->add_newer(OpenBSD::Handle->create_new($pkgname)); 277 return $set; 278} 279 280sub from_location 281{ 282 my ($class, $location) = @_; 283 my $set = $class->new; 284 $set->add_newer(OpenBSD::Handle->from_location($location)); 285 return $set; 286} 287 288package OpenBSD::PackingList; 289sub compute_size 290{ 291 my $plist = shift; 292 my $totsize = 0; 293 $plist->visit('compute_size', \$totsize); 294 $totsize = 1 if $totsize == 0; 295 $plist->{totsize} = $totsize; 296} 297 298package OpenBSD::PackingElement; 299sub mark_progress 300{ 301} 302 303sub compute_size 304{ 305} 306 307package OpenBSD::PackingElement::FileBase; 308sub mark_progress 309{ 310 my ($self, $progress, $donesize, $totsize) = @_; 311 return unless defined $self->{size}; 312 $$donesize += $self->{size}; 313 $progress->show($$donesize, $totsize); 314} 315 316sub compute_size 317{ 318 my ($self, $totsize) = @_; 319 320 $$totsize += $self->{size} if defined $self->{size}; 321} 322 323package OpenBSD::PackingElement::Sample; 324sub compute_size 325{ 326 &OpenBSD::PackingElement::FileBase::compute_size; 327} 328 3291; 330