Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fix for #217 #237

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
package org.javacs.kt.classpath

import org.javacs.kt.LOG
import org.javacs.kt.util.findCommandOnPath
import org.javacs.kt.util.execAndReadStdoutAndStderr
import java.nio.file.Path
import java.nio.file.Files
import org.javacs.kt.util.findCommandOnPath
import java.io.File
import java.nio.file.Files
import java.nio.file.Path

/** Resolver for reading maven dependencies */
internal class MavenClassPathResolver private constructor(private val pom: Path) : ClassPathResolver {
override val resolverType: String = "Maven"
override val classpath: Set<Path> get() {
val mavenOutput = generateMavenDependencyList(pom)
val artifacts = readMavenDependencyList(mavenOutput)

when {
artifacts.isEmpty() -> LOG.warn("No artifacts found in {}", pom)
artifacts.size < 5 -> LOG.info("Found {} in {}", artifacts, pom)
else -> LOG.info("Found {} artifacts in {}", artifacts.size, pom)
}
override val classpath: Set<Path>
get() {
val artifacts = generateMavenDependencySet(pom)

Files.deleteIfExists(mavenOutput)
return artifacts.mapNotNull { findMavenArtifact(it, false) }.toSet()
}
when {
artifacts.isEmpty() -> LOG.warn("No artifacts found in {}", pom)
artifacts.size < 5 -> LOG.info("Found {} in {}", artifacts, pom)
else -> LOG.info("Found {} artifacts in {}", artifacts.size, pom)
}

return artifacts.mapNotNull { findMavenArtifact(it, false) }.toSet()
}
val sourceJars: Set<Path>
get() {
val artifacts = generateMavenSourceJarSet(pom)
when {
artifacts.isEmpty() -> LOG.warn("No sources found in {}", pom)
artifacts.size < 5 -> LOG.info("Found {} sources in {}", artifacts, pom)
else -> LOG.info("Found {} sources in {}", artifacts.size, pom)
}
return artifacts.mapNotNull { findMavenArtifact(it, false) }.toSet()
}

companion object {
/** Create a maven resolver if a file is a pom. */
Expand All @@ -33,6 +42,7 @@ internal class MavenClassPathResolver private constructor(private val pom: Path)

private val artifactPattern = "^[^:]+:(?:[^:]+:)+[^:]+".toRegex()

// Can be used to read sources
private fun readMavenDependencyList(mavenOutput: Path): Set<Artifact> =
mavenOutput.toFile()
.readLines()
Expand All @@ -59,58 +69,81 @@ private fun mavenJarName(a: Artifact, source: Boolean) =
if (source) "${a.artifact}-${a.version}-sources.jar"
else "${a.artifact}-${a.version}.jar"

private fun generateMavenDependencyList(pom: Path): Path {
val mavenOutput = Files.createTempFile("deps", ".txt")
val command = "$mvnCommand dependency:list -DincludeScope=test -DoutputFile=$mavenOutput"
private fun generateMavenDependencySet(pom: Path): Set<Artifact> {
val (_, path) = runMavenCommand(pom, "dependency:list", "-DincludeScope=test")
val deps = readMavenDependencyList(path)
Files.deleteIfExists(path)
return deps
}

private fun generateMavenSourceJarSet(pom: Path): Set<Artifact> {
val (_, path) = runMavenCommand(pom, "dependency:sources", "")
val sources = readMavenDependencyList(path)
Files.deleteIfExists(path)
return sources
}

private fun runMavenCommand(pom: Path, stage: String, options: String = ""): Pair<Boolean, Path> {
val output = Files.createTempFile("""${stage}_output""", ".txt")
val command = """$mvnCommand $stage -DoutputFile=$output $options"""
val workingDirectory = pom.toAbsolutePath().parent
LOG.info("Run {} in {}", command, workingDirectory)
val (result, errors) = execAndReadStdoutAndStderr(command, workingDirectory)
LOG.debug(result)
if ("BUILD FAILURE" in errors) {
return if ("BUILD FAILURE" in errors) {
LOG.warn("Maven task failed: {}", errors.lines().firstOrNull())
Pair(false, output)
} else {
Pair(true, output)
}
return mavenOutput
}

private val mvnCommand: Path by lazy {
requireNotNull(findCommandOnPath("mvn")) { "Unable to find the 'mvn' command" }
}

fun parseMavenArtifact(rawArtifact: String, version: String? = null): Artifact {
val parts = rawArtifact.trim().split(':')
var parts = rawArtifact.trim().split(':')
val source = parts.contains("sources")
parts = parts.filter { it != "sources" }

// Creates artifact from parts of parts Array
return when (parts.size) {
3 -> Artifact(
group = parts[0],
artifact = parts[1],
packaging = null,
classifier = null,
version = version ?: parts[2],
scope = null
scope = null,
source = source
)
4 -> Artifact(
group = parts[0],
artifact = parts[1],
packaging = parts[2],
classifier = null,
version = version ?: parts[3],
scope = null
scope = null,
source = source
)
5 -> Artifact(
group = parts[0],
artifact = parts[1],
packaging = parts[2],
classifier = null,
version = version ?: parts[3],
scope = parts[4]
scope = parts[4],
source = source
)
6 -> Artifact(
group = parts[0],
artifact = parts[1],
packaging = parts[2],
classifier = parts[3],
version = version ?: parts[4],
scope = parts[5]
scope = parts[5],
source = source
)
else -> throw IllegalArgumentException("$rawArtifact is not a properly formed Maven/Gradle artifact")
}
Expand All @@ -122,7 +155,9 @@ data class Artifact(
val packaging: String?,
val classifier: String?,
val version: String,
val scope: String?
val scope: String?,
var source: Boolean = false
) {
override fun toString() = "$group:$artifact:$version"
override fun toString() = "$group:$artifact:$version:$packaging:$scope:$classifier:$source"
}
//$source:$classifier
18 changes: 15 additions & 3 deletions shared/src/test/kotlin/org/javacs/kt/MavenArtifactParsingTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class MavenArtifactParsingTest {
version = "2.4",
scope = "compile"
)))

assertThat(parseMavenArtifact("io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.36.Final:compile"), equalTo(Artifact(
group = "io.netty",
artifact = "netty-transport-native-epoll",
Expand All @@ -26,7 +26,7 @@ class MavenArtifactParsingTest {
version = "4.1.36.Final",
scope = "compile"
)))

assertThat(parseMavenArtifact("org.codehaus.mojo:my-project:1.0"), equalTo(Artifact(
group = "org.codehaus.mojo",
artifact = "my-project",
Expand All @@ -35,7 +35,7 @@ class MavenArtifactParsingTest {
version = "1.0",
scope = null
)))

assertThat(parseMavenArtifact("io.vertx:vertx-sql-client:test-jar:tests:3.8.0-SNAPSHOT:compile"), equalTo(Artifact(
group = "io.vertx",
artifact = "vertx-sql-client",
Expand All @@ -45,4 +45,16 @@ class MavenArtifactParsingTest {
scope = "compile"
)))
}
@Test
fun `parse source artifact`() {
assertThat(parseMavenArtifact("com.googlecode.lanterna:lanterna:jar:sources:3.0.2:compile"), equalTo(Artifact(
group = "com.googlecode.lanterna",
artifact = "lanterna",
packaging = "jar",
source = true,
version = "3.0.2",
scope = "compile",
classifier = null
)))
}
}