diff --git a/Core/Relationships/RelationshipResolver.cs b/Core/Relationships/RelationshipResolver.cs index f0e189f9a..8cf4d70a7 100644 --- a/Core/Relationships/RelationshipResolver.cs +++ b/Core/Relationships/RelationshipResolver.cs @@ -922,6 +922,10 @@ public Replacement(CkanModule module) public override string ToString() => string.Format(Properties.Resources.RelationshipResolverReplacementReason, Parent.name); + + public override string DescribeWith(IEnumerable others) + => string.Format(Properties.Resources.RelationshipResolverReplacementReason, + string.Join(", ", Enumerable.Repeat(this, 1).Concat(others).Select(r => r.Parent.name))); } public sealed class Suggested : SelectionReason diff --git a/GUI/Controls/ManageMods.cs b/GUI/Controls/ManageMods.cs index 9e2c330ca..55d428b06 100644 --- a/GUI/Controls/ManageMods.cs +++ b/GUI/Controls/ManageMods.cs @@ -904,6 +904,10 @@ private void ModGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e gmod.SetAutoInstallChecked(row, AutoInstalled); OnRegistryChanged?.Invoke(); break; + case "ReplaceCol": + UpdateChangeSetAndConflicts(currentInstance, + RegistryManager.Instance(currentInstance, repoData).registry); + break; } } break; diff --git a/GUI/Main/MainInstall.cs b/GUI/Main/MainInstall.cs index 7ff783f7c..907621fa3 100644 --- a/GUI/Main/MainInstall.cs +++ b/GUI/Main/MainInstall.cs @@ -124,7 +124,10 @@ private void InstallMods(object sender, DoWorkEventArgs e) if (repl != null) { toUninstall.Add(repl.ToReplace); - toInstall.Add(repl.ReplaceWith); + if (!toInstall.Contains(repl.ReplaceWith)) + { + toInstall.Add(repl.ReplaceWith); + } } break; } diff --git a/GUI/Model/ModList.cs b/GUI/Model/ModList.cs index 511856245..52420350d 100644 --- a/GUI/Model/ModList.cs +++ b/GUI/Model/ModList.cs @@ -129,7 +129,15 @@ public Tuple, Dictionary, List(); var modules_to_remove = new HashSet(); - var upgrading = new HashSet(); + var extraInstalls = new HashSet(); + + changeSet.UnionWith(changeSet.Where(ch => ch.ChangeType == GUIModChangeType.Replace) + .Select(ch => registry.GetReplacement(ch.Mod, version)) + .OfType() + .GroupBy(repl => repl.ReplaceWith) + .Select(grp => new ModChange(grp.Key, GUIModChangeType.Install, + grp.Select(repl => new SelectionReason.Replacement(repl.ToReplace)))) + .ToHashSet()); foreach (var change in changeSet) { @@ -140,7 +148,7 @@ public Tuple, Dictionary, List, Dictionary, List, Dictionary, List ch.ChangeType == GUIModChangeType.Replace + && ch.Mod.identifier == dependent) + && installed_modules.TryGetValue(dependent, out CkanModule depMod)) { - CkanModule module_by_version = registry.GetModuleByVersion(depMod.identifier, - depMod.version) - ?? registry.InstalledModule(dependent).Module; - changeSet.Add(new ModChange(module_by_version, GUIModChangeType.Remove, + var modByVer = registry.GetModuleByVersion(depMod.identifier, + depMod.version) + ?? registry.InstalledModule(dependent).Module; + changeSet.Add(new ModChange(modByVer, GUIModChangeType.Remove, new SelectionReason.DependencyRemoved())); - modules_to_remove.Add(module_by_version); + modules_to_remove.Add(modByVer); } } @@ -197,11 +206,13 @@ public Tuple, Dictionary, List, Dictionary, List>( - changeSet.Where(ch => !(ch.ChangeType is GUIModChangeType.Install)) + changeSet.Where(ch => !(ch.ChangeType is GUIModChangeType.Install + // Leave in replacements + && !ch.Reasons.Any(r => r is SelectionReason.Replacement))) .OrderBy(ch => ch.Mod.identifier) .Union(resolver.ModList() - // Changeset already contains Update changes for these - .Except(upgrading) + // Changeset already contains changes for these + .Except(extraInstalls) .Where(m => !m.IsMetapackage) .Select(m => new ModChange(m, GUIModChangeType.Install, resolver.ReasonsFor(m)))), resolver.ConflictList, @@ -226,12 +237,11 @@ private IEnumerable InstalledAfterChanges( return registry.InstalledModules .Where(im => !removingIdents.Contains(im.identifier)) .Concat(changeSet - .Where(ch => ch.ChangeType != GUIModChangeType.Remove) + .Where(ch => ch.ChangeType != GUIModChangeType.Remove + && ch.ChangeType != GUIModChangeType.Replace) .Select(ch => new InstalledModule( null, - ch.ChangeType == GUIModChangeType.Replace - ? registry.GetReplacement(ch.Mod, crit)?.ReplaceWith - : (ch as ModUpgrade)?.targetMod ?? ch.Mod, + (ch as ModUpgrade)?.targetMod ?? ch.Mod, Enumerable.Empty(), false))); }