xref: /openbsd/usr.sbin/pkg_add/OpenBSD/Handle.pm (revision 09467b48)
1# ex:ts=8 sw=4:
2# $OpenBSD: Handle.pm,v 1.42 2017/03/07 16:21:28 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 has_reported_error
138{
139	my $self = shift;
140	return $self->{error_reported};
141}
142
143sub error_message
144{
145	my $self = shift;
146	my $error = $self->{error};
147	if ($error == BAD_PACKAGE) {
148		return "bad package";
149	} elsif ($error == CANT_INSTALL) {
150		if ($self->{errorinfo}) {
151			return "$self->{errorinfo}";
152		} else {
153			return "can't install";
154		}
155	} elsif ($error == NOT_FOUND) {
156		return "not found";
157	} elsif ($error == ALREADY_INSTALLED) {
158		return "already installed";
159	} else {
160		return "no error";
161	}
162}
163
164sub complete_old
165{
166	my $self = shift;
167	my $location = $self->{location};
168
169	if (!defined $location) {
170		$self->set_error(NOT_FOUND);
171    	} else {
172		my $plist = $location->plist;
173		if (!defined $plist) {
174			$self->set_error(BAD_PACKAGE);
175		} else {
176			$self->{plist} = $plist;
177			delete $location->{contents};
178			delete $location->{update_info};
179		}
180	}
181}
182
183sub complete_dependency_info
184{
185	my $self = shift;
186	my $location = $self->{location};
187
188	if (!defined $location) {
189		$self->set_error(NOT_FOUND);
190	} else {
191		if (!defined $self->{plist}) {
192			# trigger build
193			$location->update_info;
194		}
195	}
196}
197
198sub create_old
199{
200
201	my ($class, $pkgname, $state) = @_;
202	my $self= $class->new;
203	$self->{name} = $pkgname;
204
205	my $location = $state->repo->installed->find($pkgname);
206	if (defined $location) {
207		$self->{location} = $location;
208	}
209	$self->complete_dependency_info;
210
211	return $self;
212}
213
214sub create_new
215{
216	my ($class, $pkg) = @_;
217	my $handle = $class->new;
218	$handle->{name} = $pkg;
219	$handle->{tweaked} = 0;
220	return $handle;
221}
222
223sub from_location
224{
225	my ($class, $location) = @_;
226	my $handle = $class->new;
227	$handle->{location} = $location;
228	$handle->{tweaked} = 0;
229	return $handle;
230}
231
232sub get_plist
233{
234	my ($handle, $state) = @_;
235
236	my $location = $handle->{location};
237	my $pkg = $handle->pkgname;
238
239	if ($state->verbose >= 2) {
240		$state->say("#1parsing #2", $state->deptree_header($pkg), $pkg);
241	}
242	my $plist = $location->plist;
243	unless (defined $plist) {
244		$state->say("Can't find CONTENTS from #1", $location->url)
245		    unless $location->{error_reported};
246		$location->close_with_client_error;
247		$location->wipe_info;
248		$handle->set_error(BAD_PACKAGE);
249		$handle->{error_reported} = 1;
250		return;
251	}
252	delete $location->{update_info};
253	unless ($plist->has('url')) {
254		OpenBSD::PackingElement::Url->add($plist, $location->url);
255	}
256	if ($plist->localbase ne $state->{localbase}) {
257		$state->say("Localbase mismatch: package has: #1, user wants: #2",
258		    $plist->localbase, $state->{localbase});
259		$location->close_with_client_error;
260		$location->wipe_info;
261		$handle->set_error(BAD_PACKAGE);
262		return;
263	}
264	my $pkgname = $handle->{pkgname} = $plist->pkgname;
265
266	if ($pkg ne '-') {
267		if (!defined $pkgname or $pkg ne $pkgname) {
268			$state->say("Package name is not consistent ???");
269			$location->close_with_client_error;
270			$location->wipe_info;
271			$handle->set_error(BAD_PACKAGE);
272			return;
273		}
274	}
275	$handle->{plist} = $plist;
276}
277
278sub get_location
279{
280	my ($handle, $state) = @_;
281
282	my $name = $handle->{name};
283
284	my $location = $state->repo->find($name);
285	if (!$location) {
286		$state->print("#1", $state->deptree_header($name));
287		$handle->set_error(NOT_FOUND);
288		$handle->{tweaked} =
289		    OpenBSD::Add::tweak_package_status($handle->pkgname,
290			$state);
291		if (!$handle->{tweaked}) {
292			$state->say("Can't find #1", $name);
293			$handle->{error_reported} = 1;
294			eval {
295				my $r = [$name];
296				$state->quirks->filter_obsolete($r, $state);
297			}
298		}
299		return;
300	}
301	$handle->{location} = $location;
302	$handle->{pkgname} = $location->name;
303}
304
305sub complete
306{
307	my ($handle, $state) = @_;
308
309	return if $handle->has_error;
310
311	if (!defined $handle->{location}) {
312		$handle->get_location($state);
313	}
314	return if $handle->has_error;
315	if (!defined $handle->{plist}) {
316		$handle->get_plist($state);
317	}
318}
319
320package OpenBSD::Handle::BaseSystem;
321our @ISA = qw(OpenBSD::Handle);
322sub pkgname { return "BaseSystem"; }
323
324sub is_real { return 0; }
325
3261;
327