Skip to content

Commit 3bca47d

Browse files
authored
Maven resolution fix for issue #345 (#352)
* build: updated to latest Gradle * build: added 'kotlin-scripting-dependencies-maven-all' instead of 'kotlin-scripting-dependencies-maven' (fixes #345) * build: added transformer to resolve problems with dependencies resolution (fixes #345) * test: additional test for dependencies resolution * cleanup: code improvements in DependencyResolver.kt
1 parent e12e48e commit 3bca47d

File tree

13 files changed

+89
-87
lines changed

13 files changed

+89
-87
lines changed

IntegrationTest345.main.kts

Lines changed: 0 additions & 43 deletions
This file was deleted.

build.gradle.kts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
import com.github.jengelman.gradle.plugins.shadow.transformers.ComponentsXmlResourceTransformer
23
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
34
import org.gradle.api.tasks.testing.logging.TestLogEvent
45

5-
val kotlinVersion: String = "1.6.20"
6+
val kotlinVersion: String = "1.6.21"
67

78
plugins {
8-
kotlin("jvm") version "1.6.20"
9+
kotlin("jvm") version "1.6.21"
910
application
10-
id("com.github.johnrengelman.shadow") version "6.1.0"
11+
id("com.github.johnrengelman.shadow") version "7.1.2"
1112
}
1213

1314
repositories {
@@ -20,51 +21,57 @@ tasks.test {
2021
useJUnitPlatform()
2122

2223
testLogging {
23-
events(TestLogEvent.FAILED); exceptionFormat = TestExceptionFormat.FULL
24+
events(TestLogEvent.FAILED)
25+
exceptionFormat = TestExceptionFormat.FULL
2426
}
2527
}
2628

2729
tasks.withType<Test> {
2830
addTestListener(object : TestListener {
29-
override fun beforeSuite(suite: TestDescriptor) { logger.quiet("\nTest class: ${suite.displayName}") }
31+
override fun beforeSuite(suite: TestDescriptor) {
32+
logger.quiet("\nTest class: ${suite.displayName}")
33+
}
34+
3035
override fun beforeTest(testDescriptor: TestDescriptor) {}
3136
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {
32-
logger.quiet("${String.format( "%-60s - %-10s", testDescriptor.name, result.resultType )} ")
37+
logger.quiet("${String.format("%-60s - %-10s", testDescriptor.name, result.resultType)} ")
3338
}
3439

3540
override fun afterSuite(suite: TestDescriptor, result: TestResult) {}
3641
})
3742
}
3843

39-
val launcherClassName: String ="kscript.app.KscriptKt"
44+
val launcherClassName: String = "kscript.app.KscriptKt"
4045

4146
dependencies {
4247
implementation("com.offbytwo:docopt:0.6.0.20150202")
4348

44-
implementation("org.jetbrains.kotlin:kotlin-scripting-common:$kotlinVersion")
4549
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
46-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-RC3")
50+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1")
4751

52+
implementation("org.jetbrains.kotlin:kotlin-scripting-common:$kotlinVersion")
4853
implementation("org.jetbrains.kotlin:kotlin-scripting-jvm:$kotlinVersion")
4954
implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies:$kotlinVersion")
50-
implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies-maven:$kotlinVersion")
55+
implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies-maven-all:$kotlinVersion")
5156

5257
implementation("commons-io:commons-io:2.11.0")
5358
implementation("commons-codec:commons-codec:1.15")
5459

55-
implementation("org.slf4j:slf4j-nop:1.7.32")
60+
implementation("org.slf4j:slf4j-nop:1.7.36")
5661

5762
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
5863
testImplementation("org.junit.jupiter:junit-jupiter-params:5.8.2")
5964
testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25")
60-
testImplementation("io.mockk:mockk:1.12.1")
65+
testImplementation("io.mockk:mockk:1.12.3")
6166

6267
testImplementation(kotlin("script-runtime"))
6368
}
6469

6570
val shadowJar by tasks.getting(ShadowJar::class) {
6671
// set empty string to classifier and version to get predictable jar file name: build/libs/kscript.jar
6772
archiveFileName.set("kscript.jar")
73+
transform(ComponentsXmlResourceTransformer())
74+
6875
doLast {
6976
copy {
7077
from(File(projectDir, "src/kscript"))
@@ -74,7 +81,7 @@ val shadowJar by tasks.getting(ShadowJar::class) {
7481
}
7582

7683
application {
77-
mainClassName = launcherClassName
84+
mainClass.set(launcherClassName)
7885
}
7986

8087
// Disable standard jar task to avoid building non-shadow jars
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists

src/main/kotlin/kscript/app/Kscript.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import org.docopt.DocOptWrapper
1919
* @author Marcin Kuszczak
2020
*/
2121

22-
const val KSCRIPT_VERSION = "4.0.0"
22+
const val KSCRIPT_VERSION = "4.0.1"
2323

2424
fun main(args: Array<String>) {
2525
try {

src/main/kotlin/kscript/app/KscriptHandler.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import kscript.app.util.Logger.infoMsg
1414
import org.docopt.DocOptWrapper
1515
import java.net.URI
1616

17-
1817
class KscriptHandler(private val config: Config, private val docopt: DocOptWrapper) {
1918

2019
fun handle(userArgs: List<String>) {
@@ -24,6 +23,11 @@ class KscriptHandler(private val config: Config, private val docopt: DocOptWrapp
2423
devMsg("KScript configuration:")
2524
devMsg(config.toString())
2625

26+
if (Logger.devMode) {
27+
devMsg("Classpath:")
28+
devMsg(System.getProperty("java.class.path"))
29+
}
30+
2731
// create kscript dir if it does not yet exist
2832
val appDir = AppDir(config.kscriptDir)
2933

src/main/kotlin/kscript/app/code/Templates.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package kscript.app.code
22

3-
import kscript.app.model.Dependency
43
import kscript.app.model.PackageName
5-
import kscript.app.model.Repository
6-
import kscript.app.model.Script
74
import kscript.app.util.ScriptUtils.dropExtension
85
import org.intellij.lang.annotations.Language
96

@@ -33,7 +30,7 @@ object Templates {
3330
exec java -jar ${'$'}0 "${'$'}@"
3431
""".trimIndent()
3532

36-
fun wrapperForScript(packageName: PackageName, className: String) : String {
33+
fun wrapperForScript(packageName: PackageName, className: String): String {
3734
val classReference = packageName.value + "." + className
3835

3936
return """

src/main/kotlin/kscript/app/model/Config.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ data class Config(
99
val intellijCommand: String,
1010
val gradleCommand: String,
1111
val kotlinHome: Path?,
12+
val osName: String,
1213
val classPathSeparator: String,
1314
val separatorChar: Char,
1415
val homeDir: Path,

src/main/kotlin/kscript/app/model/ConfigBuilder.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ class ConfigBuilder internal constructor() {
1313
var intellijCommand: String = System.getenv("KSCRIPT_IDEA_COMMAND") ?: "idea"
1414
var gradleCommand: String = System.getenv("KSCRIPT_GRADLE_COMMAND") ?: "gradle"
1515
var kotlinHome: Path? = (System.getenv("KOTLIN_HOME") ?: guessKotlinHome())?.let { Paths.get(it).absolute() }
16-
var classPathSeparator: String = if (System.getProperty("os.name").lowercase().contains("windows")) ";" else ":"
17-
var separatorChar: Char = File.separatorChar
16+
var osName: String = System.getProperty("os.name")
1817
var homeDir: Path = Paths.get(System.getProperty("user.home")!!)
18+
var classPathSeparator: String = if (osName.lowercase().contains("windows")) ";" else ":"
19+
var separatorChar: Char = File.separatorChar
1920
var kotlinOptsEnvVariable = System.getenv("KSCRIPT_KOTLIN_OPTS") ?: ""
2021
var repositoryUrlEnvVariable = System.getenv("KSCRIPT_REPOSITORY_URL") ?: ""
2122
var repositoryUserEnvVariable = System.getenv("KSCRIPT_REPOSITORY_USER") ?: ""
@@ -29,6 +30,7 @@ class ConfigBuilder internal constructor() {
2930
intellijCommand,
3031
gradleCommand,
3132
kotlinHome,
33+
osName,
3234
classPathSeparator,
3335
separatorChar,
3436
homeDir,

src/main/kotlin/kscript/app/resolver/CommandResolver.kt

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,21 @@ import kotlin.io.path.absolutePathString
1111
import kotlin.io.path.div
1212

1313
class CommandResolver(private val config: Config, private val script: Script) {
14+
//Syntax for different OS-es:
15+
//LINUX: kotlin -classpath "/home/vagrant/workspace/Kod/Repos/kscript/test:/home/vagrant/.kscript/cache/jar_2ccd53e06b0355d3573a4ae8698398fe/scriplet.jar:/usr/local/sdkman/candidates/kotlin/1.6.21/lib/kotlin-script-runtime.jar" Main_Scriplet
16+
//GIT-BASH: kotlin -classpath "C:\Users\Admin;C:\Users\Admin\.kscript\cache\jar_2ccd53e06b0355d3573a4ae8698398fe\scriplet.jar;C:\Users\Admin\.sdkman\candidates\kotlin\current\lib\kotlin-script-runtime.jar" Main_Scriplet
17+
//CYGWIN: kotlin -classpath "C:\Users\Admin;C:\Users\Admin\.kscript\cache\jar_2ccd53e06b0355d3573a4ae8698398fe\scriplet.jar;C:\Users\Admin\.sdkman\candidates\kotlin\current\lib\kotlin-script-runtime.jar" Main_Scriplet
18+
//WINDOWS: kotlin -classpath "C:\Users\Admin;C:\Users\Admin\.kscript\cache\jar_2ccd53e06b0355d3573a4ae8698398fe\scriplet.jar;C:\Users\Admin\.sdkman\candidates\kotlin\current\lib\kotlin-script-runtime.jar" Main_Scriplet
19+
20+
//Path conversion (Cygwin/mingw): cygpath -u "c:\Users\Admin"; /cygdrive/c/ - Cygwin; /c/ - Mingw
21+
//uname --> CYGWIN_NT-10.0 or MINGW64_NT-10.0-19043
22+
//How to find if mingw/cyg/win (second part): https://stackoverflow.com/questions/40877323/quickly-find-if-java-was-launched-from-windows-cmd-or-cygwin-terminal
23+
1424
fun compileKotlin(jar: Path, dependencies: Set<Path>, filePaths: Set<Path>): String {
1525
val compilerOptsStr = resolveCompilerOpts(script.compilerOpts)
1626
val classpath = resolveClasspath(dependencies)
1727
val files = filePaths.joinToString(" ") { "'${it.absolutePathString()}'" }
18-
19-
val kotlinc =
20-
if (config.kotlinHome != null) (config.kotlinHome / "bin" / "kotlinc").absolutePathString() else "kotlinc"
28+
val kotlinc = resolveKotlinBinary("kotlinc")
2129

2230
return "'$kotlinc' $compilerOptsStr $classpath -d '${jar.absolutePathString()}' $files"
2331
}
@@ -35,8 +43,7 @@ class CommandResolver(private val config: Config, private val script: Script) {
3543
}
3644

3745
val classpath = resolveClasspath(dependenciesSet)
38-
39-
val kotlin = if (config.kotlinHome != null) (config.kotlinHome / "bin" / "kotlin").absolutePathString() else "kotlin"
46+
val kotlin = resolveKotlinBinary("kotlin")
4047

4148
return "$kotlin $kotlinOptsStr $classpath ${jarArtifact.execClassName} $userArgsStr"
4249
}
@@ -45,8 +52,7 @@ class CommandResolver(private val config: Config, private val script: Script) {
4552
val compilerOptsStr = resolveCompilerOpts(script.compilerOpts)
4653
val kotlinOptsStr = resolveKotlinOpts(script.kotlinOpts)
4754
val classpath = resolveClasspath(dependencies)
48-
49-
val kotlinc = if (config.kotlinHome != null) (config.kotlinHome / "bin" / "kotlinc").absolutePathString() else "kotlinc"
55+
val kotlinc = resolveKotlinBinary("kotlinc")
5056

5157
return "$kotlinc $compilerOptsStr $kotlinOptsStr $classpath"
5258
}
@@ -60,10 +66,15 @@ class CommandResolver(private val config: Config, private val script: Script) {
6066
}
6167

6268
private fun resolveKotlinOpts(kotlinOpts: Set<KotlinOpt>) = kotlinOpts.joinToString(" ") { it.value }
69+
6370
private fun resolveCompilerOpts(compilerOpts: Set<CompilerOpt>) = compilerOpts.joinToString(" ") { it.value }
71+
6472
private fun resolveUserArgs(userArgs: List<String>) =
6573
userArgs.joinToString(" ") { "\"${it.replace("\"", "\\\"")}\"" }
6674

6775
private fun resolveClasspath(dependencies: Set<Path>) = if (dependencies.isEmpty()) ""
68-
else "-classpath " + dependencies.joinToString(config.classPathSeparator) { "'${it.absolutePathString()}'" }
76+
else "-classpath \"" + dependencies.joinToString(config.classPathSeparator) { it.absolutePathString() } + "\""
77+
78+
private fun resolveKotlinBinary(binary: String) =
79+
if (config.kotlinHome != null) (config.kotlinHome / "bin" / binary).absolutePathString() else binary
6980
}

src/main/kotlin/kscript/app/resolver/DependencyResolver.kt

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ class DependencyResolver(private val customRepos: Set<Repository>) {
4646
devMsg("Resolved in: ${System.currentTimeMillis() - start}")
4747
resolved
4848
}
49-
}.map {
50-
it.valueOr {
51-
throw IllegalStateException("Failed while connecting to the server. Check the connection (http/https, port, proxy, credentials, etc.) of your maven dependency locators. If you suspect this is a bug, you can create an issue on https://github.com/holgerbrandl/kscript" + it.reports.joinToString(
52-
"\n"
53-
) { it.exception?.toString() ?: it.message }, it.reports.find { it.exception != null }?.exception
54-
)
49+
}.asSequence().map { result ->
50+
result.valueOr { failure ->
51+
val details = failure.reports.joinToString("\n") { scriptDiagnostic ->
52+
scriptDiagnostic.exception?.stackTraceToString() ?: scriptDiagnostic.message
53+
}
54+
55+
val firstException =
56+
failure.reports.find { scriptDiagnostic -> scriptDiagnostic.exception != null }?.exception
57+
58+
throw IllegalStateException(exceptionMessage + "\n" + details, firstException)
5559
}
5660
}.flatten().map {
5761
it.toPath()
@@ -61,4 +65,13 @@ class DependencyResolver(private val customRepos: Set<Repository>) {
6165

6266
return resolvedDependencies
6367
}
68+
69+
companion object {
70+
//@formatter:off
71+
private const val exceptionMessage =
72+
"Failed while connecting to the server. Check the connection (http/https, port, proxy, credentials, etc.)" +
73+
"of your maven dependency locators. If you suspect this is a bug, " +
74+
"you can create an issue on https://github.com/holgerbrandl/kscript"
75+
//@formatter:on
76+
}
6477
}

0 commit comments

Comments
 (0)