From 0d3852958b919c3794edcd3aefa06c0e34f3912a Mon Sep 17 00:00:00 2001 From: J/A Date: Wed, 23 Aug 2017 14:34:31 -0500 Subject: [PATCH] Move download outside GUI transaction Here we use the new ModuleResolution class to perform the work of downloading uncached modules before initiating the GUI transaction wrapping the install process. --- Core/ModuleInstaller.cs | 40 ++++++++++++++++++++++++++++++++++++++++ GUI/MainInstall.cs | 33 +++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs index ecb207a7e9..f9a23bc740 100644 --- a/Core/ModuleInstaller.cs +++ b/Core/ModuleInstaller.cs @@ -8,6 +8,7 @@ using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Zip; using log4net; +using CKAN.Types; namespace CKAN { @@ -249,6 +250,45 @@ public void InstallList( User.RaiseProgress("Done!\r\n", 100); } + public ModuleResolution ResolveModules(IEnumerable modules, RelationshipResolverOptions options) + { + var resolver = new RelationshipResolver(modules, options, registry_manager.registry, ksp.VersionCriteria()); + return new ModuleResolution(resolver.ModList(), m => ksp.Cache.IsCachedZip(m.download)); + } + + public void EnsureCache(List modules, IDownloader downloader = null) + { + if (modules.Any()) + { + downloader = downloader ?? new NetAsyncModulesDownloader(User); + } + + downloader.DownloadModules(ksp.Cache, modules); + } + + public void InstallList(ModuleResolution modules, RelationshipResolverOptions options) + { + // We're about to install all our mods; so begin our transaction. + using (TransactionScope transaction = CkanTransaction.CreateTransactionScope()) + { + var enumeratedMods = modules.Select((m, i) => new { Idx = i, Module = m }); + foreach (var item in enumeratedMods) + { + var percentComplete = (item.Idx * 100) / modules.Count; + User.RaiseProgress(string.Format("Installing mod \"{0}\"", item.Module), percentComplete); + Install(item.Module); + } + + User.RaiseProgress("Updating registry", 70); + + registry_manager.Save(!options.without_enforce_consistency); + + User.RaiseProgress("Commiting filesystem changes", 80); + + transaction.Complete(); + } + } + /// /// Returns the module contents if and only if we have it /// available in our cache. Returns null, otherwise. diff --git a/GUI/MainInstall.cs b/GUI/MainInstall.cs index 43b2996924..df88e67518 100644 --- a/GUI/MainInstall.cs +++ b/GUI/MainInstall.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using CKAN.Types; namespace CKAN { @@ -96,6 +97,31 @@ private void InstallMods(object sender, DoWorkEventArgs e) // this probably need installCanceled = true; }; + GUI.user.RaiseMessage("About to install...\r\n"); + + // FIXME: here we should heat up the cache with any mods we're going to install, because + // when this transaction types out it fucks up everything else. + var resolvedMods = installer.ResolveModules(toInstall, opts.Value); + + foreach (var module in resolvedMods.CachedModules) + { + GUI.user.RaiseMessage(" * {0} {1}(cached)", module.name, module.version); + } + + foreach (var module in resolvedMods.UncachedModules) + { + GUI.user.RaiseMessage(" * {0} {1}", module.name, module.version); + } + + if (!GUI.user.RaiseYesNoDialog("\r\nContinue?")) + { + throw new CancelledActionKraken("User declined install list"); + } + + GUI.user.RaiseMessage(String.Empty); // Just to look tidy. + + installer.EnsureCache(resolvedMods.UncachedModules); + //Transaction is needed here to revert changes when an installation is cancelled //TODO: Cancellation should be handelt in the ModuleInstaller using (var transaction = CkanTransaction.CreateTransactionScope()) @@ -126,7 +152,7 @@ private void InstallMods(object sender, DoWorkEventArgs e) // this probably need e.Result = new KeyValuePair(false, opts.Key); return; } - var ret = InstallList(toInstall, opts.Value, downloader); + var ret = InstallList(resolvedMods, opts.Value); if (!ret) { // install failed for some reason, error message is already displayed to the user @@ -295,15 +321,14 @@ private static bool WasSuccessful(Action action) } return true; } - private bool InstallList(HashSet toInstall, RelationshipResolverOptions options, IDownloader downloader) + private bool InstallList(ModuleResolution modules, RelationshipResolverOptions options) { if (toInstall.Any()) { // actual magic happens here, we run the installer with our mod list var module_installer = ModuleInstaller.GetInstance(manager.CurrentInstance, GUI.user); module_installer.onReportModInstalled = OnModInstalled; - return WasSuccessful( - () => module_installer.InstallList(toInstall.ToList(), options, downloader)); + return WasSuccessful(() => module_installer.InstallList(modules, options)); } return true;