Skip to content

Commit

Permalink
Merge #3913 Fix auto-remove during upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Sep 20, 2023
2 parents 341adf8 + 4286998 commit 52c8a9a
Show file tree
Hide file tree
Showing 27 changed files with 658 additions and 465 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ All notable changes to this project will be documented in this file.
- [Multiple] Multi-game labels (#3885 by: HebaruSan; reviewed: techman83)
- [Multiple] Alternate mod dirs for validation and manual installs (#3891 by: HebaruSan; reviewed: techman83)
- [Core] Fix archive.org fallback URLs for versions with spaces (#3899 by: HebaruSan)
- [Multiple] Fix auto-remove during upgrade (#3913 by: HebaruSan; reviewed: techman83)

### Internal

Expand Down
43 changes: 31 additions & 12 deletions Core/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ public void UninstallList(
.Select(im => im.identifier))
.ToList();

// If there us nothing to uninstall, skip out.
// If there is nothing to uninstall, skip out.
if (!goners.Any())
{
return;
Expand Down Expand Up @@ -1063,14 +1063,15 @@ public void Upgrade(IEnumerable<string> identifiers, IDownloader netAsyncDownloa
public void Upgrade(IEnumerable<CkanModule> modules, IDownloader netAsyncDownloader, ref HashSet<string> possibleConfigOnlyDirs, RegistryManager registry_manager, bool enforceConsistency = true, bool resolveRelationships = false, bool ConfirmPrompt = true)
{
modules = modules.Memoize();
var registry = registry_manager.registry;

if (resolveRelationships)
{
var resolver = new RelationshipResolver(
modules,
modules.Select(m => registry_manager.registry.InstalledModule(m.identifier)?.Module).Where(m => m != null),
modules.Select(m => registry.InstalledModule(m.identifier)?.Module).Where(m => m != null),
RelationshipResolver.DependsOnlyOpts(),
registry_manager.registry,
registry,
ksp.VersionCriteria()
);
modules = resolver.ModList().Memoize();
Expand All @@ -1088,7 +1089,7 @@ public void Upgrade(IEnumerable<CkanModule> modules, IDownloader netAsyncDownloa
// Let's discover what we need to do with each module!
foreach (CkanModule module in modules)
{
InstalledModule installed_mod = registry_manager.registry.InstalledModule(module.identifier);
InstalledModule installed_mod = registry.InstalledModule(module.identifier);

if (installed_mod == null)
{
Expand Down Expand Up @@ -1161,6 +1162,26 @@ public void Upgrade(IEnumerable<CkanModule> modules, IDownloader netAsyncDownloa
}
}

var removingIdents = to_remove.Select(im => im.identifier).ToHashSet();
var autoRemoving = registry
.FindRemovableAutoInstalled(
// Conjure the future state of the installed modules list after upgrading
registry.InstalledModules
.Where(im => !removingIdents.Contains(im.identifier))
.Concat(modules.Select(m => new InstalledModule(null, m, new string[0], false)))
.ToList(),
ksp.VersionCriteria())
.ToList();
if (autoRemoving.Count > 0)
{
foreach (var im in autoRemoving)
{
User.RaiseMessage(Properties.Resources.ModuleInstallerUpgradeAutoRemoving,
im.Module.name, im.Module.version);
}
to_remove.AddRange(autoRemoving);
}

if (ConfirmPrompt && !User.RaiseYesNoDialog(Properties.Resources.ModuleInstallerContinuePrompt))
{
throw new CancelledActionKraken(Properties.Resources.ModuleInstallerUpgradeUserDeclined);
Expand All @@ -1169,14 +1190,12 @@ public void Upgrade(IEnumerable<CkanModule> modules, IDownloader netAsyncDownloa
// Start by making sure we've downloaded everything.
DownloadModules(modules, netAsyncDownloader);

AddRemove(
ref possibleConfigOnlyDirs,
registry_manager,
modules,
to_remove,
enforceConsistency,
true
);
AddRemove(ref possibleConfigOnlyDirs,
registry_manager,
modules,
to_remove,
enforceConsistency,
true);
User.RaiseProgress(Properties.Resources.ModuleInstallerDone, 100);
}

Expand Down
3 changes: 3 additions & 0 deletions Core/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Core/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ Overwrite?</value></data>
<data name="ModuleInstallerUpgradeDowngrading" xml:space="preserve"><value> * Downgrade: {0} from {1} to {2}</value></data>
<data name="ModuleInstallerUpgradeUpgradingUncached" xml:space="preserve"><value> * Upgrade: {0} {1} to {2} ({3}, {4})</value></data>
<data name="ModuleInstallerUpgradeUpgradingCached" xml:space="preserve"><value> * Upgrade: {0} {1} to {2} (cached)</value></data>
<data name="ModuleInstallerUpgradeAutoRemoving" xml:space="preserve"><value> * Auto-remove: {0} {1}</value></data>
<data name="ModuleInstallerUpgradeUserDeclined" xml:space="preserve"><value>User declined upgrade list</value></data>
<data name="ModuleInstallerReplaceAutodetected" xml:space="preserve"><value>Can't replace {0} as it was not installed by CKAN.
Please remove manually before trying to install it.</value></data>
Expand Down
5 changes: 3 additions & 2 deletions Core/Registry/RegistryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,9 @@ public bool ScanUnmanagedFiles()
.Where(file => file.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase))
.Select(absPath => gameInstance.ToRelativeGameDir(absPath))
.Where(relPath => !gameInstance.game.StockFolders.Any(f => relPath.StartsWith($"{f}/")))
.ToDictionary(relPath => gameInstance.DllPathToIdentifier(relPath),
relPath => relPath);
.GroupBy(relPath => gameInstance.DllPathToIdentifier(relPath))
.ToDictionary(grp => grp.Key,
grp => grp.First());
log.DebugFormat("Registering DLLs: {0}", string.Join(", ", dlls.Values));
var dllChanged = registry.SetDlls(dlls);

Expand Down
2 changes: 1 addition & 1 deletion Core/Relationships/RelationshipResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ public override string Reason
=> Properties.Resources.RelationshipResolverUserReason;
}

public class NoLongerUsed: SelectionReason
public class NoLongerUsed : SelectionReason
{
public override string Reason
=> Properties.Resources.RelationshipResolverNoLongerUsedReason;
Expand Down
2 changes: 1 addition & 1 deletion GUI/Controls/Changeset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ private ListViewItem makeItem(ModChange change, Dictionary<CkanModule, string> c
return new ListViewItem(new string[]
{
change.NameAndStatus,
change.ChangeType.ToI18nString(),
change.ChangeType.Localize(),
conflicts != null && conflicts.TryGetValue(m, out string confDescr)
? string.Format("{0} ({1})", confDescr, descr)
: warnLbl != null
Expand Down
55 changes: 15 additions & 40 deletions GUI/Controls/ManageMods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,46 +1016,21 @@ private void ModGrid_Resize(object sender, EventArgs e)

private void reinstallToolStripMenuItem_Click(object sender, EventArgs e)
{
GUIMod module = SelectedModule;
if (module == null || !module.IsCKAN)
return;

IRegistryQuerier registry = RegistryManager.Instance(Main.Instance.CurrentInstance, repoData).registry;

// Find everything we need to re-install
var revdep = registry.FindReverseDependencies(new List<string>() { module.Identifier })
.Select(ident => registry.InstalledModule(ident))
.ToHashSet();
var goners = revdep.Union(
registry.FindRemovableAutoInstalled(
registry.InstalledModules
.Where(im => !revdep.Contains(im))
.ToList(),
Main.Instance.CurrentInstance.VersionCriteria()));

// Build the list of changes
StartChangeSet?.Invoke(goners
.SelectMany(instMod => instMod.AutoInstalled
? new ModChange[]
{
new ModChange(instMod.Module, GUIModChangeType.Remove),
// Let resolver find it so the auto-installed flag is set
}
: new ModChange[]
{
new ModChange(instMod.Module, GUIModChangeType.Remove),
new ModChange(
// Install current available mod from registry, if found
registry.GetModuleByVersion(instMod.identifier, instMod.Module.version)
?? instMod.Module,
GUIModChangeType.Install,
// Preserve auto-installed checkbox
instMod.AutoInstalled
// We don't use the depending mod here, so just fake it
? (SelectionReason)new SelectionReason.Depends(module.ToModule())
: new SelectionReason.UserRequested()),
})
.ToList());
var module = SelectedModule?.ToModule();
if (module != null)
{
IRegistryQuerier registry = RegistryManager.Instance(Main.Instance.CurrentInstance, repoData).registry;
StartChangeSet?.Invoke(new List<ModChange>()
{
// "Upgrade" to latest metadata for same module version
// (avoids removing and re-installing dependencies)
new ModUpgrade(module, GUIModChangeType.Update,
registry.GetModuleByVersion(module.identifier,
module.version)
?? module,
true)
});
}
}

public Dictionary<string, GUIMod> AllGUIMods()
Expand Down
10 changes: 10 additions & 0 deletions GUI/Controls/ModInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public void RefreshModContentsTree()
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
ModInfoTable.RowStyles[1].Height = TagsHeight;
if (!string.IsNullOrEmpty(MetadataModuleDescriptionTextBox?.Text))
{
MetadataModuleDescriptionTextBox.Height = DescriptionHeight;
Expand Down Expand Up @@ -105,6 +106,14 @@ private int TextBoxStringHeight(TextBox tb)

private int DescriptionHeight => TextBoxStringHeight(MetadataModuleDescriptionTextBox);

private int LinkLabelBottom(LinkLabel lbl)
=> lbl == null ? 0
: lbl.Bottom + lbl.Margin.Bottom + lbl.Padding.Bottom;

private int TagsHeight
=> ModInfoTable.Padding.Vertical + ModInfoTable.Margin.Vertical
+ LinkLabelBottom(MetadataTagsLabelsPanel.Controls.OfType<LinkLabel>().LastOrDefault());

private void UpdateHeaderInfo(GUIMod gmod, GameVersionCriteria crit)
{
var module = gmod.ToModule();
Expand Down Expand Up @@ -170,6 +179,7 @@ private void UpdateTagsAndLabels(CkanModule mod)
}
}
MetadataTagsLabelsPanel.ResumeLayout();
ModInfoTable.RowStyles[1].Height = TagsHeight;
});
}

Expand Down
11 changes: 5 additions & 6 deletions GUI/Main/MainChangeset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,12 @@ private void Changeset_OnConfirmChanges(List<ModChange> changeset)
try
{
Wait.StartWaiting(InstallMods, PostInstallMods, true,
new KeyValuePair<List<ModChange>, RelationshipResolverOptions>(
changeset
new InstallArgument(
// Only pass along user requested mods, so auto-installed can be determined
.Where(ch => ch.Reasons.Any(r => r is SelectionReason.UserRequested)
// Include all removes and upgrades
|| ch.ChangeType != GUIModChangeType.Install)
.ToList(),
changeset.Where(ch => ch.Reasons.Any(r => r is SelectionReason.UserRequested)
// Include all removes and upgrades
|| ch.ChangeType != GUIModChangeType.Install)
.ToList(),
RelationshipResolver.DependsOnlyOpts()));
}
catch (InvalidOperationException)
Expand Down
Loading

0 comments on commit 52c8a9a

Please sign in to comment.