Skip to content

Commit

Permalink
Item8640: more refactoring - moved dependency processing into Package.pm
Browse files Browse the repository at this point in the history
Note - doesn't resolve any dependencies yet - that's next.



git-svn-id: http://svn.foswiki.org/trunk@6877 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
GeorgeClark authored and GeorgeClark committed Mar 24, 2010
1 parent ebc63ad commit 79c73a3
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 136 deletions.
53 changes: 40 additions & 13 deletions UnitTestContrib/test/unit/ConfigureTests.pm
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,9 @@ sub test_makeBackup {
my $root = File::Spec->catfile( @root, 'x' );
chop $root;

my $result = '';
my $err = '';

my $tempdir = $this->{tempdir} . '/test_util_installFiles';
rmtree($tempdir); # Clean up old files if left behind
mkpath($tempdir);
Expand All @@ -803,13 +806,11 @@ sub test_makeBackup {
use Foswiki::Configure::Package;
my $pkg = new Foswiki::Configure::Package ($root, "$extension", 'Plugin', $this->{session} );

my $err = $pkg->loadInstaller($tempdir);
($result, $err) = $pkg->loadInstaller($tempdir);
$this->assert_str_equals( '', $err );

my $result = '';
($result, $err) = $pkg->install($tempdir);

print "Running Backup ";
my $msg = $pkg->createBackup();
$this->assert_str_equals( 'Backup saved into', substr($msg, 0,17) );
#print "$msg \n";
Expand All @@ -836,13 +837,18 @@ sub postuninstall {
sub preinstall {
# Remove Templates.pm file if it exists. Dead code.
return "Pre-install entered";
return "Pre-install entered";
}
sub postinstall {
# # No POSTINSTALL script;
my $this = shift; # Get the object instance passed to the routine
if ($this) { # Verify that you are running in the new environment
my $mapped = Foswiki::Configure::Util::mapTarget( $this->{_rootdir},
'tools/obsolete.pl');
my $count = unlink $mapped if ( -e $mapped );
return "Removed $mapped \n " if ($count);
}
}
Foswiki::Extender::install( $PACKAGES_URL, 'CommentPlugin', 'CommentPlugin', @DATA );
Expand All @@ -868,9 +874,21 @@ pub/Sandbox/TestTopic43/file.att,0664,1a9a1da563535b2dad241d8571acd170,
pub/Sandbox/TestTopic43/file2.att,0664,ede33d5e092a0cb2fa00d9146eed5f9a,
<<<< DEPENDENCIES >>>>
SOAP::Lite,>=0.68,1,CPAN,Required. install from CPAN
CGI::Blah,>=10.1,0,cpan,Test lower case cpan
ImageMagick,,1,,
.\@#$%}{SOAP::Lite,>=0.68,1,CPAN,Required. install from CPAN
Time::ParseDate,>=2003.0211,1,cpan,Required. Available from the CPAN:Time::ParseDate archive.
Foswiki::Contrib::JSCalendarContrib,>=0.961,1,perl,Optional, used if installed. Used to display a neat calendar popup when editing actions. Available from the Foswiki:Extensions/JSCalendarContrib repository.
Foswiki::Contrib::BehaviourContrib,>=0,1,perl,Javascript module
Foswiki::Plugins::WysiwygPlugin,>=4315,1,perl,Translator module
Foswiki::Plugins::JQueryPlugin,>=0.5,1,perl,Required if using jquery twisties.
Foswiki::Plugins::DojoToolkitContrib,>=0,1,perl,Required if using dojo twisties.
Foswiki::Contribs::FamFamFamContrib,>=0,1,perl,Icons
FCGI, >0.67,1,cpan,FastCGI perl library
File::Spec, >0,1,cpan,This module is shipped as part of standard perl
Cwd, >0,1,cpan,This module is shipped as part of standard perl
POSIX, >0,1,cpan,This module is shipped as part of standard perl
Getopt::Long, >2.37,1,cpan,Extended processing of command line options
Pod::Usage, >1.35,1,cpan,print a usage message from embedded pod documentation
DONE
close ($fh);
Expand Down Expand Up @@ -905,11 +923,16 @@ sub test_Package {
my $root = $this->{rootdir};
use Foswiki::Configure::Package;
my $result = '';
my $err = '';

my $tempdir = $this->{tempdir} . '/test_util_installFiles';
rmtree($tempdir); # Clean up old files if left behind
mkpath($tempdir);

_makefile ( "$root/tools", "obsolete.pl", <<'DONE');
Test file data
DONE

my $extension = "MyPlugin";
_makePackage ($tempdir, $extension);

Expand All @@ -918,7 +941,7 @@ sub test_Package {
#
#
my $pkg = new Foswiki::Configure::Package ($root, 'MyPlugin', 'Plugin', $this->{session});
my $err = $pkg->loadInstaller($tempdir);
($result, $err) = $pkg->loadInstaller($tempdir);
$pkg->uninstall();
$pkg->finish();
undef $pkg;
Expand All @@ -930,7 +953,7 @@ sub test_Package {

_makePackage ($tempdir, $extension);
$pkg = new Foswiki::Configure::Package ($root, 'MyPlugin', 'Plugin', $this->{session});
$err = $pkg->loadInstaller($tempdir);
($result, $err) = $pkg->loadInstaller($tempdir);
($result, $err) = $pkg->install($tempdir);
$this->assert_str_equals( '', $err );

Expand Down Expand Up @@ -959,7 +982,7 @@ Installed: MyPlugin_installer
_makePackage ($tempdir, $extension);

my $pkg2 = new Foswiki::Configure::Package ($root, 'MyPlugin', 'Plugin', $this->{session});
$err = $pkg2->loadInstaller($tempdir);
($result, $err) = $pkg2->loadInstaller($tempdir);

$result = '';
($result, $err) = $pkg2->install($tempdir);
Expand All @@ -980,7 +1003,11 @@ Installed: MyPlugin_installer
$this->assert_str_equals( 'Pre-uninstall entered', $pkg2->preuninstall());
$this->assert_str_equals( 'Pre-install entered', $pkg2->preinstall());
$this->assert_null( $pkg2->postuninstall());
$this->assert_null( $pkg2->postinstall());
$this->assert_str_equals( 'Removed ', substr( $pkg2->postinstall(), 0, 8));

my ($installed, $missing, @install, @cpan) = $pkg2->checkDependencies();
print "===== INSTALLED =======\n$installed\n";
print "====== MISSING ========\n$missing\n";

#
# Now uninistall the package
Expand Down
115 changes: 90 additions & 25 deletions core/lib/Foswiki/Configure/Package.pm
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ package Foswiki::Configure::Package;
use strict;
use Error qw(:try);
use Assert;
use Foswiki::Configure::Dependency;

our $VERSION = '$Rev: 6590 $';

my $depwarn = ''; # Pass back warnings from untaint validation routine

############# GENERIC METHODS #############

=begin TML
Expand All @@ -61,6 +64,8 @@ Required for installer methods - used for checkin operations.

sub new {
my ( $class, $root, $pkgname, $type, $session ) = @_;
my @deps;


my $this = bless(
{
Expand All @@ -70,8 +75,8 @@ sub new {
_session => $session,
# Hash mapping the topics, attachment and other files supplied by this package
_manifest => undef,
# Hash mapping the dependencies required by this package
_dependency => undef,
# Array of dependencies required by this package
_dependency => \@deps,
_routines => undef,
},
$class
Expand Down Expand Up @@ -478,6 +483,7 @@ sub loadInstaller {

my $pkgstore = "$Foswiki::cfg{WorkingDir}/configure/pkgdata";
my $extension = $this->{_pkgname};
my $warn = '';
local $/ = "\n";

my $file;
Expand All @@ -490,12 +496,12 @@ sub loadInstaller {
if (-e "$pkgstore/${extension}_installer") {
$file = "$pkgstore/${extension}_installer";
} else {
return "ERROR - Extension $extension package not found ";
return ('', "ERROR - Extension $extension package not found ");
}
}
}

open(my $fh, '<', $file) || return "Extract manfiest failed: $file - $!";
open(my $fh, '<', $file) || return ('', "Extract manfiest failed: $file - $!");

my $found = '';
while (<$fh>) {
Expand Down Expand Up @@ -534,7 +540,7 @@ sub loadInstaller {
next;
}
chomp $_;
_parseDependency ($this, $_ ) if ($_);
$warn .= _parseDependency ($this, $_ ) if ($_);
next;
}

Expand All @@ -553,8 +559,7 @@ sub loadInstaller {
eval $this->{_routines};
}


return '';
return ($warn, '');
}

=begin TML
Expand Down Expand Up @@ -614,25 +619,62 @@ Parse the manifest line into the manifest hash.

sub _parseDependency {
my $this = shift;
my $deps = $this->{_dependency};

require Foswiki::Sandbox;

my $warn = undef;
my $warn = '';
my ( $module, $condition, $trigger, $type, $desc ) =
split( ',', $_[0], 5 );

return unless ($module);

if ( $type =~ m/cpan|perl/i ) {
$depwarn = '';
$module = Foswiki::Sandbox::untaint( $module, \&_validatePerlModule );
$warn .= $depwarn;
}

$this->{_dependency}->{$module}->{condition} = $condition;
$this->{_dependency}->{$module}->{trigger} = $trigger;
$this->{_dependency}->{$module}->{type} = $type ;
$this->{_dependency}->{$module}->{desc} = $desc ;
$this->{_dependency}->{$module}->{warning} = $warn ;

if ( $trigger eq '1' ) {

# ONLYIF is rare and dangerous
push(
@$deps,
new Foswiki::Configure::Dependency(
module => $module,
type => $type,
version => $condition || 0, # version condition
trigger => 1, # ONLYIF condition
description => $desc
)
);
}
else {

# There is a ONLYIF condition, warn user
$warn .= "The script uses an ONLYIF condition for module $module"
. ' which is potentially insecure: "'
. $trigger . '"' . "\n";
if ( $trigger =~ /^[a-zA-Z:\s<>0-9.()]*$/ ) {

# It looks more or less safe
push(
@$deps,
new Foswiki::Configure::Dependency(
module => $module,
type => $type,
version => $condition, # version condition
trigger => $1, # ONLYIF condition
description => $desc
)
);
}
else {
$warn .= 'This ' . $trigger . ' condition does not look safe and is being disabled.' . "\n";
$warn .= "This dependency on $module should be manually resolved \n";
}
}
return $warn;
}

# This is used to ensure the perl module dependencies
Expand All @@ -643,26 +685,49 @@ sub _validatePerlModule {
# Remove all non alpha-numeric caracters and :
# Do not use \w as this is localized, and might be tainted
my $replacements = $module =~ s/[^a-zA-Z:_0-9]//g;
#my $warn = 'validatePerlModule removed '
# . $replacements
# . ' characters, leading to '
# . $module . "\n"
# if $replacements;
#print "$module - $replacements - $warn \n";
$depwarn = 'validatePerlModule removed '
. $replacements
. ' characters, leading to '
. $module . "\n"
if $replacements;
return $module;
}


=begin TML
---++ ObjectMethod validateExits ()
Eval any exits loaded in the _installler module. Return any errors
from the "eval"
---++ ObjectMethod checkDependencies ()
Checks the dependencies listed for this module. Returns two "reports";
Installed dependencies and Missing dependencies. It also returns a
list of Foswiki package names that might be installed.
=cut

sub validateExits {
sub checkDependencies {
my $this = shift;
my $installed = '';
my $missing = '';
my @install;
my @cpan;

foreach my $dep ( @{$this->{_dependency}} ) {
my ($ok, $msg) = $dep->check() ;
if ($ok) {
$installed .= "$msg\n";
} else {
$missing .= "$msg\n";
if ( $dep->{module} =~ m/^(Foswiki|TWiki)::(Contrib|Plugins)::(\w*)/ ) {
my $type = $1;
my $pack = $2;
my $packname = $3;
$packname .= $pack if ( $pack eq 'Contrib' && $packname !~ /Contrib$/ );
$dep->{name} = $packname;
push( @install, $packname );
}
push ( @cpan, $dep->{module} ) if ( $dep->{type} eq 'cpan' );
}
}
return ($installed, $missing, @install, @cpan);

}

Expand Down
24 changes: 21 additions & 3 deletions core/lib/Foswiki/Configure/UIs/EXTEND.pm
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,22 @@ MESS
require Foswiki::Configure::Package;

my $pkg = new Foswiki::Configure::Package ($this->{root}, $extension, '', $session);
my $err = $pkg->loadInstaller($dir); # Recover the manifest from the _installer file
my ($rslt, $err) = $pkg->loadInstaller($dir); # Recover the manifest from the _installer file

if ($rslt) {
$feedback .= "Warnings loading installer...<br />\n";
$feedback .= "<pre>$rslt </pre>";
}

my ($installed, $missing, @install, @cpan) = $pkg->checkDependencies();
$rslt .= "===== INSTALLED =======\n$installed\n" if ($installed);
$rslt .= "====== MISSING ========\n$missing\n" if ($missing);

if ($rslt) {
$feedback .= "Dependency Report..<br />\n";
$feedback .= "<pre>$rslt </pre>";
}

my $rslt;
($rslt, $err) = $pkg->createBackup($dir) unless ($err); # Create a backup of the previous install if any

unless ($err) {
Expand Down Expand Up @@ -285,7 +298,12 @@ sub _uninstall {

require Foswiki::Configure::Package;
my $pkg = new Foswiki::Configure::Package ($this->{root}, $extension, '');
my $err = $pkg->loadInstaller();
my ($rslt, $err) = $pkg->loadInstaller();

if ($rslt) {
$feedback .= "Warnings loading installer...<br />\n";
$feedback .= "<pre>$rslt </pre>";
}

unless ($err) {
my $rslt = $pkg->createBackup();
Expand Down
Loading

0 comments on commit 79c73a3

Please sign in to comment.