Skip to content

fix: Resolve ClassNotFoundException for .kts scripts by ensuring pack… #427

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/installer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
if: matrix.variant == 'sdkman'
shell: bash
run: |
bash -c "curl -s "https://get.sdkman.io" | bash"
bash -c "curl -s "https://get.sdkman.io?ci=true" | bash"
source "$HOME/.sdkman/bin/sdkman-init.sh"

sdk install kscript ${{ env.KSCRIPT_VERSION }}
Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
import java.time.ZoneOffset
import java.time.ZonedDateTime

val kotlinVersion: String = "1.7.21"
val kotlinVersion: String = "2.1.21-embedded"

plugins {
kotlin("jvm") version "1.7.21"
kotlin("jvm") version "2.1.21-embedded"
application
id("com.adarshr.test-logger") version "3.2.0"
id("com.github.gmazzo.buildconfig") version "3.1.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object GradleTemplates {
fun createGradleIdeaScript(script: Script): String {
val kotlinVersion = KotlinVersion.CURRENT
val extendedDependencies = setOf(
Dependency("org.jetbrains.kotlin:kotlin-stdlib"),
Dependency("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"),
Dependency("org.jetbrains.kotlin:kotlin-script-runtime:$kotlinVersion"),
Dependency("io.github.kscripting:kscript-annotations:1.5.0"),
) + script.dependencies
Expand Down Expand Up @@ -42,7 +42,7 @@ object GradleTemplates {

val kotlinVersion = KotlinVersion.CURRENT
val extendedDependencies = setOf(
Dependency("org.jetbrains.kotlin:kotlin-stdlib"),
Dependency("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"),
Dependency("org.jetbrains.kotlin:kotlin-script-runtime:$kotlinVersion")
) + script.dependencies

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ class JarArtifactCreator(private val executor: Executor) {

execClassNameFile.writeText(execClassName)

FileUtils.createFile(scriptFile, script.resolvedCode)
var scriptContent = script.resolvedCode

if (script.scriptLocation.scriptType == ScriptType.KTS &&
script.packageName.value.isNotBlank() &&
!scriptContent.trimStart().startsWith("package ")
) {
scriptContent = "package ${script.packageName.value}\n\n$scriptContent"
}

FileUtils.createFile(scriptFile, scriptContent)

val filesToCompile = mutableSetOf<OsPath>()
filesToCompile.add(scriptFile)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import io.github.kscripting.kscript.model.OsConfig
import io.github.kscripting.shell.model.OsPath
import io.github.kscripting.shell.model.OsType
import io.github.kscripting.shell.model.toNativeOsPath
import java.nio.file.Files
import kotlin.io.path.writeLines

class CommandResolver(val osConfig: OsConfig) {
private val classPathSeparator =
Expand All @@ -17,6 +19,10 @@ class CommandResolver(val osConfig: OsConfig) {
else -> '\''
}

companion object {
private const val ARGFILE_PATHS_CHAR_THRESHOLD = 4096
private const val ARGFILE_PATHS_COUNT_THRESHOLD = 100
}

fun getKotlinJreVersion(): String {
val kotlin = resolveKotlinBinary("kotlin")
Expand Down Expand Up @@ -47,12 +53,51 @@ class CommandResolver(val osConfig: OsConfig) {
jar: OsPath, dependencies: Set<OsPath>, filePaths: Set<OsPath>, compilerOpts: Set<CompilerOpt>
): String {
val compilerOptsStr = resolveCompilerOpts(compilerOpts)
val classpath = resolveClasspath(dependencies)
val classpath = resolveClasspath(dependencies) // Keep classpath on command line for now
val jarFile = resolveJarFile(jar)
val files = resolveFiles(filePaths)
val kotlinc = resolveKotlinBinary("kotlinc")

return "$kotlinc $compilerOptsStr $classpath -d $jarFile $files"
// Calculate total length of all resolved file paths and classpath entries for character threshold
val totalPathLength = filePaths.sumOf { it.stringPath().length } +
dependencies.sumOf { it.stringPath().length } +
compilerOptsStr.length +
classpath.length // Approx length of classpath string itself

// Calculate total number of files/options for count threshold
val totalItemsCount = filePaths.size + dependencies.size + compilerOpts.size

if (totalPathLength > ARGFILE_PATHS_CHAR_THRESHOLD || totalItemsCount > ARGFILE_PATHS_COUNT_THRESHOLD) {
val tempArgFile = Files.createTempFile("kscript-kotlinc-args-", ".txt")
try {
val argFileLines = mutableListOf<String>()

// Add compiler options (if any)
if (compilerOptsStr.isNotBlank()) {
argFileLines.add(compilerOptsStr)
}

// Add classpath string (if any)
// resolveClasspath() returns "-classpath \"foo:bar\"" or empty string
if (classpath.isNotBlank()) {
argFileLines.add(classpath)
}

// Add source files, native and unquoted, one per line
filePaths.mapTo(argFileLines) { it.toNativeOsPath().stringPath() }

tempArgFile.writeLines(argFileLines)

val argFileArgument = "@${tempArgFile.toAbsolutePath().toString()}"

// -d $jarFile must remain on command line as it's an output specifier
return "$kotlinc $argFileArgument -d $jarFile"
} finally {
Files.deleteIfExists(tempArgFile)
}
} else {
val files = resolveFiles(filePaths) // Only resolve files if not using argfile
return "$kotlinc $compilerOptsStr $classpath -d $jarFile $files"
}
}

fun executeKotlin(
Expand Down
Loading