diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2005-09-04 22:47:57 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2005-09-04 22:47:57 +0000 |
commit | 2491e24fbcb5bf7f102559b04685505a55540a40 (patch) | |
tree | adf517bc59741fd86b70ae1478ebd17ed891f00b /usr.sbin/pkg_add | |
parent | db2b33c1ae5ac54b7cf4811c71ed9a875ec2490d (diff) |
* New -i interactive option, that can ask obnoxious questions.
* move the signature code to a packing-list method, prepend the pkgname.
* depend on distant listings, cache these systematically.
* cut the PKG_PATH at :/ systematically, much simpler than parsing URLs.
People should get used to trailing /s.
* let pkg_add -u actually run the update.
* check for signature in more places, for instance, let pkg_add installed_stuff
be a void operation.
* grab enough stuff during updates to check signatures, so that pkg_add -u
can report updates that are not needed right away, instead of waiting
for the more confusing `trying to update'
* beginning of @module support.
* @pkgpath support, including updates.
* systematically expand stems when applicable.
* use visitors systematically in pkg_info.
* pkg_info -S reports signature.
* remove hardcoding of categories in PackingList, so that future modules
will be able to expand them.
* add @updateset and @incompatibility keywords.
Diffstat (limited to 'usr.sbin/pkg_add')
-rw-r--r-- | usr.sbin/pkg_add/Makefile | 3 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/Add.pm | 13 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/Dependencies.pm | 28 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/Interactive.pm | 83 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/PackageInfo.pm | 53 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/PackageLocator.pm | 128 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/PackingElement.pm | 80 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/PackingList.pm | 51 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/ProgressMeter.pm | 9 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/Update.pm | 68 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_add | 201 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_add.1 | 8 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_create | 16 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_delete | 48 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_delete.1 | 8 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_info | 87 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_info.1 | 8 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pod/OpenBSD::PackingList.pod | 14 |
18 files changed, 655 insertions, 251 deletions
diff --git a/usr.sbin/pkg_add/Makefile b/usr.sbin/pkg_add/Makefile index e001d7cebdd..eab24498e4f 100644 --- a/usr.sbin/pkg_add/Makefile +++ b/usr.sbin/pkg_add/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.29 2005/08/17 09:45:45 espie Exp $ +# $OpenBSD: Makefile,v 1.30 2005/09/04 22:47:56 espie Exp $ .include <bsd.own.mk> @@ -15,6 +15,7 @@ PACKAGES= \ OpenBSD/Error.pm \ OpenBSD/Getopt.pm \ OpenBSD/IdCache.pm \ + OpenBSD/Interactive.pm \ OpenBSD/Mtree.pm \ OpenBSD/PackageInfo.pm \ OpenBSD/PackageLocator.pm \ diff --git a/usr.sbin/pkg_add/OpenBSD/Add.pm b/usr.sbin/pkg_add/OpenBSD/Add.pm index f65d581d6ad..caa3c10715f 100644 --- a/usr.sbin/pkg_add/OpenBSD/Add.pm +++ b/usr.sbin/pkg_add/OpenBSD/Add.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: Add.pm,v 1.39 2005/08/22 11:25:59 espie Exp $ +# $OpenBSD: Add.pm,v 1.40 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -23,6 +23,17 @@ use OpenBSD::PackageInfo; use OpenBSD::ArcCheck; use File::Copy; +sub is_needed +{ + my ($plist, $state) = @_; + my $oplist = OpenBSD::PackingList->from_installation($plist->pkgname()); + my $n = $plist->signature(); + my $o = $oplist->signature(); + print "Comparing full signature for ", $plist->pkgname(), " \"$o\" vs. \"$n\": ", $n eq $o ? "equal\n" : "different\n" + if $state->{very_verbose}; + return $n ne $o; +} + sub manpages_index { my ($state) = @_; diff --git a/usr.sbin/pkg_add/OpenBSD/Dependencies.pm b/usr.sbin/pkg_add/OpenBSD/Dependencies.pm index 0e94926513c..36be0ede258 100644 --- a/usr.sbin/pkg_add/OpenBSD/Dependencies.pm +++ b/usr.sbin/pkg_add/OpenBSD/Dependencies.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: Dependencies.pm,v 1.2 2005/08/10 11:36:28 espie Exp $ +# $OpenBSD: Dependencies.pm,v 1.3 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2005 Marc Espie <espie@openbsd.org> # @@ -25,6 +25,7 @@ use OpenBSD::PkgSpec; use OpenBSD::PackageInfo; use OpenBSD::SharedLibs; use OpenBSD::Error; +use OpenBSD::Interactive; sub solve { @@ -37,6 +38,7 @@ sub solve $to_install->{OpenBSD::PackageName::url2pkgname($fullname)} = $fullname; } + my @avail; # do simple old style pkgdep first my @deps = (); @@ -73,8 +75,14 @@ sub solve next; } } + if (!@avail) { + @avail = OpenBSD::PackageLocator::available(); + if (!$state->{forced}->{allversions}) { + @avail = OpenBSD::PackageName::keep_most_recent(@avail); + } + } # try with list of available packages - @candidates = OpenBSD::PkgSpec::match($dep->{pattern}, OpenBSD::PackageLocator::available()); + @candidates = OpenBSD::PkgSpec::match($dep->{pattern}, @avail); # one single choice if (@candidates == 1) { push(@deps, $candidates[0]); @@ -82,14 +90,14 @@ sub solve next; } if (@candidates > 1) { - # grab default if available - if (grep {$_ eq $dep->{def}} @candidates) { - push(@deps, $dep->{def}); - $to_register->{$dep->{def}} = 1; - next; - } - push(@deps, $candidates[0]); - $to_register->{$candidates[0]} = 1; + # put default first if available + @candidates = ((grep {$_ eq $dep->{def}} @candidates), + (sort (grep {$_ ne $dep->{def}} @candidates))); + my $choice = + OpenBSD::Interactive::ask_list('Choose dependency for '.$plist->pkgname().': ', + $state->{interactive}, @candidates); + push(@deps, $choice); + $to_register->{$choice} = 1; next; } # can't get a list of packages, assume default diff --git a/usr.sbin/pkg_add/OpenBSD/Interactive.pm b/usr.sbin/pkg_add/OpenBSD/Interactive.pm new file mode 100644 index 00000000000..95f0a387c97 --- /dev/null +++ b/usr.sbin/pkg_add/OpenBSD/Interactive.pm @@ -0,0 +1,83 @@ +# ex:ts=8 sw=4: +# $OpenBSD: Interactive.pm,v 1.1 2005/09/04 22:47:56 espie Exp $ +# +# Copyright (c) 2005 Marc Espie <espie@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# + +use strict; +use warnings; + +package OpenBSD::Interactive; + +sub ask_list +{ + my ($prompt, $interactive, @values) = @_; + if (!$interactive || !-t STDIN) { + return $values[0]; + } + print STDERR $prompt, "\n"; + my $i = 0; + for my $v (@values) { + printf STDERR "\t%2d: %s\n", $i, $v; + $i++; + } +LOOP: + print STDERR "Your choice: "; + my $result = <STDIN>; + chomp $result; + if ($result eq '') { + return $values[0]; + } + if ($result =~ m/^\d+$/) { + if ($result >= 0 && $result < @values) { + return $values[$result]; + } + print STDERR "invalid numeric value !\n"; + goto LOOP; + } + if (grep { $result eq $_ } @values) { + return $result; + } else { + print STDERR "Ambiguous value !\n"; + goto LOOP; + } +} + +sub confirm +{ + my ($prompt, $interactive, $default) = @_; + if (!$interactive || !-t STDIN) { + return 0; + } +LOOP2: + print STDERR $prompt, $default ? '? [Y/n] ' : '? [y/N] '; + + my $result = <STDIN>; + chomp $result; + $result =~ s/\s*//g; + $result =~ tr/A-Z/a-z/; + if ($result eq 'yes' or $result eq 'y') { + return 1; + } + if ($result eq 'no' or $result eq 'n') { + return 0; + } + if ($result eq '') { + return $default; + } + print STDERR "Ambiguous answer\n"; + goto LOOP2; +} + +1; diff --git a/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm b/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm index f0873940f5a..a82351f4e35 100644 --- a/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm +++ b/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: PackageInfo.pm,v 1.17 2005/01/16 11:16:23 espie Exp $ +# $OpenBSD: PackageInfo.pm,v 1.18 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -21,13 +21,14 @@ package OpenBSD::PackageInfo; our @ISA=qw(Exporter); our @EXPORT=qw(installed_packages installed_info installed_name info_names is_info_name lock_db unlock_db - add_installed delete_installed is_installed borked_package CONTENTS COMMENT DESC INSTALL DEINSTALL REQUIRE + add_installed delete_installed is_installed borked_package CONTENTS COMMENT DESC INSTALL DEINSTALL REQUIRE MODULE REQUIRED_BY REQUIRING DISPLAY UNDISPLAY MTREE_DIRS); use OpenBSD::PackageName; use constant { CONTENTS => '+CONTENTS', COMMENT => '+COMMENT', + MODULE => '+MODULE.pm' , DESC => '+DESC', INSTALL => '+INSTALL', DEINSTALL => '+DEINSTALL', @@ -43,13 +44,14 @@ my $pkg_db = $ENV{"PKG_DBDIR"} || '/var/db/pkg'; our $list; -our @info = (CONTENTS, COMMENT, DESC, REQUIRE, INSTALL, DEINSTALL, REQUIRED_BY, REQUIRING, DISPLAY, UNDISPLAY, MTREE_DIRS); +our @info = (CONTENTS, COMMENT, DESC, REQUIRE, INSTALL, DEINSTALL, REQUIRED_BY, REQUIRING, DISPLAY, UNDISPLAY, MTREE_DIRS, MODULE); our %info = (); for my $i (@info) { my $j = $i; $j =~ s/\+/F/; $info{$i} = $j; + $info{'+MODULE.pm'} = 'FMODULE'; } sub _init_list @@ -193,4 +195,49 @@ sub unlock_db() } } + +sub solve_installed_names +{ + my ($old, $new, $msg, $state) = @_; + + my $installed; + my $bad = 0; + + for my $pkgname (@$old) { + $pkgname =~ s/\.tgz$//; + if (is_installed($pkgname)) { + push(@$new, installed_name($pkgname)); + } else { + if (OpenBSD::PackageName::is_stem($pkgname)) { + if (!defined $installed) { + $installed = OpenBSD::PackageName::compile_stemlist(installed_packages()); + } + my @l = $installed->findstem($pkgname); + if (@l == 0) { + print "Can't resolve $pkgname to an installed package name\n"; + $bad = 1; + } elsif (@l == 1) { + push(@$new, $l[0]); + } elsif (@l != 0) { + print "Ambiguous: $pkgname could be ", join(' ', @l),"\n"; + if ($state->{forced}->{ambiguous}) { + print "$msg\n"; + push(@$new, @l); + } else { + if ($state->{interactive}) { + require OpenBSD::ProgressMeter; + + my $result = OpenBSD::ProgressMeter::ask_list('Choose one package', 1, ("<None>", sort @l)); + push(@$new, $result) if $result ne '<None>'; + } else { + $bad = 1; + } + } + } + } + } + } + return $bad; +} + 1; diff --git a/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm b/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm index 9bfd62dff0e..bd9f3acce36 100644 --- a/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm +++ b/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: PackageLocator.pm,v 1.20 2005/08/22 11:30:30 espie Exp $ +# $OpenBSD: PackageLocator.pm,v 1.21 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -89,7 +89,6 @@ sub open # kill old files if too many my $already = $self->make_room(); - my $p = $self->pipename($object->{name}); open(my $fh, '-|', $p) or return undef; @@ -100,20 +99,32 @@ sub open return $fh; } -# by default, we don't know how to list packages there. -sub simplelist +package OpenBSD::PackageLocation::SCP; +our @ISA=qw(OpenBSD::PackageLocation OpenBSD::PackageLocation::FTPorSCP); + +our %distant = (); + +sub maxcount { + return 2; } -package OpenBSD::PackageLocation::SCP; -our @ISA=qw(OpenBSD::PackageLocation OpenBSD::PackageLocation::FTPorSCP); +sub opened +{ + my $self = $_[0]; + my $k = $self->{key}; + if (!defined $distant{$k}) { + $distant{$k} = []; + } + return $distant{$k}; +} sub _new { my ($class, $location) = @_; $location =~ s/scp\:\/\///i; $location =~ m/\//; - bless { host => $`, path => "/$'" }, $class; + bless { host => $`, key => $`, path => "/$'" }, $class; } sub pipename @@ -127,9 +138,12 @@ sub pipename sub list { my ($self) = @_; - my $host = $self->{host}; - my $path = $self->{path}; - return $self->_list("ssh $host ls -l $path"); + if (!defined $self->{list}) { + my $host = $self->{host}; + my $path = $self->{path}; + $self->{list} = $self->_list("ssh $host ls -l $path"); + } + return $self->{list}; } package OpenBSD::PackageLocation::Local; @@ -151,21 +165,16 @@ sub may_exist sub list { my $self = shift; - my @l = (); + my $l = []; my $dname = $self->{location}; - opendir(my $dir, $dname) or return undef; + opendir(my $dir, $dname) or return $l; while (my $e = readdir $dir) { next unless -f "$dname/$e"; next unless $e =~ m/\.tgz$/; - push(@l, $`); + push(@$l, $`); } close($dir); - return @l; -} - -sub simplelist -{ - return $_[0]->list(); + return $l; } package OpenBSD::PackageLocation::Local::Pipe; @@ -186,22 +195,22 @@ package OpenBSD::PackageLocation::FTPorSCP; sub _list { my ($self, $cmd) = @_; - my @l =(); + my $l =[]; local $_; open(my $fh, '-|', "$cmd") or return undef; while(<$fh>) { chomp; next if m/^d.*\s+\S/; next unless m/([^\s]+)\.tgz\s*$/; - push(@l, $1); + push(@$l, $1); } close($fh); - return @l; + return $l; } package OpenBSD::PackageLocation::HTTPorFTP; -my %distant = (); +our %distant = (); sub maxcount { @@ -240,21 +249,23 @@ our @ISA=qw(OpenBSD::PackageLocation::HTTPorFTP OpenBSD::PackageLocation); sub list { my ($self) = @_; - $self->make_room(); - my $fullname = $self->{location}; - my @l =(); - local $_; - open(my $fh, '-|', "ftp -o - $fullname 2>/dev/null") or return undef; - # XXX assumes a pkg HREF won't cross a line. Is this the case ? - while(<$fh>) { - chomp; - for my $pkg (m/\<A\s+HREF=\"(.*?)\.tgz\"\>/gi) { - next if $pkg =~ m|/|; - push(@l, $pkg); + if (!defined $self->{list}) { + $self->make_room(); + my $fullname = $self->{location}; + my $l = $self->{list} = []; + local $_; + open(my $fh, '-|', "ftp -o - $fullname 2>/dev/null") or return undef; + # XXX assumes a pkg HREF won't cross a line. Is this the case ? + while(<$fh>) { + chomp; + for my $pkg (m/\<A\s+HREF=\"(.*?)\.tgz\"\>/gi) { + next if $pkg =~ m|/|; + push(@$l, $pkg); + } } + close($fh); } - close($fh); - return @l; + return $self->{list}; } package OpenBSD::PackageLocation::FTP; @@ -263,9 +274,12 @@ our @ISA=qw(OpenBSD::PackageLocation::HTTPorFTP OpenBSD::PackageLocation OpenBSD sub list { my ($self) = @_; - $self->make_room(); - my $fullname = $self->{location}; - return $self->_list("echo nlist|ftp -o - $fullname 2>/dev/null"); + if (!defined $self->{list}) { + $self->make_room(); + my $fullname = $self->{location}; + $self->{list} = $self->_list("echo nlist *.tgz|ftp -o - $fullname 2>/dev/null"); + } + return $self->{list}; } @@ -279,14 +293,18 @@ use OpenBSD::Temp; my %packages; my @pkgpath; +my $need_new_cache = 1; +my $available_packages = {}; +my @pkglist = (); + if (defined $ENV{PKG_PATH}) { - my @tentative = split /\:/, $ENV{PKG_PATH}; + my $pkgpath = $ENV{PKG_PATH}; + $pkgpath =~ s/^\:+//; + $pkgpath =~ s/\:+$//; + my @tentative = split /\/\:/, $pkgpath; @pkgpath = (); while (my $i = shift @tentative) { - if ($i =~ m/^(?:ftp|http|scp)$/i) { - $i.= ":".(shift @tentative); - } $i =~ m|/$| or $i.='/'; push @pkgpath, OpenBSD::PackageLocation->new($i); } @@ -318,6 +336,7 @@ sub find $package = $class->openAbsolute($location, $pkgname, $arch); if (defined $package) { push(@pkgpath, $location); + $need_new_cache = 1; } } else { for my $p (@pkgpath) { @@ -331,20 +350,17 @@ sub find sub available { - my @l = (); - foreach my $loc (@pkgpath) { - push(@l, $loc->simplelist()); - } - return @l; -} - -sub distant_available -{ - my @l = (); - foreach my $loc (@pkgpath) { - push(@l, $loc->list()); + if ($need_new_cache) { + $available_packages = {}; + foreach my $loc (reverse @pkgpath) { + foreach my $pkg (@{$loc->list()}) { + $available_packages->{$pkg} = $loc; + } + } + @pkglist = keys %$available_packages; + $need_new_cache = 0; } - return @l; + return @pkglist; } sub info diff --git a/usr.sbin/pkg_add/OpenBSD/PackingElement.pm b/usr.sbin/pkg_add/OpenBSD/PackingElement.pm index 0f4c74a56fe..0ee0f853ac7 100644 --- a/usr.sbin/pkg_add/OpenBSD/PackingElement.pm +++ b/usr.sbin/pkg_add/OpenBSD/PackingElement.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: PackingElement.pm,v 1.77 2005/08/14 12:01:08 espie Exp $ +# $OpenBSD: PackingElement.pm,v 1.78 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -138,6 +138,8 @@ sub IsFile() { 0 } sub NoDuplicateNames() { 0 } +sub signature {} + # Basic class hierarchy # various stuff that's only linked to objects before/after them @@ -244,6 +246,12 @@ sub add_object package OpenBSD::PackingElement::Depend; our @ISA=qw(OpenBSD::PackingElement::Meta); +sub signature +{ + my ($self, $hash) = @_; + $hash->{$self->{def}} = 1; +} + # Abstract class for all file-like elements package OpenBSD::PackingElement::FileBase; our @ISA=qw(OpenBSD::PackingElement::FileObject); @@ -647,6 +655,10 @@ sub category() { "pkgcfl" } package OpenBSD::PackingElement::PkgDep; our @ISA=qw(OpenBSD::PackingElement::Depend); +sub signature +{ +} + __PACKAGE__->setKeyword('pkgdep'); sub keyword() { "pkgdep" } sub category() { "pkgdep" } @@ -706,6 +718,11 @@ __PACKAGE__->setKeyword('wantlib'); sub category() { "wantlib" } sub keyword() { "wantlib" } +sub signature +{ + my ($self, $hash) = @_; + $hash->{$self->{name}} = 1; +} package OpenBSD::PackingElement::LibDepend; our @ISA=qw(OpenBSD::PackingElement::Depend); @@ -736,6 +753,63 @@ sub stringize($) ':'.$self->{libspec}.':'.$self->{pattern}.':'.$self->{def}; } +package OpenBSD::PackingElement::PkgPath; +our @ISA=qw(OpenBSD::PackingElement::Meta); + +__PACKAGE__->setKeyword('pkgpath'); +sub keyword() { "pkgpath" } +sub category() { "pkgpath" } + +package OpenBSD::PackingElement::Incompatibility; +our @ISA=qw(OpenBSD::PackingElement::Meta); + +__PACKAGE__->setKeyword('incompatibility'); +sub keyword() { "incompatibility" } +sub category() { "incompatibility" } + +package OpenBSD::PackingElement::UpdateSet; +our @ISA=qw(OpenBSD::PackingElement::Meta); + +__PACKAGE__->setKeyword('updateset'); +sub keyword() { "updateset" } +sub category() { "updateset" } + +package OpenBSD::PackingElement::Module; +our @ISA=qw(OpenBSD::PackingElement::Meta); + +use OpenBSD::PackageInfo; + +__PACKAGE__->setKeyword('module'); +sub keyword() { "module" } +sub category() { "module" } + +my $installed_modules = {}; + +sub add +{ + my ($class, $plist, @args) = @_; + + require OpenBSD::PkgSpec; + + my @candidates = OpenBSD::PkgSpec::match($args[0], installed_packages()); + if (@candidates == 1) { + if (!defined $installed_modules->{$candidates[0]}) { + # pull in the module right here and now; + my $f = installed_info($candidates[0]).MODULE; + eval "require \"$f\";"; + if ($@) { + die "Error in reading module $f: $@"; + } + } + } elsif (@candidates == 0) { + $plist->{need_modules} = 1; + } else { + die "Ambiguous module: ", $args[0]; + } + + $class->SUPER::add($plist, @args); +} + package OpenBSD::PackingElement::NewUser; our @ISA=qw(OpenBSD::PackingElement::Action); __PACKAGE__->setKeyword("newuser"); @@ -1153,6 +1227,10 @@ package OpenBSD::PackingElement::FCONTENTS; our @ISA=qw(OpenBSD::PackingElement::SpecialFile); sub category() { OpenBSD::PackageInfo::CONTENTS } +package OpenBSD::PackingElement::FMODULE; +our @ISA=qw(OpenBSD::PackingElement::SpecialFile); +sub category() { OpenBSD::PackageInfo::MODULE } + package OpenBSD::PackingElement::ScriptFile; our @ISA=qw(OpenBSD::PackingElement::SpecialFile); use OpenBSD::Error; diff --git a/usr.sbin/pkg_add/OpenBSD/PackingList.pm b/usr.sbin/pkg_add/OpenBSD/PackingList.pm index af9360785a7..d0c83e84982 100644 --- a/usr.sbin/pkg_add/OpenBSD/PackingList.pm +++ b/usr.sbin/pkg_add/OpenBSD/PackingList.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: PackingList.pm,v 1.47 2005/08/17 10:00:19 espie Exp $ +# $OpenBSD: PackingList.pm,v 1.48 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -74,6 +74,10 @@ sub read next if m/^\s*$/; chomp; OpenBSD::PackingElement::Factory($_, $plist); + if ($plist->{need_modules}) { + close($fh); + open($fh, '<', '/dev/null'); + } }); return $plist; } @@ -159,6 +163,27 @@ sub ExtraInfoOnly } } +sub UpdateInfoOnly +{ + my ($fh, $cont) = @_; + local $_; + while (<$fh>) { + # XXX optimization + if (m/^\@arch\b/o) { + while (<$fh>) { + if (m/^\@(?:depend|wantlib|pkgdep|newdepend|libdepend|pkgpath)\b/o) { + &$cont($_); + } elsif (m/^\@(?:groups|users|cwd)\b/o) { + last; + } + } + return; + } + next unless m/^\@(?:name\b|depend\b|wantlib\b|pkgdep\b|newdepend\b|libdepend\b|pkgpath\b|comment\s+subdir\=|arch\b)/o; + &$cont($_); + } +} + sub FatOnly { my ($fh, $cont) = @_; @@ -306,6 +331,16 @@ sub pkgbase($) } } +our @unique_categories = + (qw(name no-default-conflict manual-installation extrainfo arch)); + +our @list_categories = + (qw(pkgcfl conflict depend wantlib pkgdep newdepend + libdepend module groups users items)); + +our @cache_categories = + (qw(depend wantlib pkgdep newdepend libdepend)); + sub visit { my ($self, $method, @l) = @_; @@ -320,7 +355,7 @@ sub visit } } - for my $unique_item (qw(name no-default-conflict manual-installation extrainfo arch)) { + for my $unique_item (@unique_categories) { $self->{$unique_item}->$method(@l) if defined $self->{$unique_item}; } @@ -328,7 +363,7 @@ sub visit $self->{$special}->$method(@l) if defined $self->{$special}; } - for my $listname (qw(modules pkgcfl conflict depend wantlib pkgdep newdepend libdepend groups users items)) { + for my $listname (@list_categories) { if (defined $self->{$listname}) { for my $item (@{$self->{$listname}}) { $item->$method(@l); @@ -368,7 +403,7 @@ sub to_cache my ($self) = @_; return if defined $plist_cache->{$self->pkgname()}; my $plist = new OpenBSD::PackingList; - for my $c (qw(depend wantlib pkgdep newdepend libdepend)) { + for my $c (@cache_categories) { if (defined $self->{$c}) { $plist->{$c} = $self->{$c}; } @@ -388,6 +423,14 @@ sub to_installation } +sub signature +{ + my $self = shift; + my $k = {}; + $self->visit('signature', $k); + return join(',', $self->pkgname(), sort keys %$k); +} + sub forget { } diff --git a/usr.sbin/pkg_add/OpenBSD/ProgressMeter.pm b/usr.sbin/pkg_add/OpenBSD/ProgressMeter.pm index 68152be9817..a4e24e536fe 100644 --- a/usr.sbin/pkg_add/OpenBSD/ProgressMeter.pm +++ b/usr.sbin/pkg_add/OpenBSD/ProgressMeter.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: ProgressMeter.pm,v 1.5 2004/12/29 14:10:27 espie Exp $ +# $OpenBSD: ProgressMeter.pm,v 1.6 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2004 Marc Espie <espie@openbsd.org> # @@ -68,10 +68,9 @@ sub set_header $header = shift; if (!$enabled) { $isatty = 0; - } else { - if (!defined $isatty) { - $isatty = -t STDERR; - } + } + if (!defined $isatty) { + $isatty = -t STDERR; } if ($isatty) { find_window_size(); diff --git a/usr.sbin/pkg_add/OpenBSD/Update.pm b/usr.sbin/pkg_add/OpenBSD/Update.pm index 9a0aa61ead3..24493147f3e 100644 --- a/usr.sbin/pkg_add/OpenBSD/Update.pm +++ b/usr.sbin/pkg_add/OpenBSD/Update.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: Update.pm,v 1.55 2005/08/16 21:34:10 espie Exp $ +# $OpenBSD: Update.pm,v 1.56 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2004 Marc Espie <espie@openbsd.org> # @@ -19,6 +19,7 @@ use strict; use warnings; use OpenBSD::Delete; +use OpenBSD::Interactive; package OpenBSD::PackingElement; sub can_update @@ -51,10 +52,6 @@ sub unmark_lib { } -sub build_context -{ -} - package OpenBSD::PackingElement::FileBase; use File::Temp qw/tempfile/; @@ -170,7 +167,7 @@ sub validate_depend $state->{forcedupdates}->{$wanting} = 1; } else { $state->{okay} = 0; - Warn "Can't update forward dependency of $wanting on $toreplace: $replacement doesn't match\n"; + Warn "Can't update forward dependency of $wanting on $toreplace: $replacement doesn't match (use -F updatedepends to force it)\n"; } } } @@ -201,25 +198,6 @@ sub unmark_lib delete $libs->{"$libname"}; } -package OpenBSD::PackingElement::Wantlib; -sub build_context -{ - my ($self, $hash) = @_; - $hash->{$self->{name}} = 1; -} - -package OpenBSD::PackingElement::Depend; -sub build_context -{ - my ($self, $hash) = @_; - $hash->{$self->{def}} = 1; -} - -package OpenBSD::PackingElement::PkgDep; -sub build_context -{ -} - package OpenBSD::PackingElement::NewDepend; use OpenBSD::Error; sub validate_depend @@ -235,7 +213,7 @@ sub validate_depend Warn "Forward dependency of $wanting on $toreplace doesn't match $replacement, forcing it\n"; } else { $state->{okay} = 0; - Warn "Can't update forward dependency of $wanting on $toreplace: $replacement doesn't match\n"; + Warn "Can't update forward dependency of $wanting on $toreplace: $replacement doesn't match (use -F updatedepends to force it)\n"; } } } @@ -253,7 +231,7 @@ sub validate_depend Warn "Forward dependency of $wanting on $toreplace doesn't match $replacement, forcing it\n"; } else { $state->{okay} = 0; - Warn "Can't update forward dependency of $wanting on $toreplace: $replacement doesn't match\n"; + Warn "Can't update forward dependency of $wanting on $toreplace: $replacement doesn't match (use -F updatedepends to force it)\n"; } } } @@ -284,6 +262,12 @@ sub can_do if ($state->{forced}->{update}) { Warn "(forcing update)\n"; $state->{okay} = 1; + } elsif ($state->{interactive}) { + require OpenBSD::Interactive; + + if (OpenBSD::Interactive::confirm("proceed with update anyways", 1, 0)) { + $state->{okay} = 1; + } } } my @wantlist = OpenBSD::RequiredBy->new($toreplace)->list(); @@ -329,7 +313,7 @@ sub is_safe for my $i (@{$state->{journal}}) { Warn "\t$i\n"; } - if ($state->{forced}->{update}) { + if ($state->{forced}->{update} || OpenBSD::Interactive::confirm("Proceed with update anyways", $state->{interactive}, 0)) { Warn "(forcing update)\n"; $state->{okay} = 1; } @@ -401,9 +385,11 @@ sub convert_to_requiring sub walk_depends_closure { - my ($start, $name, $state) = @_; + my ($start, $plist, $state) = @_; my @todo = ($start); my $done = {}; + my $depend = 0; + my $name = $plist->pkgname(); print "Packages that depend on those shared libraries:\n" if $state->{beverbose}; @@ -423,8 +409,15 @@ sub walk_depends_closure convert_to_requiring($pkg2); } $l->add($name); + $depend = 1; } } +# if (!$depend && $state->{interactive}) { +# if ($state->{forced}->{zapoldlibs} || +# OpenBSD::Interactive::confirm("Nothing depends on $name. Delete it", 1, 0)) { +# OpenBSD::Delete::delete_plist($plist, $state); +# } +# } } @@ -473,7 +466,7 @@ sub save_old_libraries require OpenBSD::PkgCfl; OpenBSD::PkgCfl::register($stub_list, $state); - walk_depends_closure($old_plist->pkgname(), $stub_name, $state); + walk_depends_closure($old_plist->pkgname(), $stub_list, $state); } else { print "No libraries to keep\n" if $state->{beverbose}; } @@ -493,21 +486,6 @@ sub adjust_dependency $l->add($into); } -sub is_needed -{ - my ($plist, $state) = @_; - my $new_context = {}; - $plist->visit('build_context', $new_context); - my $oplist = OpenBSD::PackingList->from_installation($plist->pkgname()); - my $old_context = {}; - $oplist->visit('build_context', $old_context); - my $n = join(',', sort keys %$new_context); - my $o = join(',', sort keys %$old_context); - print "Comparing full signature for ", $plist->pkgname(), " \"$o\" vs. \"$n\": ", $n eq $o ? "equal\n" : "different\n" - if $state->{very_verbose}; - return $n ne $o; -} - sub figure_out_libs { my ($plist, $state, @libs) = @_; diff --git a/usr.sbin/pkg_add/pkg_add b/usr.sbin/pkg_add/pkg_add index ee60c8c694e..de0e98d4dcf 100644 --- a/usr.sbin/pkg_add/pkg_add +++ b/usr.sbin/pkg_add/pkg_add @@ -1,7 +1,7 @@ #! /usr/bin/perl # ex:ts=8 sw=4: -# $OpenBSD: pkg_add,v 1.196 2005/08/29 00:42:58 espie Exp $ +# $OpenBSD: pkg_add,v 1.197 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -31,6 +31,7 @@ use OpenBSD::Vstat; use OpenBSD::Getopt; use OpenBSD::Error; use OpenBSD::ProgressMeter; +use OpenBSD::Interactive; use OpenBSD::Add; use OpenBSD::SharedLibs; use File::Path; @@ -40,6 +41,17 @@ my $errors = 0; our %forced = (); our $not; +sub has_new_sig +{ + my ($plist, $state) = @_; + my $n = OpenBSD::PackingList->from_installation($plist->pkgname())->signature(); + my $o = $plist->signature(); + print "Comparing full signature for ", $plist->pkgname(), " \"$o\" vs. \"$n\": ", $n eq $o ? "equal\n" : "different\n" + if $state->{very_verbose}; + return $n ne $o; +} + + sub can_install($$$) { my ($plist, $state, $handle) = @_; @@ -50,14 +62,10 @@ sub can_install($$$) my %conflicts = map {($_,1)} @conflicts; - if (defined $conflicts{$pkgname}) { - if (!$state->{replace}) { - if (!$state->{forced}->{installed}) { - print "Can't install $pkgname because it's already installed\n"; - $state->{installed}->{$handle->{pkgname}} = 1; - $errors++; - } - return undef; + if ((keys %conflicts) == 1 && (keys %conflicts)[0] eq $pkgname) { + if (!OpenBSD::Add::is_needed($plist, $state)) { + print "Already installed: $pkgname\n"; + return 1; } } @@ -72,6 +80,13 @@ sub can_install($$$) } if (!$state->{replace}) { + if (@conflicts == 1 && is_installed($plist->pkgname()) && + !has_new_sig($plist, $state)) { + print "Not reinstalling $pkgname\n" if $state->{verbose}; + OpenBSD::SharedLibs::add_package_libs($plist->pkgname()); + $state->{installed}->{$pkgname} = 1; + return undef; + } print "Can't install $pkgname because of conflicts (",join(',', @conflicts, @libs), ")\n"; $errors++; return undef; @@ -86,14 +101,15 @@ sub can_install($$$) require OpenBSD::Update; if (is_installed($plist->pkgname()) && !$state->{forced}->{installed}) { - if (!OpenBSD::Update::is_needed($plist, $state)) { + if (!has_new_sig($plist, $state)) { + print "Not reinstalling $pkgname\n" if $state->{verbose}; OpenBSD::SharedLibs::add_package_libs($plist->pkgname()); $state->{installed}->{$pkgname} = 1; return undef; } } if (!OpenBSD::Update::is_safe($plist, $state)) { - print "Can't safely update to $pkgname\n"; + print "Can't safely update to $pkgname (use -F update to force it)\n"; $errors++; return undef; } @@ -495,10 +511,23 @@ sub install_package } my $plist = $handle->{plist}; + if ($plist->{need_modules}) { + if (!defined $handle->{solved_dependencies}) { + my @deps = OpenBSD::Dependencies::solve($state, $handle, @todo); + if (@deps > 0) { + build_deptree($state, $pkg, @deps); + return (@deps, $pkg); + } + } else { + my $dir = $handle->info(); + $plist = $handle->{plist} = + OpenBSD::PackingList->fromfile($dir.CONTENTS); + } + } if (is_installed($plist->pkgname()) && !$state->{forced}->{installed}) { if ($state->{replace}) { - if (!OpenBSD::Update::is_needed($plist, $state)) { + if (!OpenBSD::Add::is_needed($plist, $state)) { OpenBSD::SharedLibs::add_package_libs($plist->pkgname()); $state->{installed}->{$handle->{pkgname}} = 1; $handle->close(); @@ -568,33 +597,55 @@ sub install_package return (); } +my $bad = 0; + +sub choose1 +{ + my ($pkgname, $interactive, @l) = @_; + if (@l == 0) { + print "Can't resolve $pkgname\n"; + $bad = 1; + } elsif (@l == 1) { + return $l[0]; + } elsif (@l != 0) { + print "Ambiguous: $pkgname could be ", join(' ', @l),"\n"; + if ($interactive) { + my $result = OpenBSD::Interactive::ask_list('Choose one package', 1, ("<None>", @l)); + if ($result eq '<None>') { + $bad = 1; + } else { + return $result; + } + } else { + $bad = 1; + } + } + return undef; +} + +sub available_stems +{ + my $state = shift; + my @avail = OpenBSD::PackageLocator::available(); + unless ($state->{forced}->{allversions}) { + @avail = OpenBSD::PackageName::keep_most_recent(@avail); + } + return OpenBSD::PackageName::compile_stemlist(@avail); +} + sub find_updates { my ($old, $new, $state) = @_; my @list = (); - for my $pkgname (@$old) { - if (OpenBSD::PackageName::is_stem($pkgname)) { - my @l = OpenBSD::PackageName::findstem($pkgname, - installed_packages()); - if (@l == 0) { - Fatal("Can't resolve $pkgname to an installed package name"); - } elsif (@l == 1) { - push(@list, $l[0]); - } else { - Fatal("Ambiguous: $pkgname could be", join(',', @l)); - } - } else { - push(@list, $pkgname); - } - } + OpenBSD::PackageInfo::solve_installed_names($old, \@list, "(updating them all)", $state); unless (defined $state->{full_update} or defined $state->{forced}->{noclosure}) { require OpenBSD::RequiredBy; @list = OpenBSD::Requiring->compute_closure(@list); } my @cantupdate = (); - my $hash = OpenBSD::PackageName::compile_stemlist(OpenBSD::PackageLocator::distant_available()); + my $hash = available_stems($state); for my $pkgname (@list) { my $stem = OpenBSD::PackageName::splitstem($pkgname); @@ -609,10 +660,11 @@ sub find_updates push(@$new, $l[0]); next; } - my $plist = OpenBSD::PackingList->from_installation($pkgname, \&OpenBSD::PackingList::ExtraInfoOnly); + my $plist = OpenBSD::PackingList->from_installation($pkgname, \&OpenBSD::PackingList::UpdateInfoOnly); if (!defined $plist) { Fatal("Can't locate $pkgname"); } + my $found; for my $candidate (@l) { my $handle = OpenBSD::PackageLocator->find($candidate, $state->{arch}); if (!$handle) { @@ -621,18 +673,32 @@ sub find_updates $handle->close(); my $dir = $handle->info(); my $p2 = OpenBSD::PackingList->fromfile($dir.CONTENTS, - \&OpenBSD::PackingList::ExtraInfoOnly); + \&OpenBSD::PackingList::UpdateInfoOnly); if ($p2->has('arch')) { unless ($p2->{arch}->check($state->{arch})) { next; } } + if ($plist->signature() eq $p2->signature()) { + $found = $candidate; + } if ($p2->{extrainfo}->{subdir} eq $plist->{extrainfo}->{subdir}) { push(@l2, $candidate); + } elsif ($p2->has('pkgpath')) { + for my $p (@{$p2->{pkgpath}}) { + if ($p2->{name} eq $plist->{extrainfo}->{subdir}) { + push(@l2, $candidate); + last; + } + } } } - print "Updating $pkgname -> ", join(' ', @l2), "\n"; + if (defined $found && @l2 == 1 && $found eq $l2[0]) { + print "No need to update $pkgname\n"; + next; + } + print "Candidates for updating $pkgname -> ", join(' ', @l2), "\n"; # if all packages have the same version, but distinct p, # grab the most recent. if (@l2 > 1) { @@ -640,14 +706,42 @@ sub find_updates } if (@l2 == 1) { - push(@$new, $l2[0]); - } else { + if (defined $found && $found eq $l2[0]) { + print "No need to update $pkgname\n"; + } else { + push(@$new, $l2[0]); + } + } elsif (@l2 == 0) { push(@cantupdate, $pkgname); + } else { + push(@$new, choose1($pkgname, $state->{interactive}, sort @l2)); } } return @cantupdate; } +sub find_truenames +{ + my ($old, $new, $state) = @_; + + my $h; + + for my $pkgname (@$old) { + if (OpenBSD::PackageName::is_stem($pkgname)) { + if (!defined $h) { + $h = available_stems($state); + } + my @l = $h->findstem($pkgname); + if (@l > 1) { + @l = OpenBSD::PackageName::keep_most_recent(@l); + } + push(@$new, choose1($pkgname, $state->{interactive}, sort @l)); + } else { + push(@$new, $pkgname); + } + } +} + sub reorder { my $l = shift; @@ -661,13 +755,13 @@ sub reorder } } -set_usage('pkg_add [-acInqrvvx] [-A arch] [-B pkg-destdir] [-F keywords]', +set_usage('pkg_add [-aciInqrvvx] [-A arch] [-B pkg-destdir] [-F keywords]', '[-L localbase] [-P type] [-Q quick-destdir] pkgname [...]'); -our ($opt_a, $opt_v, $opt_n, $opt_I, $opt_L, $opt_B, $opt_A, $opt_P, $opt_Q, $opt_x, $opt_r, $opt_q, $opt_c, $opt_u); +our ($opt_a, $opt_v, $opt_n, $opt_I, $opt_L, $opt_B, $opt_A, $opt_P, $opt_Q, $opt_x, $opt_r, $opt_q, $opt_c, $opt_i, $opt_u); $opt_v = 0; try { - getopts('aqchuvnrxIL:f:F:B:A:P:Q:', + getopts('aqchivnruxIL:f:F:B:A:P:Q:', {'v' => sub {++$opt_v;}, 'h' => sub { Usage(); }, 'F' => sub { @@ -692,7 +786,6 @@ $state->{cache} = {}; $state->{installed} = {}; $state->{deptree} = {}; $state->{do_faked} = 0; -$state->{replace} = $opt_r; $state->{localbase} = $opt_L; $state->{arch} = $opt_A; $state->{forced} = \%forced; @@ -731,7 +824,7 @@ if (defined $state->{destdir}) { } -$state->{not} = $opt_n || $opt_u; +$state->{not} = $opt_n; # XXX RequiredBy $not = $opt_n; $state->{quick} = $opt_q; @@ -739,7 +832,9 @@ $state->{extra} = $opt_c; $state->{dont_run_scripts} = $opt_I; $state->{very_verbose} = $opt_v >= 2; $state->{verbose} = $opt_v; +$state->{interactive} = $opt_i; $state->{beverbose} = $opt_n || ($opt_v >= 2); +$state->{replace} = $opt_r || $opt_u; if (@ARGV == 0 && !$opt_u) { Usage "Missing pkgname"; @@ -757,27 +852,35 @@ if ($< && !$forced{nonroot}) { } lock_db($state->{not}); + +my @todo = (); + if ($opt_u) { if (@ARGV == 0) { @ARGV = sort(installed_packages()); $state->{full_update} = 1; } - my @todo = (); my @cantupdate = find_updates(\@ARGV, \@todo, $state); - print "Update using pkg_add -r ", join(' ', @todo), "\n"; if (@cantupdate > 0) { - print "Cannot find updates for ",join(' ', @cantupdate), "\n"; + unless ($state->{forced}->{alwaysupdate} || + OpenBSD::Interactive::confirm("Cannot find updates for ".join(' ', @cantupdate).". Proceed", $state->{interactive}, 0)) { + exit(1); + } + } + print "Running the equivalent of pkg_add -r ", join(' ', @todo), "\n"; +} else { + find_truenames(\@ARGV, \@todo, $state); + if (defined $state->{forced}->{kitchensink}) { + reorder(\@todo); + if (!$opt_r) { + @todo = grep {s/\.tgz$//; !is_installed($_);} @todo; + } + print "Adding in order:\n", (map { "\t$_\n" } @todo), "\n"; } - exit(0); } -my @todo = (@ARGV); -if (defined $state->{forced}->{kitchensink}) { - reorder(\@todo); - if (!$opt_r) { - @todo = grep {s/\.tgz$//; !is_installed($_);} @todo; - } - print "Adding in order:\n", (map { "\t$_\n" } @todo), "\n"; +if ($bad) { + exit(1); } eval { diff --git a/usr.sbin/pkg_add/pkg_add.1 b/usr.sbin/pkg_add/pkg_add.1 index 692d9d7df6a..260aaa3deae 100644 --- a/usr.sbin/pkg_add/pkg_add.1 +++ b/usr.sbin/pkg_add/pkg_add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_add.1,v 1.46 2005/08/17 19:22:31 espie Exp $ +.\" $OpenBSD: pkg_add.1,v 1.47 2005/09/04 22:47:56 espie Exp $ .\" .\" FreeBSD install - a package for the installation and maintenance .\" of non-core utilities. @@ -26,7 +26,7 @@ .Sh SYNOPSIS .Nm pkg_add .Bk -words -.Op Fl acInqruvx +.Op Fl aciInqruvx .Op Fl A Ar arch .Op Fl B Ar pkg-destdir .Op Fl F Ar keywords @@ -175,6 +175,10 @@ unsafe update: old packing-list will run scripts that may fail. .It Ar updatedepends force update even if forward dependencies no longer match. .El +.It Fl i +Switch on interactive mode. +.Nm +may ask questions to the user if faced with difficult decisions. .It Fl I If scripts exist for a given package, do not execute them. .It Fl L Ar localbase diff --git a/usr.sbin/pkg_add/pkg_create b/usr.sbin/pkg_add/pkg_create index 3b1943783ed..785a5da8463 100644 --- a/usr.sbin/pkg_add/pkg_create +++ b/usr.sbin/pkg_add/pkg_create @@ -1,6 +1,6 @@ #! /usr/bin/perl # ex:ts=8 sw=4: -# $OpenBSD: pkg_create,v 1.37 2005/08/14 12:01:08 espie Exp $ +# $OpenBSD: pkg_create,v 1.38 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -264,7 +264,7 @@ our $errors = 0; our ($opt_p, $opt_f, $opt_c, $opt_d, $opt_v, $opt_i, $opt_k, $opt_r, $opt_S, $opt_h, $opt_s, $opt_O, $opt_A, $opt_L, - $opt_M, $opt_U, $opt_P, $opt_W, $opt_n, + $opt_m, $opt_M, $opt_U, $opt_P, $opt_W, $opt_n, $opt_B); my @contents; @@ -272,13 +272,13 @@ my $regen_package = 0; set_usage( 'pkg_create [-hnv] [-A arches] [-B pkg-destdir] [-D name=value]', -'[-i iscript] [-k dscript] [-L localbase] [-M displayfile]', +'[-i iscript] [-k dscript] [-L localbase] [-M module] [-M displayfile]', '[-P pkg-dependency] [-p prefix] [-r rscript] [-S pkg-destdir]', '[-U undisplayfile] [-W wantedlib] -c desc -d desc -f packinglist pkgname'); my $plist = new OpenBSD::PackingList; try { - getopts('hp:f:c:d:vi:k:r:M:U:S:hs:OA:L:B:D:P:W:n', + getopts('hp:f:c:d:vi:k:r:m:M:U:S:hs:OA:L:B:D:P:W:n', {'D' => sub { local $_ = shift; @@ -367,6 +367,9 @@ if (defined $opt_M) { copy_subst($opt_M, '>', $dir.DISPLAY); } +if (defined $opt_m) { + copy_subst($opt_m, '>', $dir.MODULE); +} if (defined $opt_U) { copy_subst($opt_U, '>', $dir.UNDISPLAY); } @@ -477,6 +480,11 @@ if (!defined $plist->{extrainfo} && $fullpkgpath, $cdrom, $ftp); } +if ($plist->{need_modules}) { + print STDERR "Error: some needed modules were not found\n"; + $errors++; +} + if ($regen_package) { $plist->checksum($base); diff --git a/usr.sbin/pkg_add/pkg_delete b/usr.sbin/pkg_add/pkg_delete index 93a176dfdcc..f60b2a0bab0 100644 --- a/usr.sbin/pkg_add/pkg_delete +++ b/usr.sbin/pkg_add/pkg_delete @@ -1,6 +1,6 @@ #!/usr/bin/perl # ex:ts=8 sw=4: -# $OpenBSD: pkg_delete,v 1.90 2005/08/17 18:44:24 espie Exp $ +# $OpenBSD: pkg_delete,v 1.91 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -24,19 +24,20 @@ use OpenBSD::PackingOld; use OpenBSD::RequiredBy; use OpenBSD::Error; use OpenBSD::ProgressMeter; +use OpenBSD::Interactive; use OpenBSD::Delete; use OpenBSD::PackageInfo; our %forced = (); our $not; -set_usage('pkg_delete [-cInqvx] [-B pkg-destdir] [-F keywords] pkgname [...]'); -our ($opt_v, $opt_D, $opt_d, $opt_n, $opt_q, $opt_p, $opt_c, $opt_L, $opt_B, $opt_I, $opt_x); +set_usage('pkg_delete [-ciInqvx] [-B pkg-destdir] [-F keywords] pkgname [...]'); +our ($opt_v, $opt_D, $opt_d, $opt_n, $opt_q, $opt_p, $opt_c, $opt_L, $opt_B, $opt_I, $opt_i, $opt_x); $opt_v = 0; try { - getopts('vchxDdnf:F:qpS:L:B:I', + getopts('vchixDdnf:F:qpS:L:B:I', {'v' => sub {++$opt_v;}, 'h' => sub { Usage(); }, 'F' => sub { @@ -88,6 +89,7 @@ $state->{extra} = $opt_c; $state->{dont_run_scripts} = $opt_I; $state->{forced} = \%forced; $state->{destdir} = $opt_B; +$state->{interactive} = $opt_i; if ($opt_B eq '') { $state->{destdirname} = ''; } else { @@ -114,31 +116,8 @@ if ($< && !$forced{nonroot}) { my @realnames; my $bad; -for my $pkgname (@ARGV) { - $pkgname =~ s/\.tgz$//; - if (is_installed($pkgname)) { - push(@realnames, installed_name($pkgname)); - } else { - if (OpenBSD::PackageName::is_stem($pkgname)) { - my @l = OpenBSD::PackageName::findstem($pkgname, - installed_packages()); - if (@l == 0) { - print "Can't resolve $pkgname to an installed package name\n"; - $bad = 1 unless $forced{uninstalled}; - } elsif (@l == 1) { - push(@realnames, $l[0]); - } elsif (@l != 0) { - print "Ambiguous: $pkgname could be ", join(' ', @l),"\n"; - if ($forced{ambiguous}) { - print "(removing them all)\n"; - push(@realnames, @l); - } else { - $bad = 1; - } - } - } - } -} +OpenBSD::PackageInfo::solve_installed_names(\@ARGV, \@realnames, + "(removing them all)", $state); my @todo = OpenBSD::RequiredBy->compute_closure(@realnames); @@ -149,12 +128,11 @@ if (@todo > @realnames) { } print "Can't remove ", join(' ', @ARGV), " without also removing:\n", join(' ', keys(%extra_rm)), "\n"; - if ($forced{dependencies}) { - if (keys(%extra_rm) > 1) { - print "(removing them as well)\n"; - } else { - print "(removing it as well)\n"; - } + my $them = keys(%extra_rm) > 1 ? 'them' : 'it'; + if ($forced{dependencies} or + OpenBSD::Interactive::confirm("Do you want to remove $them as well", $state->{interactive}, 0)) { + print "(removing $them as well)\n"; + push(@realnames, keys(%extra_rm)); } else { $bad = 1; } diff --git a/usr.sbin/pkg_add/pkg_delete.1 b/usr.sbin/pkg_add/pkg_delete.1 index 088c2e0afd8..be27e327554 100644 --- a/usr.sbin/pkg_add/pkg_delete.1 +++ b/usr.sbin/pkg_add/pkg_delete.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_delete.1,v 1.17 2005/01/03 01:02:45 espie Exp $ +.\" $OpenBSD: pkg_delete.1,v 1.18 2005/09/04 22:47:56 espie Exp $ .\" .\" FreeBSD install - a package for the installation and maintenance .\" of non-core utilities. @@ -25,7 +25,7 @@ .Nd a utility for deleting previously installed software package distributions .Sh SYNOPSIS .Nm pkg_delete -.Op Fl cInqvx +.Op Fl ciInqvx .Op Fl B Ar pkg-destdir .Op Fl F Ar keywords .Ar pkgname Op Ar ... @@ -81,6 +81,10 @@ external scripts may fail. .It Ar uninstalled proceed even if some package names don't resolve to installed package names. .El +.It Fl i +Switch on interactive mode. +.Nm +may ask questions to the user if faced with difficult decisions. .It Fl I If scripts exist for a given package, do not execute them. .It Fl n diff --git a/usr.sbin/pkg_add/pkg_info b/usr.sbin/pkg_add/pkg_info index 1a6f967a505..e91327ed8ec 100644 --- a/usr.sbin/pkg_add/pkg_info +++ b/usr.sbin/pkg_add/pkg_info @@ -1,6 +1,6 @@ #! /usr/bin/perl # ex:ts=8 sw=4: -# $OpenBSD: pkg_info,v 1.30 2005/08/16 08:59:38 espie Exp $ +# $OpenBSD: pkg_info,v 1.31 2005/09/04 22:47:56 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie <espie@openbsd.org> # @@ -23,6 +23,45 @@ use OpenBSD::PackageName; use OpenBSD::Getopt; use OpenBSD::Error; +package OpenBSD::PackingElement; +sub dump_file +{ +} + +sub hunt_file +{ +} + +sub sum_up +{ + my ($self, $rsize) = @_; + if (defined $self->{size}) { + $$rsize += $self->{size}; + } +} + +package OpenBSD::PackingElement::FileBase; +sub dump_file +{ + my ($item, $opt_K) = @_; + if ($opt_K) { + print '@', $item->keyword(), " "; + } + print $item->fullname(), "\n"; +} + +sub hunt_file +{ + my ($item, $h, $pkgname, $l) = @_; + my $fname = $item->fullname(); + if (defined $h->{$fname}) { + push(@{$h->{$fname}}, $pkgname); + push(@$l, $pkgname); + } +} + +package main; + my $total_size = 0; my $pkgs = 0; @@ -115,14 +154,7 @@ sub filter_files my $plist = OpenBSD::PackingList->fromfile($dir.CONTENTS, \&OpenBSD::PackingList::FilesOnly); - for my $item (@{$plist->{items}}) { - next unless $item->IsFile(); - my $fname = $item->fullname(); - if (defined $search->{"$fname"}) { - push(@{$search->{$fname}}, $pkg); - push(@result, $pkg); - } - } + $plist->visit('hunt_file', $search, $pkg, \@result); }); } return @result; @@ -158,7 +190,7 @@ sub find_by_path our ($opt_c, $opt_D, $opt_d, $opt_f, $opt_I, $opt_i, $opt_k, $opt_K, $opt_L, $opt_m, $opt_p, $opt_q, $opt_R, $opt_r, $opt_s, $opt_v, $opt_h, $opt_l, - $opt_a, $opt_M, $opt_U, $opt_A); + $opt_a, $opt_M, $opt_U, $opt_A, $opt_S); my $terse = 0; my $exit_code = 0; my @sought_files; @@ -220,11 +252,11 @@ sub print_info print "\n"; } my $plist; - if ($opt_f || $opt_L || $opt_s) { + if ($opt_f || $opt_L || $opt_s || $opt_S) { require OpenBSD::PackingOld; require OpenBSD::PackingList; - if ($opt_f || $opt_s) { + if ($opt_f || $opt_s || $opt_S) { $plist = OpenBSD::PackingList->fromfile($dir.CONTENTS); } else { $plist = OpenBSD::PackingList->fromfile($dir.CONTENTS, \&OpenBSD::PackingList::FilesOnly); @@ -233,27 +265,21 @@ sub print_info } if ($opt_L) { print $opt_l, "Files:\n" unless $opt_q; - for my $item (@{$plist->{items}}) { - next unless $item->IsFile(); - if ($opt_K) { - print '@', $item->keyword(), " "; - } - print $item->fullname(), "\n"; - } + $plist->visit('dump_file', $opt_K); print "\n"; } if ($opt_s) { my $size = 0; - for my $item (@{$plist->{items}}) { - next unless $item->IsFile(); - if (defined $item->{size}) { - $size += $item->{size}; - } - } - print "Size: $size\n"; + $plist->visit('sum_up', \$size); + print "Size: " unless $opt_q; + print "$size\n"; $total_size += $size; $pkgs++; } + if ($opt_S) { + print "Signature: " unless $opt_q; + print $plist->signature(), "\n"; + } if ($opt_f) { print $opt_l, "Packing list:\n" unless $opt_q; @@ -264,11 +290,11 @@ sub print_info } } -set_usage('pkg_info [-cDdfIiKkLMpqRrsUv] [-E fname] [-e pkgname] [-l str] pkgname...', 'pkg_info [-Aa flags]'); +set_usage('pkg_info [-cDdfIiKkLMpqRrsSUv] [-E fname] [-e pkgname] [-l str] pkgname...', 'pkg_info [-Aa flags]'); my $locked; try { - getopts('cDdfhIikKLmpqRrsUve:E:Ml:aA', + getopts('cDdfhIikKLmpqRrsSUve:E:Ml:aA', {'e' => sub { my $pat = shift; @@ -306,7 +332,8 @@ if ($opt_D) { } unless ($opt_c || $opt_M || $opt_U || $opt_d || $opt_f || $opt_I || $opt_i || - $opt_k || $opt_L || $opt_m || $opt_p || $opt_R || $opt_r || $opt_s || $terse) { + $opt_k || $opt_L || $opt_m || $opt_p || $opt_R || $opt_r || $opt_s || + $opt_S || $terse) { if (@ARGV == 0) { $opt_I = $opt_a = 1; } else { @@ -316,7 +343,7 @@ unless ($opt_c || $opt_M || $opt_U || $opt_d || $opt_f || $opt_I || $opt_i || if ($opt_v) { $opt_c = $opt_d = $opt_f = $opt_i = $opt_k = $opt_r = $opt_M = - $opt_U = $opt_m = $opt_R = $opt_s = 1; + $opt_U = $opt_m = $opt_R = $opt_s = $opt_S = 1; } if (!defined $opt_l) { diff --git a/usr.sbin/pkg_add/pkg_info.1 b/usr.sbin/pkg_add/pkg_info.1 index 03c9fcb9614..d54393fef6c 100644 --- a/usr.sbin/pkg_add/pkg_info.1 +++ b/usr.sbin/pkg_add/pkg_info.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_info.1,v 1.16 2005/03/13 09:19:02 espie Exp $ +.\" $OpenBSD: pkg_info.1,v 1.17 2005/09/04 22:47:56 espie Exp $ .\" .\" FreeBSD install - a package for the installation and maintenance .\" of non-core utilities. @@ -26,7 +26,7 @@ .Sh SYNOPSIS .Nm pkg_info .Bk -words -.Op Fl cDdfIiKkLMpqRrsUv +.Op Fl cDdfIiKkLMpqRrsSUv .Op Fl E Ar filename .Op Fl e Ar pkg-name .Op Fl l Ar str @@ -152,6 +152,10 @@ Show which packages require a given package. Show the requirements script (if any) for each package. .It Fl s Show an estimate of the total size of each package. +.It Fl S +Show the package signature for each package. +This signature is a unique tag showing the package name, and the version number +of every dependency and shared library necessary to build this package. .It Fl U Show the deinstall-message file (if any) for each package. .It Fl v diff --git a/usr.sbin/pkg_add/pod/OpenBSD::PackingList.pod b/usr.sbin/pkg_add/pod/OpenBSD::PackingList.pod index 24cb9f0a561..14b1a50218c 100644 --- a/usr.sbin/pkg_add/pod/OpenBSD::PackingList.pod +++ b/usr.sbin/pkg_add/pod/OpenBSD::PackingList.pod @@ -1,4 +1,4 @@ -$OpenBSD: OpenBSD::PackingList.pod,v 1.2 2005/03/02 20:10:25 espie Exp $ +$OpenBSD: OpenBSD::PackingList.pod,v 1.3 2005/09/04 22:47:56 espie Exp $ =head1 NAME @@ -33,6 +33,10 @@ OpenBSD::PackingList - C<pkg_add(1)> packing-list manipulations # processing packing-lists $p4->visit('method', @args); + # signatures + if ($p3->signature() eq $p4->signature()) { + } + =head1 DESCRIPTION C<OpenBSD::PackingList> is the only supported interface for access to @@ -78,6 +82,10 @@ read only dependency information. read only the extra information field. +=item UpdateInfoOnly + +read only what is needed to decide to update a package. + =back A complete packing-list C<$plist> may be written to disk using the @@ -109,3 +117,7 @@ to the packing-list (note that C<add_object> only makes sense for subclasses of C<OpenBSD::PackingElement::Object>). See L<OpenBSD::PackingElement> for more details. +C<$plist-E<gt>pkgname()> retrieves a packing-list name (mandatory). +C<$plist-E<gt>signature()> retrieves a packing-list full signature, composed +of the package name and dependency information. + |