### ### Copyright 2000-2007 University of Illinois Board of Trustees ### All rights reserved. ### ### PSGConf::Action::PackageManager::Encap - Encap pkg action type for psgconf ### ### ### Campus Information Technologies and Educational Services ### University of Illinois at Urbana-Champaign ### package PSGConf::Action::PackageManager::Encap; use strict; use PSGConf::Action::PackageManager::FTPArchive; use PSGConf::Data::String; use PSGConf::Data::Integer; use PSGConf::Util; use File::Path; use File::Basename; use Cwd; our @ISA = qw(PSGConf::Action::PackageManager::FTPArchive); ############################################################################### ### configuration constructor ############################################################################### sub conf { my ($class, $psgconf) = @_; my ($p) = '-share|-' . $psgconf->data_obj('platform')->get(); ### FIXME: An ugly hack to covert back the platform name to ### the ambigous sparc-solarisX tag $p =~ s/-sun4[^-]-/-sparc-/ if ( $p =~ /-sun4/ ); my ($a) = join ('|', @{$psgconf->{platform_suffixes}}); PSGConf::Action::PackageManager::FTPArchive->conf($psgconf); $psgconf->register_data( pkg_encap_dir => PSGConf::Data::String->new( value => "/usr/local/encap" ), pkg_epkg_umask => PSGConf::Data::Integer->new( value => 022 ), pkg_epkg_cmd => PSGConf::Data::String->new( value => "/usr/local/bin/epkg" ), pkg_tar_cmd => PSGConf::Data::String->new( value => "/usr/local/bin/tar" ), pkg_gzip_cmd => PSGConf::Data::String->new( value => "/usr/local/bin/gzip" ), pkg_regex => PSGConf::Data::String->new( value => "(\-encap($p(\-$a)?))?\.tar\.(Z|gz)" ), ); } ############################################################################### ### pkg_get_installed() method ############################################################################### sub pkg_get_installed { my ($self, $psgconf) = @_; my (%pkg_installed_list); my (@pkgname, $dir, $pkg, $ver); local *DIR; if (!opendir(DIR, $psgconf->data_obj('pkg_encap_dir')->get())) { warn "\t!!! cannot open Encap source directory (" . $psgconf->data_obj('pkg_encap_dir')->get() . "): $!\n"; return undef; } map { my ($pkg) = $self->Parse($_); my ($ver) = $_; $ver =~ s/^\Q${pkg}\E$self->{seperator}->[0]//; push (@{$pkg_installed_list{$pkg}}, $ver); } grep { -d $psgconf->data_obj('pkg_encap_dir')->get() . '/' . $_ && !/^\.\.?$/; } readdir(DIR); closedir(DIR); return \%pkg_installed_list; } ############################################################################### ### pkg_get_latest_version() method ############################################################################### sub pkg_get_latest_version { my ($self, $psgconf, $pkg) = @_; my ($regex) = "(\Q${pkg}\E\-[^-]+)" . $psgconf->data_obj('pkg_regex')->get(); my ($path, $platform); ### ### Deal with the %p in the path. ### $platform = $psgconf->data_obj('platform')->get(); ### FIXME: An ugly hack to covert back the platform name to ### the ambigous sparc-solarisX tag $platform =~ s/sun4[^-]-/sparc-/ if ( $platform =~ /^sun4/ ); $path = $psgconf->data_obj('env_vars')->find('ENCAP_UPDATE_PATH'); $path =~ s/%p/$platform/g if ( $path =~ /%p/ ); return $self->get_latest_version ( $psgconf, $pkg, $path, qr{$regex} ); } ############################################################################### ### pkg_get_dependencies() method ############################################################################### sub pkg_get_dependencies { my ($self, $psgconf, $pkg) = @_; my (@pkgs, @files, $file, $ftp, $path, $platform); my ($regex) = "\Q${pkg}\E" . $psgconf->data_obj('pkg_regex')->get(); # First see if the package is already locally installed if ( -d $psgconf->data_obj('pkg_encap_dir')->get() . '/' . $pkg ) { @pkgs = &_extract_deps($psgconf, $psgconf->data_obj('pkg_encap_dir')->get(), $pkg); } else { ### ### Deal with the %p in the path. ### $path = $psgconf->data_obj('env_vars')->find('ENCAP_UPDATE_PATH'); ### FIXME: An ugly hack to covert back the platform name to ### the ambigous sparc-solarisX tag $platform = $psgconf->data_obj('platform')->get(); $platform =~ s/sun4[^-]-/sparc-/ if ( $platform =~ /^sun4/ ); $path =~ s/%p/$platform/g if ( $path =~ /%p/ ); # Else find the package on the server # Need to escape the + and . in the package name, hence \Q and \E @files = $self->list_files_from_url($psgconf, $path, qr{$regex}); # we should have only found one entry if ( scalar @files == 1 ) { # See if we have the encap tarball 'cached'. $file = &basename ($files[0]); $file = $self->get_file_from_url($psgconf, $files[0]) if ( ! -f "$psgconf->{tmpdir}/$file" ); if ( -f "$psgconf->{tmpdir}/$file" ) { &_unpack_encap ($psgconf, $pkg, $file); @pkgs = &_extract_deps($psgconf, $psgconf->{tmpdir}, $pkg); # Remove the encapinfo and directory. my ($dir) = $psgconf->{tmpdir} . '/' . $pkg; if ( -d $dir ) { warn "\t!!! unlink('$dir'): $!\n" if ( $psgconf->{rm_tmpfiles} && !rmtree ($dir) ); } } } elsif ( ! scalar @files ) { warn "\tCould not find URL for ($pkg)\n"; } else { warn "\tFound too many URLs for ($pkg)\n"; } } return @pkgs; } sub _unpack_encap { my ($psgconf, $pkg, $file) = @_; my ($cmd, $dir, $err); $dir = getcwd; chdir($psgconf->{tmpdir}); $cmd = $psgconf->data_obj('pkg_tar_cmd')->get() . ' --use-compress-program=' . $psgconf->data_obj('pkg_gzip_cmd')->get() . ' -xf '; $cmd .= $psgconf->{tmpdir} . '/' . $file; $cmd .= ' ' . $pkg . '/encapinfo'; $err=&PSGConf::Util::RunCommand($cmd); warn "\tCould not unpack encapinfo file\n" if ( $err ); chdir($dir); } sub _extract_deps { my ($psgconf, $dir, $pkg) = @_; my (@deps); local *FP; if (open(FP, "<$dir/$pkg/encapinfo")) { grep (/prereq pkgspec [^\s]+ ([^\s]*)$/o && (push @deps, $1), ); close FP; } else { warn "\t!!! encapinfo file for ($pkg) could not be found\n"; } return @deps; } ############################################################################### ### pkg_install() method ############################################################################### sub pkg_install { my ($self, $psgconf, $pkg) = @_; my ($err, $umask, $cmd, $tarball); $tarball = glob ($psgconf->{tmpdir} . '/' . "\Q${pkg}\E" . $psgconf->data_obj('pkg_regex')->get()); $cmd = 'ENCAP_UPDATE_PATH="'; $cmd .= $psgconf->data_obj('env_vars')->find('ENCAP_UPDATE_PATH'); $cmd .= '" ' . $psgconf->data_obj('pkg_epkg_cmd')->get() . ' -S'; ### If the package is already on disk, ### then just make it the linked in version. $cmd .= 'u' if ( ! -d $psgconf->data_obj('pkg_encap_dir')->get() . '/' . $pkg && ! -f $tarball ); $cmd .= 'q' if (! $psgconf->{verbose}); map { $cmd .= " -A $_"; } @{$psgconf->{platform_suffixes}}; $cmd .= ' ' . ((-f $tarball) ? $tarball: $pkg); ### Force the umask to be something that everyone will be ### able to read and execute the files that are being installed ### and not rely on the default enviroment to set. $umask = umask $psgconf->data_obj('pkg_epkg_umask')->get(); $err=&PSGConf::Util::RunCommand($cmd); ### Be nice and reset the umask back to what the Administrator had umask $umask; print "\n" if ($psgconf->{verbose}); return $err; } ############################################################################### ### pkg_remove() method ############################################################################### sub pkg_remove { my ($self, $psgconf, $pkg, $force) = @_; my ($err, $cmd); $cmd = $psgconf->data_obj('pkg_epkg_cmd')->get() . ' -rS'; $cmd .= 'q' if (! $psgconf->{verbose}); $cmd .= 'f' if ($force); $cmd .= " $pkg"; if (! ($err=&PSGConf::Util::RunCommand($cmd))) { ### Now clean up the removed encap package rmtree ($psgconf->data_obj('pkg_encap_dir')->get() . '/' . $pkg); } print "\n" if ($psgconf->{verbose}); return $err; } ############################################################################### ### documentation ############################################################################### 1; __END__ =head1 NAME PSGConf::Action::PackageManager::Encap - install Encap packages =head1 SYNOPSIS use PSGConf::Action::PackageManager::Encap; $psgconf->register_actions( PSGConf::Action::PackageManager::Encap->new( 'quiet' => 1 ), ... ); =head1 DESCRIPTION The B module provides a B action class for updating Encap packages. The B class is derived from the B class, but it defines/overrides the following methods: =over 4 =item I A method that will assign values to the I, which will be all the packages currently installed. The I is a reference to a hash of arrays. The array is sorted to have versions in ascending order. Called from the B method. =item I A method that will return a B that contains the latest version of $pkg from the package repository. Called from the B method. It uses the environment variable B to determine where to look for these updated packages. =item I A method that will return a B that contains all the packages that $pkg will depend upon, regardless if they have been installed or not. This is for the package on the package repository and $pkg will have the version in it as well. Called from the B method. =item I A method that will install a $pkg on the system. Returns 0 for a successfull install, non-zero for a failure. Called from B method. It uses the environment variable B to determine where to get these packages from. =item I A method that will remove $pkg from the system, and may have to force the removal, depending on the value of $force, which will be a B. Returns 0 for a successfull install, non-zero for a failure. Called from B method. =back The constructor also registers the following data objects: =over 4 =item I A B object that determines where Encap packages are installed. The default is I. =item I A B object that determines the default umask for epkg to use. The default is I<022>. =item I A B object that determines where epkg is located. The default is I. =item I A B object that determines where tar is located. Used to extract dependencies from the encap tarball. The default is I. =item I A B object that determines where gzip is located. Used to extract dependencies from the encap tarball. The default is I. =item I A B object that determines what the regex is to match against the FTPArchive listing. The default is I<(\-encap($p(\-$a)?))?\.tar\.(Z|gz)>. =back =head1 SEE ALSO Cepkg(1)E> L L L L L L L L L L =cut