Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ public static class CondaDependencyResolver
/// <param name="condaLock">The full condaLock object.</param>
/// <param name="singleFileComponentRecorder">The SingleFileComponentRecorder.</param>
public static void RecordDependencyGraphFromFile(CondaLock condaLock, ISingleFileComponentRecorder singleFileComponentRecorder)
=> GetPackages(condaLock).ForEach(package => RegisterPackageWithDependencies(package, null, condaLock, singleFileComponentRecorder));
{
HashSet<(string Name, string Version)> visitedPackages = [];
GetPackages(condaLock).ForEach(package => RegisterPackageWithDependencies(package, null, condaLock, singleFileComponentRecorder, visitedPackages));
}

/// <summary>
/// Updates all registered packages that don't have any ancestors.
Expand Down Expand Up @@ -60,7 +63,13 @@ public static void UpdateDirectlyReferencedPackages(ISingleFileComponentRecorder
/// <param name="parentId">The id of the parent package.</param>
/// <param name="condaLock">The full condaLock object.</param>
/// <param name="singleFileComponentRecorder">The SingleFileComponentRecorder.</param>
private static void RegisterPackageWithDependencies(CondaPackage package, string parentId, CondaLock condaLock, ISingleFileComponentRecorder singleFileComponentRecorder)
/// <param name="visitedPackages">The packages whose dependencies have already been registered.</param>
private static void RegisterPackageWithDependencies(
CondaPackage package,
string parentId,
CondaLock condaLock,
ISingleFileComponentRecorder singleFileComponentRecorder,
ISet<(string Name, string Version)> visitedPackages)
{
if (package == null)
{
Expand All @@ -72,13 +81,19 @@ private static void RegisterPackageWithDependencies(CondaPackage package, string
//// Register the package itself.
RegisterPackage(component, parentId, false, singleFileComponentRecorder);

if (!visitedPackages.Add((package.Name, package.Version)))
{
return;
}
Comment on lines +84 to +87

//// Register all dependencies of the package.
package.Dependencies.Keys.ToList().ForEach(dependency =>
RegisterPackageWithDependencies(
condaLock?.Package.FirstOrDefault(condaPackage => condaPackage.Name == dependency && condaPackage.Platform == package.Platform),
component.Id,
condaLock,
singleFileComponentRecorder));
singleFileComponentRecorder,
visitedPackages));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,46 @@ public async Task CondaComponentDetector_TestCondaLockFileAsync()
detectedComponents.Should().HaveCount(4);
}

[TestMethod]
public async Task CondaComponentDetector_CircularDependenciesAsync()
{
var condaLockContent =
@"version: 1
package:
- name: alpha
version: 1.0.0
manager: conda
platform: linux-64
dependencies:
beta: '>=1.0.0'
category: main
optional: false
- name: beta
version: 1.0.0
manager: conda
platform: linux-64
dependencies:
alpha: '>=1.0.0'
category: main
optional: false
";

var (scanResult, componentRecorder) = await this.detectorTestUtility
.WithFile("conda-lock.yml", condaLockContent)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);

var detectedComponents = componentRecorder.GetDetectedComponents();
var alpha = detectedComponents.Single(component => component.Component is CondaComponent condaComponent && condaComponent.Name == "alpha");
var beta = detectedComponents.Single(component => component.Component is CondaComponent condaComponent && condaComponent.Name == "beta");
var dependencyGraph = componentRecorder.GetDependencyGraphsByLocation().Values.Single();

detectedComponents.Should().HaveCount(2);
dependencyGraph.GetDependenciesForComponent(alpha.Component.Id).Should().ContainSingle(beta.Component.Id);
dependencyGraph.GetDependenciesForComponent(beta.Component.Id).Should().ContainSingle(alpha.Component.Id);
}

private void AssertCondaLockComponentNameAndVersion(IEnumerable<DetectedComponent> detectedComponents, string name, string version)
{
detectedComponents.SingleOrDefault(c =>
Expand Down
Loading