Skip to content

Commit

Permalink
Move download outside GUI transaction
Browse files Browse the repository at this point in the history
Here we use the new ModuleResolution class to perform the work of downloading uncached modules before initiating the GUI transaction wrapping the install process.
  • Loading branch information
archer884 committed Aug 23, 2017
1 parent 8cf3b0f commit 0d38529
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 4 deletions.
40 changes: 40 additions & 0 deletions Core/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using log4net;
using CKAN.Types;

namespace CKAN
{
Expand Down Expand Up @@ -249,6 +250,45 @@ public void InstallList(
User.RaiseProgress("Done!\r\n", 100);
}

public ModuleResolution ResolveModules(IEnumerable<string> 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<CkanModule> 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();
}
}

/// <summary>
/// Returns the module contents if and only if we have it
/// available in our cache. Returns null, otherwise.
Expand Down
33 changes: 29 additions & 4 deletions GUI/MainInstall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using CKAN.Types;

namespace CKAN
{
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -126,7 +152,7 @@ private void InstallMods(object sender, DoWorkEventArgs e) // this probably need
e.Result = new KeyValuePair<bool, ModChanges>(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
Expand Down Expand Up @@ -295,15 +321,14 @@ private static bool WasSuccessful(Action action)
}
return true;
}
private bool InstallList(HashSet<string> 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;
Expand Down

0 comments on commit 0d38529

Please sign in to comment.