[Scripting] Add transitive support for Maven Resolver
This commit is contained in:
+5
-8
@@ -49,8 +49,6 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
|
||||
|
||||
private fun remoteRepositories() = if (repos.isEmpty()) arrayListOf(mavenCentral) else repos
|
||||
|
||||
private fun allRepositories() = remoteRepositories() + localRepo
|
||||
|
||||
private fun String.toMavenArtifact(): DefaultArtifact? =
|
||||
if (this.isNotBlank() && this.count { it == ':' } >= 2) DefaultArtifact(this)
|
||||
else null
|
||||
@@ -63,19 +61,18 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
|
||||
|
||||
val artifactId = artifactCoordinates.toMavenArtifact()!!
|
||||
|
||||
try {
|
||||
return try {
|
||||
val dependencyScopes = options.dependencyScopes ?: listOf(JavaScopes.COMPILE, JavaScopes.RUNTIME)
|
||||
val transitive = options.transitive ?: true
|
||||
val deps = AetherResolveSession(
|
||||
localRepo, remoteRepositories()
|
||||
).resolve(
|
||||
artifactId, dependencyScopes.joinToString(",")
|
||||
artifactId, dependencyScopes.joinToString(","), transitive, null
|
||||
)
|
||||
if (deps != null)
|
||||
return ResultWithDiagnostics.Success(deps.map { it.file })
|
||||
ResultWithDiagnostics.Success(deps.map { it.file })
|
||||
} catch (e: DependencyResolutionException) {
|
||||
return makeResolveFailureResult(e.message ?: "unknown error", sourceCodeLocation)
|
||||
makeResolveFailureResult(e.message ?: "unknown error", sourceCodeLocation)
|
||||
}
|
||||
return makeResolveFailureResult(allRepositories().map { "$it: $artifactId not found" }, sourceCodeLocation)
|
||||
}
|
||||
|
||||
private fun tryResolveEnvironmentVariable(str: String) =
|
||||
|
||||
+46
-26
@@ -25,10 +25,7 @@ import org.eclipse.aether.internal.transport.wagon.PlexusWagonProvider
|
||||
import org.eclipse.aether.repository.LocalRepository
|
||||
import org.eclipse.aether.repository.Proxy
|
||||
import org.eclipse.aether.repository.RemoteRepository
|
||||
import org.eclipse.aether.resolution.ArtifactResult
|
||||
import org.eclipse.aether.resolution.DependencyRequest
|
||||
import org.eclipse.aether.resolution.DependencyResolutionException
|
||||
import org.eclipse.aether.resolution.DependencyResult
|
||||
import org.eclipse.aether.resolution.*
|
||||
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory
|
||||
import org.eclipse.aether.spi.connector.transport.TransporterFactory
|
||||
import org.eclipse.aether.transport.file.FileTransporterFactory
|
||||
@@ -123,22 +120,54 @@ class AetherResolveSession(
|
||||
}
|
||||
}
|
||||
|
||||
fun resolve(coordinates: String, scope: String, filter: DependencyFilter? = null): List<Artifact>? =
|
||||
fun resolve(coordinates: String, scope: String, filter: DependencyFilter? = null): List<Artifact> =
|
||||
resolve(DefaultArtifact(coordinates), scope, filter)
|
||||
|
||||
fun resolve(root: Artifact, scope: String, filter: DependencyFilter? = null): List<Artifact>? {
|
||||
fun resolve(root: Artifact, scope: String, transitive: Boolean, filter: DependencyFilter?): List<Artifact> {
|
||||
return if (transitive) resolve(root, scope, filter)
|
||||
else resolveArtifact(root)
|
||||
}
|
||||
|
||||
fun resolve(root: Artifact, scope: String, filter: DependencyFilter? = null): List<Artifact> {
|
||||
return fetch(
|
||||
repositorySystem,
|
||||
repositorySystemSession,
|
||||
DependencyRequest(
|
||||
request(Dependency(root, scope)),
|
||||
filter ?: DependencyFilterUtils.classpathFilter(scope)
|
||||
)
|
||||
),
|
||||
{ req -> repositorySystem.resolveDependencies(repositorySystemSession, req).artifactResults },
|
||||
{ req, ex ->
|
||||
DependencyResolutionException(
|
||||
DependencyResult(req),
|
||||
IllegalArgumentException( //Logger.format(
|
||||
// "failed to load '%s' from %[list]s into %s",
|
||||
// req.getCollectRequest().getRoot(),
|
||||
// Aether.reps(req.getCollectRequest().getRepositories()),
|
||||
// session.getLocalRepositoryManager()
|
||||
// .getRepository()
|
||||
// .getBasedir()
|
||||
//),
|
||||
ex
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun request(root: Dependency): CollectRequest? {
|
||||
private fun resolveArtifact(artifact: Artifact): List<Artifact> {
|
||||
val request = ArtifactRequest()
|
||||
request.artifact = artifact
|
||||
for (repo in remotes) {
|
||||
request.addRepository(repo)
|
||||
}
|
||||
|
||||
return fetch(
|
||||
request,
|
||||
{ req -> listOf(repositorySystem.resolveArtifact(repositorySystemSession, req)) },
|
||||
{ req, ex -> ArtifactResolutionException(listOf(ArtifactResult(req)), ex.message, IllegalArgumentException(ex)) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun request(root: Dependency): CollectRequest {
|
||||
val request = CollectRequest()
|
||||
request.root = root
|
||||
for (repo in remotes) {
|
||||
@@ -147,32 +176,23 @@ class AetherResolveSession(
|
||||
return request
|
||||
}
|
||||
|
||||
private fun fetch(system: RepositorySystem, session: RepositorySystemSession, dreq: DependencyRequest): List<Artifact>? {
|
||||
private fun <RequestT> fetch(
|
||||
request: RequestT,
|
||||
fetchBody: (RequestT) -> Collection<ArtifactResult>,
|
||||
wrapException: (RequestT, Exception) -> Exception
|
||||
): List<Artifact> {
|
||||
val deps: MutableList<Artifact> = LinkedList()
|
||||
try {
|
||||
var results: Collection<ArtifactResult>
|
||||
synchronized(this) {
|
||||
results = system.resolveDependencies(session, dreq)
|
||||
.artifactResults
|
||||
results = fetchBody(request)
|
||||
}
|
||||
for (res in results) {
|
||||
deps.add(res.artifact)
|
||||
}
|
||||
// @checkstyle IllegalCatch (1 line)
|
||||
} catch (ex: Exception) {
|
||||
throw DependencyResolutionException(
|
||||
DependencyResult(dreq),
|
||||
IllegalArgumentException( //Logger.format(
|
||||
// "failed to load '%s' from %[list]s into %s",
|
||||
// dreq.getCollectRequest().getRoot(),
|
||||
// Aether.reps(dreq.getCollectRequest().getRepositories()),
|
||||
// session.getLocalRepositoryManager()
|
||||
// .getRepository()
|
||||
// .getBasedir()
|
||||
//),
|
||||
ex
|
||||
)
|
||||
)
|
||||
throw wrapException(request, ex)
|
||||
}
|
||||
return deps
|
||||
}
|
||||
|
||||
+31
@@ -10,12 +10,15 @@ import org.junit.Assert
|
||||
import org.junit.Ignore
|
||||
import java.io.File
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
import kotlin.script.experimental.dependencies.maven.MavenDependenciesResolver
|
||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||
import kotlin.script.experimental.api.valueOrThrow
|
||||
import kotlin.script.experimental.dependencies.*
|
||||
import kotlin.script.experimental.dependencies.impl.DependenciesResolverOptionsName
|
||||
import kotlin.script.experimental.dependencies.impl.SimpleExternalDependenciesResolverOptionsParser
|
||||
import kotlin.script.experimental.dependencies.impl.makeExternalDependenciesResolverOptions
|
||||
import kotlin.script.experimental.dependencies.impl.set
|
||||
|
||||
@@ -27,6 +30,9 @@ class MavenResolverTest : ResolversTestBase() {
|
||||
options: ExternalDependenciesResolver.Options = ExternalDependenciesResolver.Options.Empty,
|
||||
checkBody: (Iterable<File>) -> Boolean = { true }
|
||||
) {
|
||||
contract {
|
||||
callsInPlace(checkBody, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val resolver = MavenDependenciesResolver()
|
||||
val result = runBlocking { resolver.resolve(coordinates, options) }
|
||||
if (result is ResultWithDiagnostics.Failure) {
|
||||
@@ -74,6 +80,31 @@ class MavenResolverTest : ResolversTestBase() {
|
||||
)
|
||||
}
|
||||
|
||||
fun testTransitiveOption() {
|
||||
val dependency = "junit:junit:4.11"
|
||||
|
||||
var transitiveFiles: Iterable<File>
|
||||
fun parseOptions(options: String) = SimpleExternalDependenciesResolverOptionsParser(options).valueOrThrow()
|
||||
|
||||
resolveAndCheck(dependency, options = parseOptions("transitive=true")) { files ->
|
||||
transitiveFiles = files
|
||||
true
|
||||
}
|
||||
|
||||
var nonTransitiveFiles: Iterable<File>
|
||||
resolveAndCheck(dependency, options = parseOptions("transitive=false")) { files ->
|
||||
nonTransitiveFiles = files
|
||||
true
|
||||
}
|
||||
|
||||
val tCount = transitiveFiles.count()
|
||||
val ntCount = nonTransitiveFiles.count()
|
||||
val artifact = nonTransitiveFiles.single()
|
||||
|
||||
assertTrue(ntCount < tCount)
|
||||
assertEquals("jar", artifact.extension)
|
||||
}
|
||||
|
||||
fun testResolveVersionsRange() {
|
||||
resolveAndCheck("org.jetbrains.kotlin:kotlin-annotations-jvm:(1.3.40,1.3.60)")
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ private val equalsRegex = Regex("^[^\\S\\r\\n]*=")
|
||||
* And additionally supports flags without any equality statement:
|
||||
* `foo bar`
|
||||
*/
|
||||
internal object SimpleExternalDependenciesResolverOptionsParser {
|
||||
object SimpleExternalDependenciesResolverOptionsParser {
|
||||
private sealed class Token {
|
||||
data class Name(val name: String) : Token()
|
||||
data class Value(val value: String) : Token()
|
||||
|
||||
Reference in New Issue
Block a user