From 19489697186f10683d6060692dd453c5ae925d16 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Wed, 25 Feb 2015 06:12:13 -0600 Subject: [PATCH 1/4] (GH-109) Container - move initialize to lazy The container should initialize when you call `SimpleInjectorContainer.Container`. This makes sure the container initialization only happens one time and allows the call to Container to do what it needs to do if it is not initialized. Split from commits by @mwrock --- src/chocolatey.console/Program.cs | 2 +- .../NUnitSetup.cs | 2 +- src/chocolatey/GetChocolatey.cs | 2 +- .../registration/SimpleInjectorContainer.cs | 24 ++++++++----------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/chocolatey.console/Program.cs b/src/chocolatey.console/Program.cs index 3726f3992f..bfe47a604d 100644 --- a/src/chocolatey.console/Program.cs +++ b/src/chocolatey.console/Program.cs @@ -52,7 +52,7 @@ private static void Main(string[] args) Bootstrap.initialize(); Bootstrap.startup(); - var container = SimpleInjectorContainer.initialize(); + var container = SimpleInjectorContainer.Container; var config = container.GetInstance(); var fileSystem = container.GetInstance(); diff --git a/src/chocolatey.tests.integration/NUnitSetup.cs b/src/chocolatey.tests.integration/NUnitSetup.cs index 5b0b0bbbce..4b3aa1a965 100644 --- a/src/chocolatey.tests.integration/NUnitSetup.cs +++ b/src/chocolatey.tests.integration/NUnitSetup.cs @@ -36,7 +36,7 @@ public class NUnitSetup : tests.NUnitSetup public override void BeforeEverything() { - Container = SimpleInjectorContainer.initialize(); + Container = SimpleInjectorContainer.Container; fix_application_parameter_variables(Container); var config = Container.GetInstance(); var force = config.Force; diff --git a/src/chocolatey/GetChocolatey.cs b/src/chocolatey/GetChocolatey.cs index 6c9e66b70c..ff0ca97d0a 100644 --- a/src/chocolatey/GetChocolatey.cs +++ b/src/chocolatey/GetChocolatey.cs @@ -59,7 +59,7 @@ public class GetChocolatey public GetChocolatey() { _configuration = new ChocolateyConfiguration(); - _container = SimpleInjectorContainer.initialize(); + _container = SimpleInjectorContainer.Container; _fileSystem = _container.GetInstance(); set_defaults(); diff --git a/src/chocolatey/infrastructure/registration/SimpleInjectorContainer.cs b/src/chocolatey/infrastructure/registration/SimpleInjectorContainer.cs index 7de3300f0e..8e8955117b 100644 --- a/src/chocolatey/infrastructure/registration/SimpleInjectorContainer.cs +++ b/src/chocolatey/infrastructure/registration/SimpleInjectorContainer.cs @@ -24,7 +24,7 @@ namespace chocolatey.infrastructure.registration /// public static class SimpleInjectorContainer { - private static readonly Lazy _container = new Lazy(() => new Container()); + private static readonly Lazy _container = new Lazy(initialize); /// /// Gets the container. @@ -37,25 +37,21 @@ public static Container Container /// /// Initializes the container /// - public static Container initialize() + private static Container initialize() { - Container.Options.AllowOverridingRegistrations = true; - var originalConstructorResolutionBehavior = Container.Options.ConstructorResolutionBehavior; - Container.Options.ConstructorResolutionBehavior = new SimpleInjectorContainerResolutionBehavior(originalConstructorResolutionBehavior); + var container = new Container(); + container.Options.AllowOverridingRegistrations = true; + var originalConstructorResolutionBehavior = container.Options.ConstructorResolutionBehavior; + container.Options.ConstructorResolutionBehavior = new SimpleInjectorContainerResolutionBehavior(originalConstructorResolutionBehavior); - initialize_container(Container); + var binding = new ContainerBinding(); + binding.RegisterComponents(container); #if DEBUG - Container.Verify(); + container.Verify(); #endif - return Container; - } - - private static void initialize_container(Container container) - { - var binding = new ContainerBinding(); - binding.RegisterComponents(container); + return container; } } } \ No newline at end of file From 5b6104fd3516f99b5cb3111f30c54bebefe3b18e Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Wed, 25 Feb 2015 06:15:51 -0600 Subject: [PATCH 2/4] (GH-109)(log) Set file appender if output dir is provided If an output directory is not provided, don't set the file appender up. This is helpful when wanting to configure logging with the API but not log to a file. Split from commits by @mwrock --- .../logging/Log4NetAppenderConfiguration.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/chocolatey/infrastructure/logging/Log4NetAppenderConfiguration.cs b/src/chocolatey/infrastructure/logging/Log4NetAppenderConfiguration.cs index 5e44f904c9..9571401815 100644 --- a/src/chocolatey/infrastructure/logging/Log4NetAppenderConfiguration.cs +++ b/src/chocolatey/infrastructure/logging/Log4NetAppenderConfiguration.cs @@ -34,10 +34,11 @@ public sealed class Log4NetAppenderConfiguration private static bool _alreadyConfiguredFileAppender; /// - /// Pulls xmlconfiguration from embedded location and applies it. Then it configures a file appender to the specified output directory. + /// Pulls xmlconfiguration from embedded location and applies it. + /// Then it configures a file appender to the specified output directory if one is provided. /// /// The output directory. - public static void configure(string outputDirectory) + public static void configure(string outputDirectory = null) { var assembly = Assembly.GetExecutingAssembly(); var resource = ApplicationParameters.Log4NetConfigurationResource; @@ -49,7 +50,11 @@ public static void configure(string outputDirectory) Stream xmlConfigStream = assembly.get_manifest_stream(resource); XmlConfigurator.Configure(xmlConfigStream); - set_file_appender(outputDirectory); + + if (outputDirectory != null) + { + set_file_appender(outputDirectory); + } _logger.DebugFormat("Configured {0} from assembly {1}", resource, assembly.FullName); } From 7862c56ec72525d9e51df7794e11fe55ac4146f0 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Wed, 25 Feb 2015 06:19:20 -0600 Subject: [PATCH 3/4] (GH-109) ConfigurationOptions explicit reset Provide a way to reset options that are previously set so a second pass through choco will not have issues setting the options available. This is necessary when working with the API as multiple passes through could happen and reconstructing the class every time could have significant performance issues. Split from commits by @mwrock --- .../configuration/ConfigurationOptionsSpec.cs | 1 + .../infrastructure.app/builders/ConfigurationBuilder.cs | 1 + .../infrastructure.app/configuration/ConfigurationOptions.cs | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/src/chocolatey.tests/infrastructure.app/configuration/ConfigurationOptionsSpec.cs b/src/chocolatey.tests/infrastructure.app/configuration/ConfigurationOptionsSpec.cs index 9d2ad6970c..99352ae65e 100644 --- a/src/chocolatey.tests/infrastructure.app/configuration/ConfigurationOptionsSpec.cs +++ b/src/chocolatey.tests/infrastructure.app/configuration/ConfigurationOptionsSpec.cs @@ -44,6 +44,7 @@ public abstract class ConfigurationOptionsSpecBase : TinySpec public override void Context() { ConfigurationOptions.initialize_with(new Lazy(() => console.Object)); + ConfigurationOptions.reset_options(); console.Setup((c) => c.Error).Returns(writer); } diff --git a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs index 6f73f667e6..5ab18a2bfc 100644 --- a/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs +++ b/src/chocolatey/infrastructure.app/builders/ConfigurationBuilder.cs @@ -61,6 +61,7 @@ private static IEnvironment Environment public static void set_up_configuration(IList args, ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action notifyWarnLoggingAction) { set_file_configuration(config, fileSystem, xmlService, notifyWarnLoggingAction); + ConfigurationOptions.reset_options(); set_global_options(args, config); set_environment_options(config); } diff --git a/src/chocolatey/infrastructure.app/configuration/ConfigurationOptions.cs b/src/chocolatey/infrastructure.app/configuration/ConfigurationOptions.cs index a8a9dd0f0e..602d203b37 100644 --- a/src/chocolatey/infrastructure.app/configuration/ConfigurationOptions.cs +++ b/src/chocolatey/infrastructure.app/configuration/ConfigurationOptions.cs @@ -34,6 +34,11 @@ public static void initialize_with(Lazy console) _console = console; } + public static void reset_options() + { + _optionSet.Clear(); + } + private static IConsole Console { get { return _console.Value; } From 405644e848f596d30a9d6669512970cd3e86f88e Mon Sep 17 00:00:00 2001 From: Matt Wrock Date: Wed, 25 Feb 2015 06:23:08 -0600 Subject: [PATCH 4/4] (GH-109) GetChocolatey can now get chocolatey Previously, when calling environment initialization in GetChocolatey, there would be settings that would cause it to throw errors when calling it subsequent times. Add default logging and log initialization to `GetChocolatey`. Before this there was no logging sent to stdout upon calling `run` by default. `GetChocolatey` now configures log4net but with no log file. Callers should be able to use `SetCustomLogger` if they do want file logging. Fixes NullRefException when calling `Lets.GetChocolatey` when the args are parsed. --- src/chocolatey.tests/GetChocolateySpecs.cs | 82 ++++++++++++++++++++ src/chocolatey.tests/chocolatey.tests.csproj | 5 ++ src/chocolatey.tests/packages.config | 1 + src/chocolatey/GetChocolatey.cs | 4 +- 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/chocolatey.tests/GetChocolateySpecs.cs diff --git a/src/chocolatey.tests/GetChocolateySpecs.cs b/src/chocolatey.tests/GetChocolateySpecs.cs new file mode 100644 index 0000000000..2b998947f8 --- /dev/null +++ b/src/chocolatey.tests/GetChocolateySpecs.cs @@ -0,0 +1,82 @@ +// 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 +{ + using log4net; + using Should; + + public class GetChocolateySpecs + { + public abstract class GetChocolateySpecsBase : TinySpec + { + public override void Context() + { + } + } + + public class when_getting_chocolatey : GetChocolateySpecsBase + { + private GetChocolatey _chocolatey; + + public override void Because() + { + _chocolatey = Lets.GetChocolatey(); + } + + [Fact] + public void should_get_chocolotey() + { + _chocolatey.ShouldNotBeNull(); + } + + [Fact] + public void should_conigure_log4net() + { + LogManager.GetRepository().Configured.ShouldBeTrue(); + } + } + + public class when_getting_chocolatey_more_than_once : GetChocolateySpecsBase + { + private GetChocolatey _chocolatey1; + private GetChocolatey _chocolatey2; + + public override void Because() + { + _chocolatey1 = Lets.GetChocolatey(); + _chocolatey2 = Lets.GetChocolatey(); + } + + [Fact] + public void should_get_instantiated_chocolotey1() + { + _chocolatey1.ShouldNotBeNull(); + } + + [Fact] + public void should_get_instantiated_chocolotey2() + { + _chocolatey2.ShouldNotBeNull(); + } + + [Fact] + public void should_have_distinct_configurations() + { + _chocolatey1.GetConfiguration().ShouldNotEqual(_chocolatey2.GetConfiguration()); + } + } + } +} \ No newline at end of file diff --git a/src/chocolatey.tests/chocolatey.tests.csproj b/src/chocolatey.tests/chocolatey.tests.csproj index d32a89f406..f31a59eecf 100644 --- a/src/chocolatey.tests/chocolatey.tests.csproj +++ b/src/chocolatey.tests/chocolatey.tests.csproj @@ -32,6 +32,10 @@ 4 + + False + ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll @@ -57,6 +61,7 @@ + diff --git a/src/chocolatey.tests/packages.config b/src/chocolatey.tests/packages.config index 585fd5cb33..4faecbfaeb 100644 --- a/src/chocolatey.tests/packages.config +++ b/src/chocolatey.tests/packages.config @@ -1,6 +1,7 @@  + diff --git a/src/chocolatey/GetChocolatey.cs b/src/chocolatey/GetChocolatey.cs index ff0ca97d0a..e85da552f3 100644 --- a/src/chocolatey/GetChocolatey.cs +++ b/src/chocolatey/GetChocolatey.cs @@ -58,6 +58,8 @@ public class GetChocolatey /// public GetChocolatey() { + Log4NetAppenderConfiguration.configure(); + Bootstrap.initialize(); _configuration = new ChocolateyConfiguration(); _container = SimpleInjectorContainer.Container; _fileSystem = _container.GetInstance(); @@ -67,7 +69,7 @@ public GetChocolatey() private void set_defaults() { - ConfigurationBuilder.set_up_configuration(null, _configuration, _fileSystem, _container.GetInstance(), null); + ConfigurationBuilder.set_up_configuration(new List(), _configuration, _fileSystem, _container.GetInstance(), null); Config.initialize_with(_configuration); _configuration.PromptForConfirmation = false;