Skip to content

Commit ddae3ad

Browse files
committed
Improve accuracy of dependency resolution diagnostic
1 parent 3840fdb commit ddae3ad

2 files changed

Lines changed: 117 additions & 12 deletions

File tree

src/main/java/org/openrewrite/java/dependencies/DependencyResolutionDiagnostic.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
import org.openrewrite.internal.lang.Nullable;
2626
import org.openrewrite.java.dependencies.table.GradleDependencyConfigurationErrors;
2727
import org.openrewrite.java.dependencies.table.RepositoryAccessibilityReport;
28+
import org.openrewrite.maven.MavenExecutionContextView;
29+
import org.openrewrite.maven.MavenSettings;
2830
import org.openrewrite.maven.internal.MavenPomDownloader;
2931
import org.openrewrite.maven.tree.MavenRepository;
32+
import org.openrewrite.maven.tree.MavenRepositoryMirror;
3033
import org.openrewrite.maven.tree.MavenResolutionResult;
3134

3235
import java.io.UncheckedIOException;
@@ -62,7 +65,10 @@ public String getDescription() {
6265
}
6366

6467
public static class Accumulator {
68+
boolean foundGradle;
6569
Set<MavenRepository> repositoriesFromGradle = new HashSet<>();
70+
71+
boolean foundMaven;
6672
Set<MavenRepository> repositoriesFromMaven = new HashSet<>();
6773
}
6874

@@ -80,11 +86,14 @@ public TreeVisitor<?, ExecutionContext> getScanner(Accumulator acc) {
8086
return null;
8187
}
8288
tree.getMarkers().findFirst(GradleProject.class).ifPresent(gp -> {
89+
acc.foundGradle = true;
8390
acc.repositoriesFromGradle.addAll(gp.getMavenRepositories());
8491
acc.repositoriesFromGradle.addAll(gp.getMavenPluginRepositories());
8592
});
86-
tree.getMarkers().findFirst(MavenResolutionResult.class).ifPresent(mrr ->
87-
acc.repositoriesFromMaven.addAll(mrr.getPom().getRepositories()));
93+
tree.getMarkers().findFirst(MavenResolutionResult.class).ifPresent(mrr -> {
94+
acc.foundMaven = true;
95+
acc.repositoriesFromMaven.addAll(mrr.getPom().getRepositories());
96+
});
8897
return tree;
8998
}
9099
};
@@ -93,8 +102,12 @@ public TreeVisitor<?, ExecutionContext> getScanner(Accumulator acc) {
93102
@Override
94103
public Collection<? extends SourceFile> generate(Accumulator acc, ExecutionContext ctx) {
95104
Set<String> seen = new HashSet<>();
96-
record(true, acc.repositoriesFromMaven, seen, ctx);
97-
record(false, acc.repositoriesFromGradle, seen, ctx);
105+
if(acc.foundMaven) {
106+
record(true, acc.repositoriesFromMaven, seen, ctx);
107+
}
108+
if(acc.foundGradle) {
109+
record(false, acc.repositoriesFromGradle, seen, ctx);
110+
}
98111
return emptyList();
99112
}
100113

@@ -123,11 +136,21 @@ private void record(boolean addMavenDefaultRepositories, Collection<MavenReposit
123136
if(reason == null) {
124137
reason = new RuntimeException("Repository unreachable for unknown reason");
125138
}
126-
seen.add(noTrailingSlash(repo.getUri()));
127-
report.insertRow(ctx, rowFor(repo, reason));
139+
140+
MavenExecutionContextView mctx = new MavenExecutionContextView(ctx);
141+
MavenSettings settings = mctx.getSettings();
142+
if(settings != null) {
143+
// normalizeRepository() internally applies mirrors,but normalizeRepository() just returned null.
144+
// Replicate mirror application so that the correct URL is recorded
145+
repo = MavenRepositoryMirror.apply(mctx.getMirrors(settings), repo);
146+
}
147+
if(seen.add(noTrailingSlash(repo.getUri()))) {
148+
report.insertRow(ctx, rowFor(repo, reason));
149+
}
128150
} else {
129-
seen.add(noTrailingSlash(normalized.getUri()));
130-
report.insertRow(ctx, rowFor(repo, null));
151+
if(seen.add(noTrailingSlash(normalized.getUri()))) {
152+
report.insertRow(ctx, rowFor(normalized, null));
153+
}
131154
}
132155
}
133156
}
@@ -156,7 +179,7 @@ private static RepositoryAccessibilityReport.Row rowFor(MavenRepository repo, @N
156179
exceptionClass = t.getClass().getName();
157180
exceptionMessage = t.getMessage();
158181
}
159-
return new RepositoryAccessibilityReport.Row(repo.getUri(), exceptionClass, exceptionMessage, httpResponseCode);
182+
return new RepositoryAccessibilityReport.Row(noTrailingSlash(repo.getUri()), exceptionClass, exceptionMessage, httpResponseCode);
160183
}
161184

162185
@Override

src/test/java/org/openrewrite/java/dependencies/DependencyResolutionDiagnosticTest.java

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@
1616
package org.openrewrite.java.dependencies;
1717

1818
import org.junit.jupiter.api.Test;
19+
import org.openrewrite.InMemoryExecutionContext;
20+
import org.openrewrite.Parser;
1921
import org.openrewrite.java.dependencies.table.RepositoryAccessibilityReport;
22+
import org.openrewrite.maven.MavenExecutionContextView;
23+
import org.openrewrite.maven.MavenSettings;
2024
import org.openrewrite.test.RecipeSpec;
2125
import org.openrewrite.test.RewriteTest;
2226

27+
import java.io.ByteArrayInputStream;
28+
import java.nio.file.Paths;
29+
2330
import static org.assertj.core.api.Assertions.assertThat;
2431
import static org.openrewrite.gradle.Assertions.buildGradle;
2532
import static org.openrewrite.gradle.Assertions.withToolingApi;
@@ -44,6 +51,40 @@ void gradle() {
4451
assertThat(rows).contains(
4552
new RepositoryAccessibilityReport.Row("https://repo.maven.apache.org/maven2", "", "", 200));
4653
assertThat(rows).filteredOn(row -> row.getUri().startsWith("file:/") && "".equals(row.getExceptionMessage())).hasSize(1);
54+
assertThat(rows).contains(
55+
new RepositoryAccessibilityReport.Row("https://plugins.gradle.org/m2", "", "", 200));
56+
assertThat(rows)
57+
.filteredOn(row -> row.getUri().equals("https://nonexistent.moderne.io/maven2") && row.getHttpCode() == null).hasSize(1);
58+
}),
59+
//language=groovy
60+
buildGradle("""
61+
plugins {
62+
id("java")
63+
}
64+
repositories {
65+
mavenLocal()
66+
mavenCentral()
67+
maven {
68+
url "https://nonexistent.moderne.io/maven2"
69+
}
70+
}
71+
72+
dependencies {
73+
implementation("org.openrewrite.nonexistent:nonexistent:0.0.0")
74+
}
75+
""")
76+
);
77+
}
78+
79+
80+
@Test
81+
void gradleNoDefaultRepos() {
82+
rewriteRun(
83+
spec -> spec.beforeRecipe(withToolingApi())
84+
// It is a limitation of the tooling API which prevents configuration-granularity error information from being collected.
85+
// So the GradleDependencyConfigurationErrors table will never be populated in unit tests.
86+
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
87+
assertThat(rows).hasSize(2);
4788
assertThat(rows).contains(
4889
new RepositoryAccessibilityReport.Row("https://plugins.gradle.org/m2", "", "", 200));
4990
assertThat(rows).contains(
@@ -59,14 +100,55 @@ void gradle() {
59100
url "https://nonexistent.moderne.io/maven2"
60101
}
61102
}
62-
103+
63104
dependencies {
64105
implementation("org.openrewrite.nonexistent:nonexistent:0.0.0")
65106
}
66107
""")
67108
);
68109
}
69110

111+
@Test
112+
void mavenSettingsWithMirrors() {
113+
rewriteRun(
114+
spec -> {
115+
MavenExecutionContextView ctx = MavenExecutionContextView.view(new InMemoryExecutionContext());
116+
MavenSettings settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream(
117+
//language=xml
118+
"""
119+
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
120+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
121+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
122+
<mirrors>
123+
<mirror>
124+
<mirrorOf>*</mirrorOf>
125+
<name>mirrored-repo</name>
126+
<url>https://nonexistent.moderne.io/maven2</url>
127+
<id>repo</id>
128+
</mirror>
129+
</mirrors>
130+
</settings>
131+
""".getBytes())), ctx);
132+
ctx.setMavenSettings(settings);
133+
spec.beforeRecipe(withToolingApi())
134+
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
135+
assertThat(rows).contains(
136+
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null)
137+
);
138+
assertThat(rows).noneMatch(repo -> repo.getUri().contains("https://repo.maven.apache.org/maven2"));
139+
})
140+
.executionContext(ctx);
141+
},
142+
//language=xml
143+
pomXml("""
144+
<project>
145+
<groupId>com.example</groupId>
146+
<artifactId>test</artifactId>
147+
<version>0.1.0</version>
148+
</project>
149+
""")
150+
);
151+
}
70152

71153
@Test
72154
void maven() {
@@ -80,8 +162,8 @@ void maven() {
80162
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null)
81163
);
82164
}),
83-
//language=xml
84-
pomXml("""
165+
//language=xml
166+
pomXml("""
85167
<project>
86168
<groupId>com.example</groupId>
87169
<artifactId>test</artifactId>

0 commit comments

Comments
 (0)