Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix auto-remove during upgrade #3913

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading