From ab27a7a666c94238fe937feead9388bde673fe2c Mon Sep 17 00:00:00 2001 From: Christian Rondeau Date: Tue, 21 Jul 2015 20:17:14 -0400 Subject: [PATCH] (GH-293) Upgrade all --except Allow passing a list of packages to skip on upgrade. There may be times when you want to process upgrades for everything except for a few applications that you may be currently running, like ConEmu. Not being able to ignore certain packages on upgrade all is problematic, especially when choco upgrades an application while a user is in the middle of using it. This could get quite annoying, especially with something like ConEmu - if you are using it to run upgarde all it will stop processing choco and continue its upgrade. There are other situations where having the ability to ignore certain packages would be very beneficial. --- Scenarios.md | 13 +++- .../scenarios/UpgradeScenarios.cs | 67 +++++++++++++++++++ .../commands/ChocolateyUpgradeCommand.cs | 5 ++ .../configuration/ChocolateyConfiguration.cs | 1 + .../services/NugetService.cs | 36 +++++++++- 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/Scenarios.md b/Scenarios.md index 734f784c25..039dad9e8f 100644 --- a/Scenarios.md +++ b/Scenarios.md @@ -623,7 +623,7 @@ * should throw an error that it is not allowed -### ChocolateyUpgradeCommand [ 27 Scenario(s), 216 Observation(s) ] +### ChocolateyUpgradeCommand [ 29 Scenario(s), 221 Observation(s) ] #### when force upgrading a package @@ -903,6 +903,17 @@ * should not upgrade the minimum version dependency * should upgrade the package +#### when upgrading all packages happy path + + * should report for all installed packages + * should skip packages without upgrades + * should upgrade packages with upgrades + +#### when upgrading all packages with except + + * should report for all non skipped packages + * should skip packages in except list + #### when upgrading an existing package happy path * config should match package result name diff --git a/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs b/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs index 8cb45eb71b..8ef598d800 100644 --- a/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs +++ b/src/chocolatey.tests.integration/scenarios/UpgradeScenarios.cs @@ -2409,5 +2409,72 @@ public void should_not_have_any_packages_upgraded() Results.Count().ShouldEqual(0); } } + + [Concern(typeof(ChocolateyUpgradeCommand))] + public class when_upgrading_all_packages_happy_path : ScenariosBase + { + public override void Context() + { + base.Context(); + Configuration.PackageNames = Configuration.Input = "all"; + } + + public override void Because() + { + Results = Service.upgrade_run(Configuration); + } + + [Fact] + public void should_report_for_all_installed_packages() + { + Results.Count().ShouldEqual(3); + } + + [Fact] + public void should_upgrade_packages_with_upgrades() + { + var upgradePackageResult = Results.Where(x => x.Key == "upgradepackage").ToList(); + upgradePackageResult.Count.ShouldEqual(1, "upgradepackage must be there once"); + upgradePackageResult.First().Value.Version.ShouldEqual("1.1.0"); + } + + [Fact] + public void should_skip_packages_without_upgrades() + { + var installPackageResult = Results.Where(x => x.Key == "installpackage").ToList(); + installPackageResult.Count.ShouldEqual(1, "installpackage must be there once"); + installPackageResult.First().Value.Version.ShouldEqual("1.0.0"); + } + } + + [Concern(typeof(ChocolateyUpgradeCommand))] + public class when_upgrading_all_packages_with_except : ScenariosBase + { + public override void Context() + { + base.Context(); + Configuration.PackageNames = Configuration.Input = "all"; + Configuration.UpgradeCommand.PackageNamesToSkip = "upgradepackage,badpackage"; + } + + public override void Because() + { + Results = Service.upgrade_run(Configuration); + } + + [Fact] + public void should_report_for_all_non_skipped_packages() + { + Results.Count().ShouldEqual(1); + Results.First().Key.ShouldEqual("installpackage"); + } + + [Fact] + public void should_skip_packages_in_except_list() + { + var upgradePackageResult = Results.Where(x => x.Key == "upgradepackage").ToList(); + upgradePackageResult.Count.ShouldEqual(0, "upgradepackage should not be in the results list"); + } + } } } \ 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 edd510f6e5..c3b1657adc 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs @@ -94,6 +94,9 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon { if (option != null) configuration.Features.CheckSumFiles = false; }) + .Add("except=", + "Except - a comma-separated list of package names that should not be upgraded when upgrading 'all'. Defaults to empty.", + option => configuration.UpgradeCommand.PackageNamesToSkip = option.remove_surrounding_quotes()) ; } @@ -137,6 +140,8 @@ choco upgrade notepadplusplus googlechrome atom 7zip -dvfy choco upgrade nodejs.install --version 0.10.35 choco upgrade git -s ""https://somewhere/out/there"" choco upgrade git -s ""https://somewhere/protected"" -u user -p pass + choco upgrade all + choco upgrade all --except=""skype,conemu"" "); "chocolatey".Log().Info(ChocolateyLoggers.Important, "Options and Switches"); diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index d13a1b1489..c5ca158ba2 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -363,6 +363,7 @@ public sealed class UpgradeCommandConfiguration public bool FailOnUnfound { get; set; } public bool FailOnNotInstalled { get; set; } public bool NotifyOnlyAvailableUpgrades { get; set; } + public string PackageNamesToSkip { get; set; } } [Serializable] diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs index 7974cb8780..b69cba6590 100644 --- a/src/chocolatey/infrastructure.app/services/NugetService.cs +++ b/src/chocolatey/infrastructure.app/services/NugetService.cs @@ -1155,13 +1155,45 @@ private void set_package_names_if_all_is_specified(ChocolateyConfiguration confi var quiet = config.QuietOutput; config.QuietOutput = true; - config.PackageNames = list_run(config).Select(p => p.Name).@join(ApplicationParameters.PackageNamesSeparator); - + var packagesToUpdate = list_run(config).Select(p => p.Name).ToList(); + + if (!string.IsNullOrWhiteSpace(config.UpgradeCommand.PackageNamesToSkip)) + { + var packagesToSkip = config.UpgradeCommand.PackageNamesToSkip + .Split(',') + .Where(item => !string.IsNullOrWhiteSpace(item)) + .Select(p => p.trim_safe()) + .ToList(); + + var unknownPackagesToSkip = packagesToSkip + .Where(p => !packagesToUpdate.Contains(p, StringComparer.OrdinalIgnoreCase)) + .ToList(); + + if (unknownPackagesToSkip.Any()) + { + this.Log().Warn(() => "Some packages specified in the 'except' list were not found in the local packages: '{0}'".format_with(string.Join(",", unknownPackagesToSkip))); + + packagesToSkip = packagesToSkip + .Where(p => !unknownPackagesToSkip.Contains(p, StringComparer.OrdinalIgnoreCase)) + .ToList(); + } + + if (packagesToSkip.Any()) + { + packagesToUpdate = packagesToUpdate + .Where(p => !packagesToSkip.Contains(p, StringComparer.OrdinalIgnoreCase)) + .ToList(); + + this.Log().Info(() => "These packages will not be upgraded because they were specified in the 'except' list: {0}".format_with(string.Join(",", packagesToSkip))); + } + } + config.QuietOutput = quiet; config.Input = input; config.Noop = noop; config.Prerelease = pre; config.Sources = sources; + config.PackageNames = packagesToUpdate.@join(ApplicationParameters.PackageNamesSeparator); if (customAction != null) customAction.Invoke(); }