Update MAVEN_REPOSITORY resolution logic in build system

Introduce support for resolving Maven repository path from MAVEN_OPTS or settings.xml. Fallback logic ensures a default path is used if custom configurations are absent or invalid.

GitOrigin-RevId: 98d2232b439ea7a05fad626380f26ad4fbd63ac8
This commit is contained in:
Dmitry.Yudin
2025-01-20 11:22:36 +01:00
committed by intellij-monorepo-bot
parent 2a608255e2
commit 538072da09
4 changed files with 79 additions and 7 deletions

View File

@@ -0,0 +1,69 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.intellij.build
import com.intellij.openapi.util.JDOMUtil
import com.intellij.util.EnvironmentUtil
import com.intellij.util.SystemProperties
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
import org.jdom.Element
import org.jetbrains.jps.model.serialization.JpsMavenSettings
import java.io.File
import java.nio.file.Path
/**
* [https://maven.apache.org/configure.html](https://maven.apache.org/configure.html)
*/
private const val MAVEN_OPTS = "MAVEN_OPTS"
/**
* [https://maven.apache.org/ref/4.0.0-rc-1/api/maven-api-core/apidocs/constant-values.html](https://maven.apache.org/ref/4.0.0-rc-1/api/maven-api-core/apidocs/constant-values.html#org.apache.maven.api.Constants.MAVEN_REPO_LOCAL)
*/
private const val MAVEN_REPO_LOCAL: String = "maven.repo.local"
/**
* Determines the Maven repository path by checking several locations:
* 1. MAVEN_OPTS environment variable with maven.repo.local parameter
* 2. localRepository settings in ~/.m2/settings.xml
* 3. Default location at ~/.m2/repository
*
* @param span Optional span for tracing/logging repository location details
* @return Path to the Maven repository
*/
internal fun getMavenRepositoryPath(span: Span? = null): Path {
val settingsFile = JpsMavenSettings.getUserMavenSettingsXml().takeIf { it.exists() }
?: JpsMavenSettings.getGlobalMavenSettingsXml().takeIf { it?.exists() == true }
val attributeKey = AttributeKey.stringKey("local maven repository path")
return findMavenRepositoryProperty(EnvironmentUtil.getValue(MAVEN_OPTS))?.trim()
?.let {
span?.addEvent("Found MAVEN_OPTS system env", Attributes.of(attributeKey, it))
Path.of(it)
}
?: settingsFile?.getRepositoryFromSettings()
?.let {
span?.addEvent("Found localRepository param in .m2/settings.xml file", Attributes.of(attributeKey, it))
Path.of(it)
}
?: Path.of(SystemProperties.getUserHome(), ".m2/repository")
}
private fun findMavenRepositoryProperty(mavenOpts: String?): String? {
mavenOpts ?: return null
// -Dmaven.repo.local=/path/to/repo -> [1]:"maven.repo.local" [2]:"" [3]:"/path/to/repo"
// -Dmaven.repo.local="/my custom/path" -> [1]:"maven.repo.local" [2]:"/my custom/path" [3]:""
val propertyRegex = Regex("""-D([^=\s]+)(?:=(?:"([^"]+)"|(\S+)))?""")
val properties = propertyRegex
.findAll(mavenOpts)
.associate { property -> property.groupValues[1] to (property.groupValues[2].takeIf { it.isNotBlank() } ?: property.groupValues[3]) }
return properties[MAVEN_REPO_LOCAL]
}
private fun File.getRepositoryFromSettings(): String? {
val element = runCatching { JDOMUtil.load(this) }.getOrNull()
return element?.content?.firstOrNull { (it as? Element)?.name == "localRepository" }?.value
}

View File

@@ -14,7 +14,7 @@ const val UTIL_8_JAR: String = "util-8.jar"
internal val isWindows: Boolean = System.getProperty("os.name").startsWith("windows", ignoreCase = true)
private val USER_HOME = Path.of(System.getProperty("user.home"))
internal val MAVEN_REPO: Path = USER_HOME.resolve(".m2/repository")
internal val MAVEN_REPO: Path = getMavenRepositoryPath()
sealed interface Source {
val filter: ((String) -> Boolean)?

View File

@@ -25,6 +25,7 @@ import org.jetbrains.intellij.build.CompilationContext
import org.jetbrains.intellij.build.JpsCompilationData
import org.jetbrains.intellij.build.dependencies.DependenciesProperties
import org.jetbrains.intellij.build.dependencies.JdkDownloader
import org.jetbrains.intellij.build.getMavenRepositoryPath
import org.jetbrains.intellij.build.impl.JdkUtils.defineJdk
import org.jetbrains.intellij.build.impl.JdkUtils.readModulesFromReleaseFile
import org.jetbrains.intellij.build.impl.compilation.checkCompilationOptions
@@ -67,6 +68,7 @@ import java.nio.file.NoSuchFileException
import java.nio.file.Path
import java.nio.file.attribute.BasicFileAttributes
import kotlin.io.path.invariantSeparatorsPathString
import kotlin.io.path.pathString
import kotlin.io.path.relativeToOrNull
@Obsolete
@@ -416,7 +418,9 @@ private suspend fun loadProject(projectHome: Path, kotlinBinaries: KotlinBinarie
}
spanBuilder("load project").use(Dispatchers.IO) { span ->
pathVariablesConfiguration.addPathVariable("MAVEN_REPOSITORY", Path.of(System.getProperty("user.home"), ".m2/repository").invariantSeparatorsPathString)
val mavenRepositoryPath = getMavenRepositoryPath(span)
pathVariablesConfiguration.addPathVariable("MAVEN_REPOSITORY", mavenRepositoryPath.pathString)
val pathVariables = JpsModelSerializationDataService.computeAllPathVariables(model.global)
loadProject(model.project, pathVariables, JpsPathMapper.IDENTITY, projectHome, null, { it: Runnable -> launch(CoroutineName("loading project")) { it.run() } }, false)
span.setAllAttributes(
@@ -628,4 +632,4 @@ suspend fun CompilationContext.getModuleOutputFileContent(module: JpsModule, rel
else {
throw IllegalStateException("Module '${module.name}' output is neither directory, nor jar $output")
}
}
}

View File

@@ -158,7 +158,7 @@ private suspend fun downloadMissingLibrarySources(librariesWithMissingSources: L
val configuration = JpsRemoteRepositoryService.getInstance().getRemoteRepositoriesConfiguration(context.project)
val repositories = configuration?.repositories?.map { ArtifactRepositoryManager.createRemoteRepository(it.id, it.url) } ?: emptyList()
val repositoryManager = ArtifactRepositoryManager(
getLocalArtifactRepositoryRoot(context.projectModel.global).toFile(), repositories,
getLocalArtifactRepositoryRoot(context.projectModel.global, span).toFile(), repositories,
ProgressConsumer.DEAF
)
for (library in librariesWithMissingSources) {
@@ -184,11 +184,10 @@ private suspend fun downloadMissingLibrarySources(librariesWithMissingSources: L
}
}
private fun getLocalArtifactRepositoryRoot(global: JpsGlobal): Path {
private fun getLocalArtifactRepositoryRoot(global: JpsGlobal, span: Span): Path {
JpsModelSerializationDataService.getPathVariablesConfiguration(global)!!.getUserVariableValue("MAVEN_REPOSITORY")?.let {
return Path.of(it)
}
val root = System.getProperty("user.home", null)
return if (root == null) Path.of(".m2/repository") else Path.of(root, ".m2/repository")
return getMavenRepositoryPath(span)
}