diff --git a/src/chocolatey/ObjectExtensions.cs b/src/chocolatey/ObjectExtensions.cs
index 44346c5e7a..3fbb18e353 100644
--- a/src/chocolatey/ObjectExtensions.cs
+++ b/src/chocolatey/ObjectExtensions.cs
@@ -15,6 +15,9 @@
namespace chocolatey
{
+ using System.IO;
+ using System.Runtime.Serialization.Formatters.Binary;
+
///
/// Extensions for Object
///
@@ -31,5 +34,17 @@ public static string to_string(this object input)
return input.ToString();
}
+
+ public static T deep_copy(this T other)
+ {
+ using (var ms = new MemoryStream())
+ {
+ var formatter = new BinaryFormatter();
+ formatter.Serialize(ms, other);
+ ms.Position = 0;
+ return (T)formatter.Deserialize(ms);
+ }
+ }
+
}
}
\ No newline at end of file
diff --git a/src/chocolatey/chocolatey.csproj b/src/chocolatey/chocolatey.csproj
index b59a2a2c25..ddc78c96dc 100644
--- a/src/chocolatey/chocolatey.csproj
+++ b/src/chocolatey/chocolatey.csproj
@@ -91,6 +91,8 @@
+
+
diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
index 68477f4cf4..2e0c8c394e 100644
--- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
+++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs
@@ -25,6 +25,7 @@ namespace chocolatey.infrastructure.app.configuration
///
/// The chocolatey configuration.
///
+ [Serializable]
public class ChocolateyConfiguration
{
public ChocolateyConfiguration()
@@ -202,6 +203,7 @@ private void output_tostring(StringBuilder propertyValues, IEnumerable TemplateProperties { get; private set; }
}
+ [Serializable]
public sealed class SourcesCommandConfiguration
{
public string Name { get; set; }
public SourceCommandType Command { get; set; }
public string Username { get; set; }
public string Password { get; set; }
- }
-
+ }
+
+ [Serializable]
public sealed class FeatureCommandConfiguration
{
public string Name { get; set; }
public FeatureCommandType Command { get; set; }
}
+ [Serializable]
public sealed class PinCommandConfiguration
{
public string Name { get; set; }
public PinCommandType Command { get; set; }
}
+ [Serializable]
public sealed class ApiKeyCommandConfiguration
{
public string Key { get; set; }
}
+ [Serializable]
public sealed class PushCommandConfiguration
{
public string Key { get; set; }
diff --git a/src/chocolatey/infrastructure.app/configuration/PackagesConfigFilePackageSetting.cs b/src/chocolatey/infrastructure.app/configuration/PackagesConfigFilePackageSetting.cs
new file mode 100644
index 0000000000..95f58f137f
--- /dev/null
+++ b/src/chocolatey/infrastructure.app/configuration/PackagesConfigFilePackageSetting.cs
@@ -0,0 +1,55 @@
+// 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 packages.config file package element
+ ///
+ [Serializable]
+ //[XmlType("package")]
+ public sealed class PackagesConfigFilePackageSetting
+ {
+ [XmlAttribute(AttributeName = "id")]
+ public string Id { get; set; }
+
+ [XmlAttribute(AttributeName = "source")]
+ public string Source { get; set; }
+
+ [XmlAttribute(AttributeName = "version")]
+ public string Version { get; set; }
+
+ [XmlAttribute(AttributeName = "installArguments")]
+ public string InstallArguments { get; set; }
+
+ [XmlAttribute(AttributeName = "packageParameters")]
+ public string PackageParameters { get; set; }
+
+ [XmlAttribute(AttributeName = "forceX86")]
+ public bool ForceX86 { get; set; }
+
+ [XmlAttribute(AttributeName = "allowMultipleVersions")]
+ public bool AllowMultipleVersions { get; set; }
+
+ [XmlAttribute(AttributeName = "ignoreDependencies")]
+ public bool IgnoreDependencies { get; set; }
+
+ [XmlAttribute(AttributeName = "disabled")]
+ public bool Disabled { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/chocolatey/infrastructure.app/configuration/PackagesConfigFileSettings.cs b/src/chocolatey/infrastructure.app/configuration/PackagesConfigFileSettings.cs
new file mode 100644
index 0000000000..204c1749e6
--- /dev/null
+++ b/src/chocolatey/infrastructure.app/configuration/PackagesConfigFileSettings.cs
@@ -0,0 +1,32 @@
+// 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.Collections.Generic;
+ using System.Xml.Serialization;
+
+ ///
+ /// XML packages.config configuration file
+ ///
+ [Serializable]
+ [XmlRoot("packages")]
+ public class PackagesConfigFileSettings
+ {
+ [XmlElement("package")]
+ public HashSet Packages { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs
index 0363cc79c8..e3de220ce9 100644
--- a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs
+++ b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs
@@ -23,6 +23,7 @@ namespace chocolatey.infrastructure.app.services
using configuration;
using domain;
using filesystem;
+ using infrastructure.services;
using logging;
using platforms;
using results;
@@ -36,8 +37,9 @@ public class ChocolateyPackageService : IChocolateyPackageService
private readonly IRegistryService _registryService;
private readonly IChocolateyPackageInformationService _packageInfoService;
private readonly IAutomaticUninstallerService _autoUninstallerService;
+ private readonly IXmlService _xmlService;
- public ChocolateyPackageService(INugetService nugetService, IPowershellService powershellService, IShimGenerationService shimgenService, IFileSystem fileSystem, IRegistryService registryService, IChocolateyPackageInformationService packageInfoService, IAutomaticUninstallerService autoUninstallerService)
+ public ChocolateyPackageService(INugetService nugetService, IPowershellService powershellService, IShimGenerationService shimgenService, IFileSystem fileSystem, IRegistryService registryService, IChocolateyPackageInformationService packageInfoService, IAutomaticUninstallerService autoUninstallerService, IXmlService xmlService)
{
_nugetService = nugetService;
_powershellService = powershellService;
@@ -46,6 +48,7 @@ public ChocolateyPackageService(INugetService nugetService, IPowershellService p
_registryService = registryService;
_packageInfoService = packageInfoService;
_autoUninstallerService = autoUninstallerService;
+ _xmlService = xmlService;
}
public void list_noop(ChocolateyConfiguration config)
@@ -140,7 +143,11 @@ public void push_run(ChocolateyConfiguration config)
public void install_noop(ChocolateyConfiguration config)
{
- _nugetService.install_noop(config, (pkg) => _powershellService.install_noop(pkg));
+ // each package can specify its own configuration values
+ foreach (var packageConfig in set_config_from_package_names_and_packages_config(config, new ConcurrentDictionary()).or_empty_list_if_null())
+ {
+ _nugetService.install_noop(packageConfig, (pkg) => _powershellService.install_noop(pkg));
+ }
}
public void handle_package_result(PackageResult packageResult, ChocolateyConfiguration config, CommandNameType commandName)
@@ -210,10 +217,20 @@ public ConcurrentDictionary install_run(ChocolateyConfigu
this.Log().Info(ChocolateyLoggers.Important, @"{0}".format_with(config.PackageNames));
this.Log().Info(@"By installing you accept licenses for the packages.");
- var packageInstalls = _nugetService.install_run(
- config,
- (packageResult) => handle_package_result(packageResult, config, CommandNameType.install)
- );
+
+ var packageInstalls = new ConcurrentDictionary();
+
+ foreach (var packageConfig in set_config_from_package_names_and_packages_config(config, packageInstalls).or_empty_list_if_null())
+ {
+ var results = _nugetService.install_run(
+ packageConfig,
+ (packageResult) => handle_package_result(packageResult, packageConfig, CommandNameType.install)
+ );
+ foreach (var result in results)
+ {
+ packageInstalls.GetOrAdd(result.Key, result.Value);
+ }
+ }
var installFailures = packageInstalls.Count(p => !p.Value.Success);
this.Log().Warn(() => @"{0}{1} installed {2}/{3} packages. {4} packages failed.{0}See the log for details.".format_with(
@@ -240,6 +257,58 @@ public ConcurrentDictionary install_run(ChocolateyConfigu
return packageInstalls;
}
+ private IEnumerable set_config_from_package_names_and_packages_config(ChocolateyConfiguration config, ConcurrentDictionary packageInstalls)
+ {
+ // if there are any .config files, split those off of the config. Then return the config without those package names.
+ foreach (var packageConfigFile in config.PackageNames.Split(new[] {ApplicationParameters.PackageNamesSeparator}, StringSplitOptions.RemoveEmptyEntries).or_empty_list_if_null().Where(p => p.Contains(".config")).ToList())
+ {
+ config.PackageNames = config.PackageNames.Replace(packageConfigFile, string.Empty);
+
+ foreach (var packageConfig in get_packages_from_config(packageConfigFile, config, packageInstalls).or_empty_list_if_null())
+ {
+ yield return packageConfig;
+ }
+ }
+
+ yield return config;
+ }
+
+ private IEnumerable get_packages_from_config(string packageConfigFile, ChocolateyConfiguration config, ConcurrentDictionary packageInstalls)
+ {
+ IList packageConfigs = new List();
+
+ if (!_fileSystem.file_exists(_fileSystem.get_full_path(packageConfigFile)))
+ {
+ var logMessage = "Could not find '{0}' in the location specified.".format_with(packageConfigFile);
+ this.Log().Error(ChocolateyLoggers.Important, logMessage);
+ var results = packageInstalls.GetOrAdd(packageConfigFile, new PackageResult(packageConfigFile, null, null));
+ results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
+
+ return packageConfigs;
+ }
+
+ var settings = _xmlService.deserialize(_fileSystem.get_full_path(packageConfigFile));
+ foreach (var pkgSettings in settings.Packages.or_empty_list_if_null())
+ {
+ if (!pkgSettings.Disabled)
+ {
+ var packageConfig = config.deep_copy();
+ packageConfig.PackageNames = pkgSettings.Id;
+ packageConfig.Sources = string.IsNullOrWhiteSpace(pkgSettings.Source) ? packageConfig.Sources : pkgSettings.Source;
+ packageConfig.Version = pkgSettings.Version;
+ packageConfig.InstallArguments = string.IsNullOrWhiteSpace(pkgSettings.InstallArguments) ? packageConfig.InstallArguments : pkgSettings.InstallArguments;
+ packageConfig.PackageParameters = string.IsNullOrWhiteSpace(pkgSettings.PackageParameters) ? packageConfig.PackageParameters : pkgSettings.PackageParameters;
+ if (pkgSettings.ForceX86) packageConfig.ForceX86 = true;
+ if (pkgSettings.AllowMultipleVersions) packageConfig.AllowMultipleVersions = true;
+ if (pkgSettings.IgnoreDependencies) packageConfig.IgnoreDependencies = true;
+
+ packageConfigs.Add(packageConfig);
+ }
+ }
+
+ return packageConfigs;
+ }
+
public void upgrade_noop(ChocolateyConfiguration config)
{
_nugetService.upgrade_noop(config, (pkg) => _powershellService.install_noop(pkg));
diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs
index 720fe47ca6..c1018cb9a7 100644
--- a/src/chocolatey/infrastructure.app/services/NugetService.cs
+++ b/src/chocolatey/infrastructure.app/services/NugetService.cs
@@ -253,57 +253,49 @@ public ConcurrentDictionary install_run(ChocolateyConfigu
foreach (string packageName in packageNames.or_empty_list_if_null())
{
- if (packageName.to_lower().EndsWith(".config"))
+ //todo: get smarter about realizing multiple versions have been installed before and allowing that
+
+ remove_existing_rollback_directory(packageName);
+
+ IPackage installedPackage = packageManager.LocalRepository.FindPackage(packageName);
+
+ if (installedPackage != null && (version == null || version == installedPackage.Version) && !config.Force)
{
- //todo: determine if .config file for packages .config
- //todo: determine if config file exists
+ string logMessage = "{0} v{1} already installed.{2} Use --force to reinstall, specify a version to install, or try upgrade.".format_with(installedPackage.Id, installedPackage.Version, Environment.NewLine);
+ var results = packageInstalls.GetOrAdd(packageName, new PackageResult(installedPackage, ApplicationParameters.PackagesLocation));
+ results.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));
+ this.Log().Warn(ChocolateyLoggers.Important, logMessage);
+ continue;
}
- else
- {
- //todo: get smarter about realizing multiple versions have been installed before and allowing that
-
- remove_existing_rollback_directory(packageName);
- IPackage installedPackage = packageManager.LocalRepository.FindPackage(packageName);
-
- if (installedPackage != null && (version == null || version == installedPackage.Version) && !config.Force)
- {
- string logMessage = "{0} v{1} already installed.{2} Use --force to reinstall, specify a version to install, or try upgrade.".format_with(installedPackage.Id, installedPackage.Version, Environment.NewLine);
- var results = packageInstalls.GetOrAdd(packageName, new PackageResult(installedPackage, ApplicationParameters.PackagesLocation));
- results.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));
- this.Log().Warn(ChocolateyLoggers.Important, logMessage);
- continue;
- }
-
- if (installedPackage != null && (version == null || version == installedPackage.Version) && config.Force)
- {
- this.Log().Debug(() => "{0} v{1} already installed. Forcing reinstall.".format_with(installedPackage.Id, installedPackage.Version));
- version = installedPackage.Version;
- }
+ if (installedPackage != null && (version == null || version == installedPackage.Version) && config.Force)
+ {
+ this.Log().Debug(() => "{0} v{1} already installed. Forcing reinstall.".format_with(installedPackage.Id, installedPackage.Version));
+ version = installedPackage.Version;
+ }
- IPackage availablePackage = packageManager.SourceRepository.FindPackage(packageName, version, config.Prerelease, allowUnlisted: false);
- if (availablePackage == null)
- {
- var logMessage = "{0} not installed. The package was not found with the source(s) listed.{1} If you specified a particular version and are receiving this message, it is possible that the package name exists but the version does not.{1} Version: \"{2}\"{1} Source(s): \"{3}\"".format_with(packageName, Environment.NewLine, config.Version, config.Sources);
- this.Log().Error(ChocolateyLoggers.Important, logMessage);
- var results = packageInstalls.GetOrAdd(packageName, new PackageResult(packageName, version.to_string(), null));
- results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
- continue;
- }
+ IPackage availablePackage = packageManager.SourceRepository.FindPackage(packageName, version, config.Prerelease, allowUnlisted: false);
+ if (availablePackage == null)
+ {
+ var logMessage = "{0} not installed. The package was not found with the source(s) listed.{1} If you specified a particular version and are receiving this message, it is possible that the package name exists but the version does not.{1} Version: \"{2}\"{1} Source(s): \"{3}\"".format_with(packageName, Environment.NewLine, config.Version, config.Sources);
+ this.Log().Error(ChocolateyLoggers.Important, logMessage);
+ var results = packageInstalls.GetOrAdd(packageName, new PackageResult(packageName, version.to_string(), null));
+ results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
+ continue;
+ }
- if (installedPackage != null && (installedPackage.Version == availablePackage.Version))
- {
- packageManager.UninstallPackage(installedPackage, forceRemove: config.Force, removeDependencies: config.ForceDependencies);
- }
+ if (installedPackage != null && (installedPackage.Version == availablePackage.Version))
+ {
+ packageManager.UninstallPackage(installedPackage, forceRemove: config.Force, removeDependencies: config.ForceDependencies);
+ }
- using (packageManager.SourceRepository.StartOperation(
- RepositoryOperationNames.Install,
- packageName,
- version == null ? null : version.ToString()))
- {
- packageManager.InstallPackage(availablePackage, config.IgnoreDependencies, config.Prerelease);
- //packageManager.InstallPackage(packageName, version, configuration.IgnoreDependencies, configuration.Prerelease);
- }
+ using (packageManager.SourceRepository.StartOperation(
+ RepositoryOperationNames.Install,
+ packageName,
+ version == null ? null : version.ToString()))
+ {
+ packageManager.InstallPackage(availablePackage, config.IgnoreDependencies, config.Prerelease);
+ //packageManager.InstallPackage(packageName, version, configuration.IgnoreDependencies, configuration.Prerelease);
}
}
@@ -341,7 +333,7 @@ public ConcurrentDictionary upgrade_run(ChocolateyConfigu
SemanticVersion version = config.Version != null ? new SemanticVersion(config.Version) : null;
var packageManager = NugetCommon.GetPackageManager(
- config,
+ config,
_nugetLogger,
installSuccessAction: (e) =>
{
@@ -372,7 +364,7 @@ public ConcurrentDictionary upgrade_run(ChocolateyConfigu
if (config.RegularOuptut) this.Log().Error(ChocolateyLoggers.Important, logMessage);
continue;
}
-
+
var pkgInfo = _packageInfoService.get_package_information(installedPackage);
if (pkgInfo != null && pkgInfo.IsPinned)
{
@@ -468,7 +460,7 @@ public void backup_existing_version(ChocolateyConfiguration config, IPackage ins
this.Log().Debug("Backing up existing {0} prior to upgrade.".format_with(installedPackage.Id));
var backupLocation = pkgInstallPath + ApplicationParameters.RollbackPackageSuffix;
- _fileSystem.copy_directory(pkgInstallPath,backupLocation,overwriteExisting:true);
+ _fileSystem.copy_directory(pkgInstallPath, backupLocation, overwriteExisting: true);
}
}