Implemented optional package removal step list.
This commit is contained in:
parent
17cbf95a36
commit
91c7116c09
199
pkgtool.pm
199
pkgtool.pm
|
@ -1658,18 +1658,10 @@ sub run_exe ($$$$$$$;$)
|
||||||
return (undef, undef);
|
return (undef, undef);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub remove_package_fallback ($$$$$$$$$$$)
|
sub remove_package_uninstall ($$$$$$$$$)
|
||||||
{
|
{
|
||||||
my ($channel, $vars, $paramlist, $inst, $condition, $dispname, $ver, $printver, $db, $counters, $removecontext) = @_;
|
my ($uninst, $channel, $vars, $paramlist, $dispname, $printver, $db, $counters, $removecontext) = @_;
|
||||||
|
|
||||||
print_log($channel, DEBUG1, 'Removing package %s%s%s', $dispname, $printver,
|
|
||||||
defined $condition ? ' with true condition' : '');
|
|
||||||
|
|
||||||
my $uninst = $$inst{Uninstall};
|
|
||||||
my $quninst = $$inst{QUninstall};
|
|
||||||
return sprintf('Cannot remove package %s%s, no remove steps defined and no UninstallString registry entry found',
|
|
||||||
$dispname, $ver) unless defined $uninst || defined $quninst;
|
|
||||||
$uninst = $quninst if defined $quninst;
|
|
||||||
$uninst =~ s/(msiexec[^ ]* )\/i/$1\/X/io;
|
$uninst =~ s/(msiexec[^ ]* )\/i/$1\/X/io;
|
||||||
$uninst =~ s/(msiexec[^ ]* )/$1\/qb \/norestart \/passive /io;
|
$uninst =~ s/(msiexec[^ ]* )/$1\/qb \/norestart \/passive /io;
|
||||||
print_log($channel, DEBUG2, 'Uninstall command: %s', $uninst);
|
print_log($channel, DEBUG2, 'Uninstall command: %s', $uninst);
|
||||||
|
@ -1705,9 +1697,168 @@ sub remove_package_fallback ($$$$$$$$$$$)
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub remove_packages ($$$$$$$$$$)
|
sub remove_package_fallback ($$$$$$$$$$$)
|
||||||
{
|
{
|
||||||
my ($channel, $vars, $def, $paramlist, $list, $condition, $db, $basedir, $config, $counters) = @_;
|
my ($channel, $vars, $paramlist, $inst, $condition, $dispname, $ver, $printver, $db, $counters, $removecontext) = @_;
|
||||||
|
|
||||||
|
print_log($channel, DEBUG1, 'Removing package %s%s%s', $dispname, $printver,
|
||||||
|
defined $condition ? ' with true condition' : '');
|
||||||
|
|
||||||
|
my $uninst = $$vars{uninstallstring};
|
||||||
|
return sprintf('Cannot remove package %s%s, no remove steps defined and no UninstallString registry entry found',
|
||||||
|
$dispname, $ver) unless defined $uninst;
|
||||||
|
return remove_package_uninstall($uninst, $channel, $vars, $paramlist, $dispname, $printver, $db, $counters, $removecontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub remove_package_steps ($$$$$$$$$$$$$$$$)
|
||||||
|
{
|
||||||
|
my ($channel, $removesteps, $paramlist, $inst, $condition, $ver, $printver,
|
||||||
|
$db, $def, $name, $dispname, $basedir, $genericmsiparams,
|
||||||
|
$config, $counters, $removecontext) = @_;
|
||||||
|
|
||||||
|
my $version = $ver;
|
||||||
|
$version = '' unless defined $version;
|
||||||
|
print_log($channel, INFO, 'Removing package %s version %s', $dispname, $version);
|
||||||
|
|
||||||
|
my $uninst = $$inst{Uninstall};
|
||||||
|
my $quninst = $$inst{QUninstall};
|
||||||
|
$quninst = $uninst unless defined $quninst;
|
||||||
|
|
||||||
|
my $vars = get_default_vars($config);
|
||||||
|
set_datetime_vars($vars);
|
||||||
|
$$vars{pkgname} = $name;
|
||||||
|
$$vars{pkgdispname} = $dispname;
|
||||||
|
$$vars{pkgversion} = $version;
|
||||||
|
$$vars{uninstallstring} = $quninst if defined $quninst;
|
||||||
|
my $appdir = substitute_variables($vars, $$def{'source-directory'}, 1, $basedir, $channel);
|
||||||
|
$$vars{appdir} = $appdir;
|
||||||
|
|
||||||
|
my $realremove = 0;
|
||||||
|
my $i = 0;
|
||||||
|
foreach my $step (@$removesteps) {
|
||||||
|
my $type = $$step{type};
|
||||||
|
$i++;
|
||||||
|
print_log($channel, DEBUG2, 'Removal step #%d type %s', $i, $type);
|
||||||
|
|
||||||
|
my $error;
|
||||||
|
my $exitcode;
|
||||||
|
my $ignore = $$step{'ignore-failure'};
|
||||||
|
$ignore = 0 unless defined $ignore;
|
||||||
|
|
||||||
|
my $condition = $$step{condition};
|
||||||
|
if (defined $condition && $type ne 'remove-pkg') {
|
||||||
|
print_log($channel, DEBUG2, 'Evaluating condition expression %s in step #%d',
|
||||||
|
$condition, $i);
|
||||||
|
($condition, $error) = check_condition($channel, $vars, $condition);
|
||||||
|
if (! defined $condition) {
|
||||||
|
print_log($channel, INFO, 'Ignoring step #%d: %s', $i, $error);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
if (! $condition) {
|
||||||
|
print_log($channel, INFO, 'Ignoring step #%d with false condition', $i);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
print_log($channel, INFO, 'Executing step #%d with true condition', $i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type eq 'remove-pkg') {
|
||||||
|
my $paramlist = $$step{parameters};
|
||||||
|
$paramlist = [] unless defined $paramlist;
|
||||||
|
$error = remove_package_fallback($channel, $vars, $paramlist, $inst, $condition, $dispname,
|
||||||
|
$ver, $printver, $db, $counters, $removecontext);
|
||||||
|
delete $$vars{'installed-version'};
|
||||||
|
$realremove = 1 unless defined $error;
|
||||||
|
}
|
||||||
|
elsif ($type eq 'run') {
|
||||||
|
my $bg = defined $$step{background} && $$step{background};
|
||||||
|
my $chdir = defined $$step{chdir} ?
|
||||||
|
substitute_variables($vars, $$step{chdir}, 1, $appdir, $channel) : undef;
|
||||||
|
my $sourcefile = substitute_variables($vars, $$step{'source-file'}, 1, $appdir, $channel);
|
||||||
|
my $paramlist = $$step{parameters};
|
||||||
|
$paramlist = [] unless defined $paramlist;
|
||||||
|
($error, $exitcode) = run_exe($channel, $db, $vars, $chdir, $sourcefile, $paramlist, $bg);
|
||||||
|
}
|
||||||
|
elsif ($type eq 'msi') {
|
||||||
|
my $sourcefile = substitute_variables($vars, $$step{'source-file'}, 1, $appdir, $channel);
|
||||||
|
my $exename = substitute_variables($vars, '%systemroot%/System32/msiexec.exe', 1, undef, $channel);
|
||||||
|
my $paramlist = $$step{parameters};
|
||||||
|
$paramlist = [] unless defined $paramlist;
|
||||||
|
unshift @$paramlist, '/x', $sourcefile;
|
||||||
|
if (-f $sourcefile) {
|
||||||
|
push @$paramlist, @$genericmsiparams if defined $genericmsiparams;
|
||||||
|
($error, $exitcode) = run_exe($channel, $db, $vars, undef, $exename, $paramlist, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$error = sprintf('Cannot find MSI file %s: %s', $sourcefile, $!);
|
||||||
|
$exitcode = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($type eq 'reg') {
|
||||||
|
my $sourcefile = substitute_variables($vars, $$step{'source-file'}, 1, $appdir, $channel);
|
||||||
|
my $exename = substitute_variables($vars, '%systemroot%/System32/reg.exe', 1, undef, $channel);
|
||||||
|
my $paramlist = ['import', $sourcefile];
|
||||||
|
if (-f $sourcefile) {
|
||||||
|
($error, $exitcode) = run_exe($channel, $db, $vars, undef, $exename, $paramlist, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$error = sprintf('Cannot find REG file %s: %s', $sourcefile, $!);
|
||||||
|
$exitcode = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($type eq 'file') {
|
||||||
|
my $sourcefile = substitute_variables($vars, $$step{'source-file'}, 1, $appdir, $channel);
|
||||||
|
my $targetfile = substitute_variables($vars, $$step{'target-file'}, 1);
|
||||||
|
$error = copy_file($channel, $sourcefile, $targetfile);
|
||||||
|
}
|
||||||
|
elsif ($type eq 'delete-file') {
|
||||||
|
my $recurse = $$step{recurse};
|
||||||
|
$recurse = defined $recurse && $recurse;
|
||||||
|
my $targetfile = substitute_variables($vars, $$step{'target-file'}, 1);
|
||||||
|
$error = delete_dir_file(0, $channel, $recurse, $targetfile);
|
||||||
|
}
|
||||||
|
elsif ($type eq 'delete-dir') {
|
||||||
|
my $recurse = $$step{recurse};
|
||||||
|
$recurse = defined $recurse && $recurse;
|
||||||
|
my $targetfile = substitute_variables($vars, $$step{'target-file'}, 1);
|
||||||
|
$error = delete_dir_file(1, $channel, $recurse, $targetfile);
|
||||||
|
}
|
||||||
|
elsif ($type eq 'setvar') {
|
||||||
|
my $varname = $$step{variable};
|
||||||
|
my $expression = $$step{expression};
|
||||||
|
my $filename = $$step{filename};
|
||||||
|
if (defined $expression) {
|
||||||
|
print_log($channel, DEBUG2, 'Evaluating variable %s expression %s in step #%d',
|
||||||
|
$varname, $expression, $i);
|
||||||
|
$error = set_install_var($channel, $vars, $varname, $expression);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_log($channel, DEBUG2, 'Evaluating variable %s filename %s in step #%d',
|
||||||
|
$varname, $filename, $i);
|
||||||
|
my $file = substitute_variables($vars, $filename, 1, $appdir, $channel);
|
||||||
|
$$vars{$varname} = $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defined $error) {
|
||||||
|
$ignore = 1 if defined $exitcode && ($exitcode == 194 || $exitcode == 63);
|
||||||
|
if (! $ignore) {
|
||||||
|
return sprintf('Removal failed in step #%d: %s', $i, $error);
|
||||||
|
}
|
||||||
|
print_log($channel, INFO, 'Ignoring failed step #%d: %s', $i, $error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_log($channel, INFO, 'Finished removing package %s version %s', $dispname, $version);
|
||||||
|
if (! $realremove) {
|
||||||
|
push @{$$counters{RemovedList}}, $dispname;
|
||||||
|
$$counters{RemovedCount}++;
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub remove_packages ($$$$$$$$$$$$)
|
||||||
|
{
|
||||||
|
my ($channel, $vars, $def, $name, $paramlist, $list, $condition, $db,
|
||||||
|
$basedir, $genericmsiparams, $config, $counters) = @_;
|
||||||
|
|
||||||
my $removecontext = {};
|
my $removecontext = {};
|
||||||
$list = sort_packages_to_remove($list);
|
$list = sort_packages_to_remove($list);
|
||||||
|
@ -1732,8 +1883,16 @@ sub remove_packages ($$$$$$$$$$)
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
my $error = remove_package_fallback($channel, $vars, $paramlist, $inst, $condition, $dispname,
|
my $error;
|
||||||
|
my $removesteps = $$def{remove};
|
||||||
|
if (defined $removesteps) {
|
||||||
|
$error = remove_package_steps($channel, $removesteps, $paramlist, $inst, $condition, $ver, $printver,
|
||||||
|
$db, $def, $name, $dispname, $basedir, $genericmsiparams, $config, $counters, $removecontext);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$error = remove_package_fallback($channel, $vars, $paramlist, $inst, $condition, $dispname,
|
||||||
$ver, $printver, $db, $counters, $removecontext);
|
$ver, $printver, $db, $counters, $removecontext);
|
||||||
|
}
|
||||||
return $error if defined $error;
|
return $error if defined $error;
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
|
@ -1759,9 +1918,9 @@ sub set_install_var ($$$$)
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub remove_package ($$$$$$$)
|
sub remove_package ($$$$$$$$)
|
||||||
{
|
{
|
||||||
my ($db, $def, $name, $list, $basedir, $config, $counters) = @_;
|
my ($db, $def, $name, $list, $basedir, $genericmsiparams, $config, $counters) = @_;
|
||||||
|
|
||||||
set_current_pkg_name($name);
|
set_current_pkg_name($name);
|
||||||
|
|
||||||
|
@ -1773,8 +1932,8 @@ sub remove_package ($$$$$$$)
|
||||||
|
|
||||||
my $paramlist = $$def{'remove-parameters'};
|
my $paramlist = $$def{'remove-parameters'};
|
||||||
$paramlist = [] unless defined $paramlist;
|
$paramlist = [] unless defined $paramlist;
|
||||||
my $error = remove_packages('pkg', $vars, $def, $paramlist,
|
my $error = remove_packages('pkg', $vars, $def, $name, $paramlist,
|
||||||
[map { $$_[1] } @$list], undef, $db, $basedir, $config, $counters);
|
[map { $$_[1] } @$list], undef, $db, $basedir, $genericmsiparams, $config, $counters);
|
||||||
print_log('pkg', ERROR, 'Package removal failed: %s', $error) if defined $error;
|
print_log('pkg', ERROR, 'Package removal failed: %s', $error) if defined $error;
|
||||||
|
|
||||||
set_current_pkg_name(undef);
|
set_current_pkg_name(undef);
|
||||||
|
@ -1835,7 +1994,8 @@ sub install_package ($$$$$$$$$)
|
||||||
$paramlist = [] unless defined $paramlist;
|
$paramlist = [] unless defined $paramlist;
|
||||||
my $list = find_installed_packages('pkg', $def, $db, $name, $basedir, $config, 0);
|
my $list = find_installed_packages('pkg', $def, $db, $name, $basedir, $config, 0);
|
||||||
if (defined $list) {
|
if (defined $list) {
|
||||||
$error = remove_packages('pkg', $vars, $def, $paramlist, $list, $condition, $db, $basedir, $config, $counters);
|
$error = remove_packages('pkg', $vars, $def, $name, $paramlist, $list, $condition,
|
||||||
|
$db, $basedir, $genericmsiparams, $config, $counters);
|
||||||
delete $$vars{'installed-version'};
|
delete $$vars{'installed-version'};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -3318,7 +3478,8 @@ sub handle_pkg ($$$$$$)
|
||||||
$$counters{ToInstallCount}++;
|
$$counters{ToInstallCount}++;
|
||||||
}
|
}
|
||||||
if ($update) {
|
if ($update) {
|
||||||
remove_package($db, $def, $name, $toremove, $base_directory, $config, $counters)
|
remove_package($db, $def, $name, $toremove, $base_directory,
|
||||||
|
$$config{'generic-msi-parameters'}, $config, $counters)
|
||||||
if scalar @$toremove > 0;
|
if scalar @$toremove > 0;
|
||||||
install_package($db, $def, $found, $name, $desired, $base_directory,
|
install_package($db, $def, $found, $name, $desired, $base_directory,
|
||||||
$$config{'generic-msi-parameters'}, $config, $counters)
|
$$config{'generic-msi-parameters'}, $config, $counters)
|
||||||
|
|
Loading…
Reference in a new issue