Skip to content

Commit

Permalink
Better version specific relationships at install and upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Mar 9, 2024
1 parent 19736d4 commit 0f7ca67
Show file tree
Hide file tree
Showing 24 changed files with 1,135 additions and 458 deletions.
10 changes: 8 additions & 2 deletions Cmdline/Action/List.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;

using log4net;

Expand Down Expand Up @@ -53,6 +54,11 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options)
if (exportFileType == null)
{
var installed = new SortedDictionary<string, ModuleVersion>(registry.Installed());
var upgradeable = registry
.CheckUpgradeable(instance.VersionCriteria(), new HashSet<string>())
[true]
.Select(m => m.identifier)
.ToHashSet();

foreach (KeyValuePair<string, ModuleVersion> mod in installed)
{
Expand Down Expand Up @@ -102,7 +108,7 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options)
}
}
}
else if (latest.version.IsEqualTo(current_version) && !registry.HasUpdate(mod.Key, instance.VersionCriteria()))
else if (!upgradeable.Contains(mod.Key))
{
// Up to date
log.InfoFormat("Latest {0} is {1}", mod.Key, latest.version);
Expand All @@ -119,7 +125,7 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options)
}
}
}
else if (latest.version.IsGreaterThan(mod.Value) || registry.HasUpdate(mod.Key, instance.VersionCriteria()))
else
{
// Upgradable
bullet = "^";
Expand Down
125 changes: 77 additions & 48 deletions Cmdline/Action/Upgrade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
using System.Transactions;

using Autofac;
using log4net;

using CKAN.Versioning;
using CKAN.Configuration;
using CKAN.Extensions;

namespace CKAN.CmdLine
{
Expand Down Expand Up @@ -114,38 +114,17 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options)
var registry = regMgr.registry;
if (options.upgrade_all)
{
var to_upgrade = new List<CkanModule>();

foreach (KeyValuePair<string, ModuleVersion> mod in registry.Installed(false))
var to_upgrade = registry
.CheckUpgradeable(instance.VersionCriteria(), new HashSet<string>())
[true];
if (to_upgrade.Count == 0)
{
try
{
// Check if upgrades are available
var latest = registry.LatestAvailable(mod.Key, instance.VersionCriteria());

// This may be an unindexed mod. If so,
// skip rather than crash. See KSP-CKAN/CKAN#841.
if (latest == null || latest.IsDLC)
{
continue;
}

if (latest.version.IsGreaterThan(mod.Value) || registry.HasUpdate(mod.Key, instance.VersionCriteria()))
{
// Upgradable
log.InfoFormat("New version {0} found for {1}",
latest.version, latest.identifier);
to_upgrade.Add(latest);
}

}
catch (ModuleNotFoundKraken)
{
log.InfoFormat("{0} is installed, but no longer in the registry",
mod.Key);
}
user.RaiseMessage(Properties.Resources.UpgradeAllUpToDate);
}
else
{
UpgradeModules(manager, user, instance, to_upgrade);
}
UpgradeModules(manager, user, instance, true, to_upgrade);
}
else
{
Expand Down Expand Up @@ -196,16 +175,15 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options)
private void UpgradeModules(GameInstanceManager manager,
IUser user,
CKAN.GameInstance instance,
bool ConfirmPrompt,
List<CkanModule> modules)
{
UpgradeModules(
manager, user, instance, repoData,
(ModuleInstaller installer, NetAsyncModulesDownloader downloader, RegistryManager regMgr, ref HashSet<string> possibleConfigOnlyDirs) =>
installer.Upgrade(modules, downloader,
ref possibleConfigOnlyDirs, regMgr, true, true, ConfirmPrompt),
m => modules.Add(m)
);
ref possibleConfigOnlyDirs,
regMgr, true, true, true),
m => modules.Add(m));
}

/// <summary>
Expand All @@ -223,19 +201,72 @@ private void UpgradeModules(GameInstanceManager manager,
UpgradeModules(
manager, user, instance, repoData,
(ModuleInstaller installer, NetAsyncModulesDownloader downloader, RegistryManager regMgr, ref HashSet<string> possibleConfigOnlyDirs) =>
installer.Upgrade(
identsAndVersions.Select(arg => CkanModule.FromIDandVersion(
regMgr.registry, arg,
instance.VersionCriteria()))
.ToList(),
downloader,
ref possibleConfigOnlyDirs,
regMgr,
true),
m => identsAndVersions.Add(m.identifier)
);
{
var crit = instance.VersionCriteria();
var registry = regMgr.registry;
// Installed modules we're NOT upgrading
var heldIdents = registry.Installed(false)
.Keys
.Except(identsAndVersions.Select(arg => UpToFirst(arg, '=')))
.ToHashSet();
// The modules we'll have after upgrading as aggressively as possible
var limiters = identsAndVersions.Select(req => CkanModule.FromIDandVersion(registry, req, crit)
?? DefaultIfThrows(
() => registry.LatestAvailable(req, crit))
?? registry.GetInstalledVersion(req))
.Concat(heldIdents.Select(ident => registry.GetInstalledVersion(ident)))
.Where(m => m != null)
.ToList();
// Modules allowed by THOSE modules' relationships
var upgradeable = registry
.CheckUpgradeable(crit, heldIdents, limiters)
[true]
.ToDictionary(m => m.identifier,
m => m);
// Substitute back in the ident=ver requested versions
var to_upgrade = new List<CkanModule>();
foreach (var request in identsAndVersions)
{
var module = CkanModule.FromIDandVersion(registry, request, crit)
?? (upgradeable.TryGetValue(request, out CkanModule m)
? m
: null);
if (module == null)
{
user.RaiseMessage(Properties.Resources.UpgradeAlreadyUpToDate, request);
}
else
{
to_upgrade.Add(module);
}
}
if (to_upgrade.Count > 0)
{
installer.Upgrade(to_upgrade, downloader, ref possibleConfigOnlyDirs, regMgr, true);
}
},
m => identsAndVersions.Add(m.identifier));
}

public static T DefaultIfThrows<T>(Func<T> func)
{
try
{
return func();
}
catch
{
return default;
}
}

private static string UpToFirst(string orig, char toFind)
=> UpTo(orig, orig.IndexOf(toFind));

private static string UpTo(string orig, int pos)
=> pos >= 0 && pos < orig.Length ? orig.Substring(0, pos)
: orig;

// Action<ref T> isn't allowed
private delegate void AttemptUpgradeAction(ModuleInstaller installer, NetAsyncModulesDownloader downloader, RegistryManager regMgr, ref HashSet<string> possibleConfigOnlyDirs);

Expand Down Expand Up @@ -292,7 +323,5 @@ private void UpgradeModules(GameInstanceManager manager,
private readonly IUser user;
private readonly GameInstanceManager manager;
private readonly RepositoryDataManager repoData;

private static readonly ILog log = LogManager.GetLogger(typeof(Upgrade));
}
}
2 changes: 2 additions & 0 deletions Cmdline/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ Try `ckan list` for a list of installed mods.</value></data>
<data name="UpgradeAlreadyHaveLatest" xml:space="preserve"><value>You already have the latest version</value></data>
<data name="UpgradeAborted" xml:space="preserve"><value>Upgrade aborted: {0}</value></data>
<data name="UpgradeNotFound" xml:space="preserve"><value>Module {0} not found</value></data>
<data name="UpgradeAlreadyUpToDate" xml:space="preserve"><value>Module {0} is already up to date</value></data>
<data name="UpgradeAllUpToDate" xml:space="preserve"><value>All modules are up to date</value></data>
<data name="UpgradeDLC" xml:space="preserve"><value>CKAN can't upgrade expansion '{0}' for you</value></data>
<data name="UpgradeDLCStorePage" xml:space="preserve"><value>To upgrade this expansion, download any updates from the store page from which you purchased it:
{0}</value></data>
Expand Down
23 changes: 17 additions & 6 deletions ConsoleUI/InstallScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,27 @@ public override void Run(ConsoleTheme theme, Action<ConsoleTheme> process = null
}
NetAsyncModulesDownloader dl = new NetAsyncModulesDownloader(this, manager.Cache);
if (plan.Install.Count > 0) {
List<CkanModule> iList = new List<CkanModule>(plan.Install);
var iList = plan.Install
.Select(m => registry.LatestAvailable(m.identifier,
manager.CurrentInstance.VersionCriteria(),
null,
registry.InstalledModules
.Select(im => im.Module)
.ToArray(),
plan.Install))
.ToArray();
inst.InstallList(iList, resolvOpts, regMgr, ref possibleConfigOnlyDirs, dl);
plan.Install.Clear();
}
if (plan.Upgrade.Count > 0) {
inst.Upgrade(plan.Upgrade
.Select(ident => regMgr.registry.LatestAvailable(
ident, manager.CurrentInstance.VersionCriteria()))
.ToList(),
dl, ref possibleConfigOnlyDirs, regMgr);
var upgGroups = registry
.CheckUpgradeable(manager.CurrentInstance.VersionCriteria(),
// Hold identifiers not chosen for upgrading
registry.Installed(false)
.Keys
.Except(plan.Upgrade)
.ToHashSet());
inst.Upgrade(upgGroups[true], dl, ref possibleConfigOnlyDirs, regMgr);
plan.Upgrade.Clear();
}
if (plan.Replace.Count > 0) {
Expand Down
9 changes: 7 additions & 2 deletions ConsoleUI/ModInfoScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ private int addDependencies(int top = 8)
const int lblW = 16;
int nameW = midL - 2 - lblW - 2 - 1;
int depsH = (h - 2) * numDeps / (numDeps + numConfs);
var upgradeableGroups = registry
.CheckUpgradeable(manager.CurrentInstance.VersionCriteria(),
new HashSet<string>());

AddObject(new ConsoleFrame(
1, top, midL, top + h - 1,
Expand All @@ -290,7 +293,8 @@ private int addDependencies(int top = 8)
foreach (RelationshipDescriptor rd in mod.depends) {
tb.AddLine(ScreenObject.TruncateLength(
// Show install status
ModListScreen.StatusSymbol(plan.GetModStatus(manager, registry, rd.ToString()))
ModListScreen.StatusSymbol(plan.GetModStatus(manager, registry, rd.ToString(),
upgradeableGroups[true]))
+ rd.ToString(),
nameW
));
Expand All @@ -315,7 +319,8 @@ private int addDependencies(int top = 8)
foreach (RelationshipDescriptor rd in mod.conflicts) {
tb.AddLine(ScreenObject.TruncateLength(
// Show install status
ModListScreen.StatusSymbol(plan.GetModStatus(manager, registry, rd.ToString()))
ModListScreen.StatusSymbol(plan.GetModStatus(manager, registry, rd.ToString(),
upgradeableGroups[true]))
+ rd.ToString(),
nameW
));
Expand Down
Loading

0 comments on commit 0f7ca67

Please sign in to comment.