From c06e0dd5919f2d39c275a13d29f02b18f265e881 Mon Sep 17 00:00:00 2001 From: Jerome Haltom Date: Tue, 27 Aug 2024 11:40:55 -0500 Subject: [PATCH 1/2] Account for circular dependencies. --- .../MavenReferenceItemResolveTests.cs | 30 +++++++++++++++++++ .../MavenReferenceItemResolve.cs | 20 +++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs index 7ec44cc..5821c80 100644 --- a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs +++ b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs @@ -518,6 +518,36 @@ public void CanResolveApacheFop() pkg.GetMetadata("References").Split(';').Should().Contain("maven$javax.media:jai-core:1.1.3"); } + [TestMethod] + public void CanResolveCircularDependency() + { + var cacheFile = Path.GetTempFileName(); + + var engine = new Mock(); + var errors = new List(); + engine.Setup(x => x.LogErrorEvent(It.IsAny())).Callback((BuildErrorEventArgs e) => { errors.Add(e); TestContext.WriteLine("ERROR: " + e.Message); }); + engine.Setup(x => x.LogWarningEvent(It.IsAny())).Callback((BuildWarningEventArgs e) => TestContext.WriteLine("WARNING: " + e.Message)); + engine.Setup(x => x.LogMessageEvent(It.IsAny())).Callback((BuildMessageEventArgs e) => TestContext.WriteLine(e.Message)); + var t = new MavenReferenceItemResolve(); + t.BuildEngine = engine.Object; + t.CacheFile = cacheFile; + t.Repositories = new[] { GetCentralRepositoryItem() }; + + var i1 = new TaskItem("org.apache.commons:commons-text:1.11.0"); + i1.SetMetadata(MavenReferenceItemMetadata.GroupId, "org.apache.commons"); + i1.SetMetadata(MavenReferenceItemMetadata.ArtifactId, "commons-text"); + i1.SetMetadata(MavenReferenceItemMetadata.Version, "1.11.0"); + i1.SetMetadata(MavenReferenceItemMetadata.Scope, "compile"); + t.References = new[] { i1 }; + + t.Execute().Should().BeTrue(); + errors.Should().BeEmpty(); + var pkg1 = t.ResolvedReferences.First(i => i.ItemSpec == "maven$org.apache.commons:commons-text:1.11.0"); + pkg1.GetMetadata("References").Split(';').Should().Contain("maven$org.apache.commons:commons-lang3:3.13.0"); + var pkg2 = t.ResolvedReferences.First(i => i.ItemSpec == "maven$org.apache.commons:commons-lang3:3.13.0"); + pkg2.GetMetadata("References").Split(';').Should().Contain("maven$org.apache.commons:commons-text:1.11.0"); + } + [TestMethod] public void CanResolveFromLocalRepository() { diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs index 07686e1..b54ec32 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs @@ -209,7 +209,7 @@ IEnumerable ResolveReferences(IList repo // walk the full dependency graph to generate items and their references var output = new Dictionary(); - CollectIkvmReferenceItems(output, graph); + CollectIkvmReferenceItems(output, graph, new HashSet()); // resolve compile and runtime items and ensure they are copied var privateScopes = new List() { JavaScopes.RUNTIME }; @@ -458,7 +458,7 @@ IEnumerable ResolveIkvmReferenceItemsForScopes(Dictionary /// /// - void CollectIkvmReferenceItems(Dictionary output, DependencyNode node) + void CollectIkvmReferenceItems(Dictionary output, DependencyNode node, HashSet processed) { if (output is null) throw new ArgumentNullException(nameof(output)); @@ -468,13 +468,17 @@ void CollectIkvmReferenceItems(Dictionary output, Dep // resolve to winner of a conflict instead node = GetEffectiveNode(node); + // check to see whether we've already processed the node, else continue + if (processed.Add(node) == false) + return; + // walk tree and ensure IkvmReferenceItem exists for each child var scopes = new HashSet() { JavaScopes.COMPILE, JavaScopes.RUNTIME, JavaScopes.PROVIDED }; if (IncludeTestScope) scopes.Add(JavaScopes.TEST); foreach (DependencyNode child in GetEffectiveChildren(node)) if (scopes.Contains(child.getDependency().getScope())) - CollectIkvmReferenceItems(output, child); + CollectIkvmReferenceItems(output, child, processed); // if artifact, obtain IkvmReferenceItem from artifact var artifact = node.getArtifact(); @@ -482,7 +486,7 @@ void CollectIkvmReferenceItems(Dictionary output, Dep // if we've got an actual item, traverse it's dependencies to assign references if (ikvmItem != null) - foreach (var ikvmReference in CollectIkvmReferenceItemReferences(output, node)) + foreach (var ikvmReference in CollectIkvmReferenceItemReferences(output, node, new HashSet())) if (ikvmItem.References.Contains(ikvmReference) == false) ikvmItem.References.Add(ikvmReference); } @@ -493,7 +497,7 @@ void CollectIkvmReferenceItems(Dictionary output, Dep /// /// /// - IEnumerable CollectIkvmReferenceItemReferences(Dictionary output, DependencyNode node) + IEnumerable CollectIkvmReferenceItemReferences(Dictionary output, DependencyNode node, HashSet processed) { if (output is null) throw new ArgumentNullException(nameof(output)); @@ -503,6 +507,10 @@ IEnumerable CollectIkvmReferenceItemReferences(Dictionary CollectIkvmReferenceItemReferences(Dictionary Date: Tue, 27 Aug 2024 11:43:28 -0500 Subject: [PATCH 2/2] Ensure circle is broken. --- .../MavenReferenceItemResolveTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs index 5821c80..71606eb 100644 --- a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs +++ b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs @@ -545,7 +545,9 @@ public void CanResolveCircularDependency() var pkg1 = t.ResolvedReferences.First(i => i.ItemSpec == "maven$org.apache.commons:commons-text:1.11.0"); pkg1.GetMetadata("References").Split(';').Should().Contain("maven$org.apache.commons:commons-lang3:3.13.0"); var pkg2 = t.ResolvedReferences.First(i => i.ItemSpec == "maven$org.apache.commons:commons-lang3:3.13.0"); - pkg2.GetMetadata("References").Split(';').Should().Contain("maven$org.apache.commons:commons-text:1.11.0"); + + // we break the circle so we can actually build them + pkg2.GetMetadata("References").Split(';').Should().NotContain("maven$org.apache.commons:commons-text:1.11.0"); } [TestMethod]