diff --git a/src/chocolatey/chocolatey.csproj b/src/chocolatey/chocolatey.csproj
index d29685d021..7980d6ce1f 100644
--- a/src/chocolatey/chocolatey.csproj
+++ b/src/chocolatey/chocolatey.csproj
@@ -99,6 +99,7 @@
+
diff --git a/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs b/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs
index 7f0f6494f9..74e98b69d1 100644
--- a/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs
+++ b/src/chocolatey/infrastructure.app/registration/ContainerBinding.cs
@@ -17,6 +17,7 @@ namespace chocolatey.infrastructure.app.registration
{
using System.Collections.Generic;
using infrastructure.events;
+ using infrastructure.tasks;
using NuGet;
using SimpleInjector;
using adapters;
@@ -28,6 +29,7 @@ namespace chocolatey.infrastructure.app.registration
using infrastructure.services;
using nuget;
using services;
+ using tasks;
using CryptoHashProvider = cryptography.CryptoHashProvider;
using IFileSystem = filesystem.IFileSystem;
using IHashProvider = cryptography.IHashProvider;
@@ -111,6 +113,18 @@ public void RegisterComponents(Container container)
container.Register(Lifestyle.Singleton);
EventManager.initialize_with(container.GetInstance);
+ container.Register>(
+ () =>
+ {
+ var list = new List
+ {
+ new RemovePendingPackagesTask(container.GetInstance())
+ };
+
+ return list.AsReadOnly();
+ },
+ Lifestyle.Singleton);
+
container.Register(Lifestyle.Singleton);
}
}
diff --git a/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs b/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs
new file mode 100644
index 0000000000..e68b2454f4
--- /dev/null
+++ b/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs
@@ -0,0 +1,63 @@
+// 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.tasks
+{
+ using System;
+ using System.IO;
+ using System.Linq;
+ using events;
+ using filesystem;
+ using infrastructure.events;
+ using infrastructure.tasks;
+ using logging;
+ using tolerance;
+
+ public class RemovePendingPackagesTask : ITask
+ {
+ private readonly IFileSystem _fileSystem;
+ private IDisposable _subscription;
+
+ public RemovePendingPackagesTask(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
+ public void initialize()
+ {
+ _subscription = EventManager.subscribe(handle_message, null, null);
+ this.Log().Debug(ChocolateyLoggers.Verbose, () => "{0} is now ready and waiting for {1}.".format_with(GetType().Name, typeof(PreRunMessage).Name));
+ }
+
+ public void shutdown()
+ {
+ if (_subscription != null) _subscription.Dispose();
+ }
+
+ private void handle_message(PreRunMessage message)
+ {
+ this.Log().Debug(ChocolateyLoggers.Verbose, "[Pending] Removing all pending packages that should not be considered installed...");
+
+ var pendingFiles = _fileSystem.get_files(ApplicationParameters.PackagesLocation, ApplicationParameters.PackagePendingFileName, SearchOption.AllDirectories).ToList();
+ foreach (var pendingFile in pendingFiles.or_empty_list_if_null())
+ {
+ var packageFolder = _fileSystem.get_directory_name(pendingFile);
+ this.Log().Warn("[Pending] Removing incomplete install for '{0}'".format_with(_fileSystem.get_directory_info_for(packageFolder).Name));
+
+ FaultTolerance.retry(2, () => _fileSystem.delete_directory_if_exists(packageFolder, recursive: true, overrideAttributes: true, isSilent: true), 500, isSilent: true);
+ }
+ }
+ }
+}