Skip to content

Commit bc138dc

Browse files
authored
[MNG-7741] Track missing files, plugin and parent pom dependencies (#1058)
Add more information when using `-Dmaven.repo.local.recordReverseTree=true`. Signed-off-by: Grzegorz Grzybek <[email protected]> --- https://issues.apache.org/jira/browse/MNG-7741
1 parent 0f18470 commit bc138dc

File tree

2 files changed

+146
-36
lines changed

2 files changed

+146
-36
lines changed

maven-core/src/main/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListener.java

Lines changed: 129 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@
1818
*/
1919
package org.apache.maven.internal.aether;
2020

21+
import java.io.File;
2122
import java.io.IOException;
2223
import java.io.UncheckedIOException;
2324
import java.nio.charset.StandardCharsets;
2425
import java.nio.file.Files;
2526
import java.nio.file.Path;
2627
import java.util.ArrayList;
28+
import java.util.List;
2729
import java.util.ListIterator;
2830
import java.util.Objects;
2931

32+
import org.apache.maven.model.InputLocation;
33+
import org.apache.maven.model.Plugin;
3034
import org.eclipse.aether.AbstractRepositoryListener;
3135
import org.eclipse.aether.RepositoryEvent;
3236
import org.eclipse.aether.RepositorySystemSession;
@@ -35,6 +39,10 @@
3539
import org.eclipse.aether.collection.CollectStepData;
3640
import org.eclipse.aether.graph.Dependency;
3741
import org.eclipse.aether.graph.DependencyNode;
42+
import org.eclipse.aether.repository.RemoteRepository;
43+
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
44+
import org.eclipse.aether.resolution.ArtifactRequest;
45+
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
3846

3947
import static java.util.Objects.requireNonNull;
4048

@@ -49,45 +57,131 @@ class ReverseTreeRepositoryListener extends AbstractRepositoryListener {
4957
public void artifactResolved(RepositoryEvent event) {
5058
requireNonNull(event, "event cannot be null");
5159

52-
if (!isLocalRepositoryArtifact(event.getSession(), event.getArtifact())) {
60+
if (!isLocalRepositoryArtifactOrMissing(event.getSession(), event.getArtifact())) {
5361
return;
5462
}
5563

56-
CollectStepData collectStepTrace = lookupCollectStepData(event.getTrace());
57-
if (collectStepTrace == null) {
58-
return;
64+
RequestTrace trace = event.getTrace();
65+
66+
CollectStepData collectStepTrace = null;
67+
ArtifactRequest artifactRequest = null;
68+
ArtifactDescriptorRequest artifactDescriptorRequest = null;
69+
Plugin plugin = null;
70+
71+
while (trace != null) {
72+
Object data = trace.getData();
73+
if (data instanceof CollectStepData) {
74+
collectStepTrace = (CollectStepData) data;
75+
} else if (data instanceof ArtifactDescriptorRequest) {
76+
artifactDescriptorRequest = (ArtifactDescriptorRequest) data;
77+
} else if (data instanceof ArtifactRequest) {
78+
artifactRequest = (ArtifactRequest) data;
79+
} else if (data instanceof Plugin) {
80+
plugin = (Plugin) data;
81+
}
82+
trace = trace.getParent();
5983
}
6084

61-
Artifact resolvedArtifact = event.getArtifact();
62-
Artifact nodeArtifact = collectStepTrace.getNode().getArtifact();
63-
64-
if (isInScope(resolvedArtifact, nodeArtifact)) {
65-
Dependency node = collectStepTrace.getNode();
66-
ArrayList<String> trackingData = new ArrayList<>();
67-
trackingData.add(node + " (" + collectStepTrace.getContext() + ")");
68-
String indent = "";
69-
ListIterator<DependencyNode> iter = collectStepTrace
70-
.getPath()
71-
.listIterator(collectStepTrace.getPath().size());
72-
while (iter.hasPrevious()) {
73-
DependencyNode curr = iter.previous();
85+
Path trackingDir;
86+
boolean missing = event.getFile() == null;
87+
if (missing) {
88+
// missing artifact - let's track the path anyway
89+
File dir = event.getSession().getLocalRepository().getBasedir();
90+
dir = new File(
91+
dir, event.getSession().getLocalRepositoryManager().getPathForLocalArtifact(event.getArtifact()));
92+
trackingDir = dir.getParentFile().toPath().resolve(".tracking");
93+
} else {
94+
trackingDir = event.getFile().getParentFile().toPath().resolve(".tracking");
95+
}
96+
97+
String baseName;
98+
String ext = missing ? ".miss" : ".dep";
99+
Path trackingFile = null;
100+
101+
String indent = "";
102+
ArrayList<String> trackingData = new ArrayList<>();
103+
104+
if (collectStepTrace == null && plugin != null) {
105+
ext = ".plugin";
106+
baseName = plugin.getGroupId() + "_" + plugin.getArtifactId() + "_" + plugin.getVersion();
107+
trackingFile = trackingDir.resolve(baseName + ext);
108+
if (Files.exists(trackingFile)) {
109+
return;
110+
}
111+
112+
if (event.getArtifact() != null) {
113+
trackingData.add(indent + event.getArtifact());
74114
indent += " ";
75-
trackingData.add(indent + curr + " (" + collectStepTrace.getContext() + ")");
76115
}
77-
try {
78-
Path trackingDir =
79-
resolvedArtifact.getFile().getParentFile().toPath().resolve(".tracking");
80-
Files.createDirectories(trackingDir);
81-
Path trackingFile = trackingDir.resolve(collectStepTrace
116+
trackingData.add(indent + plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + plugin.getVersion());
117+
indent += " ";
118+
119+
InputLocation location = plugin.getLocation("");
120+
if (location != null && location.getSource() != null) {
121+
trackingData.add(indent + location.getSource().getModelId() + " (implicit)");
122+
indent += " ";
123+
}
124+
} else if (collectStepTrace != null) {
125+
if (collectStepTrace.getPath().get(0).getArtifact() == null) {
126+
return;
127+
}
128+
baseName = ArtifactIdUtils.toId(collectStepTrace.getPath().get(0).getArtifact())
129+
.replace(":", "_");
130+
trackingFile = trackingDir.resolve(baseName + ext);
131+
if (Files.exists(trackingFile)) {
132+
return;
133+
}
134+
135+
Artifact resolvedArtifact = event.getArtifact();
136+
Artifact nodeArtifact = collectStepTrace.getNode().getArtifact();
137+
138+
if (isInScope(resolvedArtifact, nodeArtifact) || "pom".equals(resolvedArtifact.getExtension())) {
139+
Dependency node = collectStepTrace.getNode();
140+
trackingData.add(resolvedArtifact.toString());
141+
indent += " ";
142+
trackingData.add(indent + node + " (" + collectStepTrace.getContext() + ")");
143+
ListIterator<DependencyNode> iter = collectStepTrace
82144
.getPath()
83-
.get(0)
84-
.getArtifact()
85-
.toString()
86-
.replace(":", "_"));
87-
Files.write(trackingFile, trackingData, StandardCharsets.UTF_8);
88-
} catch (IOException e) {
89-
throw new UncheckedIOException(e);
145+
.listIterator(collectStepTrace.getPath().size());
146+
while (iter.hasPrevious()) {
147+
DependencyNode curr = iter.previous();
148+
indent += " ";
149+
trackingData.add(indent + curr + " (" + collectStepTrace.getContext() + ")");
150+
}
151+
}
152+
}
153+
154+
if (trackingFile == null) {
155+
return;
156+
}
157+
try {
158+
Files.createDirectories(trackingDir);
159+
160+
trackingData.add("");
161+
if (!missing) {
162+
if (event.getRepository() != null) {
163+
trackingData.add("Repository: " + event.getRepository());
164+
}
165+
} else {
166+
List<RemoteRepository> repositories = new ArrayList<>();
167+
if (artifactRequest != null && artifactRequest.getRepositories() != null) {
168+
repositories.addAll(artifactRequest.getRepositories());
169+
} else if (artifactDescriptorRequest != null && artifactDescriptorRequest.getRepositories() != null) {
170+
repositories.addAll(artifactDescriptorRequest.getRepositories());
171+
}
172+
if (!repositories.isEmpty()) {
173+
trackingData.add("Configured repositories:");
174+
for (RemoteRepository r : repositories) {
175+
trackingData.add(" - " + r.getId() + " : " + r.getUrl());
176+
}
177+
} else {
178+
trackingData.add("No repositories configured");
179+
}
90180
}
181+
182+
Files.write(trackingFile, trackingData, StandardCharsets.UTF_8);
183+
} catch (IOException e) {
184+
throw new UncheckedIOException(e);
91185
}
92186
}
93187

@@ -99,10 +193,11 @@ public void artifactResolved(RepositoryEvent event) {
99193
* <p>
100194
* Visible for testing.
101195
*/
102-
static boolean isLocalRepositoryArtifact(RepositorySystemSession session, Artifact artifact) {
103-
return artifact.getFile()
104-
.getPath()
105-
.startsWith(session.getLocalRepository().getBasedir().getPath());
196+
static boolean isLocalRepositoryArtifactOrMissing(RepositorySystemSession session, Artifact artifact) {
197+
return artifact.getFile() == null
198+
|| artifact.getFile()
199+
.getPath()
200+
.startsWith(session.getLocalRepository().getBasedir().getPath());
106201
}
107202

108203
/**

maven-core/src/test/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListenerTest.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,28 @@ public void isLocalRepositoryArtifactTest() {
5252
when(nonLocalReposioryArtifact.getFile()).thenReturn(new File("something/completely/different"));
5353

5454
assertThat(
55-
ReverseTreeRepositoryListener.isLocalRepositoryArtifact(session, localRepositoryArtifact),
55+
ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, localRepositoryArtifact),
5656
equalTo(true));
5757
assertThat(
58-
ReverseTreeRepositoryListener.isLocalRepositoryArtifact(session, nonLocalReposioryArtifact),
58+
ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, nonLocalReposioryArtifact),
5959
equalTo(false));
6060
}
6161

62+
@Test
63+
public void isMissingArtifactTest() {
64+
File baseDir = new File("local/repository");
65+
LocalRepository localRepository = new LocalRepository(baseDir);
66+
RepositorySystemSession session = mock(RepositorySystemSession.class);
67+
when(session.getLocalRepository()).thenReturn(localRepository);
68+
69+
Artifact localRepositoryArtifact = mock(Artifact.class);
70+
when(localRepositoryArtifact.getFile()).thenReturn(null);
71+
72+
assertThat(
73+
ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, localRepositoryArtifact),
74+
equalTo(true));
75+
}
76+
6277
@Test
6378
public void lookupCollectStepDataTest() {
6479
RequestTrace doesNotHaveIt =

0 commit comments

Comments
 (0)