From 204983c6f18d9f1261bbd04e3e1cb98cf9b8a944 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Sun, 20 Sep 2015 23:13:25 -0500 Subject: [PATCH 01/10] (GH-33) Allow Shutting off checksumming Allow a user to shut off checksumming either globally or as a configuration value passed to choco. --- .../helpers/functions/Get-CheckSumValid.ps1 | 4 ++++ .../infrastructure.app/commands/ChocolateyInstallCommand.cs | 6 ++++++ .../infrastructure.app/commands/ChocolateyUpgradeCommand.cs | 6 ++++++ .../infrastructure.app/services/PowershellService.cs | 4 ++++ 4 files changed, 20 insertions(+) diff --git a/src/chocolatey.resources/helpers/functions/Get-CheckSumValid.ps1 b/src/chocolatey.resources/helpers/functions/Get-CheckSumValid.ps1 index f71df1c10a..8dfb96e62f 100644 --- a/src/chocolatey.resources/helpers/functions/Get-CheckSumValid.ps1 +++ b/src/chocolatey.resources/helpers/functions/Get-CheckSumValid.ps1 @@ -20,6 +20,10 @@ param( [string] $checksumType = 'md5' ) Write-Debug "Running 'Get-ChecksumValid' with file:`'$file`', checksum: `'$checksum`', checksumType: `'$checksumType`'"; + if ($env:chocolateyIgnoreChecksums -eq 'true') { + Write-Warning "Ignoring checksums due to feature checksumFiles = false or config ignoreChecksums = true." + return + } if ($checksum -eq '' -or $checksum -eq $null) { return } if (!([System.IO.File]::Exists($file))) { throw "Unable to checksum a file that doesn't exist - Could not find file `'$file`'" } diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs index c85ff210aa..8c7539a5c0 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyInstallCommand.cs @@ -83,6 +83,12 @@ public void configure_argument_parser(OptionSet optionSet, ChocolateyConfigurati .Add("p=|password=", "Password - the user's password to the source. Defaults to empty.", option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) + .Add("ignorechecksums|ignore-checksums", + "IgnoreChecksums - Ignore checksums provided by the package", + option => + { + if (option != null) configuration.Features.CheckSumFiles = false; + }) ; //todo: Checksum / ChecksumType defaults to md5 / 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 ac76ae8392..a44c72e233 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs @@ -88,6 +88,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon .Add("p=|password=", "Password - the user's password to the source. Defaults to empty.", option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) + .Add("ignorechecksums|ignore-checksums", + "IgnoreChecksums - Ignore checksums provided by the package", + option => + { + if (option != null) configuration.Features.CheckSumFiles = false; + }) ; } diff --git a/src/chocolatey/infrastructure.app/services/PowershellService.cs b/src/chocolatey/infrastructure.app/services/PowershellService.cs index 44d3937686..6df127fa7a 100644 --- a/src/chocolatey/infrastructure.app/services/PowershellService.cs +++ b/src/chocolatey/infrastructure.app/services/PowershellService.cs @@ -208,6 +208,10 @@ public bool run_action(ChocolateyConfiguration configuration, PackageResult pack if (configuration.Verbose) { Environment.SetEnvironmentVariable("ChocolateyEnvironmentVerbose", "true"); + } + if (!configuration.Features.CheckSumFiles) + { + Environment.SetEnvironmentVariable("ChocolateyIgnoreChecksums", "true"); } //todo:if (configuration.NoOutput) //{ From e9dcb0cc12d49791511e8456b6e94438b81c369c Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Sun, 20 Sep 2015 23:37:05 -0500 Subject: [PATCH 02/10] (GH-89) Note cpack has been deprecated Cpack as a shortcut to choco pack has been deprecated and will be removed in v1. Note this in the help menu. --- .../infrastructure.app/commands/ChocolateyPackCommand.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs index adfac294f7..3a76134a76 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyPackCommand.cs @@ -58,12 +58,16 @@ public void help_message(ChocolateyConfiguration configuration) this.Log().Info(@" Chocolatey will attempt to package a nuspec into a compiled nupkg. Some may prefer to use `cpack` as a shortcut for `choco pack`. + +NOTE: `cpack` has been deprecated as it has a name collision with CMake. Please + use `choco pack` instead. The shortcut will be removed in v1. + "); "chocolatey".Log().Info(ChocolateyLoggers.Important, "Usage"); "chocolatey".Log().Info(@" choco pack [] [] - cpack [] [] + cpack [] [] (DEPRECATED) "); "chocolatey".Log().Info(ChocolateyLoggers.Important, "Examples"); From b74dbec14fbf5d11f6575542976ce85030c75558 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Sun, 20 Sep 2015 23:37:18 -0500 Subject: [PATCH 03/10] (maint) formatting --- src/chocolatey.console/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chocolatey.console/Program.cs b/src/chocolatey.console/Program.cs index 2b5a29affc..5dceaf3b2a 100644 --- a/src/chocolatey.console/Program.cs +++ b/src/chocolatey.console/Program.cs @@ -30,7 +30,6 @@ namespace chocolatey.console using infrastructure.filesystem; using infrastructure.licensing; using infrastructure.logging; - using infrastructure.platforms; using infrastructure.registration; using infrastructure.services; using resources; From 4ac23573b85fe9307d02747ac1de0fbca49a0889 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Sun, 20 Sep 2015 23:37:56 -0500 Subject: [PATCH 04/10] (maint) Case insensitive String.contains --- src/chocolatey/StringExtensions.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/chocolatey/StringExtensions.cs b/src/chocolatey/StringExtensions.cs index 1cdbce2f38..62ab04ff7e 100644 --- a/src/chocolatey/StringExtensions.cs +++ b/src/chocolatey/StringExtensions.cs @@ -113,6 +113,18 @@ public static bool is_equal_to(this string input, string other) return string.Compare(input, other, ignoreCase: true, culture: CultureInfo.InvariantCulture) == 0; } + /// + /// Determines whether a string value contains a search value. + /// + /// The input. + /// The value to search for. + /// The comparison. + /// True if the value to search for is in the input string + public static bool contains(this string input, string search, StringComparison comparison = StringComparison.OrdinalIgnoreCase) + { + return input.to_string().IndexOf(search, 0, comparison) >= 0; + } + /// /// Removes quotes or apostrophes surrounding a string /// From 583867e9d226e6437e85ab152e4cacbb1d91ca4f Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Sun, 20 Sep 2015 23:39:38 -0500 Subject: [PATCH 05/10] (maint) resharper team settings --- src/chocolatey.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chocolatey.sln.DotSettings b/src/chocolatey.sln.DotSettings index 47a2ce71dc..dc481c1cbb 100644 --- a/src/chocolatey.sln.DotSettings +++ b/src/chocolatey.sln.DotSettings @@ -6,6 +6,7 @@ <?xml version="1.0" encoding="utf-16"?><Profile name="sensible"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSharpFormatDocComments>True</CSharpFormatDocComments><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> sensible False + DO_NOT_CHANGE True True True From 11d1c4710ac08be180180ac8c7dfe4f489a1b79e Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Mon, 21 Sep 2015 00:26:15 -0500 Subject: [PATCH 06/10] (GH-71) Sources can have explicit priority order When a priority order is specified, sources will order explicitly by that order, lowest number above zero will have the highest priority and so on, then any items with a priority of 0 will be evaluated in configuration file order. --- .../builders/ConfigurationBuilder.cs | 13 +++++++-- .../commands/ChocolateySourceCommand.cs | 5 +++- .../configuration/ChocolateyConfiguration.cs | 2 ++ .../configuration/ConfigFileSourceSetting.cs | 5 +++- .../ChocolateyConfigSettingsService.cs | 27 ++++++++++++------- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs index ebf032af1c..53d5a79892 100644 --- a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs +++ b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs @@ -73,7 +73,15 @@ private static void set_file_configuration(ChocolateyConfiguration config, IFile var configFileSettings = xmlService.deserialize(globalConfigPath); var sources = new StringBuilder(); - foreach (var source in configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null()) + + var defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null().ToList(); + if (configFileSettings.Sources.Any(s => s.Priority > 0)) + { + defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled && s.Priority != 0).OrderBy(s => s.Priority).or_empty_list_if_null().ToList(); + defaultSourcesInOrder.AddRange(configFileSettings.Sources.Where(s => !s.Disabled && s.Priority == 0 ).or_empty_list_if_null().ToList()); + } + + foreach (var source in defaultSourcesInOrder) { sources.AppendFormat("{0};", source.Value); } @@ -120,7 +128,8 @@ private static void set_machine_sources(ChocolateyConfiguration config, ConfigFi Key = source.Value, Name = source.Id, Username = source.UserName, - EncryptedPassword = source.Password + EncryptedPassword = source.Password, + Priority = source.Priority }); } } diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs index 9db67cc3b4..6ccf7fc8ae 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateySourceCommand.cs @@ -53,7 +53,10 @@ public void configure_argument_parser(OptionSet optionSet, ChocolateyConfigurati option => configuration.SourceCommand.Username = option.remove_surrounding_quotes()) .Add("p=|password=", "Password - the user's password to the source. Encrypted in chocolatey.config file.", - option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) + option => configuration.SourceCommand.Password = option.remove_surrounding_quotes()) + .Add("priority=", + "Priority - The priority order of this source as compared to other sources, lower is better. Defaults to 0 (no priority). All priorities above 0 will be evaluated first, then zero-based values will be evaluated in config file order.", + option => configuration.SourceCommand.Priority = int.Parse(option.remove_surrounding_quotes())) ; } diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index 3abae13ada..a6232b94ee 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -355,6 +355,7 @@ public sealed class SourcesCommandConfiguration public SourceCommandType Command { get; set; } public string Username { get; set; } public string Password { get; set; } + public int Priority { get; set; } } [Serializable] @@ -364,6 +365,7 @@ public sealed class MachineSourceConfiguration public string Key { get; set; } public string Username { get; set; } public string EncryptedPassword { get; set; } + public int Priority { get; set; } } [Serializable] diff --git a/src/chocolatey/infrastructure.app/configuration/ConfigFileSourceSetting.cs b/src/chocolatey/infrastructure.app/configuration/ConfigFileSourceSetting.cs index e4e26a09ba..b3d0d4b856 100644 --- a/src/chocolatey/infrastructure.app/configuration/ConfigFileSourceSetting.cs +++ b/src/chocolatey/infrastructure.app/configuration/ConfigFileSourceSetting.cs @@ -38,6 +38,9 @@ public sealed class ConfigFileSourceSetting public string UserName { get; set; } [XmlAttribute(AttributeName = "password")] - public string Password { get; set; } + public string Password { get; set; } + + [XmlAttribute(AttributeName = "priority")] + public int Priority { get; set; } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs index b55c8c319e..8f135b9514 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs @@ -19,6 +19,7 @@ namespace chocolatey.infrastructure.app.services using System.Linq; using configuration; using infrastructure.services; + using logging; using nuget; internal class ChocolateyConfigSettingsService : IChocolateyConfigSettingsService @@ -47,7 +48,12 @@ public void source_list(ChocolateyConfiguration configuration) { foreach (var source in configFileSettings.Sources) { - this.Log().Info(() => "{0}{1} - {2}".format_with(source.Id, source.Disabled ? " [Disabled]" : string.Empty, source.Value)); + this.Log().Info(() => "{0}{1} - {2} {3}| Priority {4}.".format_with( + source.Id, + source.Disabled ? " [Disabled]" : string.Empty, + source.Value, + string.IsNullOrWhiteSpace(source.UserName) ? string.Empty : "(Authenticated)", + source.Priority)); } } @@ -56,17 +62,18 @@ public void source_add(ChocolateyConfiguration configuration) var source = configFileSettings.Sources.FirstOrDefault(p => p.Id.is_equal_to(configuration.SourceCommand.Name)); if (source == null) { - configFileSettings.Sources.Add(new ConfigFileSourceSetting - { - Id = configuration.SourceCommand.Name, - Value = configuration.Sources, - UserName = configuration.SourceCommand.Username, - Password = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.Password), - }); + source = new ConfigFileSourceSetting + { + Id = configuration.SourceCommand.Name, + Value = configuration.Sources, + UserName = configuration.SourceCommand.Username, + Password = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.Password), + Priority = configuration.SourceCommand.Priority + }; + configFileSettings.Sources.Add(source); _xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation); - - this.Log().Warn(() => "Added {0} - {1}".format_with(configuration.SourceCommand.Name, configuration.Sources)); + this.Log().Warn(() => "Added {0} - {1} (Priority {2})".format_with(source.Id, source.Value, source.Priority)); } else { From eb97c666aa62f98805de41b1add0a6af584be1af Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Mon, 21 Sep 2015 00:31:38 -0500 Subject: [PATCH 07/10] (GH-88) Modify existing source Modify existing source values if new bits are passed about a source, such as adding priority. --- .../ChocolateyConfigSettingsService.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs index 8f135b9514..c9cecd1589 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs @@ -77,9 +77,25 @@ public void source_add(ChocolateyConfiguration configuration) } else { - this.Log().Warn(@" -No changes made. If you are trying to change an existing source, please - remove it first."); + var currentPassword = string.IsNullOrWhiteSpace(source.Password) ? null : NugetEncryptionUtility.DecryptString(source.Password); + if (configuration.Sources.is_equal_to(source.Value) && + configuration.SourceCommand.Priority == source.Priority && + configuration.SourceCommand.Username.is_equal_to(source.UserName) && + configuration.SourceCommand.Password.is_equal_to(currentPassword) + ) + { + this.Log().Warn(NO_CHANGE_MESSAGE); + } + else + { + source.Value = configuration.Sources; + source.Priority = configuration.SourceCommand.Priority; + source.UserName = configuration.SourceCommand.Username; + source.Password = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.Password); + + _xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation); + this.Log().Warn(() => "Updated {0} - {1} (Priority {2})".format_with(source.Id, source.Value, source.Priority)); + } } } From f5c1e53b5c35dd84239e4ee23234660fa2560a86 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Mon, 21 Sep 2015 00:42:58 -0500 Subject: [PATCH 08/10] (GH-416) Features should contain description When calling `feature list`, it may not be clear to a user what each of the features provide. Adding a description will help understand what each feature does when it is turned on or off. --- .../builders/ConfigurationBuilder.cs | 23 +++++++++++++------ .../configuration/ConfigFileFeatureSetting.cs | 3 +++ .../ChocolateyConfigSettingsService.cs | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs index 53d5a79892..1b5c335be8 100644 --- a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs +++ b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs @@ -136,13 +136,13 @@ private static void set_machine_sources(ChocolateyConfiguration config, ConfigFi private static void set_feature_flags(ChocolateyConfiguration config, ConfigFileSettings configFileSettings) { - config.Features.CheckSumFiles = set_feature_flag(ApplicationParameters.Features.CheckSumFiles, configFileSettings); - config.Features.AutoUninstaller = set_feature_flag(ApplicationParameters.Features.AutoUninstaller, configFileSettings); - config.Features.FailOnAutoUninstaller = set_feature_flag(ApplicationParameters.Features.FailOnAutoUninstaller, configFileSettings); - config.PromptForConfirmation = !set_feature_flag(ApplicationParameters.Features.AllowGlobalConfirmation, configFileSettings); + config.Features.CheckSumFiles = set_feature_flag(ApplicationParameters.Features.CheckSumFiles, configFileSettings, "Checksum files when pulled in from internet (based on package)."); + config.Features.AutoUninstaller = set_feature_flag(ApplicationParameters.Features.AutoUninstaller, configFileSettings, "Uninstall from programs and features without requiring an explicit uninstall script."); + config.Features.FailOnAutoUninstaller = set_feature_flag(ApplicationParameters.Features.FailOnAutoUninstaller, configFileSettings, "Fail if automatic uninstaller fails."); + config.PromptForConfirmation = !set_feature_flag(ApplicationParameters.Features.AllowGlobalConfirmation, configFileSettings, "Prompt for confirmation in scripts or bypass."); } - private static bool set_feature_flag(string featureName, ConfigFileSettings configFileSettings) + private static bool set_feature_flag(string featureName, ConfigFileSettings configFileSettings, string description) { var enabled = false; var feature = configFileSettings.Features.FirstOrDefault(f => f.Name.is_equal_to(featureName)); @@ -150,9 +150,18 @@ private static bool set_feature_flag(string featureName, ConfigFileSettings conf if (feature == null) { - configFileSettings.Features.Add(new ConfigFileFeatureSetting {Name = featureName, Enabled = enabled}); - } + feature = new ConfigFileFeatureSetting + { + Name = featureName, + Enabled = enabled, + Description = description + }; + configFileSettings.Features.Add(feature); + } + + feature.Description = description; + return enabled; } diff --git a/src/chocolatey/infrastructure.app/configuration/ConfigFileFeatureSetting.cs b/src/chocolatey/infrastructure.app/configuration/ConfigFileFeatureSetting.cs index fefbc1b127..c5cf1715c1 100644 --- a/src/chocolatey/infrastructure.app/configuration/ConfigFileFeatureSetting.cs +++ b/src/chocolatey/infrastructure.app/configuration/ConfigFileFeatureSetting.cs @@ -33,5 +33,8 @@ public sealed class ConfigFileFeatureSetting [XmlAttribute(AttributeName = "setExplicitly")] public bool SetExplicitly { get; set; } + + [XmlAttribute(AttributeName = "description")] + public string Description { get; set; } } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs index c9cecd1589..a8c8dbeb41 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs @@ -149,7 +149,7 @@ public void feature_list(ChocolateyConfiguration configuration) { foreach (var feature in configFileSettings.Features) { - this.Log().Info(() => "{0} - {1}".format_with(feature.Name, !feature.Enabled ? "[Disabled]" : "[Enabled]")); + this.Log().Info(() => "{0} - {1} | {2}".format_with(feature.Name, !feature.Enabled ? "[Disabled]" : "[Enabled]", feature.Description)); } } From 5f77d6cdd316df56c2ad623006a3c67eb19e3427 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Mon, 21 Sep 2015 00:47:47 -0500 Subject: [PATCH 09/10] (maint) Config output skip by contains password Instead of looking at the name of the property to be Password, skip when the property contains the word "password". This should cover a few more future values versus being locked into the name Password as a value. --- .../infrastructure.app/configuration/ChocolateyConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index a6232b94ee..6b749129a5 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -68,7 +68,7 @@ private void output_tostring(StringBuilder propertyValues, IEnumerable Date: Mon, 21 Sep 2015 00:55:36 -0500 Subject: [PATCH 10/10] (GH-417) Choco config command Add a config section to the configuration file. Move the existing items into that section that are not apikeys, sources, or features. Search for existing settings and port the value to the new location. Allow querying and setting these configuration values. --- src/chocolatey.tests/chocolatey.tests.csproj | 1 + .../commands/ChocolateyConfigCommandSpecs.cs | 136 +++++++++++++++++ src/chocolatey/chocolatey.csproj | 3 + .../ApplicationParameters.cs | 7 + .../builders/ConfigurationBuilder.cs | 69 +++++++-- .../commands/ChocolateyConfigCommand.cs | 141 ++++++++++++++++++ .../configuration/ChocolateyConfiguration.cs | 26 +++- .../configuration/ConfigFileConfigSetting.cs | 37 +++++ .../configuration/ConfigFileSettings.cs | 5 +- .../configuration/chocolatey.config | 7 +- .../domain/CommandNameType.cs | 2 + .../domain/ConfigCommandType.cs | 25 ++++ .../registration/ContainerBinding.cs | 1 + .../ChocolateyConfigSettingsService.cs | 83 ++++++++++- .../IChocolateyConfigSettingsService.cs | 3 + 15 files changed, 524 insertions(+), 22 deletions(-) create mode 100644 src/chocolatey.tests/infrastructure.app/commands/ChocolateyConfigCommandSpecs.cs create mode 100644 src/chocolatey/infrastructure.app/commands/ChocolateyConfigCommand.cs create mode 100644 src/chocolatey/infrastructure.app/configuration/ConfigFileConfigSetting.cs create mode 100644 src/chocolatey/infrastructure.app/domain/ConfigCommandType.cs diff --git a/src/chocolatey.tests/chocolatey.tests.csproj b/src/chocolatey.tests/chocolatey.tests.csproj index fe703dc39f..d859a51aef 100644 --- a/src/chocolatey.tests/chocolatey.tests.csproj +++ b/src/chocolatey.tests/chocolatey.tests.csproj @@ -65,6 +65,7 @@ + diff --git a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyConfigCommandSpecs.cs b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyConfigCommandSpecs.cs new file mode 100644 index 0000000000..a0b1d63c32 --- /dev/null +++ b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyConfigCommandSpecs.cs @@ -0,0 +1,136 @@ +// 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.tests.infrastructure.app.commands +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Moq; + using Should; + using chocolatey.infrastructure.app.attributes; + using chocolatey.infrastructure.app.commands; + using chocolatey.infrastructure.app.configuration; + using chocolatey.infrastructure.app.domain; + using chocolatey.infrastructure.app.services; + using chocolatey.infrastructure.commandline; + + public class ChocolateyConfigCommandSpecs + { + public abstract class ChocolateyConfigCommandSpecsBase : TinySpec + { + protected ChocolateyConfigCommand command; + protected Mock configSettingsService = new Mock(); + protected ChocolateyConfiguration configuration = new ChocolateyConfiguration(); + + public override void Context() + { + command = new ChocolateyConfigCommand(configSettingsService.Object); + } + } + + public class when_implementing_command_for : ChocolateyConfigCommandSpecsBase + { + private List results; + + public override void Because() + { + results = command.GetType().GetCustomAttributes(typeof(CommandForAttribute), false).Cast().Select(a => a.CommandName).ToList(); + } + + [Fact] + public void should_implement_config() + { + results.ShouldContain(CommandNameType.config.to_string()); + } + } + + public class when_configurating_the_argument_parser : ChocolateyConfigCommandSpecsBase + { + private OptionSet optionSet; + + public override void Context() + { + base.Context(); + optionSet = new OptionSet(); + } + + public override void Because() + { + command.configure_argument_parser(optionSet, configuration); + } + + [Fact] + public void should_add_name_to_the_option_set() + { + optionSet.Contains("name").ShouldBeTrue(); + } + + [Fact] + public void should_add_value_to_the_option_set() + { + optionSet.Contains("value").ShouldBeTrue(); + } + } + + public class when_noop_is_called : ChocolateyConfigCommandSpecsBase + { + public override void Because() + { + command.noop(configuration); + } + + [Fact] + public void should_call_service_noop() + { + configSettingsService.Verify(c => c.noop(configuration), Times.Once); + } + } + + public class when_run_is_called : ChocolateyConfigCommandSpecsBase + { + private Action because; + + public override void Because() + { + because = () => command.run(configuration); + } + + [Fact] + public void should_call_service_source_list_when_command_is_list() + { + configuration.ConfigCommand.Command = ConfigCommandType.list; + because(); + configSettingsService.Verify(c => c.config_list(configuration), Times.Once); + } + + [Fact] + public void should_call_service_source_disable_when_command_is_disable() + { + configuration.ConfigCommand.Command = ConfigCommandType.get; + because(); + configSettingsService.Verify(c => c.config_get(configuration), Times.Once); + } + + [Fact] + public void should_call_service_source_enable_when_command_is_enable() + { + configuration.ConfigCommand.Command = ConfigCommandType.set; + because(); + configSettingsService.Verify(c => c.config_set(configuration), Times.Once); + } + } + } +} diff --git a/src/chocolatey/chocolatey.csproj b/src/chocolatey/chocolatey.csproj index 8eee6d9aeb..c7d2711451 100644 --- a/src/chocolatey/chocolatey.csproj +++ b/src/chocolatey/chocolatey.csproj @@ -79,6 +79,7 @@ + @@ -91,9 +92,11 @@ + + diff --git a/src/chocolatey/infrastructure.app/ApplicationParameters.cs b/src/chocolatey/infrastructure.app/ApplicationParameters.cs index 6b928d458f..030a0b572f 100644 --- a/src/chocolatey/infrastructure.app/ApplicationParameters.cs +++ b/src/chocolatey/infrastructure.app/ApplicationParameters.cs @@ -76,6 +76,13 @@ public static class Tools public static readonly string ShimGenExe = _fileSystem.combine_paths(InstallLocation, "tools", "shimgen.exe"); } + public static class ConfigSettings + { + public static readonly string CacheLocation = "cacheLocation"; + public static readonly string ContainsLegacyPackageInstalls = "containsLegacyPackageInstalls"; + public static readonly string CommandExecutionTimeoutSeconds = "commandExecutionTimeoutSeconds"; + } + public static class Features { public static readonly string CheckSumFiles = "checksumFiles"; diff --git a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs index 1b5c335be8..a50da77585 100644 --- a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs +++ b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs @@ -91,25 +91,14 @@ private static void set_file_configuration(ChocolateyConfiguration config, IFile } set_machine_sources(config, configFileSettings); - - config.CacheLocation = !string.IsNullOrWhiteSpace(configFileSettings.CacheLocation) ? configFileSettings.CacheLocation : System.Environment.GetEnvironmentVariable("TEMP"); - if (string.IsNullOrWhiteSpace(config.CacheLocation)) - { - config.CacheLocation = fileSystem.combine_paths(ApplicationParameters.InstallLocation, "temp"); - } + + set_config_items(config, configFileSettings, fileSystem); 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); - config.ContainsLegacyPackageInstalls = configFileSettings.ContainsLegacyPackageInstalls; - if (configFileSettings.CommandExecutionTimeoutSeconds <= 0) - { - configFileSettings.CommandExecutionTimeoutSeconds = ApplicationParameters.DefaultWaitForExitInSeconds; - } - config.CommandExecutionTimeoutSeconds = configFileSettings.CommandExecutionTimeoutSeconds; - set_feature_flags(config, configFileSettings); // save so all updated configuration items get set to existing config @@ -134,6 +123,60 @@ private static void set_machine_sources(ChocolateyConfiguration config, ConfigFi } } + private static void set_config_items(ChocolateyConfiguration config, ConfigFileSettings configFileSettings, IFileSystem fileSystem) + { + var cacheLocation = set_config_item(ApplicationParameters.ConfigSettings.CacheLocation, configFileSettings, string.IsNullOrWhiteSpace(configFileSettings.CacheLocation) ? string.Empty : configFileSettings.CacheLocation, "Cache location if not TEMP folder."); + config.CacheLocation = !string.IsNullOrWhiteSpace(cacheLocation) ? cacheLocation : System.Environment.GetEnvironmentVariable("TEMP"); + if (string.IsNullOrWhiteSpace(config.CacheLocation)) + { + config.CacheLocation = fileSystem.combine_paths(ApplicationParameters.InstallLocation, "temp"); + } + + var originalCommandTimeout = configFileSettings.CommandExecutionTimeoutSeconds; + var commandExecutionTimeoutSeconds = -1; + int.TryParse( + set_config_item( + ApplicationParameters.ConfigSettings.CommandExecutionTimeoutSeconds, + configFileSettings, + originalCommandTimeout == 0 ? + ApplicationParameters.DefaultWaitForExitInSeconds.to_string() + : originalCommandTimeout.to_string(), + "Default timeout for command execution."), + out commandExecutionTimeoutSeconds); + config.CommandExecutionTimeoutSeconds = commandExecutionTimeoutSeconds; + if (configFileSettings.CommandExecutionTimeoutSeconds <= 0) + { + set_config_item(ApplicationParameters.ConfigSettings.CommandExecutionTimeoutSeconds, configFileSettings, ApplicationParameters.DefaultWaitForExitInSeconds.to_string(), "Default timeout for command execution.", forceSettingValue: true); + config.CommandExecutionTimeoutSeconds = ApplicationParameters.DefaultWaitForExitInSeconds; + } + + config.ContainsLegacyPackageInstalls = set_config_item(ApplicationParameters.ConfigSettings.ContainsLegacyPackageInstalls, configFileSettings, "true", "Install has packages installed prior to 0.9.9 series.").is_equal_to(bool.TrueString); + } + + private static string set_config_item(string configName, ConfigFileSettings configFileSettings, string defaultValue, string description, bool forceSettingValue = false) + { + var config = configFileSettings.ConfigSettings.FirstOrDefault(f => f.Key.is_equal_to(configName)); + if (config == null) + { + config = new ConfigFileConfigSetting + { + Key = configName, + Value = defaultValue, + Description = description + }; + + configFileSettings.ConfigSettings.Add(config); + } + if (forceSettingValue) + { + config.Value = defaultValue; + } + + config.Description = description; + + return config.Value; + } + private static void set_feature_flags(ChocolateyConfiguration config, ConfigFileSettings configFileSettings) { config.Features.CheckSumFiles = set_feature_flag(ApplicationParameters.Features.CheckSumFiles, configFileSettings, "Checksum files when pulled in from internet (based on package)."); diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyConfigCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyConfigCommand.cs new file mode 100644 index 0000000000..dcc86652b5 --- /dev/null +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyConfigCommand.cs @@ -0,0 +1,141 @@ +// 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.commands +{ + using System; + using System.Collections.Generic; + using System.Linq; + using attributes; + using commandline; + using configuration; + using domain; + using infrastructure.commands; + using logging; + using services; + + [CommandFor(CommandNameType.config)] + public sealed class ChocolateyConfigCommand : ICommand + { + private readonly IChocolateyConfigSettingsService _configSettingsService; + + public ChocolateyConfigCommand(IChocolateyConfigSettingsService configSettingsService) + { + _configSettingsService = configSettingsService; + } + + public void configure_argument_parser(OptionSet optionSet, ChocolateyConfiguration configuration) + { + configuration.Sources = string.Empty; + + optionSet + .Add( + "name=", + "Name - the name of the config setting. Required with some actions. Defaults to empty.", + option => configuration.ConfigCommand.Name = option.remove_surrounding_quotes()) + .Add( + "value=", + "Value - the value of the config setting. Required with some actions. Defaults to empty.", + option => configuration.ConfigCommand.ConfigValue = option.remove_surrounding_quotes()) + ; + } + + public void handle_additional_argument_parsing(IList unparsedArguments, ChocolateyConfiguration configuration) + { + configuration.Input = string.Join(" ", unparsedArguments); + var command = ConfigCommandType.unknown; + string unparsedCommand = unparsedArguments.DefaultIfEmpty(string.Empty).FirstOrDefault().to_string().Replace("-",string.Empty); + Enum.TryParse(unparsedCommand, true, out command); + if (command == ConfigCommandType.unknown) + { + if (!string.IsNullOrWhiteSpace(unparsedCommand)) this.Log().Warn("Unknown command {0}. Setting to list.".format_with(unparsedCommand)); + command = ConfigCommandType.list; + } + + configuration.ConfigCommand.Command = command; + + if ((configuration.ConfigCommand.Command == ConfigCommandType.list + || !string.IsNullOrWhiteSpace(configuration.ConfigCommand.Name) + ) + && unparsedArguments.Count > 1) throw new ApplicationException("A single features command must be listed. Please see the help menu for those commands"); + + if (string.IsNullOrWhiteSpace(configuration.ConfigCommand.Name) && unparsedArguments.Count >=2) + { + configuration.ConfigCommand.Name = unparsedArguments[1]; + } + if (string.IsNullOrWhiteSpace(configuration.ConfigCommand.ConfigValue) && unparsedArguments.Count >= 3) + { + configuration.ConfigCommand.ConfigValue = unparsedArguments[2]; + } + } + + public void handle_validation(ChocolateyConfiguration configuration) + { + if (configuration.ConfigCommand.Command != ConfigCommandType.list && string.IsNullOrWhiteSpace(configuration.ConfigCommand.Name)) throw new ApplicationException("When specifying the subcommand '{0}', you must also specify --name by option or position.".format_with(configuration.ConfigCommand.Command.to_string())); + if (configuration.ConfigCommand.Command == ConfigCommandType.set && string.IsNullOrWhiteSpace(configuration.ConfigCommand.ConfigValue)) throw new ApplicationException("When specifying the subcommand '{0}', you must also specify --value by option or position.".format_with(configuration.ConfigCommand.Command.to_string())); + } + + public void help_message(ChocolateyConfiguration configuration) + { + this.Log().Info(ChocolateyLoggers.Important, "Config Command"); + this.Log().Info(@" +Chocolatey will allow you to interact with the configuration file settings. +"); + + "chocolatey".Log().Info(ChocolateyLoggers.Important, "Usage"); + "chocolatey".Log().Info(@" + choco config [list]|get|set [] +"); + + "chocolatey".Log().Info(ChocolateyLoggers.Important, "Examples"); + "chocolatey".Log().Info(@" + choco config + choco config list + choco config get cacheLocation + choco config get --name cacheLocation + choco config set cacheLocation c:\temp\choco + choco config set --name cacheLocation --value c:\temp\choco +"); + + "chocolatey".Log().Info(ChocolateyLoggers.Important, "Options and Switches"); + } + + public void noop(ChocolateyConfiguration configuration) + { + _configSettingsService.noop(configuration); + } + + public void run(ChocolateyConfiguration configuration) + { + switch (configuration.ConfigCommand.Command) + { + case ConfigCommandType.list: + _configSettingsService.config_list(configuration); + break; + case ConfigCommandType.get: + _configSettingsService.config_get(configuration); + break; + case ConfigCommandType.set: + _configSettingsService.config_set(configuration); + break; + } + } + + public bool may_require_admin_access() + { + return true; + } + } +} diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index 6b749129a5..b434c7bd53 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -41,6 +41,7 @@ public ChocolateyConfiguration() SourceCommand = new SourcesCommandConfiguration(); MachineSources = new List(); FeatureCommand = new FeatureCommandConfiguration(); + ConfigCommand = new ConfigCommandConfiguration(); ApiKeyCommand = new ApiKeyCommandConfiguration(); PushCommand = new PushCommandConfiguration(); PinCommand = new PinCommandConfiguration(); @@ -54,7 +55,7 @@ public override string ToString() { var properties = new StringBuilder(); - this.Log().Debug(ChocolateyLoggers.Important,@" + this.Log().Debug(ChocolateyLoggers.Important, @" NOTE: Hiding sensitive configuration data! Please double and triple check to be sure no sensitive data is shown, especially if copying output to a gist for review."); @@ -250,6 +251,7 @@ private void append_output(StringBuilder propertyValues, string append) /// public SourcesCommandConfiguration SourceCommand { get; set; } + /// /// Default Machine Sources Configuration /// @@ -264,7 +266,15 @@ private void append_output(StringBuilder propertyValues, string append) /// /// On .NET 4.0, get error CS0200 when private set - see http://stackoverflow.com/a/23809226/18475 /// - public FeatureCommandConfiguration FeatureCommand { get; set; } + public FeatureCommandConfiguration FeatureCommand { get; set; } + + /// + /// Configuration related to the configuration file. + /// + /// + /// On .NET 4.0, get error CS0200 when private set - see http://stackoverflow.com/a/23809226/18475 + /// + public ConfigCommandConfiguration ConfigCommand { get; set; } /// /// Configuration related specifically to ApiKey command @@ -324,8 +334,8 @@ public sealed class ListCommandConfiguration // list public bool LocalOnly { get; set; } public bool IncludeRegistryPrograms { get; set; } - } - + } + [Serializable] public sealed class UpgradeCommandConfiguration { @@ -373,6 +383,14 @@ public sealed class FeatureCommandConfiguration { public string Name { get; set; } public FeatureCommandType Command { get; set; } + } + + [Serializable] + public sealed class ConfigCommandConfiguration + { + public string Name { get; set; } + public string ConfigValue { get; set; } + public ConfigCommandType Command { get; set; } } [Serializable] diff --git a/src/chocolatey/infrastructure.app/configuration/ConfigFileConfigSetting.cs b/src/chocolatey/infrastructure.app/configuration/ConfigFileConfigSetting.cs new file mode 100644 index 0000000000..0f88350f49 --- /dev/null +++ b/src/chocolatey/infrastructure.app/configuration/ConfigFileConfigSetting.cs @@ -0,0 +1,37 @@ +// 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.configuration +{ + using System; + using System.Xml.Serialization; + + /// + /// XML config file config element + /// + [Serializable] + [XmlType("add")] + public sealed class ConfigFileConfigSetting + { + [XmlAttribute(AttributeName = "key")] + public string Key { get; set; } + + [XmlAttribute(AttributeName = "value")] + public string Value { get; set; } + + [XmlAttribute(AttributeName = "description")] + public string Description { get; set; } + } +} diff --git a/src/chocolatey/infrastructure.app/configuration/ConfigFileSettings.cs b/src/chocolatey/infrastructure.app/configuration/ConfigFileSettings.cs index 355804ac06..d23730f9af 100644 --- a/src/chocolatey/infrastructure.app/configuration/ConfigFileSettings.cs +++ b/src/chocolatey/infrastructure.app/configuration/ConfigFileSettings.cs @@ -34,7 +34,10 @@ public class ConfigFileSettings [XmlElement(ElementName = "commandExecutionTimeoutSeconds")] public int CommandExecutionTimeoutSeconds { get; set; } - + + [XmlArray("config")] + public HashSet ConfigSettings { get; set; } + [XmlArray("sources")] public HashSet Sources { get; set; } diff --git a/src/chocolatey/infrastructure.app/configuration/chocolatey.config b/src/chocolatey/infrastructure.app/configuration/chocolatey.config index 03881ef5ea..9c70d8d353 100644 --- a/src/chocolatey/infrastructure.app/configuration/chocolatey.config +++ b/src/chocolatey/infrastructure.app/configuration/chocolatey.config @@ -1,7 +1,10 @@  - - true + + + + + diff --git a/src/chocolatey/infrastructure.app/domain/CommandNameType.cs b/src/chocolatey/infrastructure.app/domain/CommandNameType.cs index d2e54a032f..03fc056d07 100644 --- a/src/chocolatey/infrastructure.app/domain/CommandNameType.cs +++ b/src/chocolatey/infrastructure.app/domain/CommandNameType.cs @@ -43,5 +43,7 @@ public enum CommandNameType [Description("apikey - retrieves or saves an apikey for a particular source")] apikey, [Description("setapikey - retrieves or saves an apikey for a particular source (alias for apikey)")] setapikey, + [Description("config - Retrieve and configure config file settings")] + config, } } \ No newline at end of file diff --git a/src/chocolatey/infrastructure.app/domain/ConfigCommandType.cs b/src/chocolatey/infrastructure.app/domain/ConfigCommandType.cs new file mode 100644 index 0000000000..aeb3a5a749 --- /dev/null +++ b/src/chocolatey/infrastructure.app/domain/ConfigCommandType.cs @@ -0,0 +1,25 @@ +// 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.domain +{ + public enum ConfigCommandType + { + unknown, + list, + get, + set, + } +} diff --git a/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs b/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs index 58b767cdd8..66e35cf7fa 100644 --- a/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs +++ b/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs @@ -80,6 +80,7 @@ public void RegisterComponents(Container container) new ChocolateyPushCommand(container.GetInstance(), container.GetInstance()), new ChocolateyNewCommand(container.GetInstance()), new ChocolateySourceCommand(container.GetInstance()), + new ChocolateyConfigCommand(container.GetInstance()), new ChocolateyFeatureCommand(container.GetInstance()), new ChocolateyApiKeyCommand(container.GetInstance()), new ChocolateyUnpackSelfCommand(container.GetInstance()), diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs index a8c8dbeb41..00e1754040 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs @@ -259,11 +259,90 @@ public void set_api_key(ChocolateyConfiguration configuration) _xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation); this.Log().Info(() => "Updated ApiKey for {0}".format_with(configuration.Sources)); } - else + else this.Log().Warn(NO_CHANGE_MESSAGE); + } + } + + public void config_list(ChocolateyConfiguration configuration) + { + this.Log().Info(ChocolateyLoggers.Important, "Settings"); + foreach (var config in configFileSettings.ConfigSettings) + { + this.Log().Info(() => "{0} = {1} | {2}".format_with(config.Key, config.Value, config.Description)); + } + + this.Log().Info(""); + this.Log().Info(ChocolateyLoggers.Important, "Sources"); + source_list(configuration); + this.Log().Info(""); + this.Log().Info(@"NOTE: Use choco source to interact with sources."); + this.Log().Info(""); + this.Log().Info(ChocolateyLoggers.Important, "Features"); + feature_list(configuration); + this.Log().Info(""); + this.Log().Info(@"NOTE: Use choco feature to interact with features."); + ; + this.Log().Info(""); + this.Log().Info(ChocolateyLoggers.Important, "API Keys"); + this.Log().Info(@"NOTE: Api Keys are not shown through this command. + Use choco apikey to interact with API keys."); + } + + public void config_get(ChocolateyConfiguration configuration) + { + var config = config_get(configuration.ConfigCommand.Name); + if (config == null) throw new ApplicationException("No configuration value by the name '{0}'".format_with(configuration.ConfigCommand.Name)); + this.Log().Info("{0}".format_with(config.Value)); + } + + public ConfigFileConfigSetting config_get(string configKeyName) + { + var config = configFileSettings.ConfigSettings.FirstOrDefault(p => p.Key.is_equal_to(configKeyName)); + if (config == null) return null; + + return config; + } + + public void config_set(ChocolateyConfiguration configuration) + { + var encryptValue = configuration.ConfigCommand.Name.contains("password"); + var config = config_get(configuration.ConfigCommand.Name); + var configValue = encryptValue + ? NugetEncryptionUtility.EncryptString(configuration.ConfigCommand.ConfigValue) + : configuration.ConfigCommand.ConfigValue; + + if (config == null) + { + var setting = new ConfigFileConfigSetting + { + Key = configuration.ConfigCommand.Name, + Value = configValue, + }; + + configFileSettings.ConfigSettings.Add(setting); + + _xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation); + + this.Log().Warn(() => "Added {0} = {1}".format_with(setting.Key, setting.Value)); + } + else + { + var currentValue = encryptValue && !string.IsNullOrWhiteSpace(config.Value) + ? NugetEncryptionUtility.DecryptString(config.Value) + : config.Value; + + if (configuration.ConfigCommand.ConfigValue.is_equal_to(currentValue.to_string())) { this.Log().Warn(NO_CHANGE_MESSAGE); } + else + { + config.Value = configValue; + _xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation); + + this.Log().Warn(() => "Updated {0} = {1}".format_with(config.Key, config.Value)); + } } } } -} \ No newline at end of file +} diff --git a/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs index 3d29562e6b..10a0cdb33d 100644 --- a/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs @@ -31,5 +31,8 @@ public interface IChocolateyConfigSettingsService void feature_enable(ChocolateyConfiguration configuration); string get_api_key(ChocolateyConfiguration configuration, Action keyAction); void set_api_key(ChocolateyConfiguration configuration); + void config_list(ChocolateyConfiguration configuration); + void config_get(ChocolateyConfiguration configuration); + void config_set(ChocolateyConfiguration configuration); } } \ No newline at end of file