From ee9670630cbd7e7831488ac52f7ef191f0939c32 Mon Sep 17 00:00:00 2001 From: TheCakeIsNaOH Date: Tue, 4 Jan 2022 23:05:11 -0600 Subject: [PATCH] (#2503) Add ability to export remembered arguments This adds the --include-remembered-arguments option which is used to export any remembered arguments. This reuses the set_package_config_for_upgrade method in the NugetService to read and parse the saved arguments. --- .../helpers/ChocolateyTabExpansion.ps1 | 2 +- .../commands/ChocolateyExportCommandSpecs.cs | 18 ++++- .../commands/ChocolateyExportCommand.cs | 73 ++++++++++++++++++- .../configuration/ChocolateyConfiguration.cs | 1 + .../registration/ContainerBinding.cs | 6 +- 5 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/chocolatey.resources/helpers/ChocolateyTabExpansion.ps1 b/src/chocolatey.resources/helpers/ChocolateyTabExpansion.ps1 index bc03275b70..5d1706b2d6 100644 --- a/src/chocolatey.resources/helpers/ChocolateyTabExpansion.ps1 +++ b/src/chocolatey.resources/helpers/ChocolateyTabExpansion.ps1 @@ -64,7 +64,7 @@ $commandOptions = @{ sync = "--output-directory='' --id='' --package-id='' -?" + $allcommands optimize = "--deflate-nupkg-only --id='' -?" + $allcommands export = "--include-version-numbers --output-file-path='' -?" + $allcommands - template = "--name=''" + $allcommands + template = "--name='' --include-remembered-arguments" + $allcommands } try { diff --git a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyExportCommandSpecs.cs b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyExportCommandSpecs.cs index ee28daa473..d564a4eb95 100644 --- a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyExportCommandSpecs.cs +++ b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyExportCommandSpecs.cs @@ -36,16 +36,20 @@ public abstract class ChocolateyExportCommandSpecsBase : TinySpec protected Mock nugetService = new Mock(); protected Mock fileSystem = new Mock(); protected ChocolateyConfiguration configuration = new ChocolateyConfiguration(); + protected Mock packageInfoService = new Mock(); + protected Mock packageService = new Mock(); public override void Context() { - command = new ChocolateyExportCommand(nugetService.Object, fileSystem.Object); + command = new ChocolateyExportCommand(nugetService.Object, fileSystem.Object, packageInfoService.Object, packageService.Object); } public void reset() { nugetService.ResetCalls(); fileSystem.ResetCalls(); + packageInfoService.ResetCalls(); + packageService.ResetCalls(); } } @@ -103,6 +107,18 @@ public void should_add_include_version_to_the_option_set() { optionSet.Contains("include-version").ShouldBeTrue(); } + + [Fact] + public void should_add_include_arguments_to_the_option_set() + { + optionSet.Contains("include-arguments").ShouldBeTrue(); + } + + [Fact] + public void should_add_include_remembered_arguments_to_the_option_set() + { + optionSet.Contains("include-remembered-arguments").ShouldBeTrue(); + } } public class when_handling_additional_argument_parsing : ChocolateyExportCommandSpecsBase diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyExportCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyExportCommand.cs index f27562258e..30dec8e2c7 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyExportCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyExportCommand.cs @@ -36,11 +36,19 @@ public class ChocolateyExportCommand : ICommand { private readonly INugetService _nugetService; private readonly IFileSystem _fileSystem; - - public ChocolateyExportCommand(INugetService nugetService, IFileSystem fileSystem) + private readonly IChocolateyPackageInformationService _packageInfoService; + private readonly IChocolateyPackageService _packageService; + + public ChocolateyExportCommand( + INugetService nugetService, + IFileSystem fileSystem, + IChocolateyPackageInformationService packageInfoService, + IChocolateyPackageService packageService) { _nugetService = nugetService; _fileSystem = fileSystem; + _packageInfoService = packageInfoService; + _packageService = packageService; } public void configure_argument_parser(OptionSet optionSet, ChocolateyConfiguration configuration) @@ -52,6 +60,9 @@ public void configure_argument_parser(OptionSet optionSet, ChocolateyConfigurati .Add("include-version-numbers|include-version", "Include Version Numbers - controls whether or not version numbers for each package appear in generated file. Defaults to false.", option => configuration.ExportCommand.IncludeVersionNumbers = option != null) + .Add("include-arguments|include-remembered-arguments", + "Include Remembered Arguments - controls whether or not remembered arguments for each package appear in generated file. Defaults to false. Available in 1.2.0+", + option => configuration.ExportCommand.IncludeRememberedPackageArguments = option != null) ; } @@ -97,12 +108,14 @@ choco export [] "chocolatey".Log().Info(@" choco export choco export --include-version-numbers + choco export --include-version-numbers --include-remembered-arguments choco export ""'c:\temp\packages.config'"" choco export ""'c:\temp\packages.config'"" --include-version-numbers choco export -o=""'c:\temp\packages.config'"" choco export -o=""'c:\temp\packages.config'"" --include-version-numbers choco export --output-file-path=""'c:\temp\packages.config'"" choco export --output-file-path=""'c:\temp\packages.config'"" --include-version-numbers + choco export --output-file-path=""'c:\temp\packages.config'"" --include-remembered-arguments NOTE: See scripting in the command reference (`choco -?`) for how to write proper scripts and integrations. @@ -133,13 +146,24 @@ public bool may_require_admin_access() public void noop(ChocolateyConfiguration configuration) { - this.Log().Info("Export would have been with options: {0} Output File Path={1}{0} Include Version Numbers:{2}".format_with(Environment.NewLine, configuration.ExportCommand.OutputFilePath, configuration.ExportCommand.IncludeVersionNumbers)); + this.Log().Info("Export would have been with options: {0} Output File Path={1}{0} Include Version Numbers:{2}{0} Include Remembered Arguments: {3}".format_with(Environment.NewLine, configuration.ExportCommand.OutputFilePath, configuration.ExportCommand.IncludeVersionNumbers, configuration.ExportCommand.IncludeRememberedPackageArguments)); } public void run(ChocolateyConfiguration configuration) { var packageResults = _nugetService.get_all_installed_packages(configuration); var settings = new XmlWriterSettings { Indent = true, Encoding = new UTF8Encoding(false) }; + var originalConfiguration = configuration.deep_copy(); + + if (configuration.ExportCommand.IncludeRememberedPackageArguments) + { + // The -o argument from the export command options set interferes with the -o argument from the install command options set. + ConfigurationOptions.OptionSet.Remove("o"); + + // Add the options set from the install command. + var installCommand = new ChocolateyInstallCommand(_packageService); + installCommand.configure_argument_parser(ConfigurationOptions.OptionSet, configuration); + } FaultTolerance.try_catch_with_logging_exception( () => @@ -161,6 +185,49 @@ public void run(ChocolateyConfiguration configuration) xw.WriteAttributeString("version", packageResult.Package.Version.ToString()); } + if (configuration.ExportCommand.IncludeRememberedPackageArguments) + { + var pkgInfo = _packageInfoService.get_package_information(packageResult.Package); + configuration.Features.UseRememberedArgumentsForUpgrades = true; + _nugetService.set_package_config_for_upgrade(configuration, pkgInfo); + + // Mirrors the arguments captured in ChocolateyPackageService.capture_arguments() + + if (configuration.Prerelease) xw.WriteAttributeString("prerelease", "true"); + if (configuration.IgnoreDependencies) xw.WriteAttributeString("ignoreDependencies", "true"); + if (configuration.ForceX86) xw.WriteAttributeString("forceX86", "true"); + + if (!string.IsNullOrWhiteSpace(configuration.InstallArguments)) xw.WriteAttributeString("installArguments", configuration.InstallArguments); + if (configuration.OverrideArguments) xw.WriteAttributeString("overrideArguments", "true"); + if (configuration.ApplyInstallArgumentsToDependencies) xw.WriteAttributeString("applyInstallArgumentsToDependencies", "true"); + + if (!string.IsNullOrWhiteSpace(configuration.PackageParameters)) xw.WriteAttributeString("packageParameters", configuration.PackageParameters); + if (configuration.ApplyPackageParametersToDependencies) xw.WriteAttributeString("applyPackageParametersToDependencies", "true"); + + if (configuration.AllowDowngrade) xw.WriteAttributeString("allowDowngrade", "true"); + if (configuration.AllowMultipleVersions) xw.WriteAttributeString("allowMultipleVersions", "true"); + + if (!string.IsNullOrWhiteSpace(configuration.SourceCommand.Username)) xw.WriteAttributeString("user", configuration.SourceCommand.Username); + if (!string.IsNullOrWhiteSpace(configuration.SourceCommand.Password)) xw.WriteAttributeString("password", configuration.SourceCommand.Password); + if (!string.IsNullOrWhiteSpace(configuration.SourceCommand.Certificate)) xw.WriteAttributeString("cert", configuration.SourceCommand.Certificate); + if (!string.IsNullOrWhiteSpace(configuration.SourceCommand.CertificatePassword)) xw.WriteAttributeString("certPassword", configuration.SourceCommand.CertificatePassword); + + // Arguments from the global options set + if (configuration.CommandExecutionTimeoutSeconds != ApplicationParameters.DefaultWaitForExitInSeconds) + { + xw.WriteAttributeString("timeout",configuration.CommandExecutionTimeoutSeconds.to_string()); + } + + // This was discussed in the PR, and because it is potentially system specific, it should not be included in the exported file + // if (!string.IsNullOrWhiteSpace(configuration.CacheLocation)) xw.WriteAttributeString("cacheLocation", configuration.CacheLocation); + + if (configuration.Features.FailOnStandardError) xw.WriteAttributeString("failOnStderr", "true"); + if (!configuration.Features.UsePowerShellHost) xw.WriteAttributeString("useSystemPowershell", "true"); + + // Make sure to reset the configuration + configuration = originalConfiguration.deep_copy(); + } + xw.WriteEndElement(); } diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index ca4ee25576..c796e4835e 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -572,6 +572,7 @@ public sealed class ProxyConfiguration public sealed class ExportCommandConfiguration { public bool IncludeVersionNumbers { get; set; } + public bool IncludeRememberedPackageArguments { get; set; } public string OutputFilePath { get; set; } } diff --git a/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs b/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs index ff21ee6da4..6aebc4ce2f 100644 --- a/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs +++ b/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs @@ -95,7 +95,11 @@ public void RegisterComponents(Container container) new ChocolateyFeatureCommand(container.GetInstance()), new ChocolateyApiKeyCommand(container.GetInstance()), new ChocolateyUnpackSelfCommand(container.GetInstance()), - new ChocolateyExportCommand(container.GetInstance(), container.GetInstance()), + new ChocolateyExportCommand( + container.GetInstance(), + container.GetInstance(), + container.GetInstance(), + container.GetInstance()), new ChocolateyTemplateCommand(container.GetInstance()), new ChocolateyVersionCommand(container.GetInstance()), new ChocolateyUpdateCommand(container.GetInstance())