Skip to content

Commit

Permalink
1159 relax constraints when installing bundles
Browse files Browse the repository at this point in the history
I think this is the right approach, but there are still a couple of issues:

1. If a bundle is installed like "tap image install 'DMM:2.1.2,DMM API:2.1.3'", the DMM API request is ignored. The image should fail to resolve, but will instead resolve to something the user did not ask for
2. If a bundle has a dependency on OpenTAP, the current OpenTAP installation might be downgraded, even if `--merge` is specified
3. If a new bundle member is added, downgrading to an older version will uninstall the new bundle member

These are a couple of strange behaviors I can think of off the top of my head. We should resolve these issues before merging this

Closes #1159
  • Loading branch information
alnlarsen committed Jan 30, 2024
1 parent b5d65fe commit 8f407f2
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 8 deletions.
5 changes: 1 addition & 4 deletions Engine/ThreadManager.cs
Expand Up @@ -693,10 +693,7 @@ void processQueue()
}

private static TraceSource _log;
private static TraceSource log
{
get => (_log ?? (_log = Log.CreateSource("thread")));
}
private static TraceSource log => _log ??= Log.CreateSource("thread");

/// <summary> Disposes the ThreadManager. This can optionally be done at program exit.</summary>
public void Dispose()
Expand Down
9 changes: 9 additions & 0 deletions Package/Image/ImageSpecifier.cs
Expand Up @@ -113,6 +113,15 @@ public ImageIdentifier Resolve(CancellationToken cancellationToken)
cache.AddPackages(InstalledPackages);
cache.AddPackages(AdditionalPackages);
var sw = Stopwatch.StartNew();

var packageNames = this.Packages.Select(p => p.Name).ToArray();
foreach (var pn in packageNames)
{
foreach (var bundlePackage in cache.Graph.GetBundlePackages(pn))
{
this.Packages.RemoveAll(p => p.Name == bundlePackage);
}
}

var resolver = new ImageResolver(cancellationToken);

Expand Down
28 changes: 25 additions & 3 deletions Package/Image/PackageDependencyGraph.cs
Expand Up @@ -29,6 +29,7 @@ class PackageDependencyGraph

// versions contains all versions of a given name. Eg all versions of OpenTAP/
readonly Dictionary<int, HashSet<int>> versions = new Dictionary<int, HashSet<int>>();
readonly Dictionary<int, string[]> bundlePackages = new Dictionary<int, string[]>();

// Dependencies for a given version
readonly Dictionary<(int packageNameId, int packageVersion), (int packageNameId, int versionSpecifierId)[]> dependencies = new Dictionary<(int, int), (int, int)[]>();
Expand Down Expand Up @@ -113,6 +114,8 @@ public void LoadFromPackageDefs(IEnumerable<PackageDef> packages)
}

dependencies[(id, GetVersionId(version))] = deps;
if (elem.IsBundle())
bundlePackages[id] = elem.Dependencies.Select(dep => dep.Name).ToArray();
}
}

Expand All @@ -124,17 +127,20 @@ public void LoadFromDictionaries(List<Dictionary<string, object>> dicts)
{
var name = d["name"] as string;
var version = d["version"] as string;
if (!SemanticVersion.TryParse(version, out var v))
var @class = d["class"] as string;
if (!SemanticVersion.TryParse(version, out _))
continue;
var id = GetNameId(name);
var thisVersion = versions[id];

if (!thisVersion.Add(GetVersionId(version)))
continue; // package already added.
var depMap = d["dependencies"] as List<Dictionary<string, object>>;
if (depMap == null || depMap.Count == 0) continue;

var deps = new (int id, int y)[depMap.Count];
int i = 0;
int i = 0;
var depNames = new string[depMap.Count];
foreach (var dep in depMap)
{
var depname = dep["name"] as string;
Expand All @@ -144,6 +150,10 @@ public void LoadFromDictionaries(List<Dictionary<string, object>> dicts)
i++;
}

if (@class?.Equals("bundle", StringComparison.InvariantCultureIgnoreCase) == true)
if (!bundlePackages.ContainsKey(id))
bundlePackages[id] = depNames;

dependencies[(id, GetVersionId(version))] = deps;
}
}
Expand Down Expand Up @@ -257,14 +267,18 @@ public IEnumerable<PackageDef> PackageSpecifiers()
foreach (var thing in versions)
{
var pkgName = nameLookup[thing.Key];
bool isBundle = bundlePackages.ContainsKey(thing.Key);
foreach (var v in thing.Value)
{
var version = this.versionLookup[v];
var pkg = new PackageDef
{
Name = pkgName,
Version = version
Version = version,
};
if (isBundle)
pkg.Class = "bundle";

if (dependencies.TryGetValue((thing.Key, v), out var deps))
{
foreach (var dep in deps)
Expand Down Expand Up @@ -367,6 +381,14 @@ public IEnumerable<PackageSpecifier> GetDependencies(string pkgName, SemanticVer
}
}

public string[] GetBundlePackages(string pkgName)
{
if (name2Id.TryGetValue(pkgName, out var id) &&
bundlePackages.TryGetValue(id, out var result))
return result;
return Array.Empty<string>();
}

public bool HasPackage(string pkgName, SemanticVersion version)
{
return name2Id.TryGetValue(pkgName, out var Id)
Expand Down
2 changes: 1 addition & 1 deletion Package/Image/PackageDependencyQuery.cs
Expand Up @@ -39,7 +39,7 @@ static class PackageDependencyQuery
var parameters = HttpPackageRepository.GetQueryParameters(version: VersionSpecifier.TryParse(preRelease, out var spec) ? spec : VersionSpecifier.AnyRelease, os: os,
architecture: deploymentInstallationArchitecture, name: name);

var result = repoClient.Query(parameters, CancellationToken.None, "name", "version",
var result = repoClient.Query(parameters, CancellationToken.None, "name", "version", "class",
new QuerySelection("dependencies", new List<QuerySelection>() { "name", "version" }));
var graph = new PackageDependencyGraph();
graph.LoadFromDictionaries(result);
Expand Down

0 comments on commit 8f407f2

Please sign in to comment.