Skip to content

Commit

Permalink
Merge branch 'stable'
Browse files Browse the repository at this point in the history
* stable:
  (GH-212) Do not strip switch char from uninstall args
  (maint) Use installshield installer when installshield
  (GH-255) Uninstaller should not depend on InstallLocation
  (GH-255) Add updateProcessPath to CommandExecutor
  (maint) formatting
  (GH-254) Ensure nupkg is removed on uninstall
  (doc) update help menus
  • Loading branch information
ferventcoder committed Apr 22, 2015
2 parents 41d84fd + 4bb65a8 commit eeadfb6
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void should_add_includeprograms_to_the_option_set()
[Fact]
public void should_add_short_version_of_includeprograms_to_the_option_set()
{
optionSet.Contains("p").ShouldBeTrue();
optionSet.Contains("i").ShouldBeTrue();
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public void should_not_get_package_information()
[Fact]
public void should_not_call_command_executor()
{
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Never);
}
}

Expand All @@ -134,7 +134,7 @@ public void should_log_why_it_skips_auto_uninstaller()
[Fact]
public void should_not_call_command_executor()
{
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Never);
}
}

Expand All @@ -160,7 +160,7 @@ public void should_log_why_it_skips_auto_uninstaller()
[Fact]
public void should_not_call_command_executor()
{
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Never);
}
}

Expand All @@ -187,7 +187,43 @@ public void should_log_why_it_skips_auto_uninstaller()
[Fact]
public void should_not_call_command_executor()
{
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Never);
}
}

public class when_install_location_is_empty : AutomaticUninstallerServiceSpecsBase
{
public override void Context()
{
base.Context();
fileSystem.ResetCalls();
registryKeys.Clear();
registryKeys.Add(new RegistryApplicationKey
{
InstallLocation = string.Empty,
UninstallString = originalUninstallString,
HasQuietUninstall = false,
KeyPath = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinDirStat"
});
packageInformation.RegistrySnapshot = new Registry("123", registryKeys);
}

public override void Because()
{
service.run(packageResult, config);
}

[Fact]
public void should_call_get_package_information()
{
packageInfoService.Verify(s => s.get_package_information(It.IsAny<IPackage>()), Times.Once);
}

[Fact]
public void should_call_command_executor()
{
var args = installerType.build_uninstall_command_arguments().trim_safe();
commandExecutor.Verify(c => c.execute(expectedUninstallString, args, It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Once);
}
}

Expand All @@ -214,7 +250,7 @@ public void should_log_why_it_skips_auto_uninstaller()
[Fact]
public void should_not_call_command_executor()
{
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Never);
}
}

Expand Down Expand Up @@ -243,7 +279,7 @@ public void should_log_why_it_skips_auto_uninstaller()
[Fact]
public void should_not_call_command_executor()
{
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Never);
}
}

Expand All @@ -263,14 +299,14 @@ public void should_call_get_package_information()
[Fact]
public void should_call_command_executor()
{
commandExecutor.Verify(c => c.execute(expectedUninstallString, installerType.build_uninstall_command_arguments().trim_safe(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(expectedUninstallString, installerType.build_uninstall_command_arguments().trim_safe(), It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Once);
}
}

public class when_AutomaticUninstallerService_defines_uninstall_switches : AutomaticUninstallerServiceSpecsBase
{
private Action because;
private readonly string registryUninstallArgs = "bob";
private readonly string registryUninstallArgs = "/bob";

public override void Because()
{
Expand All @@ -280,86 +316,88 @@ public override void Because()
public void reset()
{
Context();
registryKeys.Clear();
commandExecutor.ResetCalls();
}

private void test_installertype(IInstaller installer,bool useInstallerDefaultArgs)
private void test_installertype(IInstaller installer, bool hasQuietUninstallString)
{
reset();
registryKeys.Add(new RegistryApplicationKey
{
InstallLocation = @"C:\Program Files (x86)\WinDirStat",
UninstallString = "{0} {1}".format_with(originalUninstallString,registryUninstallArgs),
HasQuietUninstall = false,
UninstallString = "{0} {1}".format_with(originalUninstallString, registryUninstallArgs),
HasQuietUninstall = hasQuietUninstallString,
KeyPath = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinDirStat",
InstallerType = installer.InstallerType,
});
packageInformation.RegistrySnapshot = new Registry("123", registryKeys);

because();

var uninstallArgs = useInstallerDefaultArgs ? installer.build_uninstall_command_arguments().trim_safe() : registryUninstallArgs.trim_safe();
var uninstallArgs = !hasQuietUninstallString ? registryUninstallArgs.trim_safe() + " " + installer.build_uninstall_command_arguments().trim_safe() : registryUninstallArgs.trim_safe();

commandExecutor.Verify(c => c.execute(expectedUninstallString, uninstallArgs, It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>()), Times.Never);
commandExecutor.Verify(c => c.execute(expectedUninstallString, uninstallArgs, It.IsAny<int>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<Action<object, DataReceivedEventArgs>>(), It.IsAny<bool>()), Times.Once);
}

[Fact]
public void should_use_CustomInstaller_uninstall_args_when_installtype_is_unknown_and_has_quiet_uninstall_is_false()
{
test_installertype(new CustomInstaller(), useInstallerDefaultArgs: true);
test_installertype(new CustomInstaller(), hasQuietUninstallString: false);
}

[Fact]
public void should_use_registry_uninstall_args_when_installtype_is_unknown_and_has_quiet_uninstall_is_true()
{
test_installertype(new CustomInstaller(), useInstallerDefaultArgs: false);
test_installertype(new CustomInstaller(), hasQuietUninstallString: true);
}

[Fact]
public void should_use_MsiInstaller_uninstall_args_when_installtype_is_msi_and_has_quiet_uninstall_is_false()
{
test_installertype(new MsiInstaller(), useInstallerDefaultArgs: true);
test_installertype(new MsiInstaller(), hasQuietUninstallString: false);
}

[Fact]
public void should_use_registry_uninstall_args_when_installtype_is_msi_and_has_quiet_uninstall_is_true()
{
test_installertype(new MsiInstaller(), useInstallerDefaultArgs: false);
test_installertype(new MsiInstaller(), hasQuietUninstallString: true);
}

[Fact]
public void should_use_InnoSetupInstaller_uninstall_args_when_installtype_is_innosetup_and_has_quiet_uninstall_is_false()
{
test_installertype(new InnoSetupInstaller(), useInstallerDefaultArgs: true);
test_installertype(new InnoSetupInstaller(), hasQuietUninstallString: false);
}

[Fact]
public void should_use_registry_uninstall_args_when_installtype_is_innosetup_and_has_quiet_uninstall_is_true()
{
test_installertype(new InnoSetupInstaller(), useInstallerDefaultArgs: false);
test_installertype(new InnoSetupInstaller(), hasQuietUninstallString: true);
}

[Fact]
public void should_use_InstallShieldInstaller_uninstall_args_when_installtype_is_installshield_and_has_quiet_uninstall_is_false()
{
test_installertype(new InstallShieldInstaller(), useInstallerDefaultArgs: true);
test_installertype(new InstallShieldInstaller(), hasQuietUninstallString: false);
}

[Fact]
public void should_use_registry_uninstall_args_when_installtype_is_installshield_and_has_quiet_uninstall_is_true()
{
test_installertype(new InstallShieldInstaller(), useInstallerDefaultArgs: false);
test_installertype(new InstallShieldInstaller(), hasQuietUninstallString: true);
}

[Fact]
public void should_use_NsisInstaller_uninstall_args_when_installtype_is_nsis_and_has_quiet_uninstall_is_false()
{
test_installertype(new NsisInstaller(), useInstallerDefaultArgs: true);
test_installertype(new NsisInstaller(), hasQuietUninstallString: false);
}

[Fact]
public void should_use_registry_uninstall_args_when_installtype_is_nsis_and_has_quiet_uninstall_is_true()
{
test_installertype(new NsisInstaller(), useInstallerDefaultArgs: false);
test_installertype(new NsisInstaller(), hasQuietUninstallString: true);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ choco install notepadplusplus --force --force-dependencies
choco install notepadplusplus googlechrome atom 7zip -dvfy
choco install git --params=""/GitAndUnixToolsOnPath /NoAutoCrlf"" -y
choco install nodejs.install --version 0.10.35
choco install git -s ""https://somewhere/out/there""
choco install git -s ""https://somewhere/protected"" -u user -p pass
Choco can also install directly from a nuspec/nupkg file. This aids in
testing packages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,11 @@ choco list <filter> [<options/switches>]
"chocolatey".Log().Info(ChocolateyLoggers.Important, "Examples");
"chocolatey".Log().Info(@"
choco list --local-only
choco list -lp
choco list -lap
choco list -li
choco list -lai
choco search git
choco search git -s ""https://somewhere/out/there""
choco search bob -s ""https://somewhere/protected"" -u user -p pass
");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ choco upgrade notepadplusplus googlechrome atom 7zip
choco upgrade notepadplusplus googlechrome atom 7zip -dvfy
choco upgrade git --params=""/GitAndUnixToolsOnPath /NoAutoCrlf"" -y
choco upgrade nodejs.install --version 0.10.35
choco upgrade git -s ""https://somewhere/out/there""
choco upgrade git -s ""https://somewhere/protected"" -u user -p pass
");

"chocolatey".Log().Info(ChocolateyLoggers.Important, "Options and Switches");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void run(PackageResult packageResult, ChocolateyConfiguration config)
{
this.Log().Debug(() => " Preparing uninstall key '{0}'".format_with(key.UninstallString));

if (!_fileSystem.directory_exists(key.InstallLocation) || !_registryService.value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))
if ((!string.IsNullOrWhiteSpace(key.InstallLocation) && !_fileSystem.directory_exists(key.InstallLocation)) || !_registryService.value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))
{
this.Log().Info(" Skipping auto uninstaller - The application appears to have been uninstalled already by other means.");
this.Log().Debug(() => " Searched for install path '{0}' - found? {1}".format_with(key.InstallLocation.escape_curly_braces(), _fileSystem.directory_exists(key.InstallLocation)));
Expand All @@ -77,11 +77,10 @@ public void run(PackageResult packageResult, ChocolateyConfiguration config)
}

// split on " /" and " -" for quite a bit more accuracy
IList<string> uninstallArgs = key.UninstallString.to_string().Split(new[] {" /", " -"}, StringSplitOptions.RemoveEmptyEntries).ToList();
var uninstallExe = uninstallArgs.DefaultIfEmpty(string.Empty).FirstOrDefault();
uninstallArgs.Remove(uninstallExe);
IList<string> uninstallArgsSplit = key.UninstallString.to_string().Split(new[] {" /", " -"}, StringSplitOptions.RemoveEmptyEntries).ToList();
var uninstallExe = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault();
var uninstallArgs = key.UninstallString.to_string().Replace(uninstallExe.to_string(), string.Empty);
uninstallExe = uninstallExe.remove_surrounding_quotes();
if (uninstallExe.is_equal_to("msiexec.exe")) uninstallExe = _fileSystem.combine_paths(Environment.SystemDirectory, uninstallExe);
this.Log().Debug(() => " Uninstaller path is '{0}'".format_with(uninstallExe));

//todo: ultimately we should merge keys with logging
Expand All @@ -101,7 +100,7 @@ public void run(PackageResult packageResult, ChocolateyConfiguration config)
installer = new NsisInstaller();
break;
case InstallerType.InstallShield:
installer = new CustomInstaller();
installer = new InstallShieldInstaller();
break;
default:
// skip
Expand All @@ -110,14 +109,14 @@ public void run(PackageResult packageResult, ChocolateyConfiguration config)

this.Log().Debug(() => " Installer type is '{0}'".format_with(installer.GetType().Name));

uninstallArgs.Add(installer.build_uninstall_command_arguments());
uninstallArgs += " " + installer.build_uninstall_command_arguments();
}

this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs.@join(" ")));
this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs));

var exitCode = _commandExecutor.execute(
uninstallExe,
uninstallArgs.@join(" "),
uninstallExe,
uninstallArgs.trim_safe(),
config.CommandExecutionTimeoutSeconds,
(s, e) =>
{
Expand All @@ -128,7 +127,8 @@ public void run(PackageResult packageResult, ChocolateyConfiguration config)
{
if (e == null || string.IsNullOrWhiteSpace(e.Data)) return;
this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data));
});
},
updateProcessPath: false);

if (exitCode != 0)
{
Expand Down
Loading

0 comments on commit eeadfb6

Please sign in to comment.