diff --git a/CHANGELOG.md b/CHANGELOG.md index c2751efc6d..0689ffb1c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +## [0.9.9.5](https://github.com/chocolatey/choco/issues?q=milestone%3A0.9.9.5+is%3Aclosed) (April 20, 2015) + +### BREAKING CHANGES + + * Renamed short option `p` to `i` for list --include-programs so that `p` could be ubiquitous for password across commands that optionally can pass a password - see [#240](https://github.com/chocolatey/choco/issues/240) + +### BUG FIXES + + * Fix - Secure Sources Not Working - see [#240](https://github.com/chocolatey/choco/issues/240) + * Fix - Generate-BinFile / Remove-BinFile - see [#230](https://github.com/chocolatey/choco/issues/230) + * Fix - cpack should only include files from nuspec - see [#232](https://github.com/chocolatey/choco/issues/232) + * Fix - cpack should leave nupkg in current directory - see [#231](https://github.com/chocolatey/choco/issues/231) + * Fix - Install-PowerShellCommand uses incorrect path - see [#241](https://github.com/chocolatey/choco/issues/241) + * Fix - choco list source with redirects does not resolve - see [#171](https://github.com/chocolatey/choco/issues/171) + * Fix - choco tried to resolve disabled repo - see [#169](https://github.com/chocolatey/choco/issues/169) + * Fix - cpack nuspec results in "The path is not of a legal form" - see [#164](https://github.com/chocolatey/choco/issues/164) + * Fix - cpack hangs on security related issue - see [#160](https://github.com/chocolatey/choco/issues/160) + * Fix - spelling error in "package has been upgradeed successfully" - see [#64](https://github.com/chocolatey/choco/issues/64) + +### IMPROVEMENTS + + * Api Key and Source matching could be more intuitive - see [#228](https://github.com/chocolatey/choco/issues/238) + * Remove warning about allowGlobalConfirmation being enabled - see [#237](https://github.com/chocolatey/choco/issues/237) + * Include log file path when saying 'See the log for details' - see [#187](https://github.com/chocolatey/choco/issues/187) + * Uninstall prompts for version when there is only one installed - see [#186](https://github.com/chocolatey/choco/issues/186) + * Do not offer a default option when prompting for a user choice - see [#185](https://github.com/chocolatey/choco/issues/185) + * Remove the warning note about skipping, and instead show the warning when selecting skip - see [#183](https://github.com/chocolatey/choco/issues/183) + * Do not print PowerShell install/update scripts by default - see [#182](https://github.com/chocolatey/choco/issues/182) + ## [0.9.9.4](https://github.com/chocolatey/choco/issues?q=milestone%3A0.9.9.4+is%3Aclosed) (March 30, 2015) ### BUG FIXES diff --git a/nuget/chocolatey/chocolatey.nuspec b/nuget/chocolatey/chocolatey.nuspec index 92324bb289..c30e27142f 100644 --- a/nuget/chocolatey/chocolatey.nuspec +++ b/nuget/chocolatey/chocolatey.nuspec @@ -40,6 +40,35 @@ In that mess there is a link to the [Helper Reference](https://github.com/chocol See all - https://github.com/chocolatey/choco/blob/master/CHANGELOG.md +## 0.9.9.5 + +### BREAKING CHANGES + + * Renamed short option `p` to `i` for list --include-programs so that `p` could be ubiquitous for password across commands that optionally can pass a password - see [#240](https://github.com/chocolatey/choco/issues/240) + +### BUG FIXES + + * Fix - Secure Sources Not Working - see [#240](https://github.com/chocolatey/choco/issues/240) + * Fix - Generate-BinFile / Remove-BinFile - see [#230](https://github.com/chocolatey/choco/issues/230) + * Fix - cpack should only include files from nuspec - see [#232](https://github.com/chocolatey/choco/issues/232) + * Fix - cpack should leave nupkg in current directory - see [#231](https://github.com/chocolatey/choco/issues/231) + * Fix - Install-PowerShellCommand uses incorrect path - see [#241](https://github.com/chocolatey/choco/issues/241) + * Fix - choco list source with redirects does not resolve - see [#171](https://github.com/chocolatey/choco/issues/171) + * Fix - choco tried to resolve disabled repo - see [#169](https://github.com/chocolatey/choco/issues/169) + * Fix - cpack nuspec results in "The path is not of a legal form" - see [#164](https://github.com/chocolatey/choco/issues/164) + * Fix - cpack hangs on security related issue - see [#160](https://github.com/chocolatey/choco/issues/160) + * Fix - spelling error in "package has been upgradeed successfully" - see [#64](https://github.com/chocolatey/choco/issues/64) + +### IMPROVEMENTS + + * Api Key and Source matching could be more intuitive - see [#228](https://github.com/chocolatey/choco/issues/238) + * Remove warning about allowGlobalConfirmation being enabled - see [#237](https://github.com/chocolatey/choco/issues/237) + * Include log file path when saying 'See the log for details' - see [#187](https://github.com/chocolatey/choco/issues/187) + * Uninstall prompts for version when there is only one installed - see [#186](https://github.com/chocolatey/choco/issues/186) + * Do not offer a default option when prompting for a user choice - see [#185](https://github.com/chocolatey/choco/issues/185) + * Remove the warning note about skipping, and instead show the warning when selecting skip - see [#183](https://github.com/chocolatey/choco/issues/183) + * Do not print PowerShell install/update scripts by default - see [#182](https://github.com/chocolatey/choco/issues/182) + ## 0.9.9.4 ### BUG FIXES diff --git a/src/chocolatey.console/Program.cs b/src/chocolatey.console/Program.cs index 67f50cc3f1..ab64b5bf0d 100644 --- a/src/chocolatey.console/Program.cs +++ b/src/chocolatey.console/Program.cs @@ -102,7 +102,6 @@ private static void Main(string[] args) "chocolatey".Log().Debug(() => "{0} is running on {1} v {2}".format_with(ApplicationParameters.Name, config.Information.PlatformType, config.Information.PlatformVersion.to_string())); //"chocolatey".Log().Debug(() => "Command Line: {0}".format_with(Environment.CommandLine)); - warn_when_admin_needs_elevation(config); remove_old_chocolatey_exe(fileSystem); LicenseValidation.validate(fileSystem); @@ -180,30 +179,6 @@ private static void trap_exit_scenarios(ChocolateyConfiguration config) ExitScenarioHandler.SetHandler(); } - private static void warn_when_admin_needs_elevation(ChocolateyConfiguration config) - { - // NOTE: blended options may not have been fully initialized yet - if (!config.PromptForConfirmation) return; - - if (!config.Information.IsProcessElevated && config.Information.IsUserAdministrator) - { - var selection = InteractivePrompt.prompt_for_confirmation(@" -Chocolatey detected you are not running from an elevated command shell - (cmd/powershell). You may experience errors - many functions/packages - require admin rights. Only advanced users should run choco w/out an - elevated shell. When you open the command shell, you should ensure - that you do so with ""Run as Administrator"" selected. - - Do you want to continue?", new[] {"yes", "no"}, "no", requireAnswer: true); - - if (selection.is_equal_to("no")) - { - pause_execution_if_debug(); - Environment.Exit(-1); - } - } - } - private static void remove_old_chocolatey_exe(IFileSystem fileSystem) { try diff --git a/src/chocolatey.resources/chocolatey.resources.csproj b/src/chocolatey.resources/chocolatey.resources.csproj index be6e89404c..bbd951ecd9 100644 --- a/src/chocolatey.resources/chocolatey.resources.csproj +++ b/src/chocolatey.resources/chocolatey.resources.csproj @@ -116,8 +116,8 @@ - - + + diff --git a/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 b/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 index cc3f00f924..bfc0a37bbd 100644 --- a/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 +++ b/src/chocolatey.resources/helpers/chocolateyInstaller.psm1 @@ -39,7 +39,7 @@ Get-Item $helpersPath\functions\*.ps1 | ? { -not ($_.Name.Contains(".Tests.")) } | % { . $_.FullName; - Export-ModuleMember -Function $_.BaseName + #Export-ModuleMember -Function $_.BaseName } # load extensions if they exist @@ -48,4 +48,6 @@ 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 +} + +Export-ModuleMember -Function * -Alias * \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/Generate-BinFile.ps1 b/src/chocolatey.resources/helpers/functions/Install-BinFile.ps1 similarity index 87% rename from src/chocolatey.resources/helpers/functions/Generate-BinFile.ps1 rename to src/chocolatey.resources/helpers/functions/Install-BinFile.ps1 index 5333bbef4c..dae58ee596 100644 --- a/src/chocolatey.resources/helpers/functions/Generate-BinFile.ps1 +++ b/src/chocolatey.resources/helpers/functions/Install-BinFile.ps1 @@ -12,15 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -function Generate-BinFile { +function Install-BinFile { param( [string] $name, [string] $path, [switch] $useStart, [string] $command = '' ) - Write-Debug "Running 'Generate-BinFile' for $name with path:`'$path`'|`$useStart:$useStart|`$command:$command"; + Write-Debug "Running 'Install-BinFile' for $name with path:`'$path`'|`$useStart:$useStart|`$command:$command"; + $nugetPath = [System.IO.Path]::GetFullPath((Join-Path "$helpersPath" '..\')) + $nugetExePath = Join-Path "$nugetPath" 'bin' $packageBatchFileName = Join-Path $nugetExePath "$name.bat" $packageBashFileName = Join-Path $nugetExePath "$name" $packageShimFileName = Join-Path $nugetExePath "$name.exe" @@ -68,16 +70,16 @@ param( } if (Test-Path ($packageShimFileName)) { - Write-Host "Added $packageShimFileName shim pointed to `'$path`'." -ForegroundColor $Note + Write-Host "Added $packageShimFileName shim pointed to `'$path`'." } else { Write-Warning "An error occurred generating shim, using old method." $path = "%DIR%$($path)" $pathBash = $path.Replace("%DIR%..\","`$DIR/../").Replace("\","/") - Write-Host "Adding $packageBatchFileName and pointing to `'$path`'." -ForegroundColor $Note - Write-Host "Adding $packageBashFileName and pointing to `'$path`'." -ForegroundColor $Note + Write-Host "Adding $packageBatchFileName and pointing to `'$path`'." + Write-Host "Adding $packageBashFileName and pointing to `'$path`'." if ($useStart) { - Write-Host "Setting up $name as a non-command line application." -ForegroundColor $Note + Write-Host "Setting up $name as a non-command line application." "@echo off SET DIR=%~dp0% start """" ""$path"" %*" | Out-File $packageBatchFileName -encoding ASCII @@ -100,4 +102,7 @@ exit /b %ERRORLEVEL%" | Out-File $packageBatchFileName -encoding ASCII } } -} \ No newline at end of file +} + +Set-Alias Generate-BinFile Install-BinFile +Set-Alias Add-BinFile Install-BinFile \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 b/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 index 7dc5f61f78..ac38766127 100644 --- a/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 +++ b/src/chocolatey.resources/helpers/functions/UnInstall-ChocolateyZipPackage.ps1 @@ -10,8 +10,8 @@ # 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. - +# limitations under the License. + function UnInstall-ChocolateyZipPackage { <# .SYNOPSIS @@ -50,7 +50,7 @@ param( $zipContentFile $zipContents=get-content $zipContentFile foreach ($fileInZip in $zipContents) { - remove-item "$fileInZip" -ErrorAction SilentlyContinue + remove-item -Path "$fileInZip" -ErrorAction SilentlyContinue -Recurse -Force } } -} \ No newline at end of file +} diff --git a/src/chocolatey.resources/helpers/functions/Remove-BinFile.ps1 b/src/chocolatey.resources/helpers/functions/Uninstall-BinFile.ps1 similarity index 83% rename from src/chocolatey.resources/helpers/functions/Remove-BinFile.ps1 rename to src/chocolatey.resources/helpers/functions/Uninstall-BinFile.ps1 index e68c6ad52d..904a180952 100644 --- a/src/chocolatey.resources/helpers/functions/Remove-BinFile.ps1 +++ b/src/chocolatey.resources/helpers/functions/Uninstall-BinFile.ps1 @@ -12,13 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -function Remove-BinFile { +function Uninstall-BinFile { param( [string] $name, [string] $path ) - Write-Debug "Running 'Remove-BinFile' for $name with path:`'$path`'"; + Write-Debug "Running 'Uninstall-BinFile' for $name with path:`'$path`'"; + $nugetPath = [System.IO.Path]::GetFullPath((Join-Path "$helpersPath" '..\')) + $nugetExePath = Join-Path "$nugetPath" 'bin' $packageBatchFileName = Join-Path $nugetExePath "$name.bat" $packageBashFileName = Join-Path $nugetExePath "$name" $packageShimFileName = Join-Path $nugetExePath "$name.exe" @@ -28,7 +30,7 @@ param( Write-Debug "Attempting to remove the batch and bash shortcuts: $packageBatchFileName and $packageBashFileName" if (Test-Path $packageBatchFileName) { - Write-Host "Removing batch file $packageBatchFileName which pointed to `'$path`'." -ForegroundColor $Note + Write-Host "Removing batch file $packageBatchFileName which pointed to `'$path`'." Remove-Item $packageBatchFileName } else { @@ -36,7 +38,7 @@ param( } if (Test-Path $packageBashFileName) { - Write-Host "Removing bash file $packageBashFileName which pointed to `'$path`'." -ForegroundColor $Note + Write-Host "Removing bash file $packageBashFileName which pointed to `'$path`'." Remove-Item $packageBashFileName } else { @@ -45,10 +47,12 @@ param( Write-Debug "Attempting to remove the shim: $packageShimFileName" if (Test-Path $packageShimFileName) { - Write-Host "Removing shim $packageShimFileName which pointed to `'$path`'." -ForegroundColor $Note + Write-Host "Removing shim $packageShimFileName which pointed to `'$path`'." Remove-Item $packageShimFileName } else { Write-Debug "Tried to remove shim $packageShimFileName but it was already removed." } -} \ No newline at end of file +} + +Set-Alias Remove-BinFile Uninstall-BinFile \ No newline at end of file diff --git a/src/chocolatey/chocolatey.csproj b/src/chocolatey/chocolatey.csproj index 854bd24c55..e737eee412 100644 --- a/src/chocolatey/chocolatey.csproj +++ b/src/chocolatey/chocolatey.csproj @@ -98,6 +98,7 @@ + diff --git a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs index aea4d41cae..c0a41987d4 100644 --- a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs +++ b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs @@ -73,7 +73,7 @@ private static void set_file_configuration(ChocolateyConfiguration config, IFile var configFileSettings = xmlService.deserialize(globalConfigPath); var sources = new StringBuilder(); - foreach (var source in configFileSettings.Sources.or_empty_list_if_null()) + foreach (var source in configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null()) { sources.AppendFormat("{0};", source.Value); } @@ -82,6 +82,8 @@ private static void set_file_configuration(ChocolateyConfiguration config, IFile config.Sources = sources.Remove(sources.Length - 1, 1).ToString(); } + set_machine_sources(config, configFileSettings); + config.CacheLocation = !string.IsNullOrWhiteSpace(configFileSettings.CacheLocation) ? configFileSettings.CacheLocation : System.Environment.GetEnvironmentVariable("TEMP"); if (string.IsNullOrWhiteSpace(config.CacheLocation)) { @@ -89,9 +91,9 @@ private static void set_file_configuration(ChocolateyConfiguration config, IFile } FaultTolerance.try_catch_with_logging_exception( - () => fileSystem.create_directory_if_not_exists(config.CacheLocation), - "Could not create temp directory at '{0}'".format_with(config.CacheLocation), - logWarningInsteadOfError: true); + () => fileSystem.create_directory_if_not_exists(config.CacheLocation), + "Could not create temp directory at '{0}'".format_with(config.CacheLocation), + logWarningInsteadOfError: true); config.ContainsLegacyPackageInstalls = configFileSettings.ContainsLegacyPackageInstalls; if (configFileSettings.CommandExecutionTimeoutSeconds <= 0) @@ -101,20 +103,6 @@ private static void set_file_configuration(ChocolateyConfiguration config, IFile config.CommandExecutionTimeoutSeconds = configFileSettings.CommandExecutionTimeoutSeconds; set_feature_flags(config, configFileSettings); - if (!config.PromptForConfirmation) - { - if (notifyWarnLoggingAction != null) - { - const string logMessage = @" -Config has insecure allowGlobalConfirmation set to true. - This setting lowers the integrity of the security of your system. If - this is not intended, please change the setting using the feature - command. -"; - notifyWarnLoggingAction.Invoke(logMessage); - } - } - // save so all updated configuration items get set to existing config FaultTolerance.try_catch_with_logging_exception( @@ -123,6 +111,20 @@ This setting lowers the integrity of the security of your system. If logWarningInsteadOfError: true); } + private static void set_machine_sources(ChocolateyConfiguration config, ConfigFileSettings configFileSettings) + { + foreach (var source in configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null()) + { + config.MachineSources.Add(new MachineSourceConfiguration + { + Key = source.Value, + Name = source.Id, + Username = source.UserName, + EncryptedPassword = source.Password + }); + } + } + private static void set_feature_flags(ChocolateyConfiguration config, ConfigFileSettings configFileSettings) { config.Features.CheckSumFiles = set_feature_flag(ApplicationParameters.Features.CheckSumFiles, configFileSettings); @@ -228,10 +230,12 @@ the local options are parsed. * **Use Equals**: You can also include or not include an equals sign `=` between options and values. * **Quote Values**: When you need to quote things, such as when using - spaces, please use single quote marks (`'`). In cmd.exe, you can - also use double double quotes (i.e. `""""yo""""`). This is due to - the hand off to PowerShell - it seems to strip off the outer set of - quotes. TODO: TEST THIS, MAY NOT BE RELEVANT NOW. + spaces, please use apostrophes (`'value'`). In cmd.exe you may be + able to use just double quotes (`""value""`) but in powershell.exe + you may need to either escape the quotes with backticks + (`` `""value`"" ``) or use a combination of double quotes and + apostrophes (`""'value'""`). This is due to the hand off to + PowerShell - it seems to strip off the outer set of quotes. * Options and switches apply to all items passed, so if you are installing multiple packages, and you use `--version=1.0.0`, choco is going to look for and try to install version 1.0.0 of every diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs index 9264bf96c0..cc8fa00867 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs @@ -127,5 +127,10 @@ public void run(ChocolateyConfiguration configuration) _configSettingsService.set_api_key(configuration); } } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyFeatureCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyFeatureCommand.cs index 3353fb84af..d192de8371 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyFeatureCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyFeatureCommand.cs @@ -62,7 +62,7 @@ public void handle_additional_argument_parsing(IList unparsedArguments, Enum.TryParse(unparsedCommand, true, out command); if (command == FeatureCommandType.unknown) { - this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); + if (!string.IsNullOrWhiteSpace(unparsedCommand)) this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); command = FeatureCommandType.list; } @@ -120,5 +120,10 @@ public void run(ChocolateyConfiguration configuration) break; } } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs index c2b8af1969..5a517ddd96 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs @@ -74,6 +74,12 @@ public void configure_argument_parser(OptionSet optionSet, ChocolateyConfigurati .Add("n|skippowershell|skip-powershell", "Skip Powershell - Do not run chocolateyInstall.ps1. Defaults to false.", option => configuration.SkipPackageInstallProvider = option != null) + .Add("u=|user=", + "User - used with authenticated feeds. Defaults to empty.", + option => configuration.SourceCommand.Username = option.remove_surrounding_quotes()) + .Add("p=|password=", + "Password - the user's password to the source. Defaults to empty.", + option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) ; //todo: Checksum / ChecksumType defaults to md5 / package name can be a url / installertype @@ -165,5 +171,10 @@ public void run(ChocolateyConfiguration configuration) { _packageService.install_run(configuration); } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyListCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyListCommand.cs index cd5b0af76b..bc3ddf5b92 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyListCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyListCommand.cs @@ -47,12 +47,18 @@ public void configure_argument_parser(OptionSet optionSet, ChocolateyConfigurati .Add("pre|prerelease", "Prerelease - Include Prereleases? Defaults to false.", option => configuration.Prerelease = option != null) - .Add("p|includeprograms|include-programs", + .Add("i|includeprograms|include-programs", "IncludePrograms - Used in conjunction with LocalOnly, filters out apps chocolatey has listed as packages and includes those in the list. Defaults to false.", option => configuration.ListCommand.IncludeRegistryPrograms = option != null) .Add("a|all|allversions|all-versions", "AllVersions - include results from all versions.", option => configuration.AllVersions = option != null) + .Add("u=|user=", + "User - used with authenticated feeds. Defaults to empty.", + option => configuration.SourceCommand.Username = option.remove_surrounding_quotes()) + .Add("p=|password=", + "Password - the user's password to the source. Defaults to empty.", + option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) ; //todo exact name } @@ -109,5 +115,10 @@ public void run(ChocolateyConfiguration configuration) { _packageService.list_run(configuration, logResults: true); } + + public bool may_require_admin_access() + { + return false; + } } } diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyNewCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyNewCommand.cs index fa9bd065ab..2f42b938d2 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyNewCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyNewCommand.cs @@ -143,5 +143,10 @@ public void run(ChocolateyConfiguration configuration) { _templateService.generate(configuration); } + + public bool may_require_admin_access() + { + return false; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs index 4e04db7e97..adfac294f7 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs @@ -86,5 +86,10 @@ public void run(ChocolateyConfiguration configuration) { _packageService.pack_run(configuration); } + + public bool may_require_admin_access() + { + return false; + } } } diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyPinCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyPinCommand.cs index 4c30d38998..e7a45ad708 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyPinCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyPinCommand.cs @@ -69,7 +69,7 @@ public void handle_additional_argument_parsing(IList unparsedArguments, if (command == PinCommandType.unknown) { - this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); + if (!string.IsNullOrWhiteSpace(unparsedCommand)) this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); command = PinCommandType.list; } @@ -165,5 +165,10 @@ public void set_pin(IPackageManager packageManager, ChocolateyConfiguration conf pkgInfo.IsPinned = config.PinCommand.Command == PinCommandType.add; _packageInfoService.save_package_information(pkgInfo); } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyPushCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyPushCommand.cs index cb36695b79..5de65894f2 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyPushCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyPushCommand.cs @@ -177,5 +177,10 @@ public void run(ChocolateyConfiguration configuration) { _packageService.push_run(configuration); } + + public bool may_require_admin_access() + { + return false; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs index 317ee453c8..baca7f45c4 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs @@ -71,7 +71,7 @@ public void handle_additional_argument_parsing(IList unparsedArguments, Enum.TryParse(unparsedCommand, true, out command); if (command == SourceCommandType.unknown) { - this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); + if (!string.IsNullOrWhiteSpace(unparsedCommand)) this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); command = SourceCommandType.list; } @@ -144,5 +144,10 @@ public IEnumerable list(ChocolateyConfiguration configuration) { return _configSettingsService.source_list(configuration); } + + public bool may_require_admin_access() + { + return true; + } } } diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyUninstallCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyUninstallCommand.cs index 2cea4a1408..e1e4134a57 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyUninstallCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUninstallCommand.cs @@ -130,5 +130,10 @@ public void run(ChocolateyConfiguration configuration) { _packageService.uninstall_run(configuration); } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyUnpackSelfCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyUnpackSelfCommand.cs index abfc0247f3..49c257fc76 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyUnpackSelfCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUnpackSelfCommand.cs @@ -104,5 +104,10 @@ public void run(ChocolateyConfiguration configuration) overwriteExisting: configuration.Force, logOutput: true); } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs index 2f352bad7f..04538ad6e9 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs @@ -76,6 +76,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon .Add("failonunfound|fail-on-unfound", "Fail On Unfound Packages - If a package is not found in feeds specified, fail instead of warn.", option => configuration.UpgradeCommand.FailOnUnfound = option != null) + .Add("u=|user=", + "User - used with authenticated feeds. Defaults to empty.", + option => configuration.SourceCommand.Username = option.remove_surrounding_quotes()) + .Add("p=|password=", + "Password - the user's password to the source. Defaults to empty.", + option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) ; } @@ -140,5 +146,10 @@ public virtual void run(ChocolateyConfiguration configuration) { _packageService.upgrade_run(configuration); } + + public bool may_require_admin_access() + { + return true; + } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index f8a163b778..dadd8b4322 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -39,6 +39,7 @@ public ChocolateyConfiguration() ListCommand = new ListCommandConfiguration(); UpgradeCommand = new UpgradeCommandConfiguration(); SourceCommand = new SourcesCommandConfiguration(); + MachineSources = new List(); FeatureCommand = new FeatureCommandConfiguration(); ApiKeyCommand = new ApiKeyCommandConfiguration(); PushCommand = new PushCommandConfiguration(); @@ -67,7 +68,7 @@ private void output_tostring(StringBuilder propertyValues, IEnumerable /// On .NET 4.0, get error CS0200 when private set - see http://stackoverflow.com/a/23809226/18475 /// - public SourcesCommandConfiguration SourceCommand { get; set; } + public SourcesCommandConfiguration SourceCommand { get; set; } + + /// + /// Default Machine Sources Configuration + /// + /// + /// On .NET 4.0, get error CS0200 when private set - see http://stackoverflow.com/a/23809226/18475 + /// + public IList MachineSources { get; set; } /// /// Configuration related specifically to the Feature command @@ -328,6 +337,15 @@ public sealed class SourcesCommandConfiguration public string Password { get; set; } } + [Serializable] + public sealed class MachineSourceConfiguration + { + public string Name { get; set; } + public string Key { get; set; } + public string Username { get; set; } + public string EncryptedPassword { get; set; } + } + [Serializable] public sealed class FeatureCommandConfiguration { diff --git a/src/chocolatey/infrastructure.app/nuget/ChocolateyNugetCredentialProvider.cs b/src/chocolatey/infrastructure.app/nuget/ChocolateyNugetCredentialProvider.cs new file mode 100644 index 0000000000..a5a261f225 --- /dev/null +++ b/src/chocolatey/infrastructure.app/nuget/ChocolateyNugetCredentialProvider.cs @@ -0,0 +1,113 @@ +// Copyright © 2011 - Present 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.nuget +{ + using System; + using System.Linq; + using System.Net; + using NuGet; + using configuration; + using logging; + + // ReSharper disable InconsistentNaming + + public sealed class ChocolateyNugetCredentialProvider : ICredentialProvider + { + private readonly ChocolateyConfiguration _config; + + public ChocolateyNugetCredentialProvider(ChocolateyConfiguration config) + { + _config = config; + } + + public ICredentials GetCredentials(Uri uri, IWebProxy proxy, CredentialType credentialType, bool retrying) + { + if (uri == null) + { + throw new ArgumentNullException("uri"); + } + if (retrying) + { + this.Log().Warn("Invalid credentials specified."); + } + + if (_config.Sources.TrimEnd('/').is_equal_to(uri.OriginalString.TrimEnd('/'))) + { + if (!string.IsNullOrWhiteSpace(_config.SourceCommand.Username) && !string.IsNullOrWhiteSpace(_config.SourceCommand.Password)) + { + this.Log().Debug("Using passed in credentials"); + + return new NetworkCredential(_config.SourceCommand.Username, _config.SourceCommand.Password); + } + } + + var source = _config.MachineSources.FirstOrDefault(s => + { + var sourceUri = s.Key.TrimEnd('/'); + return sourceUri.is_equal_to(uri.OriginalString.TrimEnd('/')) + && !string.IsNullOrWhiteSpace(s.Username) + && !string.IsNullOrWhiteSpace(s.EncryptedPassword); + }); + + if (source == null) + { + return get_credentials_from_user(uri, proxy, credentialType); + } + + this.Log().Debug("Using saved credentials"); + + return new NetworkCredential(source.Username, NugetEncryptionUtility.DecryptString(source.EncryptedPassword)); + } + + public ICredentials get_credentials_from_user(Uri uri, IWebProxy proxy, CredentialType credentialType) + { + if (!_config.Information.IsInteractive) + { + return CredentialCache.DefaultCredentials; + } + + string message = credentialType == CredentialType.ProxyCredentials ? + "Please provide proxy credentials:" : + "Please provide credentials for: {0}".format_with(uri.OriginalString); + this.Log().Info(ChocolateyLoggers.Important, message); + + Console.Write("User name: "); + string username = Console.ReadLine(); + Console.Write("Password: "); + var password = Console.ReadLine(); + + //todo: set this up as secure + //using (var securePassword = new SecureString()) + //{ + // foreach (var letter in password.to_string()) + // { + // securePassword.AppendChar(letter); + // } + + var credentials = new NetworkCredential + { + UserName = username, + Password = password, + //SecurePassword = securePassword + }; + return credentials; + // } + } + } + + + // ReSharper restore InconsistentNaming +} \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs b/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs index efeea9d99c..2a45ac5f54 100644 --- a/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs +++ b/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs @@ -54,6 +54,10 @@ public static IPackageRepository GetRemoteRepository(ChocolateyConfiguration con IEnumerable sources = configuration.Sources.Split(new[] {";", ","}, StringSplitOptions.RemoveEmptyEntries); IList repositories = new List(); + + // ensure credentials can be grabbed from configuration + HttpClient.DefaultCredentialProvider = new ChocolateyNugetCredentialProvider(configuration); + foreach (var source in sources.or_empty_list_if_null()) { try @@ -65,7 +69,7 @@ public static IPackageRepository GetRemoteRepository(ChocolateyConfiguration con } else { - repositories.Add(new DataServicePackageRepository(uri)); + repositories.Add(new DataServicePackageRepository(new RedirectedHttpClient(uri))); } } catch (Exception) @@ -76,7 +80,7 @@ public static IPackageRepository GetRemoteRepository(ChocolateyConfiguration con //todo well that didn't work on failing repos... grrr var repository = new AggregateRepository(repositories) {IgnoreFailingRepositories = true}; - //,ResolveDependenciesVertically = true}; + //repository.ResolveDependenciesVertically = true; if (configuration.Debug) { repository.Logger = nugetLogger; diff --git a/src/chocolatey/infrastructure.app/runners/GenericRunner.cs b/src/chocolatey/infrastructure.app/runners/GenericRunner.cs index 46fb9570d5..a19b845135 100644 --- a/src/chocolatey/infrastructure.app/runners/GenericRunner.cs +++ b/src/chocolatey/infrastructure.app/runners/GenericRunner.cs @@ -22,6 +22,7 @@ namespace chocolatey.infrastructure.app.runners using SimpleInjector; using adapters; using attributes; + using commandline; using configuration; using infrastructure.commands; using logging; @@ -51,6 +52,11 @@ private ICommand find_command(ChocolateyConfiguration config, Container containe } else { + if (command.may_require_admin_access()) + { + warn_when_admin_needs_elevation(config); + } + if (parseArgs != null) { parseArgs.Invoke(command); @@ -131,5 +137,30 @@ public IEnumerable list(ChocolateyConfiguration config, Container containe return command.list(config); } } + + public void warn_when_admin_needs_elevation(ChocolateyConfiguration config) + { + // NOTE: blended options may not have been fully initialized yet + if (!config.PromptForConfirmation) return; + + if (!config.Information.IsProcessElevated && config.Information.IsUserAdministrator) + { + var selection = InteractivePrompt.prompt_for_confirmation(@" +Chocolatey detected you are not running from an elevated command shell + (cmd/powershell). You may experience errors - many functions/packages + require admin rights. Only advanced users should run choco w/out an + elevated shell. When you open the command shell, you should ensure + that you do so with ""Run as Administrator"" selected. + + Do you want to continue?", new[] { "yes", "no" }, defaultChoice: null, requireAnswer: true); + + if (selection.is_equal_to("no")) + { + Environment.Exit(-1); + } + } + } + } -} +} + diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs index 5f60b3feb8..8b318c4164 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs @@ -187,7 +187,7 @@ public string get_api_key(ChocolateyConfiguration configuration, Action p.Source.is_equal_to(configuration.Sources)); + var apiKey = configFileSettings.ApiKeys.FirstOrDefault(p => p.Source.TrimEnd('/').is_equal_to(configuration.Sources.TrimEnd('/'))); if (apiKey != null) { apiKeyValue = NugetEncryptionUtility.DecryptString(apiKey.Key).to_string(); diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs index 98739afff8..603ddcf0bc 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs @@ -241,13 +241,15 @@ public ConcurrentDictionary install_run(ChocolateyConfigu var installFailures = packageInstalls.Count(p => !p.Value.Success); var installWarnings = packageInstalls.Count(p => p.Value.Warning); - this.Log().Warn(() => @"{0}{1} installed {2}/{3} package(s). {4} package(s) failed.{5}{0} See the log for details.".format_with( + this.Log().Warn(() => @"{0}{1} installed {2}/{3} package(s). {4} package(s) failed.{5}{0} See the log for details ({6}).".format_with( Environment.NewLine, ApplicationParameters.Name, packageInstalls.Count(p => p.Value.Success && !p.Value.Inconclusive), packageInstalls.Count, installFailures, - installWarnings == 0 ? string.Empty : "{0} {1} package(s) had warnings.".format_with(Environment.NewLine, installWarnings))); + installWarnings == 0 ? string.Empty : "{0} {1} package(s) had warnings.".format_with(Environment.NewLine, installWarnings), + _fileSystem.combine_paths(ApplicationParameters.LoggingLocation,ApplicationParameters.LoggingFile) + )); if (installWarnings != 0) { @@ -333,12 +335,14 @@ public void upgrade_noop(ChocolateyConfiguration config) if (config.RegularOutput) { var upgradeWarnings = noopUpgrades.Count(p => p.Value.Warning); - this.Log().Warn(() => @"{0}{1} can upgrade {2}/{3} package(s). {4}{0} See the log for details.".format_with( + this.Log().Warn(() => @"{0}{1} can upgrade {2}/{3} package(s). {4}{0} See the log for details ({5}).".format_with( Environment.NewLine, ApplicationParameters.Name, noopUpgrades.Count(p => p.Value.Success && !p.Value.Inconclusive), noopUpgrades.Count, - upgradeWarnings == 0 ? string.Empty : "{0} {1} package(s) had warnings.".format_with(Environment.NewLine, upgradeWarnings))); + upgradeWarnings == 0 ? string.Empty : "{0} {1} package(s) had warnings.".format_with(Environment.NewLine, upgradeWarnings), + _fileSystem.combine_paths(ApplicationParameters.LoggingLocation, ApplicationParameters.LoggingFile) + )); if (upgradeWarnings != 0) { @@ -371,13 +375,15 @@ public ConcurrentDictionary upgrade_run(ChocolateyConfigu var upgradeFailures = packageUpgrades.Count(p => !p.Value.Success); var upgradeWarnings = packageUpgrades.Count(p => p.Value.Warning); - this.Log().Warn(() => @"{0}{1} upgraded {2}/{3} package(s). {4} package(s) failed.{5}{0} See the log for details.".format_with( + this.Log().Warn(() => @"{0}{1} upgraded {2}/{3} package(s). {4} package(s) failed.{5}{0} See the log for details ({6}).".format_with( Environment.NewLine, ApplicationParameters.Name, packageUpgrades.Count(p => p.Value.Success && !p.Value.Inconclusive), packageUpgrades.Count, upgradeFailures, - upgradeWarnings == 0 ? string.Empty : "{0} {1} package(s) had warnings.".format_with(Environment.NewLine, upgradeWarnings))); + upgradeWarnings == 0 ? string.Empty : "{0} {1} package(s) had warnings.".format_with(Environment.NewLine, upgradeWarnings), + _fileSystem.combine_paths(ApplicationParameters.LoggingLocation, ApplicationParameters.LoggingFile) + )); if (upgradeWarnings != 0) { @@ -453,12 +459,14 @@ public ConcurrentDictionary uninstall_run(ChocolateyConfi }); var uninstallFailures = packageUninstalls.Count(p => !p.Value.Success); - this.Log().Warn(() => @"{0}{1} uninstalled {2}/{3} packages. {4} packages failed.{0}See the log for details.".format_with( + this.Log().Warn(() => @"{0}{1} uninstalled {2}/{3} packages. {4} packages failed.{0} See the log for details ({5}).".format_with( Environment.NewLine, ApplicationParameters.Name, packageUninstalls.Count(p => p.Value.Success && !p.Value.Inconclusive), packageUninstalls.Count, - uninstallFailures)); + uninstallFailures, + _fileSystem.combine_paths(ApplicationParameters.LoggingLocation, ApplicationParameters.LoggingFile) + )); if (uninstallFailures != 0) { @@ -618,7 +626,7 @@ private void rollback_previous_version(ChocolateyConfiguration config, PackageRe var rollback = true; if (config.PromptForConfirmation) { - var selection = InteractivePrompt.prompt_for_confirmation(" Unsuccessful operation for {0}.{1} Do you want to rollback to previous version (package files only)?".format_with(packageResult.Name, Environment.NewLine), new[] { "yes", "no" }, "yes", requireAnswer: true); + var selection = InteractivePrompt.prompt_for_confirmation(" Unsuccessful operation for {0}.{1} Do you want to rollback to previous version (package files only)?".format_with(packageResult.Name, Environment.NewLine), new[] { "yes", "no" }, defaultChoice: null, requireAnswer: true); if (selection.is_equal_to("no")) rollback = false; } diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs index b39a7c54b6..cf9bc016ed 100644 --- a/src/chocolatey/infrastructure.app/services/NugetService.cs +++ b/src/chocolatey/infrastructure.app/services/NugetService.cs @@ -797,7 +797,7 @@ public ConcurrentDictionary uninstall_run(ChocolateyConfi } var packageVersionsToRemove = installedPackageVersions.ToList(); - if (!config.AllVersions) + if (!config.AllVersions && installedPackageVersions.Count > 1) { if (config.PromptForConfirmation) { @@ -817,7 +817,7 @@ public ConcurrentDictionary uninstall_run(ChocolateyConfi choices.Add(allVersionsChoice); } - var selection = InteractivePrompt.prompt_for_confirmation("Which version of {0} would you like to uninstall?".format_with(packageName), choices, abortChoice, true); + var selection = InteractivePrompt.prompt_for_confirmation("Which version of {0} would you like to uninstall?".format_with(packageName), choices, defaultChoice: null, requireAnswer: true); if (string.IsNullOrWhiteSpace(selection)) continue; if (selection.is_equal_to(abortChoice)) continue; diff --git a/src/chocolatey/infrastructure.app/services/PowershellService.cs b/src/chocolatey/infrastructure.app/services/PowershellService.cs index ef4f79aa9d..80d5f10246 100644 --- a/src/chocolatey/infrastructure.app/services/PowershellService.cs +++ b/src/chocolatey/infrastructure.app/services/PowershellService.cs @@ -217,16 +217,19 @@ public bool run_action(ChocolateyConfiguration configuration, PackageResult pack if (!shouldRun) { - this.Log().Info(ChocolateyLoggers.Important, () => " Found '{0}':".format_with(_fileSystem.get_file_name(chocoPowerShellScript))); - this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents.escape_curly_braces())); - var selection = InteractivePrompt - .prompt_for_confirmation(@" -Do you want to run the script? - NOTE: If you choose not to run the script, the installation will - fail. - Skip is an advanced option and most likely will never be wanted. -" - , new[] {"yes", "no", "skip"}, "no", requireAnswer: true); + this.Log().Info(ChocolateyLoggers.Important, () => "The package {0} wants to run '{1}'.".format_with(package.Id, _fileSystem.get_file_name(chocoPowerShellScript))); + this.Log().Info(ChocolateyLoggers.Important, () => "Note: If you don't run this script, the installation will fail."); + + var selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run the script?", new[] {"yes", "no", "print"}, defaultChoice: null, requireAnswer: true); + + if (selection.is_equal_to("print")) + { + this.Log().Info(ChocolateyLoggers.Important, "------ BEGIN SCRIPT ------"); + this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents.escape_curly_braces())); + this.Log().Info(ChocolateyLoggers.Important, "------- END SCRIPT -------"); + selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run this script?", new[] { "yes", "no" }, defaultChoice: null, requireAnswer: true); + } + if (selection.is_equal_to("yes")) shouldRun = true; if (selection.is_equal_to("no")) { diff --git a/src/chocolatey/infrastructure/commands/ICommand.cs b/src/chocolatey/infrastructure/commands/ICommand.cs index 1efa93447c..abd958a4d7 100644 --- a/src/chocolatey/infrastructure/commands/ICommand.cs +++ b/src/chocolatey/infrastructure/commands/ICommand.cs @@ -57,5 +57,11 @@ public interface ICommand /// /// The configuration. void run(ChocolateyConfiguration config); + + /// + /// This command may require admin rights + /// + /// + bool may_require_admin_access(); } } \ No newline at end of file