mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
[maven] IDEA-359760 handle transitive dependencies in Maven incremental sync
GitOrigin-RevId: 83fd261e83cfe692ab4b4249d960bb650bc3cf5b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3286019377
commit
184410038c
@@ -6,18 +6,36 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class PomHashMap implements Serializable {
|
||||
@NotNull
|
||||
private final Map<@NotNull File, @NotNull PomHashValue> pomMap = new HashMap<>();
|
||||
|
||||
@NotNull
|
||||
private final Map<@NotNull File, @NotNull HashSet<@NotNull File>> pomDependencies = new HashMap<>();
|
||||
|
||||
public void put(@NotNull File pom, @Nullable String dependencyHash) {
|
||||
pomMap.put(pom, new PomHashValue(dependencyHash));
|
||||
}
|
||||
|
||||
public void addFileDependency(@NotNull File pom, @NotNull File dependentPom) {
|
||||
pomDependencies.putIfAbsent(pom, new HashSet<>());
|
||||
pomDependencies.get(pom).add(dependentPom);
|
||||
}
|
||||
|
||||
public void addFileDependencies(@NotNull File pom, @NotNull Collection<@NotNull File> dependentPoms) {
|
||||
for (File dependentPom : dependentPoms) {
|
||||
addFileDependency(pom, dependentPom);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<@NotNull File> getFileDependencies(@NotNull File pom) {
|
||||
Set<@NotNull File> dependencies = pomDependencies.get(pom);
|
||||
return dependencies == null ? Collections.emptySet() : dependencies;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<@NotNull File> keySet() {
|
||||
return pomMap.keySet();
|
||||
|
||||
@@ -35,8 +35,6 @@ import org.jetbrains.idea.maven.server.*;
|
||||
import org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator2;
|
||||
|
||||
import java.io.File;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -178,7 +176,7 @@ public class Maven3XProjectResolver {
|
||||
}
|
||||
|
||||
String newDependencyHash = fileToNewDependencyHash.get(pomFile);
|
||||
if (!dependenciesChanged(pomFile, newDependencyHash, fileToNewDependencyHash)) {
|
||||
if (!transitiveDependenciesChanged(pomFile, newDependencyHash, fileToNewDependencyHash)) {
|
||||
executionResults.add(createExecutionResult(project, newDependencyHash));
|
||||
continue;
|
||||
}
|
||||
@@ -215,11 +213,17 @@ public class Maven3XProjectResolver {
|
||||
return executionResults;
|
||||
}
|
||||
|
||||
private boolean dependenciesChanged(@NotNull File pomFile, String newDependencyHash, Map<File, String> fileToNewDependencyHash) {
|
||||
private boolean transitiveDependenciesChanged(@NotNull File pomFile, String newDependencyHash, Map<File, String> fileToNewDependencyHash) {
|
||||
if (dependenciesChanged(pomFile, newDependencyHash)) return true;
|
||||
for (File dependencyPomFile : myPomHashMap.getFileDependencies(pomFile)) {
|
||||
if (dependenciesChanged(dependencyPomFile, fileToNewDependencyHash.get(dependencyPomFile))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean dependenciesChanged(@NotNull File pomFile, String newDependencyHash) {
|
||||
String previousDependencyHash = myPomHashMap.getDependencyHash(pomFile);
|
||||
if (null == previousDependencyHash) return true;
|
||||
if (previousDependencyHash.equals(newDependencyHash)) return false;
|
||||
return true;
|
||||
return previousDependencyHash == null || !previousDependencyHash.equals(newDependencyHash);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -30,8 +30,6 @@ import org.jetbrains.idea.maven.server.MavenServerGlobals;
|
||||
import org.jetbrains.idea.maven.server.PomHashMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -159,7 +157,7 @@ public class Maven40ProjectResolver {
|
||||
}
|
||||
|
||||
String newDependencyHash = fileToNewDependencyHash.get(pomFile);
|
||||
if (!dependenciesChanged(pomFile, newDependencyHash, fileToNewDependencyHash)) {
|
||||
if (!transitiveDependenciesChanged(pomFile, newDependencyHash, fileToNewDependencyHash)) {
|
||||
executionResults.add(createExecutionResult(project, newDependencyHash));
|
||||
continue;
|
||||
}
|
||||
@@ -196,11 +194,17 @@ public class Maven40ProjectResolver {
|
||||
return executionResults;
|
||||
}
|
||||
|
||||
private boolean dependenciesChanged(@NotNull File pomFile, String newDependencyHash, Map<File, String> fileToNewDependencyHash) {
|
||||
private boolean transitiveDependenciesChanged(@NotNull File pomFile, String newDependencyHash, Map<File, String> fileToNewDependencyHash) {
|
||||
if (dependenciesChanged(pomFile, newDependencyHash)) return true;
|
||||
for (File dependencyPomFile : myPomHashMap.getFileDependencies(pomFile)) {
|
||||
if (dependenciesChanged(dependencyPomFile, fileToNewDependencyHash.get(dependencyPomFile))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean dependenciesChanged(@NotNull File pomFile, String newDependencyHash) {
|
||||
String previousDependencyHash = myPomHashMap.getDependencyHash(pomFile);
|
||||
if (null == previousDependencyHash) return true;
|
||||
if (previousDependencyHash.equals(newDependencyHash)) return false;
|
||||
return true;
|
||||
return previousDependencyHash == null || !previousDependencyHash.equals(newDependencyHash);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.idea.maven.server.*
|
||||
import org.jetbrains.idea.maven.telemetry.tracer
|
||||
import org.jetbrains.idea.maven.utils.MavenLog
|
||||
import org.jetbrains.idea.maven.utils.MavenUtil
|
||||
import java.io.File
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
@@ -82,7 +83,7 @@ class MavenProjectResolver(private val myProject: Project) {
|
||||
eventHandler: MavenEventHandler): MavenProjectResolutionResult {
|
||||
val updateSnapshots = MavenProjectsManager.getInstance(myProject).forceUpdateSnapshots || generalSettings.isAlwaysUpdateSnapshots
|
||||
val projectsWithUnresolvedPlugins = HashMap<String, Collection<MavenProject>>()
|
||||
val fileToDependencyHash = tree.projects.associate { it.file to if (incrementally) it.dependencyHash else null }
|
||||
val pomToDependencyHash = tree.projects.associate { it.file to if (incrementally) it.dependencyHash else null }
|
||||
val projectMultiMap = MavenUtil.groupByBasedir(mavenProjects, tree)
|
||||
for ((baseDir, mavenProjectsInBaseDir) in projectMultiMap.entrySet()) {
|
||||
val embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE, baseDir)
|
||||
@@ -96,7 +97,7 @@ class MavenProjectResolver(private val myProject: Project) {
|
||||
}
|
||||
val projectsWithUnresolvedPluginsChunk = withContext(tracer.span("doResolve $baseDir")) {
|
||||
doResolve(
|
||||
fileToDependencyHash,
|
||||
pomToDependencyHash,
|
||||
mavenProjectsInBaseDir,
|
||||
tree,
|
||||
generalSettings,
|
||||
@@ -132,13 +133,13 @@ class MavenProjectResolver(private val myProject: Project) {
|
||||
MavenUtil.restartConfigHighlighting(mavenProjects)
|
||||
|
||||
if (incrementally && updateSnapshots) {
|
||||
updateSnapshotsAfterIncrementalSync(tree, fileToDependencyHash, embeddersManager, progressReporter, eventHandler)
|
||||
updateSnapshotsAfterIncrementalSync(tree, pomToDependencyHash, embeddersManager, progressReporter, eventHandler)
|
||||
}
|
||||
return MavenProjectResolutionResult(projectsWithUnresolvedPlugins)
|
||||
}
|
||||
|
||||
private suspend fun doResolve(
|
||||
fileToDependencyHash: Map<VirtualFile, String?>,
|
||||
pomToDependencyHash: Map<VirtualFile, String?>,
|
||||
mavenProjects: Collection<MavenProject>,
|
||||
tree: MavenProjectsTree,
|
||||
generalSettings: MavenGeneralSettings,
|
||||
@@ -156,9 +157,14 @@ class MavenProjectResolver(private val myProject: Project) {
|
||||
val text = StringUtil.shortenPathWithEllipsis(StringUtil.join(names, ", "), 200)
|
||||
progressReporter.text(MavenProjectBundle.message("maven.resolving.pom", text))
|
||||
val explicitProfiles = tree.explicitProfiles
|
||||
val projects = tree.projects
|
||||
val pomDependencies = projects
|
||||
.associate { it.file to it.dependencies.filter { it.file.path.endsWith(MavenConstants.POM_XML) }.map { it.file }.toSet() }
|
||||
.filterValues { it.isNotEmpty() }
|
||||
val resultsAndProblems = resolveProjectsInEmbedder(
|
||||
embedder,
|
||||
fileToDependencyHash,
|
||||
pomToDependencyHash,
|
||||
pomDependencies,
|
||||
explicitProfiles,
|
||||
progressReporter,
|
||||
eventHandler,
|
||||
@@ -309,21 +315,25 @@ class MavenProjectResolver(private val myProject: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun resolveProjectsInEmbedder(embedder: MavenEmbedderWrapper,
|
||||
fileToDependencyHash: Map<VirtualFile, String?>,
|
||||
explicitProfiles: MavenExplicitProfiles,
|
||||
progressReporter: RawProgressReporter,
|
||||
eventHandler: MavenEventHandler,
|
||||
workspaceMap: MavenWorkspaceMap?,
|
||||
updateSnapshots: Boolean,
|
||||
userProperties: Properties): Pair<Collection<MavenProjectResolverResult>, Collection<MavenProjectProblem>> {
|
||||
val files = fileToDependencyHash.keys
|
||||
private suspend fun resolveProjectsInEmbedder(
|
||||
embedder: MavenEmbedderWrapper,
|
||||
pomToDependencyHash: Map<VirtualFile, String?>,
|
||||
pomDependencies: Map<VirtualFile, Set<File>>,
|
||||
explicitProfiles: MavenExplicitProfiles,
|
||||
progressReporter: RawProgressReporter,
|
||||
eventHandler: MavenEventHandler,
|
||||
workspaceMap: MavenWorkspaceMap?,
|
||||
updateSnapshots: Boolean,
|
||||
userProperties: Properties
|
||||
): Pair<Collection<MavenProjectResolverResult>, Collection<MavenProjectProblem>> {
|
||||
val files = pomToDependencyHash.keys
|
||||
val resolverResults: MutableCollection<MavenProjectResolverResult> = ArrayList()
|
||||
val readingProblems = mutableListOf<MavenProjectProblem>()
|
||||
try {
|
||||
val executionResults = withContext(tracer.span("embedder.resolveProject")) {
|
||||
embedder.resolveProject(
|
||||
fileToDependencyHash,
|
||||
pomToDependencyHash,
|
||||
pomDependencies,
|
||||
explicitProfiles,
|
||||
progressReporter,
|
||||
eventHandler,
|
||||
@@ -456,6 +466,7 @@ class MavenProjectResolver(private val myProject: Project) {
|
||||
resolveProjectsInEmbedder(
|
||||
embedder,
|
||||
files.associateWith { null },
|
||||
mapOf(),
|
||||
explicitProfiles,
|
||||
object : RawProgressReporter {},
|
||||
MavenLogEventHandler,
|
||||
|
||||
@@ -53,23 +53,32 @@ abstract class MavenEmbedderWrapper internal constructor(private val project: Pr
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun resolveProject(fileToDependencyHash: Map<VirtualFile, String?>,
|
||||
explicitProfiles: MavenExplicitProfiles,
|
||||
progressReporter: RawProgressReporter,
|
||||
eventHandler: MavenEventHandler,
|
||||
workspaceMap: MavenWorkspaceMap?,
|
||||
updateSnapshots: Boolean,
|
||||
userProperties: Properties): Collection<MavenServerExecutionResult> {
|
||||
val transformer = if (fileToDependencyHash.isEmpty()) RemotePathTransformerFactory.Transformer.ID
|
||||
suspend fun resolveProject(
|
||||
pomToDependencyHash: Map<VirtualFile, String?>,
|
||||
pomDependencies: Map<VirtualFile, Set<File>>,
|
||||
explicitProfiles: MavenExplicitProfiles,
|
||||
progressReporter: RawProgressReporter,
|
||||
eventHandler: MavenEventHandler,
|
||||
workspaceMap: MavenWorkspaceMap?,
|
||||
updateSnapshots: Boolean,
|
||||
userProperties: Properties,
|
||||
): Collection<MavenServerExecutionResult> {
|
||||
val transformer = if (pomToDependencyHash.isEmpty()) RemotePathTransformerFactory.Transformer.ID
|
||||
else RemotePathTransformerFactory.createForProject(project)
|
||||
|
||||
val pomHashMap = PomHashMap()
|
||||
fileToDependencyHash.mapNotNull { (file, checkSum) ->
|
||||
pomToDependencyHash.mapNotNull { (file, checkSum) ->
|
||||
transformer.toRemotePath(file.getPath())?.let {
|
||||
pomHashMap.put(File(it), checkSum)
|
||||
}
|
||||
}
|
||||
|
||||
pomDependencies.map { (file, dependencies) ->
|
||||
transformer.toRemotePath(file.getPath())?.let {
|
||||
pomHashMap.addFileDependencies(File(it), dependencies.mapNotNull { transformer.toRemotePath(it.path) }.map { File(it) })
|
||||
}
|
||||
}
|
||||
|
||||
val serverWorkspaceMap = convertWorkspaceMap(workspaceMap)
|
||||
|
||||
val request = ProjectResolutionRequest(
|
||||
|
||||
@@ -70,6 +70,7 @@ class MavenConnectorApiTest : MavenMultiVersionImportingTestCase() {
|
||||
map.register(MavenId("test:m2:1"), m2.toNioPath().toFile())
|
||||
map.register(MavenId("test:project:1"), project.toNioPath().toFile())
|
||||
val executionResults = embedder.resolveProject(mapOf(project to null, m1 to null, m2 to null),
|
||||
mapOf(),
|
||||
MavenExplicitProfiles(listOf("test"), emptyList()),
|
||||
MockReporter(),
|
||||
MavenLogEventHandler,
|
||||
|
||||
@@ -32,7 +32,7 @@ class MavenProjectsManagerAutoImportTest : MavenMultiVersionImportingTestCase()
|
||||
fun testResolvingEnvVariableInRepositoryPath() = runBlocking {
|
||||
val temp = System.getenv(envVar)
|
||||
waitForImportWithinTimeout {
|
||||
updateSettingsXml("<localRepository>\${env." + envVar + "}/tmpRepo</localRepository>")
|
||||
updateSettingsXml("<localRepository>\${env.$envVar}/tmpRepo</localRepository>")
|
||||
}
|
||||
val repo = File("$temp/tmpRepo").getCanonicalFile()
|
||||
assertEquals(repo.path, mavenGeneralSettings.getEffectiveLocalRepository().path)
|
||||
@@ -444,10 +444,7 @@ class MavenProjectsManagerAutoImportTest : MavenMultiVersionImportingTestCase()
|
||||
scheduleProjectImportAndWait()
|
||||
assertModuleModuleDeps("m1", "m2")
|
||||
|
||||
// relying on transitive dependencies is not a good practice
|
||||
// transitive dependency updating is not fully supported by incremental sync
|
||||
// run full sync to pick up transitive dependency
|
||||
updateAllProjectsFullSync()
|
||||
updateAllProjects()
|
||||
assertModuleLibDeps("m1", "Maven: junit:junit:4.0")
|
||||
}
|
||||
|
||||
@@ -533,10 +530,7 @@ class MavenProjectsManagerAutoImportTest : MavenMultiVersionImportingTestCase()
|
||||
assertModules("project", "m1")
|
||||
assertModuleModuleDeps("m1")
|
||||
|
||||
// relying on transitive dependencies is not a good practice
|
||||
// transitive dependency updating is not fully supported by incremental sync
|
||||
// run full sync to pick up transitive dependency changes
|
||||
updateAllProjectsFullSync()
|
||||
updateAllProjects()
|
||||
assertModuleLibDeps("m1", "Maven: test:m2:1")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user