Skip to content

Commit

Permalink
Address more multiple enumerations
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Jan 8, 2020
1 parent 27a92bd commit 6e11ef6
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 24 deletions.
5 changes: 5 additions & 0 deletions Core/Extensions/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public static IEnumerable<T> Memoize<T>(this IEnumerable<T> source)
{
throw new ArgumentNullException("source");
}
else if (source is Memoized<T>)
{
// Already memoized, don't wrap another layer
return source;
}
else
{
return new Memoized<T>(source);
Expand Down
18 changes: 12 additions & 6 deletions Core/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ internal static void CopyZipEntry(ZipFile zipfile, ZipEntry entry, string fullPa
/// </summary>
public void UninstallList(IEnumerable<string> mods, bool ConfirmPrompt = true, IEnumerable<string> installing = null)
{
mods = mods.Memoize();
// Pre-check, have they even asked for things which are installed?

foreach (string mod in mods.Where(mod => registry_manager.registry.InstalledModule(mod) == null))
Expand All @@ -736,13 +737,14 @@ public void UninstallList(IEnumerable<string> mods, bool ConfirmPrompt = true, I
}

// Find all the things which need uninstalling.
IEnumerable<string> revdep = mods.Union(
registry_manager.registry.FindReverseDependencies(
mods.Except(installing ?? new string[] {})));
IEnumerable<string> revdep = mods
.Union(registry_manager.registry.FindReverseDependencies(
mods.Except(installing ?? new string[] {})))
.Memoize();
IEnumerable<string> goners = revdep.Union(
registry_manager.registry.FindRemovableAutoInstalled(
registry_manager.registry.InstalledModules.Where(im => !revdep.Contains(im.identifier))
).Select(im => im.identifier))
registry_manager.registry.FindRemovableAutoInstalled(
registry_manager.registry.InstalledModules.Where(im => !revdep.Contains(im.identifier)))
.Select(im => im.identifier))
.Memoize();

// If there us nothing to uninstall, skip out.
Expand Down Expand Up @@ -985,6 +987,8 @@ public void AddRemove(IEnumerable<CkanModule> add = null, IEnumerable<InstalledM

using (var tx = CkanTransaction.CreateTransactionScope())
{
remove = remove.Memoize();
add = add.Memoize();
int totSteps = (remove?.Count() ?? 0)
+ (add?.Count() ?? 0);
int step = 0;
Expand Down Expand Up @@ -1032,6 +1036,7 @@ public void Upgrade(IEnumerable<string> identifiers, IDownloader netAsyncDownloa
/// </summary>
public void Upgrade(IEnumerable<CkanModule> modules, IDownloader netAsyncDownloader, bool enforceConsistency = true)
{
modules = modules.Memoize();
User.RaiseMessage("About to upgrade...\r\n");

// Start by making sure we've downloaded everything.
Expand Down Expand Up @@ -1095,6 +1100,7 @@ public void Upgrade(IEnumerable<CkanModule> modules, IDownloader netAsyncDownloa
/// </summary>
public void Replace(IEnumerable<ModuleReplacement> replacements, RelationshipResolverOptions options, IDownloader netAsyncDownloader, bool enforceConsistency = true)
{
replacements = replacements.Memoize();
log.Debug("Using Replace method");
List<CkanModule> modsToInstall = new List<CkanModule>();
var modsToRemove = new List<InstalledModule>();
Expand Down
4 changes: 3 additions & 1 deletion Core/Registry/AvailableModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using CKAN.Extensions;
using CKAN.Versioning;
using log4net;
using Newtonsoft.Json;
Expand Down Expand Up @@ -109,6 +110,7 @@ public CkanModule Latest(

private static bool DependsAndConflictsOK(CkanModule module, IEnumerable<CkanModule> others)
{
others = others.Memoize();
if (module.depends != null)
{
foreach (RelationshipDescriptor rel in module.depends)
Expand All @@ -123,7 +125,7 @@ private static bool DependsAndConflictsOK(CkanModule module, IEnumerable<CkanMod
if (module.conflicts != null)
{
// Skip self-conflicts (but catch other modules providing self)
var othersMinusSelf = others.Where(m => m.identifier != module.identifier);
var othersMinusSelf = others.Where(m => m.identifier != module.identifier).Memoize();
foreach (RelationshipDescriptor rel in module.conflicts)
{
// If any of the conflicts are present, fail
Expand Down
24 changes: 15 additions & 9 deletions Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,8 @@ public CkanModule GetModuleByVersion(string ident, ModuleVersion version)
}

/// <summary>
/// Register the supplied module as having been installed, thereby keeping
/// track of its metadata and files.
/// Register the supplied module as having been installed, thereby keeping
/// track of its metadata and files.
/// </summary>
public void RegisterModule(CkanModule mod, IEnumerable<string> absolute_files, KSP ksp, bool autoInstalled)
{
Expand All @@ -760,7 +760,9 @@ public void RegisterModule(CkanModule mod, IEnumerable<string> absolute_files, K
var inconsistencies = new List<string>();

// We always work with relative files, so let's get some!
IEnumerable<string> relative_files = absolute_files.Select(x => ksp.ToRelativeGameDir(x));
IEnumerable<string> relative_files = absolute_files
.Select(x => ksp.ToRelativeGameDir(x))
.Memoize();

// For now, it's always cool if a module wants to register a directory.
// We have to flip back to absolute paths to actually test this.
Expand All @@ -771,10 +773,10 @@ public void RegisterModule(CkanModule mod, IEnumerable<string> absolute_files, K
{
// Woah! Registering an already owned file? Not cool!
// (Although if it existed, we should have thrown a kraken well before this.)
inconsistencies.Add(
string.Format("{0} wishes to install {1}, but this file is registered to {2}",
mod.identifier, file, owner
));
inconsistencies.Add(string.Format(
"{0} wishes to install {1}, but this file is registered to {2}",
mod.identifier, file, owner
));
}
}

Expand Down Expand Up @@ -1082,6 +1084,9 @@ internal static IEnumerable<string> FindReverseDependencies(
IDictionary<string, UnmanagedModuleVersion> dlc
)
{
modules_to_remove = modules_to_remove.Memoize();
orig_installed = orig_installed.Memoize();
var dllSet = dlls.ToHashSet();
// The empty list has no reverse dependencies
// (Don't remove broken modules if we're only installing)
if (modules_to_remove.Any())
Expand All @@ -1097,10 +1102,10 @@ IDictionary<string, UnmanagedModuleVersion> dlc
HashSet<CkanModule> hypothetical = new HashSet<CkanModule>(orig_installed); // Clone because we alter hypothetical.
hypothetical.RemoveWhere(mod => modules_to_remove.Contains(mod.identifier));

log.DebugFormat("Started with {0}, removing {1}, and keeping {2}; our dlls are {3}", string.Join(", ", orig_installed), string.Join(", ", modules_to_remove), string.Join(", ", hypothetical), string.Join(", ", dlls));
log.DebugFormat("Started with {0}, removing {1}, and keeping {2}; our dlls are {3}", string.Join(", ", orig_installed), string.Join(", ", modules_to_remove), string.Join(", ", hypothetical), string.Join(", ", dllSet));

// Find what would break with this configuration.
var broken = SanityChecker.FindUnsatisfiedDepends(hypothetical, dlls.ToHashSet(), dlc)
var broken = SanityChecker.FindUnsatisfiedDepends(hypothetical, dllSet, dlc)
.Select(x => x.Key.identifier).ToHashSet();

// Lazily return each newly found rev dep
Expand Down Expand Up @@ -1151,6 +1156,7 @@ IDictionary<string, UnmanagedModuleVersion> dlc
)
{
// ToList ensures that the collection isn't modified while the enumeration operation is executing
installedModules = installedModules.Memoize();
var autoInstMods = installedModules.Where(im => im.AutoInstalled).ToList();
var autoInstIds = autoInstMods.Select(im => im.Module.identifier).ToHashSet();
var instCkanMods = installedModules.Select(im => im.Module);
Expand Down
3 changes: 3 additions & 0 deletions Core/Relationships/RelationshipResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ private void Resolve(CkanModule module, RelationshipResolverOptions options, IEn
// is true.
var sub_options = (RelationshipResolverOptions) options.Clone();
sub_options.with_suggests = false;

old_stanza = old_stanza?.Memoize();

log.DebugFormat("Resolving dependencies for {0}", module.identifier);
ResolveStanza(module.depends, new SelectionReason.Depends(module), sub_options, false, old_stanza);
Expand Down Expand Up @@ -348,6 +350,7 @@ private void ResolveStanza(IEnumerable<RelationshipDescriptor> stanza, Selection
{
return;
}
stanza = stanza.Memoize();

foreach (RelationshipDescriptor descriptor in stanza)
{
Expand Down
10 changes: 7 additions & 3 deletions Core/Relationships/SanityChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ private static bool CheckConsistency(
out List<KeyValuePair<CkanModule, RelationshipDescriptor>> Conflicts
)
{
UnmetDepends = FindUnsatisfiedDepends(modules?.ToList(), dlls?.ToHashSet(), dlc);
Conflicts = FindConflicting( modules, dlls?.ToHashSet(), dlc);
modules = modules?.Memoize();
var dllSet = dlls?.ToHashSet();
UnmetDepends = FindUnsatisfiedDepends(modules?.ToList(), dllSet, dlc);
Conflicts = FindConflicting( modules, dllSet, dlc);
return !UnmetDepends.Any() && !Conflicts.Any();
}

Expand All @@ -106,6 +108,7 @@ IDictionary<string, UnmanagedModuleVersion> dlc
var unsat = new List<KeyValuePair<CkanModule, RelationshipDescriptor>>();
if (modules != null)
{
modules = modules.Memoize();
foreach (CkanModule m in modules.Where(m => m.depends != null))
{
foreach (RelationshipDescriptor dep in m.depends)
Expand Down Expand Up @@ -139,11 +142,12 @@ IDictionary<string, UnmanagedModuleVersion> dlc
var confl = new List<KeyValuePair<CkanModule, RelationshipDescriptor>>();
if (modules != null)
{
modules = modules.Memoize();
foreach (CkanModule m in modules.Where(m => m.conflicts != null))
{
// Remove self from the list, so we're only comparing to OTHER modules.
// Also remove other versions of self, to avoid conflicts during upgrades.
var others = modules.Where(other => other.identifier != m.identifier);
var others = modules.Where(other => other.identifier != m.identifier).Memoize();
foreach (RelationshipDescriptor dep in m.conflicts)
{
if (dep.MatchesAny(others, dlls, dlc))
Expand Down
8 changes: 6 additions & 2 deletions GUI/MainChangeset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using CKAN.Extensions;

namespace CKAN
{
Expand Down Expand Up @@ -93,8 +94,11 @@ private void ClearChangeSet()
/// </summary>
/// <param name="changes">Every leftover ModChange that should be sorted</param>
/// <param name="parent"></param>
private void CreateSortedModList(IEnumerable<ModChange> changes, ModChange parent=null)
private void CreateSortedModList(IEnumerable<ModChange> changes, ModChange parent = null)
{
var notUserReq = changes
.Where(c => !(c.Reason is SelectionReason.UserRequested))
.Memoize();
foreach (ModChange change in changes)
{
bool goDeeper = parent == null || change.Reason.Parent.identifier == parent.Mod.identifier;
Expand All @@ -103,7 +107,7 @@ private void CreateSortedModList(IEnumerable<ModChange> changes, ModChange paren
{
if (!changeSet.Any(c => c.Mod.identifier == change.Mod.identifier && c.ChangeType != GUIModChangeType.Remove))
changeSet.Add(change);
CreateSortedModList(changes.Where(c => !(c.Reason is SelectionReason.UserRequested)), change);
CreateSortedModList(notUserReq, change);
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions GUI/MainLabels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections.Generic;
using CKAN.Extensions;

namespace CKAN
{
Expand Down Expand Up @@ -129,14 +130,16 @@ private void LabelsAfterUpdate(IEnumerable<GUIMod> mods)
{
Util.Invoke(Main.Instance, () =>
{
mods = mods.Memoize();
var notifLabs = mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.Where(l => l.NotifyOnChange);
.Where(l => l.NotifyOnChange)
.Memoize();
var toNotif = mods
.Where(m =>
notifLabs.Any(l =>
l.ModuleIdentifiers.Contains(m.Identifier)))
.Select(m => m.Name)
.ToArray();
.Memoize();
if (toNotif.Any())
{
MessageBox.Show(
Expand All @@ -157,7 +160,6 @@ private void LabelsAfterUpdate(IEnumerable<GUIMod> mods)
{
l.Remove(mod.Identifier);
}
}
});
}
Expand Down

0 comments on commit 6e11ef6

Please sign in to comment.