diff --git a/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 b/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 index dce848afc4..4281f15384 100644 --- a/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 +++ b/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 @@ -19,6 +19,9 @@ if ($env:ChocolateyEnvironmentDebug -eq 'true') { $DebugPreference = "Continue"; $VerbosePreference = "SilentlyContinue" if ($env:ChocolateyEnvironmentVerbose -eq 'true') { $VerbosePreference = "Continue"; $verbosity = $true } +# ensure module loading preference is on +$PSModuleAutoLoadingPreference = "All"; + Write-Debug "Posh version is $($psversiontable.PsVersion.ToString())" # grab functions from files @@ -27,4 +30,12 @@ Get-Item $helpersPath\functions\*.ps1 | % { . $_.FullName; Export-ModuleMember -Function $_.BaseName - } \ No newline at end of file + } + +# load extensions if they exist +$extensionsPath = Join-Path "$helpersPath" '..\extensions' +if(Test-Path($extensionsPath)) { + Write-Debug 'Loading community extensions' + #Resolve-Path $extensionsPath\**\*\*.psm1 | % { Write-Debug "Importing `'$_`'"; Import-Module $_.ProviderPath } + Get-ChildItem $extensionsPath -recurse -filter "*.psm1" | Select -ExpandProperty FullName | % { Write-Debug "Importing `'$_`'"; Import-Module $_; } +} \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/Get-BinRoot.ps1 b/src/chocolatey.resources/helpers/functions/Get-BinRoot.ps1 index e80d499a56..a512f6a4a5 100644 --- a/src/chocolatey.resources/helpers/functions/Get-BinRoot.ps1 +++ b/src/chocolatey.resources/helpers/functions/Get-BinRoot.ps1 @@ -15,6 +15,7 @@ function Get-BinRoot { Write-Debug "Running 'Get-BinRoot'"; + Write-Output "Get-BinRoot is going to be deprecated by v1. Many packages no longer require it since the folders no longer have versions on them." # Since CamelCase was decided upon when $env:ChocolateyInstall was first invented, whe should stick to this convention and use $env:ChocolateyBinRoot. # I propose: diff --git a/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 b/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 index b02291bf47..a6acd609c5 100644 --- a/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 +++ b/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 @@ -60,7 +60,7 @@ param( Write-Debug "Running 'Get-ChocolateyUnzip' with fileFullPath:`'$fileFullPath`'', destination: `'$destination`', specificFolder: `'$specificFolder``, packageName: `'$packageName`'"; if ($packageName) { - $packagelibPath = Join-Path $env:ChocolateyPackageFolder $packageName + $packagelibPath = $env:ChocolateyPackageFolder if (!(Test-Path -path $packagelibPath)) { New-Item $packagelibPath -type directory } diff --git a/src/chocolatey.resources/helpers/functions/Install-ChocolateyDesktopLink.ps1 b/src/chocolatey.resources/helpers/functions/Install-ChocolateyDesktopLink.ps1 index 6e21516e6c..12f81ffc1c 100644 --- a/src/chocolatey.resources/helpers/functions/Install-ChocolateyDesktopLink.ps1 +++ b/src/chocolatey.resources/helpers/functions/Install-ChocolateyDesktopLink.ps1 @@ -32,19 +32,20 @@ param( Write-Debug "Running 'Install-ChocolateyDesktopLink' with targetFilePath:`'$targetFilePath`'"; if(!$targetFilePath) { - Write-ChocolateyFailure "Install-ChocolateyDesktopLink" "Missing TargetFilePath input parameter." - return + throw "Install-ChocolateyDesktopLink - `$targetFilePath can not be null." } if(!(Test-Path($targetFilePath))) { - Write-ChocolateyFailure "Install-ChocolateyDesktopLink" "TargetPath does not exist, so can't create shortcut." - return + Write-Warning "'$targetFilePath' does not exist. If it is not created the shortcut will not be valid." } Write-Debug "Creating Shortcut..." try { $desktop = $([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::DesktopDirectory)) + if(!(Test-Path($desktop))) { + [System.IO.Directory]::CreateDirectory($desktop) | Out-Null + } $link = Join-Path $desktop "$([System.IO.Path]::GetFileName($targetFilePath)).lnk" $workingDirectory = $([System.IO.Path]::GetDirectoryName($targetFilePath)) @@ -58,6 +59,6 @@ param( } catch { - Write-ChocolateyFailure "Install-ChocolateyDesktopLink" "There were errors attempting to create shortcut. The error message was '$_'." + throw $_.Exception } } \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/Install-ChocolateyShortcut.ps1 b/src/chocolatey.resources/helpers/functions/Install-ChocolateyShortcut.ps1 index 1d94d6a63f..038a688a62 100644 --- a/src/chocolatey.resources/helpers/functions/Install-ChocolateyShortcut.ps1 +++ b/src/chocolatey.resources/helpers/functions/Install-ChocolateyShortcut.ps1 @@ -66,32 +66,32 @@ directoy, an icon to be used for the shortcut, along with a description and argu Write-Debug "Running 'Install-ChocolateyShortcut' with parameters ShortcutFilePath: `'$shortcutFilePath`', TargetPath: `'$targetPath`', WorkingDirectory: `'$workingDirectory`', Arguments: `'$arguments`', IconLocation: `'$iconLocation`', Description: `'$description`'"; if(!$shortcutFilePath) { - Write-ChocolateyFailure "Install-ChocolateyShortcut" "Missing ShortCutFilePath input parameter." - return + throw "Install-ChocolateyShortcut - `$shortcutFilePath can not be null." } + $shortcutDirectory = $([System.IO.Path]::GetDirectoryName($shortcutFilePath)) + if (!(Test-Path($shortcutDirectory))) { + [System.IO.Directory]::CreateDirectory($shortcutDirectory) | Out-Null + } + if(!$targetPath) { - Write-ChocolateyFailure "Install-ChocolateyShortcut" "Missing TargetPath input parameter." - return + throw "Install-ChocolateyShortcut - `$targetFilePath can not be null." } - + if(!(Test-Path($targetPath))) { - Write-ChocolateyFailure "Install-ChocolateyShortcut" "TargetPath does not exist, so can't create shortcut." - return + Write-Warning "'$targetFilePath' does not exist. If it is not created the shortcut will not be valid." } if($iconLocation) { if(!(Test-Path($iconLocation))) { - Write-ChocolateyFailure "Install-ChocolateyShortcut" "IconLocation does not exist, so can't create shortcut." - return + Write-Warning "'$iconLocation' does not exist. A default icon will be used." } } - if($workingDirectory) { - if(!(Test-Path($workingDirectory))) { - Write-ChocolateyFailure "Install-ChocolateyShortcut" "WorkingDirectory does not exist, so can't create shortcut." - return - } + if ($workingDirectory) { + if (!(Test-Path($workingDirectory))) { + [System.IO.Directory]::CreateDirectory($workingDirectory) | Out-Null + } } Write-Debug "Creating Shortcut..." @@ -103,15 +103,17 @@ directoy, an icon to be used for the shortcut, along with a description and argu $lnk.WorkingDirectory = $workingDirectory $lnk.Arguments = $arguments if($iconLocation) { - $lnk.IconLocation = $iconLocation + $lnk.IconLocation = $iconLocation } - $lnk.Description = $description + if ($description) { + $lnk.Description = $description + } + $lnk.Save() Write-Debug "Shortcut created." - } catch { - Write-ChocolateyFailure "Install-ChocolateyShortcut" "There were errors attempting to create shortcut. The error message was '$_'." + throw $_.Exception } } \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/Install-ChocolateyVsixPackage.ps1 b/src/chocolatey.resources/helpers/functions/Install-ChocolateyVsixPackage.ps1 index 18484a4c4f..049496ee93 100644 --- a/src/chocolatey.resources/helpers/functions/Install-ChocolateyVsixPackage.ps1 +++ b/src/chocolatey.resources/helpers/functions/Install-ChocolateyVsixPackage.ps1 @@ -96,8 +96,7 @@ param( if($version){ $vnum=$version.PSPath.Substring($version.PSPath.LastIndexOf('\')+1) if($vnum -as [int] -lt 10) { - Write-ChocolateyFailure $packageName "This installed VS version, $vnum, does not support installing VSIX packages. Version 10 is the minimum acceptable version." - return + throw "This installed VS version, $vnum, does not support installing VSIX packages. Version 10 is the minimum acceptable version." } $dir=(get-itemProperty $version.PSPath "InstallDir").InstallDir $installer = Join-Path $dir "VsixInstaller.exe" @@ -108,18 +107,16 @@ param( Get-ChocolateyWebFile $packageName $download $vsixUrl -checksum $checksum -checksumType $checksumType } catch { - Write-ChocolateyFailure $packageName "There were errors attempting to retrieve the vsix from $vsixUrl. The error message was '$_'." - return + throw "There were errors attempting to retrieve the vsix from $vsixUrl. The error message was '$_'." } Write-Debug "Installing VSIX using $installer" $exitCode = Install-Vsix "$installer" "$download" if($exitCode -gt 0 -and $exitCode -ne 1001) { #1001: Already installed - Write-ChocolateyFailure $packageName "There was an error installing '$packageName'. The exit code returned was $exitCode." - return + throw "There was an error installing '$packageName'. The exit code returned was $exitCode." } } else { - Write-ChocolateyFailure $packageName "Visual Studio is not installed or the specified version is not present." + throw "Visual Studio is not installed or the specified version is not present." } } diff --git a/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 b/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 index cf8cb116e7..7dc5f61f78 100644 --- a/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 +++ b/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 @@ -46,9 +46,11 @@ param( $packagelibPath=$env:chocolateyPackageFolder $zipContentFile=(join-path $packagelibPath $zipFileName) + ".txt" - $zipContentFile - $zipContents=get-content $zipContentFile - foreach ($fileInZip in $zipContents) { - remove-item "$fileInZip" -ErrorAction SilentlyContinue + if ((Test-Path -path $zipContentFile)) { + $zipContentFile + $zipContents=get-content $zipContentFile + foreach ($fileInZip in $zipContents) { + remove-item "$fileInZip" -ErrorAction SilentlyContinue + } } } \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/Write-ChocolateyFailure.ps1 b/src/chocolatey.resources/helpers/functions/Write-ChocolateyFailure.ps1 index 0f476d2f8c..5d4dbf19fc 100644 --- a/src/chocolatey.resources/helpers/functions/Write-ChocolateyFailure.ps1 +++ b/src/chocolatey.resources/helpers/functions/Write-ChocolateyFailure.ps1 @@ -20,4 +20,6 @@ param( Write-Warning "Write-ChocolateyFailure is deprecated. If you are the package maintainer, please use 'throw `$_.Exception' instead." $error | %{ $_.Exception | fl * | Out-String } + + throw "$failureMessage" } diff --git a/src/chocolatey.tests.integration/Scenario.cs b/src/chocolatey.tests.integration/Scenario.cs index 22b7d6691c..d97fde1337 100644 --- a/src/chocolatey.tests.integration/Scenario.cs +++ b/src/chocolatey.tests.integration/Scenario.cs @@ -53,6 +53,7 @@ public static void reset(ChocolateyConfiguration config) _fileSystem.delete_directory_if_exists(badPackagesPath, recursive: true); _fileSystem.delete_directory_if_exists(backupPackagesPath, recursive: true); _fileSystem.delete_directory_if_exists(_fileSystem.combine_paths(get_top_level(), ".chocolatey"), recursive: true); + _fileSystem.delete_directory_if_exists(_fileSystem.combine_paths(get_top_level(), "extensions"), recursive: true); _fileSystem.create_directory(config.CacheLocation); _fileSystem.create_directory(config.Sources); @@ -61,6 +62,7 @@ public static void reset(ChocolateyConfiguration config) _fileSystem.create_directory(badPackagesPath); _fileSystem.create_directory(backupPackagesPath); _fileSystem.create_directory(_fileSystem.combine_paths(get_top_level(), ".chocolatey")); + _fileSystem.create_directory(_fileSystem.combine_paths(get_top_level(), "extensions")); } public static void add_packages_to_source_location(ChocolateyConfiguration config, string pattern) diff --git a/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs b/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs index 0154a79536..e7b09d3c26 100644 --- a/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs +++ b/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs @@ -210,6 +210,14 @@ public void should_not_create_a_shim_for_mismatched_case_ignored_executable_in_t var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "casemismatch.exe"); File.Exists(shimfile).ShouldBeFalse(); + } + + [Fact] + public void should_not_create_an_extensions_folder_for_the_pacakge() + { + var extensionsDirectory = Path.Combine(Scenario.get_top_level(), "extensions", Configuration.PackageNames); + + Directory.Exists(extensionsDirectory).ShouldBeFalse(); } [Fact] diff --git a/src/chocolatey/infrastructure.app/ApplicationParameters.cs b/src/chocolatey/infrastructure.app/ApplicationParameters.cs index 082aa2de9f..a55cf8bbf7 100644 --- a/src/chocolatey/infrastructure.app/ApplicationParameters.cs +++ b/src/chocolatey/infrastructure.app/ApplicationParameters.cs @@ -52,6 +52,7 @@ public static class ApplicationParameters public static readonly string PackageBackupLocation = _fileSystem.combine_paths(InstallLocation, "lib-bkp"); public static readonly string ShimsLocation = _fileSystem.combine_paths(InstallLocation, "bin"); public static readonly string ChocolateyPackageInfoStoreLocation = _fileSystem.combine_paths(InstallLocation, ".chocolatey"); + public static readonly string ExtensionsLocation = _fileSystem.combine_paths(InstallLocation, "extensions"); public static readonly string ChocolateyCommunityFeedPushSource = "https://chocolatey.org/"; public static readonly string UserAgent = "Chocolatey Command Line"; public static readonly string RegistryValueInstallLocation = "InstallLocation"; diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs index 8ee04262a9..a9abc0c987 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs @@ -196,6 +196,11 @@ public void handle_package_result(PackageResult packageResult, ChocolateyConfigu if (config.Information.PlatformType != PlatformType.Windows) this.Log().Info(ChocolateyLoggers.Important, () => " Skipping Powershell and shimgen portions of the install due to non-Windows."); } + if (packageResult.Success) + { + handle_extension_packages(config, packageResult); + } + _packageInfoService.save_package_information(pkgInfo); ensure_bad_package_path_is_clean(config, packageResult); @@ -477,6 +482,8 @@ private void uninstall_cleanup(ChocolateyConfiguration config, PackageResult pac _packageInfoService.remove_package_information(packageResult.Package); ensure_bad_package_path_is_clean(config, packageResult); remove_rollback_if_exists(packageResult); + handle_extension_packages(config, packageResult); + if (config.Force) { var packageDirectory = _fileSystem.combine_paths(packageResult.InstallLocation); @@ -496,11 +503,38 @@ private void uninstall_cleanup(ChocolateyConfiguration config, PackageResult pac FaultTolerance.try_catch_with_logging_exception( () => _fileSystem.delete_directory_if_exists(packageDirectory, recursive: true), - "Attempted to remove '{0}' but had an error:".format_with(packageDirectory), + "Attempted to remove '{0}' but had an error".format_with(packageDirectory), logWarningInsteadOfError: true); } } + private void handle_extension_packages(ChocolateyConfiguration config, PackageResult packageResult) + { + if (packageResult == null) return; + _fileSystem.create_directory_if_not_exists(ApplicationParameters.ExtensionsLocation); + + if (!packageResult.Name.to_lower().EndsWith(".extension")) return; + + var pkgExtensions = _fileSystem.combine_paths(ApplicationParameters.ExtensionsLocation, packageResult.Name); + FaultTolerance.try_catch_with_logging_exception( + () => _fileSystem.delete_directory_if_exists(pkgExtensions, recursive: true), + "Attempted to remove '{0}' but had an error".format_with(pkgExtensions)); + + if (!config.CommandName.is_equal_to(CommandNameType.uninstall.to_string())) + { + if (packageResult.InstallLocation == null) return; + + _fileSystem.create_directory_if_not_exists(pkgExtensions); + FaultTolerance.try_catch_with_logging_exception( + () => _fileSystem.copy_directory(packageResult.InstallLocation, pkgExtensions, overwriteExisting: true), + "Attempted to copy{0} '{1}'{0} to '{2}'{0} but had an error".format_with(Environment.NewLine, packageResult.InstallLocation, pkgExtensions)); + + string logMessage = "Installed/updated extension for {0}. You will be able to use it on next run.".format_with(packageResult.Name); + this.Log().Warn(logMessage); + packageResult.Messages.Add(new ResultMessage(ResultType.Note, logMessage)); + } + } + private void ensure_bad_package_path_is_clean(ChocolateyConfiguration config, PackageResult packageResult) { FaultTolerance.try_catch_with_logging_exception( diff --git a/src/chocolatey/infrastructure.app/services/PowershellService.cs b/src/chocolatey/infrastructure.app/services/PowershellService.cs index 80f9736f80..3ba74fb63a 100644 --- a/src/chocolatey/infrastructure.app/services/PowershellService.cs +++ b/src/chocolatey/infrastructure.app/services/PowershellService.cs @@ -158,8 +158,8 @@ public bool run_action(ChocolateyConfiguration configuration, PackageResult pack Environment.SetEnvironmentVariable("packageName", package.Id); Environment.SetEnvironmentVariable("chocolateyPackageVersion", package.Version.to_string()); Environment.SetEnvironmentVariable("packageVersion", package.Version.to_string()); - Environment.SetEnvironmentVariable("chocolateyPackageFolder", ApplicationParameters.PackagesLocation); - Environment.SetEnvironmentVariable("packageFolder", ApplicationParameters.PackagesLocation); + Environment.SetEnvironmentVariable("chocolateyPackageFolder", packageDirectory); + Environment.SetEnvironmentVariable("packageFolder", packageDirectory); Environment.SetEnvironmentVariable("installerArguments", configuration.InstallArguments); Environment.SetEnvironmentVariable("chocolateyPackageParameters", configuration.PackageParameters); if (configuration.ForceX86)