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 modpack installation, install incompatible with confirmation #3675

Merged
merged 1 commit into from
Nov 4, 2022
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
4 changes: 4 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 @@ -308,4 +308,5 @@ Free up space on that device or change your settings to use another location.
<data name="NetModuleCacheModuleResuming" xml:space="preserve"><value>{0} {1} ({2}, {3} remaining)</value></data>
<data name="ModuleInstallerUpgradeInstallingUncached" xml:space="preserve"><value> * Install: {0} {1} ({2}, {3} remaining)</value></data>
<data name="ModuleInstallerUpgradeUpgradingResuming" xml:space="preserve"><value> * Upgrade: {0} {1} to {2} ({3}, {4} remaining)</value></data>
<data name="ModpackName" xml:space="preserve"><value>installed-{0}</value></data>
</root>
80 changes: 50 additions & 30 deletions Core/Registry/RegistryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel;
using System.Reflection;

using ChinhDo.Transactions.FileManager;
using log4net;
Expand Down Expand Up @@ -462,59 +464,77 @@ private string SerializeCurrentInstall(bool recommends = false, bool with_versio
public CkanModule GenerateModpack(bool recommends = false, bool with_versions = true)
{
string gameInstanceName = gameInstance.Name;
string name = $"installed-{gameInstanceName}";
string name = string.Format(Properties.Resources.ModpackName, gameInstanceName);
var crit = gameInstance.VersionCriteria();
var minAndMax = crit.MinAndMax;
var module = new CkanModule(
// v1.18 to allow Unlicense
new ModuleVersion("v1.18"),
Identifier.Sanitize(name),
name,
string.Format(Properties.Resources.RegistryManagerDefaultModpackAbstract, gameInstanceName),
null,
new List<string>() { Environment.UserName },
new List<License>() { new License("unknown") },
new List<string>() { Environment.UserName },
new List<License>() { License.UnknownLicense },
new ModuleVersion(DateTime.UtcNow.ToString("yyyy.MM.dd.hh.mm.ss")),
null,
"metapackage"
)
{
download_content_type = "application/zip",
release_date = DateTime.Now,
"metapackage")
{
ksp_version_min = minAndMax.Lower.AsInclusiveLower().WithoutBuild,
ksp_version_max = minAndMax.Upper.AsInclusiveUpper().WithoutBuild,
download_content_type = typeof(CkanModule).GetTypeInfo()
.GetDeclaredField("download_content_type")
.GetCustomAttribute<DefaultValueAttribute>()
.Value.ToString(),
release_date = DateTime.Now,
};

List<RelationshipDescriptor> mods = registry.Installed(false, false)
.Where(kvp => {
// Skip unavailable modules (custom .ckan files)
try
{
var avail = registry.LatestAvailable(kvp.Key, null, null);
return !avail.IsDLC;
}
catch
{
return false;
}
})
// Case insensitive sort by identifier
.OrderBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)
.Select(kvp => (RelationshipDescriptor) new ModuleRelationshipDescriptor()
{
name = kvp.Key,
version = with_versions ? kvp.Value : null
})
var rels = registry.InstalledModules
.Where(inst => !inst.Module.IsDLC && IsAvailable(inst))
.OrderBy(inst => inst.identifier, StringComparer.OrdinalIgnoreCase)
.Select(with_versions ? (Func<InstalledModule, RelationshipDescriptor>) RelationshipWithVersion
: RelationshipWithoutVersion)
.ToList();

if (recommends)
{
module.recommends = mods;
module.recommends = rels;
}
else
{
module.depends = mods;
module.depends = rels;
}

return module;
}

private bool IsAvailable(InstalledModule inst)
{
try
{
var avail = registry.LatestAvailable(inst.identifier, null, null);
return true;
}
catch
{
// Skip unavailable modules (custom .ckan files)
return false;
}
}

private RelationshipDescriptor RelationshipWithVersion(InstalledModule inst)
=> new ModuleRelationshipDescriptor()
{
name = inst.identifier,
version = inst.Module.version,
};

private RelationshipDescriptor RelationshipWithoutVersion(InstalledModule inst)
=> new ModuleRelationshipDescriptor()
{
name = inst.identifier,
};

/// <summary>
/// Look for DLC installed in GameData
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions Core/Relationships/RelationshipResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,10 @@ private void ResolveStanza(IEnumerable<RelationshipDescriptor> stanza, Selection
private void Add(CkanModule module, SelectionReason reason)
{
if (module.IsMetapackage)
{
AddReason(module, reason);
return;
}
if (module.IsDLC)
{
throw new ModuleIsDLCKraken(module);
Expand Down Expand Up @@ -698,6 +701,12 @@ public IEnumerable<CkanModule> ModList()
log.DebugFormat("Parent found: {0}, {1}", index, module);
sortedDepsFirst.Insert(index, module);
}
catch (ArgumentException)
{
// ReasonsFor throws this for mods without reasons, just add it to the end
log.DebugFormat("Reasons for parent not found: {0}", module);
sortedDepsFirst.Add(module);
}
catch (InvalidOperationException)
{
// No index, just append
Expand Down
61 changes: 27 additions & 34 deletions Core/Types/RelationshipDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ out CkanModule matched

public abstract List<CkanModule> LatestAvailableWithProvides(
IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable<CkanModule> installed = null,
IEnumerable<CkanModule> toInstall = null
);
IEnumerable<CkanModule> toInstall = null);

public abstract CkanModule ExactMatch(
IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable<CkanModule> installed = null,
IEnumerable<CkanModule> toInstall = null);

public abstract bool Equals(RelationshipDescriptor other);

Expand Down Expand Up @@ -167,11 +170,14 @@ out CkanModule matched

public override List<CkanModule> LatestAvailableWithProvides(
IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable<CkanModule> installed = null,
IEnumerable<CkanModule> toInstall = null
)
{
return registry.LatestAvailableWithProvides(name, crit, this, installed, toInstall);
}
IEnumerable<CkanModule> toInstall = null)
=> registry.LatestAvailableWithProvides(name, crit, this, installed, toInstall);

public override CkanModule ExactMatch(
IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable<CkanModule> installed = null,
IEnumerable<CkanModule> toInstall = null)
=> registry.LatestAvailableWithProvides(name, crit, this, installed, toInstall)
.FirstOrDefault(mod => mod.identifier == name);

public override bool Equals(RelationshipDescriptor other)
{
Expand All @@ -183,15 +189,10 @@ public override bool Equals(RelationshipDescriptor other)
&& max_version == modRel.max_version;
}

public override bool ContainsAny(IEnumerable<string> identifiers)
{
return identifiers.Contains(name);
}
public override bool ContainsAny(IEnumerable<string> identifiers) => identifiers.Contains(name);

public override bool StartsWith(string prefix)
{
return name.IndexOf(prefix, StringComparison.CurrentCultureIgnoreCase) == 0;
}
=> name.IndexOf(prefix, StringComparison.CurrentCultureIgnoreCase) == 0;

/// <summary>
/// Generate a user readable description of the relationship
Expand All @@ -205,16 +206,13 @@ public override bool StartsWith(string prefix)
/// name max_version or earlier
/// </returns>
public override string ToString()
{
return
version != null ? $"{name} {version}"
=> version != null ? $"{name} {version}"
: min_version != null && max_version != null ? $"{name} {min_version}–{max_version}"
: min_version != null
? string.Format(Properties.Resources.RelationshipDescriptorMinVersionOnly, name, min_version)
: max_version != null
? string.Format(Properties.Resources.RelationshipDescriptorMaxVersionOnly, name, max_version)
: name;
}

}

Expand Down Expand Up @@ -262,11 +260,14 @@ out CkanModule matched

public override List<CkanModule> LatestAvailableWithProvides(
IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable<CkanModule> installed = null,
IEnumerable<CkanModule> toInstall = null
)
{
return any_of?.SelectMany(r => r.LatestAvailableWithProvides(registry, crit, installed, toInstall)).Distinct().ToList();
}
IEnumerable<CkanModule> toInstall = null)
=> any_of?.SelectMany(r => r.LatestAvailableWithProvides(registry, crit, installed, toInstall)).Distinct().ToList();

// Exact match is not possible for any_of
public override CkanModule ExactMatch(
IRegistryQuerier registry, GameVersionCriteria crit, IEnumerable<CkanModule> installed = null,
IEnumerable<CkanModule> toInstall = null)
=> null;

public override bool Equals(RelationshipDescriptor other)
{
Expand All @@ -276,22 +277,14 @@ public override bool Equals(RelationshipDescriptor other)
}

public override bool ContainsAny(IEnumerable<string> identifiers)
{
return any_of?.Any(r => r.ContainsAny(identifiers))
?? false;
}
=> any_of?.Any(r => r.ContainsAny(identifiers)) ?? false;

public override bool StartsWith(string prefix)
{
return any_of?.Any(r => r.StartsWith(prefix))
?? false;
}
=> any_of?.Any(r => r.StartsWith(prefix)) ?? false;

public override string ToString()
{
return any_of?.Select(r => r.ToString())
=> any_of?.Select(r => r.ToString())
.Aggregate((a, b) =>
string.Format(Properties.Resources.RelationshipDescriptorAnyOfJoiner, a, b));
}
}
}
Loading