Add new script dependency resolvers
Changes in new API for dependency resolvers (GenericDependenciesResolver) comparing to an old one (GenericResolver: - Add ability to fast check whether artifact or repository is suitable for current resolver to distinguish between unsuitable resolvers and resolution failures - Return all artifact resolution failures in ResultWithDiagnostics - Use single string for artifact coordinates - Add compound resolver that combines several resolvers - Merge Direct and FlatLib resolver into single FileSystemDependencyResolver - Mark resolve() method as suspend to indicate long operation - Add credentials support for maven resolver (https://youtrack.jetbrains.com/issue/KT-27701)
This commit is contained in:
committed by
Ilya Chernikov
parent
81e2e119e2
commit
c7e9a6c5d9
@@ -0,0 +1,32 @@
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
jvmTarget = "1.6"
|
||||
|
||||
dependencies {
|
||||
compile(kotlinStdlib())
|
||||
compile(project(":kotlin-scripting-dependencies"))
|
||||
compile("org.jetbrains.kotlin:jcabi-aether:1.0-dev-3")
|
||||
compile("org.sonatype.aether:aether-api:1.13.1")
|
||||
testCompile("org.apache.maven:maven-settings-builder:3.0.5")
|
||||
testCompile(projectTests(":kotlin-scripting-dependencies"))
|
||||
testCompile(commonDep("junit"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
|
||||
kotlinOptions.freeCompilerArgs += "-Xallow-kotlin-package"
|
||||
}
|
||||
|
||||
publish()
|
||||
|
||||
runtimeJar()
|
||||
sourcesJar()
|
||||
javadocJar()
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
import com.jcabi.aether.Aether
|
||||
import org.sonatype.aether.repository.Authentication
|
||||
import org.sonatype.aether.repository.RemoteRepository
|
||||
import org.sonatype.aether.resolution.DependencyResolutionException
|
||||
import org.sonatype.aether.util.artifact.DefaultArtifact
|
||||
import org.sonatype.aether.util.artifact.JavaScopes
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||
import kotlin.script.experimental.dependencies.ExternalDependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.RepositoryCoordinates
|
||||
import kotlin.script.experimental.dependencies.impl.makeResolveFailureResult
|
||||
import kotlin.script.experimental.dependencies.impl.toRepositoryUrlOrNull
|
||||
|
||||
val mavenCentral = RemoteRepository("maven-central", "default", "https://repo.maven.apache.org/maven2/")
|
||||
|
||||
class MavenRepositoryCoordinates(
|
||||
url: String,
|
||||
val username: String?,
|
||||
val password: String?,
|
||||
val privateKeyFile: String?,
|
||||
val passPhrase: String?
|
||||
) : RepositoryCoordinates(url)
|
||||
|
||||
class MavenDependenciesResolver : ExternalDependenciesResolver {
|
||||
|
||||
override fun acceptsArtifact(artifactCoordinates: String): Boolean =
|
||||
artifactCoordinates.toMavenArtifact() != null
|
||||
|
||||
override fun acceptsRepository(repositoryCoordinates: RepositoryCoordinates): Boolean {
|
||||
return repositoryCoordinates.toRepositoryUrlOrNull() != null
|
||||
}
|
||||
|
||||
// TODO: make robust
|
||||
val localRepo = File(File(System.getProperty("user.home")!!, ".m2"), "repository")
|
||||
|
||||
val repos: ArrayList<RemoteRepository> = arrayListOf()
|
||||
|
||||
private fun remoteRepositories() = if (repos.isEmpty()) arrayListOf(mavenCentral) else repos
|
||||
|
||||
private fun allRepositories() = remoteRepositories().map { it.url!!.toString() } + localRepo.toString()
|
||||
|
||||
private fun String.toMavenArtifact(): DefaultArtifact? =
|
||||
if (this.isNotBlank() && this.count { it == ':' } == 2) DefaultArtifact(this)
|
||||
else null
|
||||
|
||||
override suspend fun resolve(artifactCoordinates: String): ResultWithDiagnostics<List<File>> {
|
||||
|
||||
val artifactId = artifactCoordinates.toMavenArtifact()!!
|
||||
|
||||
try {
|
||||
val deps = Aether(remoteRepositories(), localRepo).resolve(artifactId, JavaScopes.RUNTIME)
|
||||
if (deps != null)
|
||||
return ResultWithDiagnostics.Success(deps.map { it.file })
|
||||
} catch (e: DependencyResolutionException) {
|
||||
|
||||
}
|
||||
return makeResolveFailureResult(allRepositories().map { "$it: $artifactId not found" })
|
||||
}
|
||||
|
||||
private fun tryResolveEnvironmentVariable(str: String) =
|
||||
if (str.startsWith("$")) System.getenv(str.substring(1)) ?: str
|
||||
else str
|
||||
|
||||
override fun addRepository(repositoryCoordinates: RepositoryCoordinates) {
|
||||
val url = repositoryCoordinates.toRepositoryUrlOrNull()
|
||||
?: throw IllegalArgumentException("Invalid Maven repository URL: ${repositoryCoordinates}")
|
||||
val repo = RemoteRepository(
|
||||
repositoryCoordinates.string,
|
||||
"default",
|
||||
url.toString()
|
||||
)
|
||||
if (repositoryCoordinates is MavenRepositoryCoordinates) {
|
||||
val username = repositoryCoordinates.username?.let(::tryResolveEnvironmentVariable)
|
||||
val password = repositoryCoordinates.password?.let(::tryResolveEnvironmentVariable)
|
||||
repo.authentication = Authentication(username, password, repositoryCoordinates.privateKeyFile, repositoryCoordinates.passPhrase)
|
||||
}
|
||||
repos.add(repo)
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.test
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.script.experimental.dependencies.maven.MavenDependenciesResolver
|
||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||
import kotlin.script.experimental.api.valueOrThrow
|
||||
|
||||
@ExperimentalContracts
|
||||
class MavenResolverTest : ResolversTestBase() {
|
||||
|
||||
fun testResolve() {
|
||||
val resolver = MavenDependenciesResolver()
|
||||
val result = runBlocking { resolver.resolve("org.jetbrains.kotlin:kotlin-annotations-jvm:1.3.50") }
|
||||
Assert.assertTrue(result is ResultWithDiagnostics.Success)
|
||||
val files = result.valueOrThrow()
|
||||
files.forEach { it.delete() }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user