Implemented optional package removal step list.

This commit is contained in:
László Valkó 2018-05-12 15:26:14 +02:00
parent 17cbf95a36
commit 91c7116c09

View file

@ -1658,18 +1658,10 @@ sub run_exe ($$$$$$$;$)
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[^ ]* )/$1\/qb \/norestart \/passive /io;
print_log($channel, DEBUG2, 'Uninstall command: %s', $uninst);
@ -1705,9 +1697,168 @@ sub remove_package_fallback ($$$$$$$$$$$)
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 = {};
$list = sort_packages_to_remove($list);
@ -1732,8 +1883,16 @@ sub remove_packages ($$$$$$$$$$)
next;
}
}
my $error = remove_package_fallback($channel, $vars, $paramlist, $inst, $condition, $dispname,
$ver, $printver, $db, $counters, $removecontext);
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);
}
return $error if defined $error;
}
return undef;
@ -1759,9 +1918,9 @@ sub set_install_var ($$$$)
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);
@ -1773,8 +1932,8 @@ sub remove_package ($$$$$$$)
my $paramlist = $$def{'remove-parameters'};
$paramlist = [] unless defined $paramlist;
my $error = remove_packages('pkg', $vars, $def, $paramlist,
[map { $$_[1] } @$list], undef, $db, $basedir, $config, $counters);
my $error = remove_packages('pkg', $vars, $def, $name, $paramlist,
[map { $$_[1] } @$list], undef, $db, $basedir, $genericmsiparams, $config, $counters);
print_log('pkg', ERROR, 'Package removal failed: %s', $error) if defined $error;
set_current_pkg_name(undef);
@ -1835,7 +1994,8 @@ sub install_package ($$$$$$$$$)
$paramlist = [] unless defined $paramlist;
my $list = find_installed_packages('pkg', $def, $db, $name, $basedir, $config, 0);
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'};
}
else {
@ -3318,7 +3478,8 @@ sub handle_pkg ($$$$$$)
$$counters{ToInstallCount}++;
}
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;
install_package($db, $def, $found, $name, $desired, $base_directory,
$$config{'generic-msi-parameters'}, $config, $counters)