xref: /openbsd/usr.sbin/pkg_add/OpenBSD/Handle.pm (revision a6445c1d)
1# ex:ts=8 sw=4:
2# $OpenBSD: Handle.pm,v 1.39 2014/02/08 16:11:02 espie Exp $
3#
4# Copyright (c) 2007-2009 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
18# fairly non-descriptive name. Used to store various package information
19# during installs and updates.
20
21use strict;
22use warnings;
23
24package OpenBSD::Handle;
25
26use OpenBSD::PackageInfo;
27use OpenBSD::Error;
28
29use constant {
30	BAD_PACKAGE => 1,
31	CANT_INSTALL => 2,
32	ALREADY_INSTALLED => 3,
33	NOT_FOUND => 4,
34	CANT_DELETE => 5,
35};
36
37sub is_real { return 1; }
38
39sub cleanup
40{
41	my ($self, $error, $errorinfo) = @_;
42	if (defined $error) {
43		$self->{error} //= $error;
44		$self->{errorinfo} //= $errorinfo;
45	}
46	if (defined $self->location) {
47		if (defined $self->{error} && $self->{error} == BAD_PACKAGE) {
48			$self->location->close_with_client_error;
49		} else {
50			$self->location->close_now;
51		}
52		$self->location->wipe_info;
53	}
54	delete $self->{plist};
55	delete $self->{db};
56	delete $self->{conflict_list};
57}
58
59sub new
60{
61	my $class = shift;
62	return bless {}, $class;
63}
64
65sub system
66{
67	my $class = shift;
68	return OpenBSD::Handle::BaseSystem->new;
69}
70
71sub pkgname
72{
73	my $self = shift;
74	if (!defined $self->{pkgname}) {
75		if (defined $self->{plist}) {
76			$self->{pkgname} = $self->{plist}->pkgname;
77		} elsif (defined $self->{location}) {
78			$self->{pkgname} = $self->{location}->name;
79		} elsif (defined $self->{name}) {
80			require OpenBSD::PackageName;
81
82			$self->{pkgname} =
83			    OpenBSD::PackageName::url2pkgname($self->{name});
84		}
85	}
86
87	return $self->{pkgname};
88}
89
90sub location
91{
92	return shift->{location};
93}
94
95sub plist
96{
97	return shift->{plist};
98}
99
100sub dependency_info
101{
102	my $self = shift;
103	if (defined $self->{plist}) {
104		return $self->{plist};
105	} elsif (defined $self->{location} &&
106	    defined $self->{location}{update_info}) {
107		return $self->{location}{update_info};
108	} else {
109		return undef;
110	}
111}
112
113OpenBSD::Auto::cache(conflict_list,
114    sub {
115    	require OpenBSD::PkgCfl;
116	return OpenBSD::PkgCfl->make_conflict_list(shift->dependency_info);
117    });
118
119sub set_error
120{
121	my ($self, $error) = @_;
122	$self->{error} = $error;
123}
124
125sub has_error
126{
127	my ($self, $error) = @_;
128	if (!defined $self->{error}) {
129		return undef;
130	}
131	if (defined $error) {
132		return $self->{error} eq $error;
133	}
134	return $self->{error};
135}
136
137sub error_message
138{
139	my $self = shift;
140	my $error = $self->{error};
141	if ($error == BAD_PACKAGE) {
142		return "bad package";
143	} elsif ($error == CANT_INSTALL) {
144		if ($self->{errorinfo}) {
145			return "$self->{errorinfo}";
146		} else {
147			return "can't install";
148		}
149	} elsif ($error == NOT_FOUND) {
150		return "not found";
151	} elsif ($error == ALREADY_INSTALLED) {
152		return "already installed";
153	} else {
154		return "no error";
155	}
156}
157
158sub complete_old
159{
160	my $self = shift;
161	my $location = $self->{location};
162
163	if (!defined $location) {
164		$self->set_error(NOT_FOUND);
165    	} else {
166		my $plist = $location->plist;
167		if (!defined $plist) {
168			$self->set_error(BAD_PACKAGE);
169		} else {
170			$self->{plist} = $plist;
171			delete $location->{contents};
172			delete $location->{update_info};
173		}
174	}
175}
176
177sub complete_dependency_info
178{
179	my $self = shift;
180	my $location = $self->{location};
181
182	if (!defined $location) {
183		$self->set_error(NOT_FOUND);
184	} else {
185		if (!defined $self->{plist}) {
186			# trigger build
187			$location->update_info;
188		}
189	}
190}
191
192sub create_old
193{
194
195	my ($class, $pkgname, $state) = @_;
196	my $self= $class->new;
197	$self->{name} = $pkgname;
198
199	my $location = $state->repo->installed->find($pkgname);
200	if (defined $location) {
201		$self->{location} = $location;
202	}
203	$self->complete_dependency_info;
204
205	return $self;
206}
207
208sub create_new
209{
210	my ($class, $pkg) = @_;
211	my $handle = $class->new;
212	$handle->{name} = $pkg;
213	$handle->{tweaked} = 0;
214	return $handle;
215}
216
217sub from_location
218{
219	my ($class, $location) = @_;
220	my $handle = $class->new;
221	$handle->{location} = $location;
222	$handle->{tweaked} = 0;
223	return $handle;
224}
225
226sub get_plist
227{
228	my ($handle, $state) = @_;
229
230	my $location = $handle->{location};
231	my $pkg = $handle->pkgname;
232
233	if ($state->verbose >= 2) {
234		$state->say("#1parsing #2", $state->deptree_header($pkg), $pkg);
235	}
236	my $plist = $location->plist;
237	unless (defined $plist) {
238		$state->say("Can't find CONTENTS from #1", $location->url);
239		$location->close_with_client_error;
240		$location->wipe_info;
241		$handle->set_error(BAD_PACKAGE);
242		return;
243	}
244	delete $location->{update_info};
245	unless ($plist->has('url')) {
246		OpenBSD::PackingElement::Url->add($plist, $location->url);
247	}
248	if ($plist->localbase ne $state->{localbase}) {
249		$state->say("Localbase mismatch: package has: #1, user wants: #2",
250		    $plist->localbase, $state->{localbase});
251		$location->close_with_client_error;
252		$location->wipe_info;
253		$handle->set_error(BAD_PACKAGE);
254		return;
255	}
256	my $pkgname = $handle->{pkgname} = $plist->pkgname;
257
258	if ($pkg ne '-') {
259		if (!defined $pkgname or $pkg ne $pkgname) {
260			$state->say("Package name is not consistent ???");
261			$location->close_with_client_error;
262			$location->wipe_info;
263			$handle->set_error(BAD_PACKAGE);
264			return;
265		}
266	}
267	$handle->{plist} = $plist;
268}
269
270sub get_location
271{
272	my ($handle, $state) = @_;
273
274	my $name = $handle->{name};
275
276	my $location = $state->repo->find($name);
277	if (!$location) {
278		$state->print("#1", $state->deptree_header($name));
279		$handle->set_error(NOT_FOUND);
280		$handle->{tweaked} =
281		    OpenBSD::Add::tweak_package_status($handle->pkgname,
282			$state);
283		if (!$handle->{tweaked}) {
284			$state->say("Can't find #1", $name);
285			eval {
286				my $r = [$name];
287				$state->quirks->filter_obsolete($r, $state);
288			}
289		}
290		return;
291	}
292	$handle->{location} = $location;
293	$handle->{pkgname} = $location->name;
294}
295
296sub complete
297{
298	my ($handle, $state) = @_;
299
300	return if $handle->has_error;
301
302	if (!defined $handle->{location}) {
303		$handle->get_location($state);
304	}
305	return if $handle->has_error;
306	if (!defined $handle->{plist}) {
307		$handle->get_plist($state);
308	}
309}
310
311package OpenBSD::Handle::BaseSystem;
312our @ISA = qw(OpenBSD::Handle);
313sub pkgname { return "BaseSystem"; }
314
315sub is_real { return 0; }
316
3171;
318