Skip to content

Commit

Permalink
Resolve virtual module dependencies in same order as non-virtual
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Nov 17, 2021
1 parent 35927bc commit 8492d1a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
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

0 comments on commit 8492d1a

Please sign in to comment.