xref: /openbsd-src/usr.sbin/pkg_add/OpenBSD/UpdateSet.pm (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
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