From edacd90a6cf90a34b07353dfcc92000477212ca7 Mon Sep 17 00:00:00 2001 From: Ilya Muradyan Date: Thu, 12 May 2022 22:12:49 +0300 Subject: [PATCH] [Scripting] Take local repository path from settings if it exists --- .../maven/MavenDependenciesResolver.kt | 5 +- .../dependencies/maven/impl/aether.kt | 61 ++---------- .../dependencies/maven/impl/mavenSettings.kt | 96 +++++++++++++++++++ .../experimental/test/MavenResolverTest.kt | 6 ++ 4 files changed, 110 insertions(+), 58 deletions(-) create mode 100644 libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/mavenSettings.kt diff --git a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt index f7e52326c1e..cd38491d10f 100644 --- a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt +++ b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt @@ -40,9 +40,6 @@ class MavenDependenciesResolver : ExternalDependenciesResolver { return repositoryCoordinates.toRepositoryUrlOrNull() != null } - // TODO: make robust - val localRepo = File(File(System.getProperty("user.home")!!, ".m2"), "repository") - val repos: ArrayList = arrayListOf() private fun remoteRepositories() = if (repos.isEmpty()) arrayListOf(mavenCentral) else repos @@ -65,7 +62,7 @@ class MavenDependenciesResolver : ExternalDependenciesResolver { val classifier = options.classifier val extension = options.extension val deps = AetherResolveSession( - localRepo, remoteRepositories() + null, remoteRepositories() ).resolve( artifactId, dependencyScopes.joinToString(","), transitive, null, classifier, extension ) diff --git a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/aether.kt b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/aether.kt index 7c3d7236057..6069bf7204a 100644 --- a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/aether.kt +++ b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/aether.kt @@ -5,12 +5,8 @@ package kotlin.script.experimental.dependencies.maven.impl -import org.apache.commons.io.filefilter.NameFileFilter import org.apache.maven.repository.internal.MavenRepositorySystemUtils import org.apache.maven.settings.Settings -import org.apache.maven.settings.SettingsUtils -import org.apache.maven.settings.TrackableBase -import org.apache.maven.settings.building.* import org.apache.maven.wagon.Wagon import org.codehaus.plexus.DefaultContainerConfiguration import org.codehaus.plexus.DefaultPlexusContainer @@ -43,16 +39,19 @@ import org.eclipse.aether.util.repository.AuthenticationBuilder import org.eclipse.aether.util.repository.DefaultMirrorSelector import org.eclipse.aether.util.repository.DefaultProxySelector import java.io.File -import java.io.FileFilter import java.util.* val mavenCentral: RemoteRepository = RemoteRepository.Builder("maven central", "default", "https://repo.maven.apache.org/maven2/").build() internal class AetherResolveSession( - private val localRepo: File = File(File(System.getProperty("user.home")!!, ".m2"), "repository"), + localRepoDirectory: File? = null, remoteRepos: List = listOf(mavenCentral) ) { + private val localRepoPath by lazy { + localRepoDirectory?.absolutePath ?: settings.localRepository + } + private val remotes by lazy { val proxySelector = settings.activeProxy?.let { proxy -> val selector = DefaultProxySelector() @@ -125,7 +124,7 @@ internal class AetherResolveSession( } private val repositorySystemSession: RepositorySystemSession by lazy { - val localRepo = LocalRepository(localRepo.absolutePath) + val localRepo = LocalRepository(localRepoPath) MavenRepositorySystemUtils.newSession().also { it.localRepositoryManager = repositorySystem.newLocalRepositoryManager(it, localRepo) } @@ -236,52 +235,6 @@ internal class AetherResolveSession( } private val settings: Settings by lazy { - val builder: SettingsBuilder = DefaultSettingsBuilderFactory().newInstance() - val request: SettingsBuildingRequest = DefaultSettingsBuildingRequest() - val user = System.getProperty("org.apache.maven.user-settings") - if (user == null) { - request.userSettingsFile = File( - File(System.getProperty("user.home")).absoluteFile, - "/.m2/settings.xml" - ) - } else { - request.userSettingsFile = File(user) - } - val global = System.getProperty("org.apache.maven.global-settings") - if (global != null) { - request.globalSettingsFile = File(global) - } - val result: SettingsBuildingResult = try { - builder.build(request) - } catch (ex: SettingsBuildingException) { - throw IllegalStateException(ex) - } - this.invokers(builder, result) - } - - private fun invokers( - builder: SettingsBuilder, - result: SettingsBuildingResult - ): Settings { - var main = result.effectiveSettings - val files = File(System.getProperty("user.dir")) - .parentFile?.listFiles( - NameFileFilter("interpolated-settings.xml") as FileFilter - ) - val settingsFile = files?.singleOrNull() - if (settingsFile != null) { - val irequest = - DefaultSettingsBuildingRequest() - irequest.userSettingsFile = settingsFile - main = try { - val isettings = builder.build(irequest) - .effectiveSettings - SettingsUtils.merge(isettings, main, TrackableBase.USER_LEVEL) - isettings - } catch (ex: SettingsBuildingException) { - throw java.lang.IllegalStateException(ex) - } - } - return main + createMavenSettings() } } \ No newline at end of file diff --git a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/mavenSettings.kt b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/mavenSettings.kt new file mode 100644 index 00000000000..0860cbfd426 --- /dev/null +++ b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/impl/mavenSettings.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.script.experimental.dependencies.maven.impl + +import org.apache.commons.io.filefilter.NameFileFilter +import org.apache.maven.settings.DefaultMavenSettingsBuilder +import org.apache.maven.settings.Settings +import org.apache.maven.settings.SettingsUtils +import org.apache.maven.settings.TrackableBase +import org.apache.maven.settings.building.* +import java.io.File +import java.io.FileFilter + +fun createMavenSettings(): Settings { + val builder: SettingsBuilder = DefaultSettingsBuilderFactory().newInstance() + val request: SettingsBuildingRequest = DefaultSettingsBuildingRequest() + val user = System.getProperty("org.apache.maven.user-settings") + if (user == null) { + request.userSettingsFile = File( + File(System.getProperty("user.home")).absoluteFile, + ".m2/settings.xml" + ) + } else { + request.userSettingsFile = File(user) + } + val global = System.getProperty("org.apache.maven.global-settings") + if (global != null) { + request.globalSettingsFile = File(global) + } + val result: SettingsBuildingResult = try { + builder.build(request) + } catch (ex: SettingsBuildingException) { + throw IllegalStateException(ex) + } + return invokers(builder, result) +} + +private fun invokers( + builder: SettingsBuilder, + result: SettingsBuildingResult +): Settings { + var main = result.effectiveSettings + val files = File(System.getProperty("user.dir")) + .parentFile?.listFiles( + NameFileFilter("interpolated-settings.xml") as FileFilter + ) + val settingsFile = files?.singleOrNull() + if (settingsFile != null) { + val irequest = + DefaultSettingsBuildingRequest() + irequest.userSettingsFile = settingsFile + main = try { + val isettings = builder.build(irequest) + .effectiveSettings + SettingsUtils.merge(isettings, main, TrackableBase.USER_LEVEL) + isettings + } catch (ex: SettingsBuildingException) { + throw java.lang.IllegalStateException(ex) + } + } + + main.localRepository = getFilePath(main.localRepository ?: "\${user.home}/.m2/repository") + + return main +} + +/** + * Get file path from a string pattern + * + * Implementation is mostly copied from [DefaultMavenSettingsBuilder.getFile] + */ +private fun getFilePath(filePattern: String): String { + return substitutePropertiesValues(filePattern) { propertyValue -> + propertyValue + .replace('\\', '/') + .replace("$", "\\$") + }.replace('\\', '/') +} + +/** + * This pattern is built in [DefaultMavenSettingsBuilder.getFile] only for + * one property (basedirSysProp). We allow any system variable name here. + */ +private val systemPropertyPattern = Regex("\\$\\{([^{}\$]+)}") + +private fun substitutePropertiesValues(pattern: String, propValueMapper: (String) -> String = { it }): String { + return systemPropertyPattern + .replace(pattern) { match -> + val propName = match.groups[1]?.value.orEmpty().trim() + val propValue: String? = System.getProperty(propName) + propValueMapper(propValue.orEmpty()) + } +} \ No newline at end of file diff --git a/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt b/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt index dceea989107..01c6546d973 100644 --- a/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt +++ b/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt @@ -21,6 +21,7 @@ import kotlin.script.experimental.dependencies.impl.SimpleExternalDependenciesRe import kotlin.script.experimental.dependencies.impl.makeExternalDependenciesResolverOptions import kotlin.script.experimental.dependencies.impl.set import kotlin.script.experimental.dependencies.maven.MavenDependenciesResolver +import kotlin.script.experimental.dependencies.maven.impl.createMavenSettings @ExperimentalContracts class MavenResolverTest : ResolversTestBase() { @@ -55,6 +56,11 @@ class MavenResolverTest : ResolversTestBase() { private val resolvedKotlinVersion = "1.5.31" + fun testDefaultSettings() { + val settings = createMavenSettings() + assertNotNull(settings.localRepository) + } + fun testResolveSimple() { resolveAndCheck("org.jetbrains.kotlin:kotlin-annotations-jvm:$resolvedKotlinVersion") { files -> files.any { it.name.startsWith("kotlin-annotations-jvm") }