mirror of
https://github.com/apple/pkl.git
synced 2026-03-24 01:51:19 +01:00
Add support for Windows (#492)
This adds support for Windows. The in-language path separator is still `/`, to ensure Pkl programs are cross-platform. Log lines are written using CRLF endings on Windows. Modules that are combined with `--module-output-separator` uses LF endings to ensure consistent rendering across platforms. `jpkl` does not work on Windows as a direct executable. However, it can work with `java -jar jpkl`. Additional details: * Adjust git settings for Windows * Add native executable for pkl cli * Add jdk17 windows Gradle check in CI * Adjust CI test reports to be staged within Gradle rather than by shell script. * Fix: encode more characters that are not safe Windows paths * Skip running tests involving symbolic links on Windows (these require administrator privileges to run). * Introduce custom implementation of `IoUtils.relativize` * Allow Gradle to initialize ExecutableJar `Property` values * Add Gradle flag to enable remote JVM debugging Co-authored-by: Philip K.F. Hölzenspies <holzensp@gmail.com>
This commit is contained in:
@@ -17,11 +17,6 @@ package org.pkl.commons.cli.commands
|
||||
|
||||
import com.github.ajalt.clikt.core.CliktCommand
|
||||
import com.github.ajalt.clikt.parameters.groups.provideDelegate
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
import org.pkl.commons.cli.CliException
|
||||
import org.pkl.core.runtime.VmUtils
|
||||
import org.pkl.core.util.IoUtils
|
||||
|
||||
abstract class BaseCommand(name: String, helpLink: String, help: String = "") :
|
||||
CliktCommand(
|
||||
@@ -30,30 +25,4 @@ abstract class BaseCommand(name: String, helpLink: String, help: String = "") :
|
||||
epilog = "For more information, visit $helpLink",
|
||||
) {
|
||||
val baseOptions by BaseOptions()
|
||||
|
||||
/**
|
||||
* Parses [moduleName] into a URI. If scheme is not present, we expect that this is a file path
|
||||
* and encode any possibly invalid characters. If a scheme is present, we expect that this is a
|
||||
* valid URI.
|
||||
*/
|
||||
protected fun parseModuleName(moduleName: String): URI =
|
||||
when (moduleName) {
|
||||
"-" -> VmUtils.REPL_TEXT_URI
|
||||
else ->
|
||||
try {
|
||||
IoUtils.toUri(moduleName)
|
||||
} catch (e: URISyntaxException) {
|
||||
val message = buildString {
|
||||
append("Module URI `$moduleName` has invalid syntax (${e.reason}).")
|
||||
if (e.index > -1) {
|
||||
append("\n\n")
|
||||
append(moduleName)
|
||||
append("\n")
|
||||
append(" ".repeat(e.index))
|
||||
append("^")
|
||||
}
|
||||
}
|
||||
throw CliException(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,50 @@ import com.github.ajalt.clikt.parameters.types.long
|
||||
import com.github.ajalt.clikt.parameters.types.path
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
import java.nio.file.Path
|
||||
import java.time.Duration
|
||||
import java.util.regex.Pattern
|
||||
import org.pkl.commons.cli.CliBaseOptions
|
||||
import org.pkl.commons.cli.CliException
|
||||
import org.pkl.core.runtime.VmUtils
|
||||
import org.pkl.core.util.IoUtils
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class BaseOptions : OptionGroup() {
|
||||
companion object {
|
||||
/**
|
||||
* Parses [moduleName] into a URI. If scheme is not present, we expect that this is a file path
|
||||
* and encode any possibly invalid characters, and also normalize directory separators. If a
|
||||
* scheme is present, we expect that this is a valid URI.
|
||||
*/
|
||||
fun parseModuleName(moduleName: String): URI =
|
||||
when (moduleName) {
|
||||
"-" -> VmUtils.REPL_TEXT_URI
|
||||
else ->
|
||||
// Don't use `IoUtils.toUri` here becaus we need to normalize `\` paths to `/` on Windows.
|
||||
try {
|
||||
if (IoUtils.isUriLike(moduleName)) URI(moduleName)
|
||||
// Can't just use URI constructor, because URI(null, null, "C:/foo/bar", null) turns
|
||||
// into `URI("C", null, "/foo/bar", null)`.
|
||||
else if (IoUtils.isWindowsAbsolutePath(moduleName)) Path.of(moduleName).toUri()
|
||||
else URI(null, null, IoUtils.toNormalizedPathString(Path.of(moduleName)), null)
|
||||
} catch (e: URISyntaxException) {
|
||||
val message = buildString {
|
||||
append("Module URI `$moduleName` has invalid syntax (${e.reason}).")
|
||||
if (e.index > -1) {
|
||||
append("\n\n")
|
||||
append(moduleName)
|
||||
append("\n")
|
||||
append(" ".repeat(e.index))
|
||||
append("^")
|
||||
}
|
||||
}
|
||||
throw CliException(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val defaults = CliBaseOptions()
|
||||
|
||||
private val output =
|
||||
@@ -114,7 +150,7 @@ class BaseOptions : OptionGroup() {
|
||||
|
||||
val settings: URI? by
|
||||
option(names = arrayOf("--settings"), help = "Pkl settings module to use.").single().convert {
|
||||
IoUtils.toUri(it)
|
||||
parseModuleName(it)
|
||||
}
|
||||
|
||||
val timeout: Duration? by
|
||||
|
||||
@@ -29,7 +29,7 @@ abstract class ModulesCommand(name: String, helpLink: String, help: String = "")
|
||||
) {
|
||||
open val modules: List<URI> by
|
||||
argument(name = "<modules>", help = "Module paths or URIs to evaluate.")
|
||||
.convert { parseModuleName(it) }
|
||||
.convert { BaseOptions.parseModuleName(it) }
|
||||
.multiple(required = true)
|
||||
|
||||
protected val projectOptions by ProjectOptions()
|
||||
|
||||
Reference in New Issue
Block a user