Skip to content

Commit b9259f6

Browse files
committed
* Added APP_BUILD_TIME
* Refactored version and options implementation Signed-off-by: Marcin Kuszczak <1508798+aartiPl@users.noreply.github.com>
1 parent 6dcf324 commit b9259f6

10 files changed

Lines changed: 129 additions & 83 deletions

File tree

build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
22
import com.github.jengelman.gradle.plugins.shadow.transformers.ComponentsXmlResourceTransformer
3+
import java.time.ZoneOffset
4+
import java.time.ZonedDateTime
35

46
val kotlinVersion: String = "1.7.21"
57

@@ -29,8 +31,11 @@ buildConfig {
2931
packageName(project.group.toString() + "." + project.name)
3032
useKotlinOutput()
3133

34+
val dateTime = ZonedDateTime.now(ZoneOffset.UTC)
35+
3236
buildConfigField("String", "APP_NAME", "\"${project.name}\"")
3337
buildConfigField("String", "APP_VERSION", provider { "\"${project.version}\"" })
38+
buildConfigField("java.time.ZonedDateTime", "APP_BUILD_TIME", provider { "java.time.ZonedDateTime.parse(\"$dateTime\")" })
3439
buildConfigField("String", "KOTLIN_VERSION", provider { "\"${kotlinVersion}\"" })
3540
}
3641

@@ -123,6 +128,7 @@ tasks.test {
123128
dependencies {
124129
//compileOnly(fileTree("libs"))
125130
implementation("com.offbytwo:docopt:0.6.0.20150202")
131+
implementation("commons-cli:commons-cli:1.5.0")
126132

127133
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
128134
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")

src/main/kotlin/io/github/kscripting/kscript/Kscript.kt

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package io.github.kscripting.kscript
22

3-
import io.github.kscripting.kscript.code.Templates
3+
import io.github.kscripting.kscript.code.Templates.createUsageOptions
44
import io.github.kscripting.kscript.model.ConfigBuilder
5+
import io.github.kscripting.kscript.util.DocoptParser
56
import io.github.kscripting.kscript.util.Logger.errorMsg
6-
import io.github.kscripting.kscript.util.Logger.info
7-
import io.github.kscripting.kscript.util.VersionChecker
87
import io.github.kscripting.shell.model.OsType
9-
import org.docopt.DocoptParser
108
import kotlin.system.exitProcess
119

1210
/**
@@ -24,28 +22,19 @@ fun main(args: Array<String>) {
2422
OsType.findOrThrow(args[0]), System.getProperties(), System.getenv()
2523
).build()
2624

25+
// note: first argument has to be OSTYPE
2726
val remainingArgs = args.drop(1)
2827

29-
// skip DocOpt for version and help to allow lazy version-check
30-
if (remainingArgs.size == 1 && listOf("--help", "-h", "--version", "-v").contains(remainingArgs[0])) {
31-
val versionChecker = VersionChecker(config.osConfig)
32-
33-
val newVersion =
34-
if (versionChecker.isThereANewKscriptVersion()) versionChecker.remoteKscriptVersion else ""
35-
36-
info(Templates.createUsageOptions(config.osConfig.selfName, BuildConfig.APP_VERSION, newVersion))
37-
38-
info("Kotlin : ${versionChecker.localKotlinVersion}")
39-
info("Java : ${versionChecker.localJreVersion}")
40-
return
41-
}
42-
4328
// note: with current implementation we still don't support `kscript -1` where "-1" is a valid kotlin expression
4429
val userArgs = remainingArgs.dropWhile { it.startsWith("-") && it != "-" }.drop(1)
4530
val kscriptArgs = remainingArgs.take(remainingArgs.size - userArgs.size)
4631

47-
val usage = Templates.createUsageOptions(config.osConfig.selfName, BuildConfig.APP_VERSION)
48-
KscriptHandler(config, DocoptParser.parse(kscriptArgs, usage)).handle(kscriptArgs, userArgs)
32+
val options = DocoptParser.parse(
33+
kscriptArgs,
34+
createUsageOptions(config.osConfig.selfName, BuildConfig.APP_BUILD_TIME, BuildConfig.APP_VERSION)
35+
)
36+
37+
KscriptHandler(config, options).handle(kscriptArgs, userArgs)
4938
} catch (e: Exception) {
5039
errorMsg(e)
5140
exitProcess(1)

src/main/kotlin/io/github/kscripting/kscript/KscriptHandler.kt

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import io.github.kscripting.kscript.util.Logger
1212
import io.github.kscripting.kscript.util.Logger.info
1313
import io.github.kscripting.kscript.util.Logger.infoMsg
1414
import io.github.kscripting.kscript.util.Logger.warnMsg
15+
import io.github.kscripting.kscript.util.VersionChecker
1516
import io.github.kscripting.shell.model.ScriptType
1617
import java.net.URI
1718

@@ -24,6 +25,34 @@ class KscriptHandler(private val config: Config, private val options: Map<String
2425
info(DebugInfoCreator().create(config, kscriptArgs, userArgs))
2526
}
2627

28+
val executor = Executor(CommandResolver(config.osConfig))
29+
30+
if (options.getBoolean("help") || options.getBoolean("version")) {
31+
val versionChecker = VersionChecker(executor)
32+
33+
val newVersion =
34+
if (versionChecker.isThereANewKscriptVersion()) versionChecker.remoteKscriptVersion else ""
35+
36+
info(
37+
Templates.createUsageOptions(
38+
config.osConfig.selfName,
39+
BuildConfig.APP_BUILD_TIME,
40+
BuildConfig.APP_VERSION,
41+
newVersion,
42+
versionChecker.localKotlinVersion,
43+
versionChecker.localJreVersion
44+
)
45+
)
46+
47+
val message = options.getOrDefault("message", "")
48+
49+
if (message.isNotBlank()) {
50+
throw IllegalArgumentException(message)
51+
}
52+
53+
return
54+
}
55+
2756
val cache = Cache(config.osConfig.cacheDir)
2857

2958
// optionally clear up the jar cache
@@ -78,8 +107,6 @@ class KscriptHandler(private val config: Config, private val options: Map<String
78107
DependencyResolver(script.repositories).resolve(script.dependencies)
79108
} + localArtifacts
80109

81-
val executor = Executor(CommandResolver(config.osConfig), config.osConfig)
82-
83110
// Create temporary dev environment
84111
if (options.getBoolean("idea")) {
85112
val path = cache.getOrCreateIdeaProject(script.digest) { basePath ->
@@ -123,6 +150,6 @@ class KscriptHandler(private val config: Config, private val options: Map<String
123150
executor.executeKotlin(jar, resolvedDependencies, userArgs, script.kotlinOpts)
124151
}
125152

126-
private fun Map<String, String>.getBoolean(key: String): Boolean = getValue(key).toBoolean()
153+
private fun Map<String, String>.getBoolean(key: String): Boolean = getOrDefault(key, "false").toBoolean()
127154
private fun Map<String, String>.getString(key: String): String = getValue(key)
128155
}

src/main/kotlin/io/github/kscripting/kscript/code/Templates.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.github.kscripting.kscript.model.KotlinOpt
44
import io.github.kscripting.kscript.model.PackageName
55
import io.github.kscripting.shell.model.ScriptType
66
import org.intellij.lang.annotations.Language
7+
import java.time.ZonedDateTime
78

89
object Templates {
910
@Language("sh")
@@ -95,7 +96,20 @@ object Templates {
9596
|""".trimStart().trimMargin()
9697
}
9798

98-
fun createUsageOptions(selfName: String, version: String, newVersion: String = "") = """
99+
fun createUsageOptions(
100+
selfName: String, buildDateTime: ZonedDateTime, version: String, newVersion: String = "", kotlinVersion: String = "", jreVersion: String = ""
101+
): String {
102+
val versionLine =
103+
"Version : $version ${if (newVersion.isNotBlank()) "(new version v$newVersion is available)" else ""}"
104+
105+
val kotlinAndJreVersion = if (kotlinVersion.isNotBlank()) {
106+
"""|
107+
|Kotlin : $kotlinVersion
108+
|Java : $jreVersion
109+
|""".trimMargin()
110+
} else ""
111+
112+
return """
99113
|$selfName - Enhanced scripting support for Kotlin on *nix-based systems.
100114
|
101115
|Usage:
@@ -115,11 +129,15 @@ object Templates {
115129
| --report Prints script's deprecated features report
116130
| --package Package script and dependencies into self-dependent binary
117131
| --add-bootstrap-header Prepend bash header that installs kscript if necessary
132+
| -h --help Prints help information
133+
| -v --version Same as '--help'
118134
|
119135
|
120136
|Copyright : 2022 Holger Brandl, Marcin Kuszczak
121137
|License : MIT
122-
|Version : $version ${if (newVersion.isNotBlank()) "(new version v$newVersion is available)" else ""}
138+
|$versionLine
139+
|Build : $buildDateTime
123140
|Website : https://github.com/kscripting/kscript
124-
|""".trimMargin().trim()
141+
|""".trimMargin().trim() + kotlinAndJreVersion
142+
}
125143
}

src/main/kotlin/io/github/kscripting/kscript/resolver/CommandResolver.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ import io.github.kscripting.shell.model.OsPath
88
import io.github.kscripting.shell.model.OsType
99
import io.github.kscripting.shell.model.toNativeOsPath
1010

11-
class CommandResolver(private val osConfig: OsConfig) {
11+
class CommandResolver(val osConfig: OsConfig) {
1212
private val classPathSeparator =
1313
if (osConfig.osType.isWindowsLike() || osConfig.osType.isPosixHostedOnWindows()) ";" else ":"
1414

15+
fun getKotlinJreVersion(): String {
16+
val kotlin = resolveKotlinBinary("kotlin")
17+
return "$kotlin -version"
18+
}
19+
1520
//Syntax for different OS-es:
1621
//LINUX: /usr/local/sdkman/..../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
1722
//GIT-BASH: /c/Users/Admin/.sdkman/candidates/kotlin/current/bin/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

src/main/kotlin/io/github/kscripting/kscript/util/DocoptParser.kt

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
1-
//NOTE: org.docopt package is needed because printUsage property is internal,
2-
//and not accessible from kscript package
3-
@file:Suppress("PackageDirectoryMismatch")
1+
package io.github.kscripting.kscript.util
42

5-
package org.docopt
6-
7-
import kotlin.system.exitProcess
3+
import org.docopt.Docopt
4+
import org.docopt.DocoptExitException
85

96
object DocoptParser {
107
fun parse(args: Iterable<String>, usage: String): Map<String, String> {
11-
val parsedArgs = try {
12-
Docopt(usage).withExit(false).parse(args.toList())
13-
} catch (e: DocoptExitException) {
14-
// mimic docopts exit behavior but using process-substituion handler at the end
15-
if (e.message != null) {
16-
System.err.println(e.message)
17-
}
8+
// note: DocOpt has very strange behavior for --help: it throws exception with exitCode=0.
9+
// It is very unfortunate as it should be possible to provide also --development option, even with help.
10+
// Because of that, the --help is replaced with --version in arguments, which has the same behaviour in kscript,
11+
// but does not throw exception from DocOpt.
1812

19-
if (e.printUsage) {
20-
System.err.println(usage)
21-
}
13+
val help = (args.contains("--help") || args.contains("-h") || (args.find {
14+
!it.startsWith("--") && it.startsWith("-") && it.substring(1).contains("h")
15+
} != null))
2216

23-
exitProcess(e.exitCode)
17+
val development = (args.contains("--development") || args.contains("-d") || (args.find {
18+
!it.startsWith("--") && it.startsWith("-") && it.substring(1).contains("d")
19+
} != null))
20+
21+
val parsedArgs = try {
22+
if (help) {
23+
mapOf("help" to "true", "development" to "$development")
24+
} else {
25+
Docopt(usage).withExit(false).parse(args.toList())
26+
}
27+
} catch (e: DocoptExitException) {
28+
val message = "Invalid usage pattern"
29+
mapOf("help" to "true", "message" to message)
2430
}
2531

2632
return parsedArgs.map {

src/main/kotlin/io/github/kscripting/kscript/util/Executor.kt

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package io.github.kscripting.kscript.util
33
import io.github.kscripting.kscript.creator.JarArtifact
44
import io.github.kscripting.kscript.model.CompilerOpt
55
import io.github.kscripting.kscript.model.KotlinOpt
6-
import io.github.kscripting.kscript.model.OsConfig
76
import io.github.kscripting.kscript.resolver.CommandResolver
87
import io.github.kscripting.kscript.util.Logger.devMsg
98
import io.github.kscripting.kscript.util.Logger.infoMsg
@@ -12,7 +11,19 @@ import io.github.kscripting.kscript.util.ShellUtils.isInPath
1211
import io.github.kscripting.shell.ShellExecutor
1312
import io.github.kscripting.shell.model.OsPath
1413

15-
class Executor(private val commandResolver: CommandResolver, private val osConfig: OsConfig) {
14+
class Executor(private val commandResolver: CommandResolver) {
15+
16+
fun retrieveLocalKotlinAndJreVersion(): String {
17+
val command = commandResolver.getKotlinJreVersion()
18+
19+
return ShellExecutor.evalAndGobble(
20+
commandResolver.osConfig.osType,
21+
command,
22+
null,
23+
ShellUtils::environmentAdjuster
24+
).stdout
25+
}
26+
1627
//NOTE: for direct execution from Kotlin jars:
1728
//# Kotlin compilation / running dependencies
1829
//#CLASS_PATH="$KOTLIN_HOME/lib/kotlin-runner.jar:$KOTLIN_HOME/lib/kotlin-preloader.jar:$KOTLIN_HOME/lib/kotlin-compiler.jar:$KOTLIN_HOME/lib/kotlin-script-runtime.jar"
@@ -22,7 +33,7 @@ class Executor(private val commandResolver: CommandResolver, private val osConfi
2233
devMsg("JAR compile command: $command")
2334

2435
val processResult = ShellExecutor.evalAndGobble(
25-
osConfig.osType, command, envAdjuster = ShellUtils::environmentAdjuster, waitTimeMinutes = 30
36+
commandResolver.osConfig.osType, command, envAdjuster = ShellUtils::environmentAdjuster, waitTimeMinutes = 30
2637
)
2738

2839
devMsg("Script compilation result:\n$processResult")
@@ -39,7 +50,7 @@ class Executor(private val commandResolver: CommandResolver, private val osConfi
3950
devMsg("Kotlin execute command: $command")
4051

4152
val processResult = ShellExecutor.eval(
42-
osConfig.osType,
53+
commandResolver.osConfig.osType,
4354
command,
4455
envAdjuster = ShellUtils::environmentAdjuster,
4556
waitTimeMinutes = Int.MAX_VALUE,
@@ -62,7 +73,7 @@ class Executor(private val commandResolver: CommandResolver, private val osConfi
6273
devMsg("REPL Kotlin command: $command")
6374

6475
val processResult = ShellExecutor.eval(
65-
osConfig.osType,
76+
commandResolver.osConfig.osType,
6677
command,
6778
envAdjuster = ShellUtils::environmentAdjuster,
6879
waitTimeMinutes = Int.MAX_VALUE,
@@ -73,19 +84,19 @@ class Executor(private val commandResolver: CommandResolver, private val osConfi
7384
}
7485

7586
fun runGradleInIdeaProject(projectPath: OsPath) {
76-
if (isInPath(osConfig.osType, osConfig.gradleCommand)) {
87+
if (isInPath(commandResolver.osConfig.osType, commandResolver.osConfig.gradleCommand)) {
7788
// Create gradle wrapper
78-
ShellExecutor.evalAndGobble(osConfig.osType, "gradle wrapper", workingDirectory = projectPath)
89+
ShellExecutor.evalAndGobble(commandResolver.osConfig.osType, "gradle wrapper", workingDirectory = projectPath)
7990
} else {
80-
warnMsg("Could not find '${osConfig.gradleCommand}' in your PATH. You must set the command used to launch your intellij as 'KSCRIPT_COMMAND_GRADLE' env property")
91+
warnMsg("Could not find '${commandResolver.osConfig.gradleCommand}' in your PATH. You must set the command used to launch your intellij as 'KSCRIPT_COMMAND_GRADLE' env property")
8192
}
8293

83-
if (isInPath(osConfig.osType, osConfig.intellijCommand)) {
94+
if (isInPath(commandResolver.osConfig.osType, commandResolver.osConfig.intellijCommand)) {
8495
val command = commandResolver.executeIdea(projectPath)
8596
devMsg("Idea execute command: $command")
8697

8798
val processResult = ShellExecutor.evalAndGobble(
88-
osConfig.osType, command
99+
commandResolver.osConfig.osType, command
89100
)
90101

91102
devMsg("Script execution result:\n$processResult")
@@ -94,19 +105,19 @@ class Executor(private val commandResolver: CommandResolver, private val osConfi
94105
throw IllegalStateException("Execution of idea command failed:\n$processResult")
95106
}
96107
} else {
97-
warnMsg("Could not find '${osConfig.intellijCommand}' in your PATH. You should set the command used to launch your intellij as 'KSCRIPT_COMMAND_IDEA' env property")
108+
warnMsg("Could not find '${commandResolver.osConfig.intellijCommand}' in your PATH. You should set the command used to launch your intellij as 'KSCRIPT_COMMAND_IDEA' env property")
98109
}
99110
}
100111

101112
fun createPackage(projectPath: OsPath) {
102-
if (!isInPath(osConfig.osType, osConfig.gradleCommand)) {
113+
if (!isInPath(commandResolver.osConfig.osType, commandResolver.osConfig.gradleCommand)) {
103114
throw IllegalStateException("Gradle is required to package scripts.")
104115
}
105116

106117
val command = commandResolver.createPackage()
107118
devMsg("Create package command: $command")
108119

109-
val result = ShellExecutor.evalAndGobble(osConfig.osType, command, workingDirectory = projectPath)
120+
val result = ShellExecutor.evalAndGobble(commandResolver.osConfig.osType, command, workingDirectory = projectPath)
110121

111122
if (result.exitCode != 0) {
112123
throw IllegalStateException("Packaging for path: '$projectPath' failed:$result")

src/main/kotlin/io/github/kscripting/kscript/util/Logger.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ object Logger {
44
var devMode = false
55
var silentMode = false
66

7-
fun info(msg: String) = printer(msg)
8-
fun infoMsg(message: String) = if (!silentMode) printer(message, KSCRIPT_NAME) else ""
9-
fun devMsg(message: String) = if (devMode) printer(message, KSCRIPT_NAME, "DEV") else ""
10-
fun warnMsg(msg: String) = printer(msg, KSCRIPT_NAME, "WARN")
7+
fun info(msg: String = "") = printer(msg)
8+
fun infoMsg(message: String = "") = if (!silentMode) printer(message, KSCRIPT_NAME) else ""
9+
fun devMsg(message: String = "") = if (devMode) printer(message, KSCRIPT_NAME, "DEV") else ""
10+
fun warnMsg(msg: String = "") = printer(msg, KSCRIPT_NAME, "WARN")
1111
fun errorMsg(exception: Exception): String {
1212
var message = exception.message ?: exception.javaClass.simpleName
1313

@@ -17,7 +17,7 @@ object Logger {
1717

1818
return errorMsg(message)
1919
}
20-
fun errorMsg(msg: String) = printer(msg, KSCRIPT_NAME, "ERROR")
20+
fun errorMsg(msg: String = "") = printer(msg, KSCRIPT_NAME, "ERROR")
2121

2222
private fun printer(message: String, vararg tags: String): String {
2323
var prefix = tags.joinToString(" ") { "[$it]" }

0 commit comments

Comments
 (0)