diff --git a/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj b/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj
index 30fddbaff6..a7a6209a26 100644
--- a/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj
+++ b/src/chocolatey.tests.integration/chocolatey.tests.integration.csproj
@@ -86,6 +86,7 @@
+
diff --git a/src/chocolatey.tests.integration/scenarios/UpgradeAllScenarios.cs b/src/chocolatey.tests.integration/scenarios/UpgradeAllScenarios.cs
new file mode 100644
index 0000000000..c6132754b4
--- /dev/null
+++ b/src/chocolatey.tests.integration/scenarios/UpgradeAllScenarios.cs
@@ -0,0 +1,105 @@
+// 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.integration.scenarios
+{
+ using System.Collections.Concurrent;
+ using System.Linq;
+ using NuGet;
+ using Should;
+ using bdddoc.core;
+ using chocolatey.infrastructure.app.commands;
+ using chocolatey.infrastructure.app.configuration;
+ using chocolatey.infrastructure.app.services;
+ using chocolatey.infrastructure.results;
+
+ public class UpgradeAllScenarios
+ {
+ public abstract class ScenariosBase : TinySpec
+ {
+ protected ConcurrentDictionary Results;
+ protected ChocolateyConfiguration Configuration;
+ protected IChocolateyPackageService Service;
+
+ public override void Context()
+ {
+ Configuration = Scenario.upgrade();
+ Scenario.reset(Configuration);
+ Configuration.PackageNames = Configuration.Input = "all";
+ Scenario.add_packages_to_source_location(Configuration, "upgradepackage*" + Constants.PackageExtension);
+ Scenario.add_packages_to_source_location(Configuration, "installpackage*" + Constants.PackageExtension);
+ Scenario.install_package(Configuration, "installpackage", "1.0.0");
+ Scenario.install_package(Configuration, "upgradepackage", "1.0.0");
+ Configuration.SkipPackageInstallProvider = true;
+
+ Service = NUnitSetup.Container.GetInstance();
+ }
+ }
+
+ [Concern(typeof (ChocolateyUpgradeCommand))]
+ public class when_upgrading_all_packages_happy_path : ScenariosBase
+ {
+ public override void Because()
+ {
+ Results = Service.upgrade_run(Configuration);
+ }
+
+ [Fact]
+ public void should_report_for_all_installed_packages()
+ {
+ Results.Count().ShouldEqual(2);
+ }
+
+ [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 Because()
+ {
+ Configuration.UpgradeCommand.PackageNamesToSkip = "upgradepackage";
+ Results = Service.upgrade_run(Configuration);
+ }
+
+ [Fact]
+ public void should_report_for_all_non_skipped_packages()
+ {
+ Results.Count().ShouldEqual(1);
+ }
+
+ [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 a5b0763faf..b8b6674142 100644
--- a/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs
+++ b/src/chocolatey/infrastructure.app/commands/ChocolateyUpgradeCommand.cs
@@ -85,6 +85,9 @@ 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("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())
;
}
@@ -128,6 +131,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 8ecd74249d..144b0568d9 100644
--- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
+++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
@@ -333,6 +333,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 4711f1717d..86945fa31f 100644
--- a/src/chocolatey/infrastructure.app/services/NugetService.cs
+++ b/src/chocolatey/infrastructure.app/services/NugetService.cs
@@ -1047,13 +1047,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(x => !String.IsNullOrWhiteSpace(x))
+ .Select(x => x.trim_safe())
+ .ToList();
+
+ var unknownPackagesToSkip = packagesToSkip
+ .Where(x => !packagesToUpdate.Contains(x, 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(x => !unknownPackagesToSkip.Contains(x))
+ .ToList();
+ }
+
+ if (packagesToSkip.Any())
+ {
+ packagesToUpdate = packagesToUpdate
+ .Where(x => !packagesToSkip.Contains(x, 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();
}