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

Resolve virtual module dependencies in same order as non-virtual #3476

Merged
merged 1 commit into from
Apr 22, 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
24 changes: 22 additions & 2 deletions Core/Relationships/RelationshipResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public class RelationshipResolver
/// </summary>
private readonly HashSet<CkanModule> installed_modules;

private HashSet<CkanModule> alreadyResolved = new HashSet<CkanModule>();

/// <summary>
/// Creates a new Relationship resolver.
/// </summary>
Expand Down Expand Up @@ -327,6 +329,16 @@ private void RemoveModsFromInstalledList(IEnumerable<CkanModule> mods)
/// </summary>
private void Resolve(CkanModule module, RelationshipResolverOptions options, IEnumerable<RelationshipDescriptor> old_stanza = null)
{
if (alreadyResolved.Contains(module))
{
return;
}
else
{
// Mark this module as resolved so we don't recurse here again
alreadyResolved.Add(module);
}

// Even though we may resolve top-level suggests for our module,
// we don't install suggestions all the down unless with_all_suggests
// is true.
Expand Down Expand Up @@ -378,9 +390,17 @@ private void ResolveStanza(IEnumerable<RelationshipDescriptor> stanza, Selection
{
log.DebugFormat("Considering {0}", descriptor.ToString());

// If we already have this dependency covered, skip.
if (descriptor.MatchesAny(modlist.Values, null, null))
// If we already have this dependency covered,
// resolve its relationships if we haven't already.
if (descriptor.MatchesAny(modlist.Values, null, null, out CkanModule installingCandidate))
{
if (installingCandidate != null)
{
// Resolve the relationships of the matching module here
// because that's when it would happen if non-virtual
Resolve(installingCandidate, options, stanza);
}
// If null, it's a DLL or DLC, which we can't resolve
continue;
}
else if (descriptor.ContainsAny(modlist.Keys))
Expand Down
46 changes: 40 additions & 6 deletions Core/Types/RelationshipDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ namespace CKAN
{
public abstract class RelationshipDescriptor : IEquatable<RelationshipDescriptor>
{
public abstract bool MatchesAny(
public bool MatchesAny(
IEnumerable<CkanModule> modules,
HashSet<string> dlls,
IDictionary<string, ModuleVersion> dlc
)
{
return MatchesAny(modules, dlls, dlc, out CkanModule _);
}

public abstract bool MatchesAny(
IEnumerable<CkanModule> modules,
HashSet<string> dlls,
IDictionary<string, ModuleVersion> dlc,
out CkanModule matched
);

public abstract bool WithinBounds(CkanModule otherModule);
Expand Down Expand Up @@ -99,23 +109,32 @@ public bool WithinBounds(ModuleVersion other)
public override bool MatchesAny(
IEnumerable<CkanModule> modules,
HashSet<string> dlls,
IDictionary<string, ModuleVersion> dlc
IDictionary<string, ModuleVersion> dlc,
out CkanModule matched
)
{
modules = modules?.AsCollection();

// DLLs are considered to match any version
if (dlls != null && dlls.Contains(name))
{
matched = null;
return true;
}

if (modules != null)
{
// See if anyone else "provides" the target name
// Note that versions can't be checked for "provides" clauses
if (modules.Any(m => m.identifier != name && m.provides != null && m.provides.Contains(name)))
var matches = modules
.Where(m =>
m.identifier != name
&& m.provides != null
&& m.provides.Contains(name))
.ToList();
if (matches.Any())
{
matched = matches.FirstOrDefault();
return true;
}

Expand All @@ -124,6 +143,7 @@ IDictionary<string, ModuleVersion> dlc
{
if (WithinBounds(m))
{
matched = m;
return true;
}
}
Expand All @@ -135,11 +155,13 @@ IDictionary<string, ModuleVersion> dlc
{
if (WithinBounds(d.Value))
{
matched = null;
return true;
}
}
}

matched = null;
return false;
}

Expand Down Expand Up @@ -233,11 +255,23 @@ public override bool WithinBounds(CkanModule otherModule)
public override bool MatchesAny(
IEnumerable<CkanModule> modules,
HashSet<string> dlls,
IDictionary<string, ModuleVersion> dlc
IDictionary<string, ModuleVersion> dlc,
out CkanModule matched
)
{
return any_of?.Any(r => r.MatchesAny(modules, dlls, dlc))
?? false;
if (any_of != null)
{
foreach (RelationshipDescriptor rel in any_of)
{
if (rel.MatchesAny(modules, dlls, dlc, out CkanModule whatMatched))
{
matched = whatMatched;
return true;
}
}
}
matched = null;
return false;
}

public override List<CkanModule> LatestAvailableWithProvides(
Expand Down