diff --git a/Scenarios.md b/Scenarios.md
index c9767724fb..011ebfa259 100644
--- a/Scenarios.md
+++ b/Scenarios.md
@@ -1,6 +1,6 @@
## Chocolatey Usage Scenarios
-### ChocolateyInstallCommand [ 35 Scenario(s), 293 Observation(s) ]
+### ChocolateyInstallCommand [ 42 Scenario(s), 312 Observation(s) ]
#### when force installing a package that depends on an unavailable newer version of an installed dependency forcing dependencies
@@ -247,6 +247,20 @@
* should not install a package in the lib directory
* should put a package in the lib bad directory
+#### when installing a package that tries to overwrite another shim
+
+ * should have a shim
+ * should have a shim with target in other package tools folder
+ * should have an error message
+ * should have shim target
+
+#### when installing a package that tries to overwrite its own shim
+
+ * should create a shim
+ * should have a shim with target in tools folder
+ * should have an error message
+ * should have shim targets
+
#### when installing a package with a dependent package that also depends on a less constrained but still valid dependency of the same package
* [PENDING] should contain a message that everything installed successfully
@@ -282,6 +296,18 @@
* should not install a package in the lib directory
* should not install the dependency in the lib directory
+#### when installing a package with dependencies and noshims
+
+ * should create a shim for the dependency
+ * should have shim targets
+ * should not create a shim for the package
+
+#### when installing a package with dependencies and noshimsglobal
+
+ * should have shim targets
+ * should not create a shim for the dependency
+ * should not create a shim for the package
+
#### when installing a package with dependencies happy
* should contain a message that everything installed successfully
@@ -326,11 +352,25 @@
* [PENDING] should not install the conflicting package in the lib directory
* [PENDING] should not upgrade the exact version dependency
+#### when installing a package with install bin file
+
+ * should not see the shim as an existing shim and remove it
+
+#### when installing a package with install bin file and noshims
+
+ * should have shim target
+ * should not create a shim
+
#### when installing a package with no sources enabled
* should have no sources enabled result
* should not install any packages
+#### when installing a package with noshims
+
+ * should have shim target
+ * should not create a shim for the package
+
#### when installing a side by side package
* config should match package result name
@@ -541,7 +581,7 @@
* should contain success message
-### ChocolateyUninstallCommand [ 13 Scenario(s), 93 Observation(s) ]
+### ChocolateyUninstallCommand [ 14 Scenario(s), 95 Observation(s) ]
#### when force uninstalling a package
@@ -617,6 +657,11 @@
* should not remove package from the lib directory
* should still have the package file in the directory
+#### when uninstalling a package that forgets to call uninstall bin file
+
+ * should have had a shim
+ * should have removed the shim
+
#### when uninstalling a package with a read and delete share locked file
* should contain a message that it uninstalled successfully
@@ -675,7 +720,7 @@
* should throw an error that it is not allowed
-### ChocolateyUpgradeCommand [ 36 Scenario(s), 295 Observation(s) ]
+### ChocolateyUpgradeCommand [ 40 Scenario(s), 307 Observation(s) ]
#### when force upgrading a package
@@ -920,6 +965,11 @@
* should have no sources enabled result
* should not have any packages upgraded
+#### when upgrading a package with noshims
+
+ * should have shim target
+ * should not create a shim
+
#### when upgrading a package with readonly files
* should contain a warning message that it upgraded successfully
@@ -933,6 +983,25 @@
* should upgrade the package
* should upgrade where install location reports
+#### when upgrading a package with shims
+
+ * should create a shim
+ * should have had original shim
+ * should have shim target
+ * should not have original shim
+
+#### when upgrading a package with shims that errors
+
+ * should have original shim
+ * should not create a shim
+
+#### when upgrading a package with shims with noshims
+
+ * should have had original shim
+ * should have shim target
+ * should not create a shim
+ * should not have original shim
+
#### when upgrading a package with unavailable dependencies
* should contain a message that it was unable to upgrade anything
diff --git a/src/chocolatey.resources/helpers/functions/Install-BinFile.ps1 b/src/chocolatey.resources/helpers/functions/Install-BinFile.ps1
index 972b432fca..eff970dfbf 100644
--- a/src/chocolatey.resources/helpers/functions/Install-BinFile.ps1
+++ b/src/chocolatey.resources/helpers/functions/Install-BinFile.ps1
@@ -86,6 +86,13 @@ param(
Write-FunctionCallLogMessage -Invocation $MyInvocation -Parameters $PSBoundParameters
+ if ($env:ChocolateyNoShims) {
+ Write-Debug "File shimming disabled for `'$($env:ChocolateyPackageName)`'."
+ Write-Debug "Removing any existing shim for `'$name`'."
+ Uninstall-BinFile $name $path
+ return
+ }
+
$nugetPath = [System.IO.Path]::GetFullPath((Join-Path "$helpersPath" '..\'))
$nugetExePath = Join-Path "$nugetPath" 'bin'
$packageBatchFileName = Join-Path $nugetExePath "$name.bat"
diff --git a/src/chocolatey.tests.integration/Scenario.cs b/src/chocolatey.tests.integration/Scenario.cs
index 4077b192f9..d40dd87cae 100644
--- a/src/chocolatey.tests.integration/Scenario.cs
+++ b/src/chocolatey.tests.integration/Scenario.cs
@@ -177,6 +177,8 @@ private static ChocolateyConfiguration baseline_configuration()
config.PinCommand.Name = string.Empty;
config.PinCommand.Command = PinCommandType.unknown;
config.ListCommand.IdOnly = false;
+ config.NoShims = false;
+ config.NoShimsGlobal = false;
return config;
}
diff --git a/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj b/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj
index aaf566b4d4..23f26ddfbf 100644
--- a/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj
+++ b/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj
@@ -346,6 +346,105 @@
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
diff --git a/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/shimbasepackage.nuspec b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/shimbasepackage.nuspec
new file mode 100644
index 0000000000..b620fe06cd
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/shimbasepackage.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ shimbasepackage
+ 1.0.0
+ shimbasepackage
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ __REPLACE__
+ __REPLACE__
+ shimbasepackage
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..5cc9f79b7a
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/shimbasepackage1.exe b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/shimbasepackage1.exe
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimbasepackage/1.0.0/tools/shimbasepackage1.exe
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/shimhasdependency.nuspec b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/shimhasdependency.nuspec
new file mode 100644
index 0000000000..342b618af3
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/shimhasdependency.nuspec
@@ -0,0 +1,20 @@
+
+
+
+ shimhasdependency
+ 1.0.0
+ shimhasdependency
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ __REPLACE__
+ __REPLACE__
+ shimhasdependency
+
+
+
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..5cc9f79b7a
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/shimhasdependency1.exe b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/shimhasdependency1.exe
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimhasdependency/1.0.0/tools/shimhasdependency1.exe
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/shimoverwrite.nuspec b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/shimoverwrite.nuspec
new file mode 100644
index 0000000000..3c52b00e54
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/shimoverwrite.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ shimoverwrite
+ 1.0.0
+ shimoverwrite
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ __REPLACE__
+ __REPLACE__
+ overwrite-own
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..5cc9f79b7a
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/install/shimoverwrite1.exe b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/install/shimoverwrite1.exe
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/install/shimoverwrite1.exe
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/shimoverwrite1.exe b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/shimoverwrite1.exe
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwrite/1.0.0/tools/shimoverwrite1.exe
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/shimoverwriteother.nuspec b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/shimoverwriteother.nuspec
new file mode 100644
index 0000000000..e8941cd7bf
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/shimoverwriteother.nuspec
@@ -0,0 +1,20 @@
+
+
+
+ shimoverwriteother
+ 1.0.0
+ shimoverwriteother
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ __REPLACE__
+ __REPLACE__
+ shimoverwriteother
+
+
+
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..5cc9f79b7a
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/shimbasepackage1.exe b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/shimbasepackage1.exe
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimoverwriteother/1.0.0/tools/shimbasepackage1.exe
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/shimupgrade.nuspec b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/shimupgrade.nuspec
new file mode 100644
index 0000000000..ef00377e59
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/shimupgrade.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ shimupgrade
+ 1.0.0
+ shimupgrade
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ __REPLACE__
+ __REPLACE__
+ shimupgrade
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..5cc9f79b7a
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/shimupgrade1.exe b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/shimupgrade1.exe
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/1.0.0/tools/shimupgrade1.exe
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/shimupgrade.nuspec b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/shimupgrade.nuspec
new file mode 100644
index 0000000000..c4213d5185
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/shimupgrade.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ shimupgrade
+ 2.0.0
+ shimupgrade
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ This version throws an error when installing
+ __REPLACE__
+ shimupgrade
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..9b17e662f9
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1,7 @@
+try {
+ Write-Output "This is $packageName v$packageVersion being installed to `n '$packageFolder'."
+ Write-Error "Oh no! An error"
+ throw "We had an error captain!"
+} catch {
+ throw $_.Exception
+}
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/shimupgrade2.exe b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/shimupgrade2.exe
new file mode 100644
index 0000000000..359a5b952d
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/2.0.0/tools/shimupgrade2.exe
@@ -0,0 +1 @@
+2.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/shimupgrade.nuspec b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/shimupgrade.nuspec
new file mode 100644
index 0000000000..7559fd0990
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/shimupgrade.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ shimupgrade
+ 3.0.0
+ shimupgrade
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ __REPLACE__
+ __REPLACE__
+ shimupgrade
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..5cc9f79b7a
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..6489cba588
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1 @@
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/shimupgrade3.exe b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/shimupgrade3.exe
new file mode 100644
index 0000000000..56fea8a08d
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimupgrade/3.0.0/tools/shimupgrade3.exe
@@ -0,0 +1 @@
+3.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/shimwithbinfile.nuspec b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/shimwithbinfile.nuspec
new file mode 100644
index 0000000000..ec1d5047f5
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/shimwithbinfile.nuspec
@@ -0,0 +1,17 @@
+
+
+
+ shimwithbinfile
+ 1.0.0
+ shimwithbinfile
+ __REPLACE_AUTHORS_OF_SOFTWARE__
+ __REPLACE_YOUR_NAME__
+ false
+ This version forgets to call Uninstall-BinFile when uninstalling
+ __REPLACE__
+ shimwithbinfile
+
+
+
+
+
diff --git a/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/chocolateyInstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000000..6e9af8f601
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/chocolateyInstall.ps1
@@ -0,0 +1,7 @@
+$ErrorActionPreference = 'Stop'
+
+$toolsDir = Split-Path $MyInvocation.MyCommand.Definition
+$filePath = Join-Path $toolsDir "shimwithbinfile1.bat"
+
+Install-Binfile "shimwithbinfile1" "$filePath"
+Write-Output "$env:PackageName $env:PackageVersion Installed"
diff --git a/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/chocolateyUninstall.ps1 b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000000..f329925b82
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/chocolateyUninstall.ps1
@@ -0,0 +1,4 @@
+$ErrorActionPreference = 'Stop'
+
+Write-Output "Oops, we've forgotten to call 'Uninstall-BinFile `"shimwithbinfile1`"'"
+Write-Output "$env:PackageName $env:PackageVersion Uninstalled"
diff --git a/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/shimwithbinfile1.bat b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/shimwithbinfile1.bat
new file mode 100644
index 0000000000..afaf360d37
--- /dev/null
+++ b/src/chocolatey.tests.integration/context/shims/shimwithbinfile/1.0.0/tools/shimwithbinfile1.bat
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs b/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs
index f0856ff6ac..f20a54e192 100644
--- a/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs
+++ b/src/chocolatey.tests.integration/scenarios/InstallScenarios.cs
@@ -3391,5 +3391,372 @@ public void should_not_install_any_packages()
Results.Count().ShouldEqual(0);
}
}
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_with_noshims : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimbasepackage";
+ Scenario.add_packages_to_source_location(Configuration, "shimbasepackage.1.0.0*" + Constants.PackageExtension);
+ Configuration.NoShims = true;
+ }
+
+ public override void Because()
+ {
+ Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_target()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var target = Path.Combine(packageDir, "tools", "shimbasepackage1.exe");
+
+ File.Exists(target).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_not_create_a_shim_for_the_package()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimbasepackage1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+ }
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_with_dependencies_and_noshims : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimhasdependency";
+ Scenario.add_packages_to_source_location(Configuration, "shimhasdependency.1.0.0*" + Constants.PackageExtension);
+ Scenario.add_packages_to_source_location(Configuration, "shimbasepackage.1.0.0*" + Constants.PackageExtension);
+ Configuration.NoShims = true;
+ }
+
+ public override void Because()
+ {
+ Results = Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_targets()
+ {
+ var targetsExist = true;
+ var errorMessage = string.Empty;
+
+ foreach (var packageResult in Results)
+ {
+ var target = Path.Combine(packageResult.Value.InstallLocation, "tools", packageResult.Value.Name + "1.exe");
+
+ if (!File.Exists(target))
+ {
+ targetsExist = false;
+ errorMessage = "Target file missing: {0}".format_with(target);
+ break;
+ }
+ }
+
+ targetsExist.ShouldBeTrue(errorMessage);
+ }
+
+ [Fact]
+ public void should_not_create_a_shim_for_the_package()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimhasdependency1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+
+ [Fact]
+ public void should_create_a_shim_for_the_dependency()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimbasepackage1.exe");
+
+ File.Exists(shimfile).ShouldBeTrue();
+ }
+ }
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_with_dependencies_and_noshimsglobal : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimhasdependency";
+ Scenario.add_packages_to_source_location(Configuration, "shimhasdependency.1.0.0*" + Constants.PackageExtension);
+ Scenario.add_packages_to_source_location(Configuration, "shimbasepackage.1.0.0*" + Constants.PackageExtension);
+ Configuration.NoShimsGlobal = true;
+ }
+
+ public override void Because()
+ {
+ Results = Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_targets()
+ {
+ var targetsExist = true;
+ var errorMessage = string.Empty;
+
+ foreach (var packageResult in Results)
+ {
+ var target = Path.Combine(packageResult.Value.InstallLocation, "tools", packageResult.Value.Name + "1.exe");
+
+ if (!File.Exists(target))
+ {
+ targetsExist = false;
+ errorMessage = "Target file missing: {0}".format_with(target);
+ break;
+ }
+ }
+
+ targetsExist.ShouldBeTrue(errorMessage);
+ }
+
+ [Fact]
+ public void should_not_create_a_shim_for_the_package()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimhasdependency1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+
+ [Fact]
+ public void should_not_create_a_shim_for_the_dependency()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimbasepackage1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+ }
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_with_install_bin_file : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimwithbinfile";
+ Scenario.add_packages_to_source_location(Configuration, "shimwithbinfile.1.0.0*" + Constants.PackageExtension);
+ }
+
+ public override void Because()
+ {
+ Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_not_see_the_shim_as_an_existing_shim_and_remove_it()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimwithbinfile1.exe");
+
+ File.Exists(shimfile).ShouldBeTrue();
+ }
+ }
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_with_install_bin_file_and_noshims : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimwithbinfile";
+ Scenario.add_packages_to_source_location(Configuration, "shimwithbinfile.1.0.0*" + Constants.PackageExtension);
+ Configuration.NoShims = true;
+ }
+
+ public override void Because()
+ {
+ Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_target()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var target = Path.Combine(packageDir, "tools", "shimwithbinfile1.bat");
+
+ File.Exists(target).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_not_create_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimwithbinfile1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+ }
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_that_tries_to_overwrite_its_own_shim : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimoverwrite";
+ Scenario.add_packages_to_source_location(Configuration, "shimoverwrite.1.0.0*" + Constants.PackageExtension);
+ }
+
+ public override void Because()
+ {
+ Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_targets()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var toolsPath = Path.Combine(packageDir, "tools");
+
+ string[] targets = {
+ Path.Combine(toolsPath, "shimoverwrite1.exe"),
+ Path.Combine(toolsPath, "install", "shimoverwrite1.exe")
+ };
+
+ var targetsExist = true;
+ var errorMessage = string.Empty;
+
+ foreach (string target in targets)
+ {
+ if (!File.Exists(target))
+ {
+ targetsExist = false;
+ errorMessage = "Target file missing: {0}".format_with(target);
+ break;
+ }
+ }
+
+ targetsExist.ShouldBeTrue(errorMessage);
+ }
+
+ [Fact]
+ public void should_have_an_error_message()
+ {
+ bool expectedMessage = false;
+ foreach (var message in MockLogger.MessagesFor(LogLevel.Error).or_empty_list_if_null())
+ {
+ if (message.Contains("cannot overwrite")) expectedMessage = true;
+ }
+
+ expectedMessage.ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_create_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimoverwrite1.exe");
+
+ File.Exists(shimfile).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_have_a_shim_with_target_in_tools_folder()
+ {
+ var messages = new List();
+
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimoverwrite1.exe");
+ CommandExecutor.execute(
+ shimfile,
+ "--shimgen-noop",
+ 10,
+ stdOutAction: (s, e) => messages.Add(e.Data),
+ stdErrAction: (s, e) => messages.Add(e.Data)
+ );
+
+ var messageFound = false;
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var path = Path.Combine(packageDir, "tools", "shimoverwrite1.exe");
+
+ foreach (var message in messages.or_empty_list_if_null())
+ {
+ if (string.IsNullOrWhiteSpace(message)) continue;
+ if (message.Contains(path)) messageFound = true;
+ }
+
+ messageFound.ShouldBeTrue("Target file message not found for: {0}".format_with(path));
+ }
+ }
+
+ [Concern(typeof(ChocolateyInstallCommand))]
+ public class when_installing_a_package_that_tries_to_overwrite_another_shim : ScenariosBase
+ {
+ public override void Context()
+ {
+ base.Context();
+ Configuration.PackageNames = Configuration.Input = "shimoverwriteother";
+ Scenario.add_packages_to_source_location(Configuration, "shimoverwriteother.1.0.0*" + Constants.PackageExtension);
+ Scenario.add_packages_to_source_location(Configuration, "shimbasepackage.1.0.0*" + Constants.PackageExtension);
+ }
+
+ public override void Because()
+ {
+ Service.install_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_target()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+
+ // this matches the name of the existing shim from the shimbasepackage dependency
+ var target = Path.Combine(packageDir, "tools", "shimbasepackage1.exe");
+
+ File.Exists(target).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_have_an_error_message()
+ {
+ bool expectedMessage = false;
+ foreach (var message in MockLogger.MessagesFor(LogLevel.Error).or_empty_list_if_null())
+ {
+ if (message.Contains("cannot overwrite")) expectedMessage = true;
+ }
+
+ expectedMessage.ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_have_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimbasepackage1.exe");
+
+ File.Exists(shimfile).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_have_a_shim_with_target_in_other_package_tools_folder()
+ {
+ var messages = new List();
+
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimbasepackage1.exe");
+ CommandExecutor.execute(
+ shimfile,
+ "--shimgen-noop",
+ 10,
+ stdOutAction: (s, e) => messages.Add(e.Data),
+ stdErrAction: (s, e) => messages.Add(e.Data)
+ );
+
+ var messageFound = false;
+ var dependencyDir = Path.Combine(Scenario.get_top_level(), "lib", "shimbasepackage");
+ var path = Path.Combine(dependencyDir, "tools", "shimbasepackage1.exe");
+
+ foreach (var message in messages.or_empty_list_if_null())
+ {
+ if (string.IsNullOrWhiteSpace(message)) continue;
+ if (message.Contains(path)) messageFound = true;
+ }
+
+ messageFound.ShouldBeTrue("Target file message not found for: {0}".format_with(path));
+ }
+ }
}
}
diff --git a/src/chocolatey.tests.integration/scenarios/UninstallScenarios.cs b/src/chocolatey.tests.integration/scenarios/UninstallScenarios.cs
index 2279bb3ff1..6471a8ce78 100644
--- a/src/chocolatey.tests.integration/scenarios/UninstallScenarios.cs
+++ b/src/chocolatey.tests.integration/scenarios/UninstallScenarios.cs
@@ -1047,5 +1047,43 @@ public void should_have_expected_error_in_package_result()
errorFound.ShouldBeTrue();
}
}
+
+ [Concern(typeof(ChocolateyUninstallCommand))]
+ public class when_uninstalling_a_package_that_forgets_to_call_uninstall_bin_file : ScenariosBase
+ {
+ private string shimFile;
+ private bool shimExisted;
+
+ public override void Context()
+ {
+ Configuration = Scenario.upgrade();
+ Scenario.reset(Configuration);
+ Service = NUnitSetup.Container.GetInstance();
+
+ Configuration.PackageNames = Configuration.Input = "shimwithbinfile";
+ Scenario.add_packages_to_source_location(Configuration, Configuration.Input + "*" + Constants.PackageExtension);
+ Scenario.install_package(Configuration, "shimwithbinfile", "1.0.0");
+ }
+
+ public override void Because()
+ {
+ shimFile = Path.Combine(Scenario.get_top_level(), "bin", "shimwithbinfile1.exe");
+ shimExisted = File.Exists(shimFile);
+
+ Service.uninstall_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_had_a_shim()
+ {
+ shimExisted.ShouldBeTrue(shimFile);
+ }
+
+ [Fact]
+ public void should_have_removed_the_shim()
+ {
+ File.Exists(shimFile).ShouldBeFalse();
+ }
+ }
}
}
diff --git a/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs b/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs
index b9e152fcb0..b4ac0752a8 100644
--- a/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs
+++ b/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs
@@ -3182,5 +3182,207 @@ public void should_skip_packages_in_except_list()
upgradePackageResult.Count.ShouldEqual(0, "upgradepackage should not be in the results list");
}
}
+
+ [Concern(typeof(ChocolateyUpgradeCommand))]
+ public class when_upgrading_a_package_with_noshims : ScenariosBase
+ {
+ public override void Context()
+ {
+ Configuration = Scenario.upgrade();
+ Scenario.reset(Configuration);
+ Service = NUnitSetup.Container.GetInstance();
+
+ Configuration.PackageNames = Configuration.Input = "shimupgrade";
+ Scenario.add_packages_to_source_location(Configuration, Configuration.Input + "*" + Constants.PackageExtension);
+ Configuration.Version = "1.0.0";
+ Configuration.NoShims = true;
+ }
+
+ public override void Because()
+ {
+ Service.upgrade_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_shim_target()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var target = Path.Combine(packageDir, "tools", "shimupgrade1.exe");
+
+ File.Exists(target).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_not_create_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+ }
+
+ [Concern(typeof(ChocolateyUpgradeCommand))]
+ public class when_upgrading_a_package_with_shims_that_errors : ScenariosBase
+ {
+ public override void Context()
+ {
+ Configuration = Scenario.upgrade();
+ Scenario.reset(Configuration);
+ Service = NUnitSetup.Container.GetInstance();
+
+ Configuration.PackageNames = Configuration.Input = "shimupgrade";
+ Scenario.add_packages_to_source_location(Configuration, Configuration.Input + "*" + Constants.PackageExtension);
+ Scenario.install_package(Configuration, "shimupgrade", "1.0.0");
+
+ // version 2.0.0 errors on script install
+ Configuration.Version = "2.0.0";
+ }
+
+ public override void Because()
+ {
+ Service.upgrade_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_original_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade1.exe");
+
+ File.Exists(shimfile).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_not_create_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade2.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+ }
+
+ [Concern(typeof(ChocolateyUpgradeCommand))]
+ public class when_upgrading_a_package_with_shims : ScenariosBase
+ {
+ private string _original_shim = string.Empty;
+ private bool _original_shim_existed = false;
+
+ public override void Context()
+ {
+ Configuration = Scenario.upgrade();
+ Scenario.reset(Configuration);
+ Service = NUnitSetup.Container.GetInstance();
+
+ Configuration.PackageNames = Configuration.Input = "shimupgrade";
+ Scenario.add_packages_to_source_location(Configuration, Configuration.Input + "*" + Constants.PackageExtension);
+ Scenario.install_package(Configuration, "shimupgrade", "1.0.0");
+
+ _original_shim = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade1.exe");
+ _original_shim_existed = File.Exists(_original_shim);
+
+ // version 3.0.0 is okay
+ Configuration.Version = "3.0.0";
+ }
+
+ public override void Because()
+ {
+ Service.upgrade_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_had_original_shim()
+ {
+ var errorMessage = "Original shim file was not created: {0}".format_with(_original_shim);
+
+ _original_shim_existed.ShouldBeTrue(errorMessage);
+ }
+
+ [Fact]
+ public void should_have_shim_target()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var target = Path.Combine(packageDir, "tools", "shimupgrade3.exe");
+
+ File.Exists(target).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_not_have_original_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+
+ [Fact]
+ public void should_create_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade3.exe");
+
+ File.Exists(shimfile).ShouldBeTrue();
+ }
+ }
+
+ [Concern(typeof(ChocolateyUpgradeCommand))]
+ public class when_upgrading_a_package_with_shims_with_noshims : ScenariosBase
+ {
+ private string _original_shim = string.Empty;
+ private bool _original_shim_existed = false;
+
+ public override void Context()
+ {
+ Configuration = Scenario.upgrade();
+ Scenario.reset(Configuration);
+ Service = NUnitSetup.Container.GetInstance();
+
+ Configuration.PackageNames = Configuration.Input = "shimupgrade";
+ Scenario.add_packages_to_source_location(Configuration, Configuration.Input + "*" + Constants.PackageExtension);
+ Scenario.install_package(Configuration, "shimupgrade", "1.0.0");
+
+ _original_shim = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade1.exe");
+ _original_shim_existed = File.Exists(_original_shim);
+
+ // version 3.0.0 is okay
+ Configuration.Version = "3.0.0";
+ Configuration.NoShims = true;
+ }
+
+ public override void Because()
+ {
+ Service.upgrade_run(Configuration);
+ }
+
+ [Fact]
+ public void should_have_had_original_shim()
+ {
+ var errorMessage = "Original shim file was not created: {0}".format_with(_original_shim);
+
+ _original_shim_existed.ShouldBeTrue(errorMessage);
+ }
+
+ [Fact]
+ public void should_have_shim_target()
+ {
+ var packageDir = Path.Combine(Scenario.get_top_level(), "lib", Configuration.PackageNames);
+ var target = Path.Combine(packageDir, "tools", "shimupgrade3.exe");
+
+ File.Exists(target).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_not_have_original_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade1.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+
+ [Fact]
+ public void should_not_create_a_shim()
+ {
+ var shimfile = Path.Combine(Scenario.get_top_level(), "bin", "shimupgrade3.exe");
+
+ File.Exists(shimfile).ShouldBeFalse();
+ }
+ }
}
}
diff --git a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyInstallCommandSpecs.cs b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyInstallCommandSpecs.cs
index f32acfd5e6..5ff6ddc5c9 100644
--- a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyInstallCommandSpecs.cs
+++ b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyInstallCommandSpecs.cs
@@ -235,6 +235,18 @@ public void should_add_short_version_of_password_to_the_option_set()
{
optionSet.Contains("p").ShouldBeTrue();
}
+
+ [Fact]
+ public void should_add_noshims_to_the_option_set()
+ {
+ optionSet.Contains("noshims").ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_add_noshimsglobal_to_the_option_set()
+ {
+ optionSet.Contains("noshimsglobal").ShouldBeTrue();
+ }
}
public class when_handling_additional_argument_parsing : ChocolateyInstallCommandSpecsBase
diff --git a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyUpgradeCommandSpecs.cs b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyUpgradeCommandSpecs.cs
index 15f16f875f..41dc123fdb 100644
--- a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyUpgradeCommandSpecs.cs
+++ b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyUpgradeCommandSpecs.cs
@@ -217,6 +217,18 @@ public void should_add_short_version_of_password_to_the_option_set()
{
optionSet.Contains("p").ShouldBeTrue();
}
+
+ [Fact]
+ public void should_add_noshims_to_the_option_set()
+ {
+ optionSet.Contains("noshims").ShouldBeTrue();
+ }
+
+ [Fact]
+ public void should_add_noshimsglobal_to_the_option_set()
+ {
+ optionSet.Contains("noshimsglobal").ShouldBeTrue();
+ }
}
public class when_handling_additional_argument_parsing : ChocolateyUpgradeCommandSpecsBase
diff --git a/src/chocolatey/chocolatey.csproj b/src/chocolatey/chocolatey.csproj
index f1d4e6bc7e..6e88de73e8 100644
--- a/src/chocolatey/chocolatey.csproj
+++ b/src/chocolatey/chocolatey.csproj
@@ -134,6 +134,9 @@
+
+
+
diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs
index ba9cf33556..1c2fcc5669 100644
--- a/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs
+++ b/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs
@@ -180,6 +180,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
configuration.Features.UsePackageRepositoryOptimizations = false;
}
})
+ .Add("noshims|no-shims",
+ "No Shims - Stop shims being created for the package. Defaults to false. Available in 0.10.16+.",
+ option => configuration.NoShims = option != null)
+ .Add("noshimsglobal|no-shims-global",
+ "No Shims Global - Stop shims being created for the package and its dependencies. Defaults to false. Available in 0.10.16+.",
+ option => configuration.NoShimsGlobal = option != null)
;
//todo: package name can be a url / installertype
diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs
index f8a4c31f6a..64e061ee1e 100644
--- a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs
+++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs
@@ -220,6 +220,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
configuration.Features.UsePackageRepositoryOptimizations = false;
}
})
+ .Add("noshims|no-shims",
+ "No Shims - Stop shims being created for the package. Defaults to false. Available in 0.10.16+.",
+ option => configuration.NoShims = option != null)
+ .Add("noshimsglobal|no-shims-global",
+ "No Shims Global - Stop shims being created for the package and its dependencies. Defaults to false. Available in 0.10.16+.",
+ option => configuration.NoShimsGlobal = option != null)
;
}
diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
index c5cc33f73f..13f842977e 100644
--- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
+++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
@@ -221,6 +221,8 @@ private void append_output(StringBuilder propertyValues, string append)
public string DownloadChecksum64 { get; set; }
public string DownloadChecksumType { get; set; }
public string DownloadChecksumType64 { get; set; }
+ public bool NoShims { get; set; }
+ public bool NoShimsGlobal { get; set; }
///
/// Configuration values provided by choco.
diff --git a/src/chocolatey/infrastructure.app/domain/ShimRecord.cs b/src/chocolatey/infrastructure.app/domain/ShimRecord.cs
new file mode 100644
index 0000000000..370ade1e27
--- /dev/null
+++ b/src/chocolatey/infrastructure.app/domain/ShimRecord.cs
@@ -0,0 +1,60 @@
+// Copyright © 2017 - 2018 Chocolatey Software, Inc
+// Copyright © 2011 - 2017 RealDimensions Software, LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+//
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace chocolatey.infrastructure.app.domain
+{
+ public class ShimRecord
+ {
+ ///
+ /// The exe file from the shim directory.
+ ///
+ public string ExeFile { get; set; }
+
+ ///
+ /// The package name (could be empty).
+ ///
+ public string PackageName { get; set; }
+
+ ///
+ /// The file being shimmed (could be empty).
+ ///
+ public string TargetFile { get; set; }
+
+ ///
+ /// Creates a ShimRecord instance.
+ ///
+ /// The exe file from the shim directory.
+ public ShimRecord(string exeFile)
+ {
+ ExeFile = exeFile;
+ PackageName = string.Empty;
+ TargetFile = string.Empty;
+ }
+
+ ///
+ /// Creates a ShimRecord instance.
+ ///
+ /// The exe file from the shim directory.
+ /// The package name.
+ /// The file being shimmed.
+ public ShimRecord(string exeFile, string packageName, string targetFile)
+ {
+ ExeFile = exeFile;
+ PackageName = packageName;
+ TargetFile = targetFile;
+ }
+ }
+}
diff --git a/src/chocolatey/infrastructure.app/domain/ShimRegistry.cs b/src/chocolatey/infrastructure.app/domain/ShimRegistry.cs
new file mode 100644
index 0000000000..2df0f79600
--- /dev/null
+++ b/src/chocolatey/infrastructure.app/domain/ShimRegistry.cs
@@ -0,0 +1,306 @@
+// Copyright © 2017 - 2018 Chocolatey Software, Inc
+// Copyright © 2011 - 2017 RealDimensions Software, LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+//
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace chocolatey.infrastructure.app.domain
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using filesystem;
+
+ public class ShimRegistry
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly string _shimsLocation;
+ private readonly string _packagesLocation;
+ private readonly string _pathRoot;
+ private readonly Regex _packageRegex;
+ private ShimStore _store;
+
+ ///
+ /// The level required when accessing the data.
+ ///
+ public enum DataLevel
+ {
+ Current,
+ Latest
+ }
+
+ ///
+ /// Creates a ShimRegistry instance.
+ ///
+ /// The file system.
+ public ShimRegistry(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ _shimsLocation = ApplicationParameters.ShimsLocation;
+ _packagesLocation = ApplicationParameters.PackagesLocation;
+ _pathRoot = Path.GetPathRoot(_shimsLocation);
+ _packageRegex = new Regex(@"{0}\\(.[^\\]+)\\".format_with(_packagesLocation.Replace(@"\", @"\\")),
+ RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ }
+
+ ///
+ /// Adds a shim to the store.
+ ///
+ /// The shim exe file.
+ /// The package name.
+ /// The file being shimmed.
+ public void add(string exeFile, string packageName, string targetFile)
+ {
+ ensure_storage_exists(DataLevel.Current);
+ var record = new ShimRecord(exeFile, packageName, targetFile);
+ _store.add_record(record);
+ }
+
+ ///
+ /// Gets a shim record from the store it if exists.
+ ///
+ /// The shim exe file.
+ /// The record or null.
+ public ShimRecord get(string exeFile)
+ {
+ ensure_storage_exists(DataLevel.Current);
+ return _store.get_record(exeFile);
+ }
+
+ ///
+ /// Updates the store from the file system.
+ ///
+ public void create_snapshot()
+ {
+ ensure_storage_exists(DataLevel.Latest);
+ }
+
+ ///
+ /// Returns all shim records for the package.
+ ///
+ /// The package name.
+ /// The shim records.
+ public IList get_all(string packageName)
+ {
+ ensure_storage_exists(DataLevel.Latest);
+ return _store.get_all_records(packageName);
+ }
+
+ ///
+ /// Returns all shim records for the package that have not been modified.
+ ///
+ /// The package name.
+ /// The unmodified shim records.
+ public IList get_snapshot(string packageName)
+ {
+ ensure_storage_exists(DataLevel.Current);
+ var exeFiles = get_shim_exe_files();
+
+ return _store.get_snapshot_records(exeFiles, packageName);
+ }
+
+ ///
+ /// Removes a shim from the store.
+ ///
+ /// The shim exe file.
+ public void remove(string exeFile)
+ {
+ ensure_storage_exists(DataLevel.Current);
+ _store.remove_record(exeFile);
+ }
+
+ ///
+ /// Initializes or updates the store.
+ ///
+ /// The data level required.
+ private void ensure_storage_exists(DataLevel level)
+ {
+ if (_store == null)
+ {
+ init_store();
+ }
+ else if (level == DataLevel.Latest)
+ {
+ update_store();
+ }
+ }
+
+ ///
+ /// Creates and initializes the store from the file system.
+ ///
+ private void init_store()
+ {
+ _store = new ShimStore(_fileSystem);
+ var exeFiles = get_shim_exe_files();
+
+ foreach (string file in exeFiles.or_empty_list_if_null())
+ {
+ _store.add_record(get_shim_data(file));
+ }
+ }
+
+ ///
+ /// Updates the store from the file system.
+ ///
+ private void update_store()
+ {
+ var exeFiles = get_shim_exe_files();
+
+ foreach (string file in _store.get_files_to_update(exeFiles))
+ {
+ _store.add_record(get_shim_data(file));
+ }
+ }
+
+ ///
+ /// Gets the exe files in the shim directory.
+ ///
+ /// The exe files.
+ private IEnumerable get_shim_exe_files()
+ {
+ return _fileSystem.get_files(_shimsLocation, pattern: "*.exe");
+ }
+
+ ///
+ /// Extracts any shim data from an exe file.
+ ///
+ /// The exe file
+ /// A record containing full or partial shim data.
+ private ShimRecord get_shim_data(string exeFile)
+ {
+ var item = new ShimRecord(exeFile);
+
+ // check the exe is shimgen generated from the file info
+ FileVersionInfo info = FileVersionInfo.GetVersionInfo(exeFile);
+
+ // note that this will not catch chocolatey specific shims
+ if (!info.ProductName.contains("shimgen")) return item;
+
+ // extract the target file from the binary
+ string target = find_shim_target(exeFile);
+
+ item.TargetFile = check_and_get_targetFile(target);
+
+ // try and extract the package name
+ if (item.TargetFile.contains(_packagesLocation))
+ {
+ var match = _packageRegex.Match(item.TargetFile).Groups[1];
+ if (match != null)
+ {
+ item.PackageName = match.Value;
+ }
+ }
+
+ return item;
+ }
+
+ ///
+ /// Searches an exe file for the shim target file name.
+ ///
+ /// The exe file.
+ /// The target file name or null.
+ private string find_shim_target(string exeFile)
+ {
+ string target = null;
+ byte[] bytes = File.ReadAllBytes(exeFile);
+
+ // search for the pattern: file at ''
+ int startIndex = 0;
+ string pattern = "file at '";
+ int foundIndex = search_binary(bytes, pattern, startIndex);
+
+ if (foundIndex == -1)
+ {
+ return target;
+ }
+
+ // search for the closing single-quote
+ startIndex = foundIndex + (pattern.Length * 2);
+ pattern = "'";
+ foundIndex = search_binary(bytes, pattern, startIndex);
+
+ if (foundIndex != -1)
+ {
+ int count = foundIndex - startIndex;
+ var slice = new byte[count];
+ Array.Copy(bytes, startIndex, slice, 0, count);
+ target = Encoding.Unicode.GetString(slice);
+ }
+
+ return target;
+ }
+
+ ///
+ /// Searches an array of bytes for a pattern.
+ ///
+ /// The array of bytes.
+ /// The pattern to search for.
+ /// The index to start searching from.
+ /// The index of the pattern or -1.
+ private int search_binary(byte[] bytes, string search, int startIndex)
+ {
+ int foundIndex = -1;
+ byte[] pattern = Encoding.Unicode.GetBytes(search);
+ int end = bytes.Length - pattern.Length + 1;
+ int i = startIndex;
+ int m = 0;
+
+ while (i < end)
+ {
+ if (bytes[i] == pattern[m])
+ {
+ ++m;
+ if (m == pattern.Length) {
+ foundIndex = i - pattern.Length + 1;
+ break;
+ }
+ }
+ else if (m > 0)
+ {
+ i -= m;
+ m = 0;
+ }
+ ++i;
+ }
+
+ return foundIndex;
+ }
+
+ ///
+ /// Checks that the extracted file name is valid.
+ ///
+ /// The target file name.
+ /// The fully qualified path or an empty string.
+ private string check_and_get_targetFile(string target)
+ {
+ if (string.IsNullOrEmpty(target)) return string.Empty;
+
+ if (!target.Replace('/', '\\').StartsWith(_pathRoot, StringComparison.OrdinalIgnoreCase))
+ {
+ target = _fileSystem.combine_paths(_packagesLocation, target);
+ }
+
+ try
+ {
+ return _fileSystem.get_full_path(target);
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+ }
+}
diff --git a/src/chocolatey/infrastructure.app/domain/ShimStore.cs b/src/chocolatey/infrastructure.app/domain/ShimStore.cs
new file mode 100644
index 0000000000..ce1f3ae335
--- /dev/null
+++ b/src/chocolatey/infrastructure.app/domain/ShimStore.cs
@@ -0,0 +1,260 @@
+// Copyright © 2017 - 2018 Chocolatey Software, Inc
+// Copyright © 2011 - 2017 RealDimensions Software, LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+//
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace chocolatey.infrastructure.app.domain
+{
+ using System;
+ using System.Collections.Generic;
+ using filesystem;
+
+ public class ShimStore
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly IDictionary _items;
+
+ public class BaseRecord
+ {
+ ///
+ /// The exe file from the shim directory.
+ ///
+ public string ExeFile { get; set; }
+
+ ///
+ /// The package name (could be empty).
+ ///
+ public string PackageName { get; set; }
+
+ ///
+ /// The file being shimmed (could be empty).
+ ///
+ public string TargetFile { get; set; }
+
+ ///
+ /// ExeFile last modification time.
+ ///
+ public Int64 LastModified { get; set; }
+
+ ///
+ /// Internal flag for synchronizing.
+ ///
+ public bool Current { get; set; }
+
+ ///
+ /// Creates a BaseRecord instance.
+ ///
+ /// The data record.
+ /// Last modification time of the exe file.
+ public BaseRecord(ShimRecord record, Int64 lastModified)
+ {
+ ExeFile = record.ExeFile;
+ PackageName = record.PackageName;
+ TargetFile = record.TargetFile;
+ LastModified = lastModified;
+ Current = false;
+ }
+ }
+
+ ///
+ /// Creates a ShimStore instance.
+ ///
+ /// The filesystem.
+ public ShimStore(IFileSystem filesystem)
+ {
+ _fileSystem = filesystem;
+ _items = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Adds a record to the store.
+ ///
+ /// The record.
+ public void add_record(ShimRecord record)
+ {
+ string key = get_key(record.ExeFile);
+ _items[key] = new BaseRecord(record, get_timestamp(record.ExeFile));
+ }
+
+ ///
+ /// Removes a record from the store.
+ ///
+ /// The exe file to remove.
+ public void remove_record(string exeFile)
+ {
+ string key = get_key(exeFile);
+ _items.Remove(key);
+ }
+
+ ///
+ /// Gets a record from the store if it exsists.
+ ///
+ /// The exe file to get
+ /// The record or null.
+ public ShimRecord get_record(string exeFile)
+ {
+ BaseRecord record;
+ if (_items.TryGetValue(get_key(exeFile), out record))
+ {
+ return new ShimRecord(record.ExeFile, record.PackageName, record.TargetFile);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Synchronizes the store with the file system.
+ ///
+ /// The exe files in the shims directory.
+ /// A list of exe files that need adding or updating.
+ public IList get_files_to_update(IEnumerable exeFiles)
+ {
+ var updates = new List();
+ BaseRecord record;
+
+ // set found records as current and collect new or out-of-date ones
+ foreach (string file in exeFiles.or_empty_list_if_null())
+ {
+ if (_items.TryGetValue(get_key(file), out record))
+ {
+ if (get_timestamp(file) > record.LastModified)
+ {
+ updates.Add(file);
+ }
+
+ record.Current = true;
+ }
+ else
+ {
+ updates.Add(file);
+ }
+ }
+
+ remove_non_current();
+
+ return updates;
+ }
+
+ ///
+ /// Returns all records for the package.
+ ///
+ /// The package name.
+ /// The list of records.
+ public IList get_all_records(string forPackage)
+ {
+ var records = new List();
+ var values = _items.Values;
+
+ foreach (BaseRecord record in values)
+ {
+ if (record.PackageName.Equals(forPackage, StringComparison.OrdinalIgnoreCase))
+ {
+ records.Add(get_record_from_base(record));
+ }
+ }
+
+ return records;
+ }
+
+ ///
+ /// Returns all records for the package that have not been modified.
+ ///
+ /// The exe files in the shims directory.
+ /// The package name.
+ /// The list of unmodified records.
+ public IList get_snapshot_records(IEnumerable exeFiles, string forPackage)
+ {
+ var records = new List();
+ BaseRecord record;
+
+ // set found records as current and collect non-changed items
+ foreach (string file in exeFiles.or_empty_list_if_null())
+ {
+ if (_items.TryGetValue(get_key(file), out record))
+ {
+ if (record.PackageName.Equals(forPackage, StringComparison.OrdinalIgnoreCase))
+ {
+ if (get_timestamp(file) == record.LastModified)
+ {
+ records.Add(get_record_from_base(record));
+ }
+
+ }
+
+ record.Current = true;
+ }
+ }
+
+ remove_non_current();
+
+ return records;
+ }
+
+ ///
+ /// Gets the storage key.
+ ///
+ /// The exe file.
+ /// The file name of the exe file.
+ private string get_key(string exeFile)
+ {
+ return _fileSystem.get_file_name(exeFile);
+ }
+
+ ///
+ /// Create a ShimRecord from an internal base record.
+ ///
+ /// The internal base record.
+ /// The ShimRecord.
+ private ShimRecord get_record_from_base(BaseRecord record)
+ {
+ return new ShimRecord(record.ExeFile, record.PackageName, record.TargetFile);
+ }
+
+ ///
+ /// Gets the timestamp of a file.
+ ///
+ /// The exe file.
+ /// The last modified UTC time.
+ private Int64 get_timestamp(string exeFile)
+ {
+ return _fileSystem.get_file_modified_date(exeFile).ToFileTimeUtc();
+ }
+
+ ///
+ /// Removes records marked as not current and resets the property.
+ ///
+ /// Only call this after setting the current records to true.
+ private void remove_non_current()
+ {
+ var removed = new List();
+
+ // collect the non-current records and reset property
+ foreach (KeyValuePair record in _items)
+ {
+ if (!record.Value.Current)
+ {
+ removed.Add(record.Key);
+ }
+
+ record.Value.Current = false;
+ }
+
+ // remove the non-current records
+ foreach (string key in removed)
+ {
+ _items.Remove(key);
+ }
+ }
+ }
+}
diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs
index 0b4295d93d..231f577237 100644
--- a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs
+++ b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs
@@ -344,6 +344,9 @@ public virtual void handle_package_result(PackageResult packageResult, Chocolate
if (packageResult.Success && config.Information.PlatformType == PlatformType.Windows)
{
+ // take the snapshot before running any install/uninstall scripts
+ _shimgenService.take_snapshot();
+
if (!config.SkipPackageInstallProvider)
{
var installersBefore = _registryService.get_installer_keys();
diff --git a/src/chocolatey/infrastructure.app/services/IShimGenerationService.cs b/src/chocolatey/infrastructure.app/services/IShimGenerationService.cs
index c6916ed5c6..2878021490 100644
--- a/src/chocolatey/infrastructure.app/services/IShimGenerationService.cs
+++ b/src/chocolatey/infrastructure.app/services/IShimGenerationService.cs
@@ -16,6 +16,7 @@
namespace chocolatey.infrastructure.app.services
{
+ using System.Collections.Generic;
using configuration;
using results;
@@ -34,5 +35,10 @@ public interface IShimGenerationService
/// The configuration.
/// The package result.
void uninstall(ChocolateyConfiguration configuration, PackageResult packageResult);
+
+ ///
+ /// Takes a snapshot of the existing shimgens
+ ///
+ void take_snapshot();
}
}
diff --git a/src/chocolatey/infrastructure.app/services/PowershellService.cs b/src/chocolatey/infrastructure.app/services/PowershellService.cs
index 653c22d5b7..faeb4341f6 100644
--- a/src/chocolatey/infrastructure.app/services/PowershellService.cs
+++ b/src/chocolatey/infrastructure.app/services/PowershellService.cs
@@ -398,11 +398,14 @@ public void prepare_powershell_environment(IPackage package, ChocolateyConfigura
Environment.SetEnvironmentVariable("chocolateyChecksumType64", null);
Environment.SetEnvironmentVariable("chocolateyForceX86", null);
Environment.SetEnvironmentVariable("DownloadCacheAvailable", null);
+ Environment.SetEnvironmentVariable("chocolateyNoShims", null);
+
+ var isDependency = PackageUtility.package_is_a_dependency(configuration, package.Id);
// we only want to pass the following args to packages that would apply.
// like choco install git --params '' should pass those params to git.install,
// but not another package unless the switch apply-install-arguments-to-dependencies is used
- if (!PackageUtility.package_is_a_dependency(configuration, package.Id) || configuration.ApplyInstallArgumentsToDependencies)
+ if (!isDependency || configuration.ApplyInstallArgumentsToDependencies)
{
this.Log().Debug(ChocolateyLoggers.Verbose, "Setting installer args for {0}".format_with(package.Id));
Environment.SetEnvironmentVariable("installArguments", configuration.InstallArguments);
@@ -417,13 +420,20 @@ public void prepare_powershell_environment(IPackage package, ChocolateyConfigura
// we only want to pass package parameters to packages that would apply.
// but not another package unless the switch apply-package-parameters-to-dependencies is used
- if (!PackageUtility.package_is_a_dependency(configuration, package.Id) || configuration.ApplyPackageParametersToDependencies)
+ if (!isDependency || configuration.ApplyPackageParametersToDependencies)
{
this.Log().Debug(ChocolateyLoggers.Verbose, "Setting package parameters for {0}".format_with(package.Id));
Environment.SetEnvironmentVariable("packageParameters", configuration.PackageParameters);
Environment.SetEnvironmentVariable("chocolateyPackageParameters", configuration.PackageParameters);
}
+ // we only want to disable shimming for packages that would apply.
+ if (configuration.NoShimsGlobal || (!isDependency && configuration.NoShims))
+ {
+ this.Log().Debug(ChocolateyLoggers.Verbose, "Setting noshims for {0}".format_with(package.Id));
+ Environment.SetEnvironmentVariable("chocolateyNoShims", "true");
+ }
+
if (!string.IsNullOrWhiteSpace(configuration.DownloadChecksum))
{
Environment.SetEnvironmentVariable("chocolateyChecksum32", configuration.DownloadChecksum);
diff --git a/src/chocolatey/infrastructure.app/services/ShimGenerationService.cs b/src/chocolatey/infrastructure.app/services/ShimGenerationService.cs
index 01d6991b24..24faecfbf6 100644
--- a/src/chocolatey/infrastructure.app/services/ShimGenerationService.cs
+++ b/src/chocolatey/infrastructure.app/services/ShimGenerationService.cs
@@ -1,13 +1,13 @@
// Copyright © 2017 - 2018 Chocolatey Software, Inc
// Copyright © 2011 - 2017 RealDimensions Software, LLC
-//
+//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
-//
+//
// You may obtain a copy of the License at
-//
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,6 +21,8 @@ namespace chocolatey.infrastructure.app.services
using System.IO;
using configuration;
using filesystem;
+ using infrastructure.app.domain;
+ using infrastructure.app.utility;
using infrastructure.commands;
using results;
@@ -33,13 +35,14 @@ public class ShimGenerationService : IShimGenerationService
private const string OUTPUT_TOKEN = "{{output}}";
private readonly string _shimGenExePath = ApplicationParameters.Tools.ShimGenExe;
private readonly IDictionary _shimGenArguments = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
-
+ private readonly ShimRegistry _registry;
public ShimGenerationService(IFileSystem fileSystem, ICommandExecutor commandExecutor)
{
_fileSystem = fileSystem;
_commandExecutor = commandExecutor;
set_shimgen_args_dictionary();
+ _registry = new ShimRegistry(_fileSystem);
}
///
@@ -87,15 +90,54 @@ public void install(ChocolateyConfiguration configuration, PackageResult package
return;
}
- //gather all .exes in the folder
- var exeFiles = _fileSystem.get_files(packageResult.InstallLocation, pattern: "*.exe", option: SearchOption.AllDirectories);
- foreach (string file in exeFiles.or_empty_list_if_null())
+ var existingShims = _registry.get_snapshot(packageResult.Name);
+ var noShims = is_shimming_disabled(configuration, packageResult);
+
+ if (noShims)
+ {
+ this.Log().Debug(() => "Automatic package shimming disabled for {0}".format_with(packageResult.Name));
+ }
+
+ if (existingShims.Count > 0)
+ {
+ this.Log().Debug(() => "Removing previous shims for {0}".format_with(packageResult.Name));
+ uninstall_shims(existingShims);
+ }
+
+ if (!noShims)
+ {
+ //gather all relevant .exes in the folder
+ var exeFiles = get_exe_files_to_shim(packageResult.InstallLocation);
+ install_shims(configuration, packageResult.Name, exeFiles);
+ }
+ }
+
+ public void uninstall(ChocolateyConfiguration configuration, PackageResult packageResult)
+ {
+ var existingShims = _registry.get_all(packageResult.Name);
+ uninstall_shims(existingShims);
+ }
+
+ public void take_snapshot()
+ {
+ _registry.create_snapshot();
+ }
+
+ ///
+ /// Installs shimgens for the package
+ ///
+ /// The configuration.
+ /// The package name.
+ /// The exe files to shim
+ private void install_shims(ChocolateyConfiguration configuration, string packageName, IList exeFiles)
+ {
+ var args = ExternalCommandArgsBuilder.build_arguments(configuration, _shimGenArguments);
+
+ foreach (string file in exeFiles)
{
- if (_fileSystem.file_exists(file + ".ignore")) continue;
bool isGui = _fileSystem.file_exists(file + ".gui");
//todo: v2 be able to determine gui automatically
- var args = ExternalCommandArgsBuilder.build_arguments(configuration, _shimGenArguments);
var shimLocation = _fileSystem.combine_paths(ApplicationParameters.ShimsLocation, _fileSystem.get_file_name(file));
var argsForPackage = args.Replace(PATH_TOKEN, file.Replace(ApplicationParameters.InstallLocation, "..\\")).Replace(OUTPUT_TOKEN, shimLocation).Replace(ICON_PATH_TOKEN, file);
if (isGui)
@@ -103,18 +145,28 @@ public void install(ChocolateyConfiguration configuration, PackageResult package
argsForPackage += " --gui";
}
+ // check for an existing shim
+ ShimRecord record = _registry.get(shimLocation);
+ if (record != null)
+ {
+ this.Log().Error(() => " ShimGen cannot overwrite shim {0} in {1} package".format_with(_fileSystem.get_file_name(file), record.PackageName));
+ this.Log().Debug(() => " Shim: {0}{1} Target: {2}{1} New target: {3}{1}".format_with(shimLocation, Environment.NewLine, record.TargetFile, file));
+ Environment.ExitCode = 1;
+ continue;
+ }
+
var exitCode = _commandExecutor.execute(
_shimGenExePath, argsForPackage, configuration.CommandExecutionTimeoutSeconds,
(s, e) =>
- {
- if (string.IsNullOrWhiteSpace(e.Data)) return;
- this.Log().Debug(() => " [ShimGen] {0}".format_with(e.Data.escape_curly_braces()));
- },
+ {
+ if (string.IsNullOrWhiteSpace(e.Data)) return;
+ this.Log().Debug(() => " [ShimGen] {0}".format_with(e.Data.escape_curly_braces()));
+ },
(s, e) =>
- {
- if (string.IsNullOrWhiteSpace(e.Data)) return;
- this.Log().Error(() => " [ShimGen] {0}".format_with(e.Data.escape_curly_braces()));
- },
+ {
+ if (string.IsNullOrWhiteSpace(e.Data)) return;
+ this.Log().Error(() => " [ShimGen] {0}".format_with(e.Data.escape_curly_braces()));
+ },
updateProcessPath: true
);
@@ -124,24 +176,67 @@ public void install(ChocolateyConfiguration configuration, PackageResult package
}
else
{
+ _registry.add(shimLocation, packageName, file);
this.Log().Info(() => " ShimGen has successfully created a {0}shim for {1}".format_with(isGui ? "gui " : string.Empty, _fileSystem.get_file_name(file)));
- this.Log().Debug(() => " Created: {0}{1} Targeting: {2}{1} IsGui:{3}{1}".format_with(shimLocation, Environment.NewLine, file, isGui));
+ this.Log().Debug(() => " Created: {0}{1} Targeting: {2}{1} IsGui: {3}{1}".format_with(shimLocation, Environment.NewLine, file, isGui));
}
}
}
- public void uninstall(ChocolateyConfiguration configuration, PackageResult packageResult)
+ ///
+ /// Uninstalls shimgens for the package
+ ///
+ /// The shim records for the package.
+ private void uninstall_shims(IList existingShims)
{
- //gather all .exes in the folder
- var exeFiles = _fileSystem.get_files(packageResult.InstallLocation, pattern: "*.exe", option: SearchOption.AllDirectories);
- foreach (string file in exeFiles.or_empty_list_if_null())
+ foreach (ShimRecord record in existingShims)
{
- if (_fileSystem.file_exists(file + ".ignore")) continue;
+ this.Log().Debug(() => "Removing shim {0} targetting '{1}'".format_with(_fileSystem.get_file_name(record.ExeFile), record.TargetFile));
+ _fileSystem.delete_file(record.ExeFile);
- var shimLocation = _fileSystem.combine_paths(ApplicationParameters.ShimsLocation, _fileSystem.get_file_name(file));
- this.Log().Debug(() => "Removing shim for {0} at '{1}".format_with(_fileSystem.get_file_name(file), shimLocation));
- _fileSystem.delete_file(shimLocation);
+ if (!_fileSystem.file_exists(record.ExeFile))
+ {
+ _registry.remove(record.ExeFile);
+ }
}
}
+
+ ///
+ /// Returns the exe files to shim
+ ///
+ /// The package install location.
+ ///
+ private IList get_exe_files_to_shim(string installLocation)
+ {
+ var exeFiles = new List();
+
+ if (!_fileSystem.directory_exists(installLocation) || installLocation.is_equal_to(ApplicationParameters.InstallLocation) || installLocation.is_equal_to(ApplicationParameters.PackagesLocation))
+ {
+ return exeFiles;
+ }
+
+ var targetFiles = _fileSystem.get_files(installLocation, pattern: "*.exe", option: SearchOption.AllDirectories);
+ foreach (string file in targetFiles.or_empty_list_if_null())
+ {
+ if (!_fileSystem.file_exists(file + ".ignore"))
+ {
+ exeFiles.Add(file);
+ }
+ }
+
+ return exeFiles;
+ }
+
+ ///
+ /// Checks if shimming is disabled for the package
+ ///
+ /// The configuration.
+ /// The package result.
+ /// true if shimming is disabled
+ private bool is_shimming_disabled(ChocolateyConfiguration configuration, PackageResult packageResult)
+ {
+ return configuration.NoShimsGlobal || (configuration.NoShims
+ && !PackageUtility.package_is_a_dependency(configuration, packageResult.Package.Id));
+ }
}
-}
\ No newline at end of file
+}