Skip to content

Commit 147adbb

Browse files
committed
Added tests for local jar files.
Signed-off-by: Marcin Kuszczak <1508798+aartiPl@users.noreply.github.com>
1 parent 0e36ff3 commit 147adbb

15 files changed

Lines changed: 127 additions & 50 deletions

File tree

NEWS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
* Improved implementation: VersionChecker, ConfigBuilder etc.
1818
* Updated Gradle and dependencies
1919
* Deprecated @file:Include in favour of @file:Import as a preparation of switch to Kotlin Scripting
20-
* Get rid of docopt handler from KscriptHandler (helps with using kscript as library)
20+
* Replaced DocOpt with Apache CLI
2121
* Changed the way of creating distribution package - now it is handled by Gradle
2222
* Version of kscript is set by Gradle (generated BuildConfig class)
2323
* Improved DependencyResolver: aar archives are also included in classpath
2424
* When creating IntelliJ project Gradle and Idea are no more required
25-
* Ability to provide local artifacts path through KSCRIPT_DIRECTORY_ARTIFACTS or configuration file property:
26-
scripting.directory.artifacts (thanks to [Vsajip](https://github.com/vsajip) for initial implementation)
25+
* Ability to provide local artifacts path through **KSCRIPT_DIRECTORY_ARTIFACTS** or configuration file property:
26+
**scripting.directory.artifacts** (thanks to [Vsajip](https://github.com/vsajip) for initial implementation)
2727

2828
**Bugfixes**
2929

README.md

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ kotlin scripting interpreter.
4040
- [Script Configuration](#script-configuration)
4141
- [Text Processing Mode](#text-processing-mode)
4242
- [Treat yourself a REPL with `--interactive`](#treat-yourself-a-repl-with---interactive)
43-
- [Boostrap IDEA from a `kscript`let](#boostrap-idea-from-a-kscriptlet)
43+
- [Boostrap IDEA from a scriptlet](#boostrap-idea-from-a-scriptlet)
4444
- [Deploy scripts as standalone binaries](#deploy-scripts-as-standalone-binaries)
4545
- [Embed kscript installer within your script](#embed-kscript-installer-within-your-script)
4646
- [KScript configuration file](#kscript-configuration-file)
@@ -105,7 +105,8 @@ instance [bind mounts](https://docs.docker.com/storage/bind-mounts/).
105105
#### Installation without `sdkman`
106106

107107
If you have Kotlin already, and you would like to install the latest `kscript` release without using `sdkman`
108-
you can do so by unzipping the [latest ](https://github.com/holgerbrandl/kscript/releases/latest) binary release. Don't forget to update your `$PATH` accordingly.
108+
you can do so by unzipping the [latest ](https://github.com/holgerbrandl/kscript/releases/latest) binary release. Don't
109+
forget to update your `$PATH` accordingly.
109110

110111
#### Installation with Homebrew
111112

@@ -132,6 +133,23 @@ favorite [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers) to insta
132133
yay -S kscript
133134
```
134135

136+
There is an uncommon directory layout of Kotlin package for Arch Linux, which causes problems when using kscript with
137+
default Kotlin package.
138+
Two workarounds for ArchLinux exists, which can be used to make 'kscript' working with ArchLinux:
139+
140+
1. Manually create symlinks in the system:
141+
142+
```shell
143+
sudo mkdir /usr/share/kotlin/bin
144+
sudo ln -s /usr/bin/kotlin /usr/share/kotlin/bin/kotlin
145+
sudo ln -s /usr/bin/kotlinc /usr/share/kotlin/bin/kotlinc
146+
```
147+
2. Install Kotlin using SdkMan:
148+
[Installation of SdkMan](#installation)
149+
150+
The problem should be fixed in the Kotlin package for ArchLinux. See more in the Github issue:
151+
https://github.com/kscripting/kscript/issues/371
152+
135153
#### Build it yourself
136154

137155
To build `kscript` yourself, simply clone the repo and do
@@ -279,12 +297,14 @@ println("Hello from Kotlin!")
279297
println("Parsed script arguments are: \n" + doArgs)
280298
```
281299
282-
`kscript` will read dependencies from all lines in a script that start with `@file:DependsOn` (if any). Multiple dependencies can
300+
`kscript` will read dependencies from all lines in a script that start with `@file:DependsOn` (if any). Multiple
301+
dependencies can
283302
be split by comma, space or semicolon.
284303
285304
### Configure the runtime with `@file:KotlinOptions`
286305
287-
`kscript` allows to provide a `@file:KotlinOptions` directive followed by parameters passed on to `kotlin` similar to how
306+
`kscript` allows to provide a `@file:KotlinOptions` directive followed by parameters passed on to `kotlin` similar to
307+
how
288308
dependencies are defined:
289309
290310
```kotlin
@@ -298,7 +318,8 @@ Note: Similar to the runtime you can also tweak the compile step by providing `@
298318
299319
### Ease prototyping with `@file:Import`
300320
301-
`kscript` supports an `@file:Import` directive to directly include other source files without prior compilation. Absolute
321+
`kscript` supports an `@file:Import` directive to directly include other source files without prior compilation.
322+
Absolute
302323
and relative paths, as well as URLs are supported. Example:
303324
304325
```kotlin
@@ -359,7 +380,7 @@ The latter is the default for `kt` files and could be omitted
359380
#!/usr/bin/env kscript
360381
361382
// Declare dependencies
362-
@file:DependsOn("com.github.holgerbrandl:kutils:0.12")
383+
@file:DependsOn("com.github.holgerbrandl:kutils:0.12")
363384
@file:DependsOn("com.beust:klaxon:0.24", "com.github.kittinunf.fuel:fuel:2.3.1")
364385
365386
// To use a custom maven repository you can declare it with
@@ -380,8 +401,8 @@ The latter is the default for `kt` files and could be omitted
380401
@file:Import("util.kt")
381402
382403
// Define kotlin options
383-
@file:KotlinOptions("-J-Xmx5g")
384-
@file:KotlinOptions("-J-server")
404+
@file:KotlinOptions("-J-Xmx5g")
405+
@file:KotlinOptions("-J-server")
385406
@file:CompilerOptions("-jvm-target 1.8")
386407
387408
// declare application entry point (applies on for kt-files)
@@ -472,7 +493,7 @@ Welcome to Kotlin version 1.1.51 (JRE 1.8.0_151-b12)
472493
>>>
473494
```
474495
475-
Boostrap IDEA from a `kscript`let
496+
Boostrap IDEA from a scriptlet
476497
-----------------------------------
477498
478499
Artifacts and versions will differ between scripts, so it is hard to maintain them all in a single project. To
@@ -483,14 +504,14 @@ for `<script>` arguments.
483504
kscript --idea CountRecords.kts
484505
```
485506
486-
If you have available `gradle` in the path project will be automatically built and if there is `idea` in the path
487-
the project will be opened in [IntelliJ IDEA](https://www.jetbrains.com/idea/) with a minimalistic project containing
507+
If you have available `gradle` in the path project will be automatically built and if there is `idea` in the path
508+
the project will be opened in [IntelliJ IDEA](https://www.jetbrains.com/idea/) with a minimalistic project containing
488509
just your (1) `<script>` and (2) a generated `build.gradle.kts` file:
489510
490511
![](misc/readme_images/minus_idea.png)
491512
492-
The `idea` command line launcher can can be created in IntelliJ with `Create Command-line Launcher` command, or you can
493-
set the command used to launch your IntelliJ as `KSCRIPT_COMMAND_IDEA` env property. Similarly, you can set `gradle`
513+
The `idea` command line launcher can can be created in IntelliJ with `Create Command-line Launcher` command, or you can
514+
set the command used to launch your IntelliJ as `KSCRIPT_COMMAND_IDEA` env property. Similarly, you can set `gradle`
494515
command using `KSCRIPT_COMMAND_GRADLE` env property.
495516
496517
Deploy scripts as standalone binaries
@@ -523,7 +544,7 @@ the [Installation](#installation) steps first.
523544
524545
Note that unlike the [`--package` option](#deploy-scripts-as-standalone-binaries) this doesn't produce a separate file,
525546
allowing the distributed script to be read and modified(including
526-
with [`kscript --idea`](#boostrap-idea-from-a-kscriptlet)) similar to what you might expect with bash/python/ruby
547+
with [`kscript --idea`](#boostrap-idea-from-a-scriptlet)) similar to what you might expect with bash/python/ruby
527548
scripts.
528549
On the other hand this doesn't embed dependencies within the script("fat jar"), so internet connection may be required
529550
on its first run.
@@ -533,14 +554,17 @@ kscript configuration file
533554
534555
To keep some options stored permanently in configuration you can create kscript configuration file.
535556
536-
KScript follows XDG directory standard, so the file should be created in:
537-
557+
KScript follows XDG directory standard, so the file should be created in (paths are resolved in provided order; first
558+
existing path is used):
538559
539-
| OS | PATH |
540-
|-------------|-------------------------------------------------------------------------------------|
541-
| **Windows** | %LOCALAPPDATA%\kscript.properties |
542-
| **Posix** | \\${XDG_CONFIG_DIR}/kscript.properties or \\${user.home}/.config/kscript.properties |
560+
| OS | PATH |
561+
|-------------|---------------------------------------------------------------------------------------------------|
562+
| **Windows** | %LOCALAPPDATA%\kscript\kscript.properties; %USERPROFILE%\.config\kscript\kscript.properties |
563+
| **MacOs** | ~/Library/Application Support/kscript/kscript.properties; |
564+
| **Posix** | \\${XDG_CONFIG_DIR}/kscript/kscript.properties; \\${user.home}/.config/kscript/kscript.properties |
543565
566+
If the environment variable: **KSCRIPT_DIRECTORY** is defined the configuration file 'kscript.properties' will be placed
567+
directly inside it.
544568
545569
Content of kscript.properties file is a standard Java format, with following properties available:
546570
@@ -550,6 +574,7 @@ scripting.kotlin.opts=
550574
scripting.repository.url=
551575
scripting.repository.user=
552576
scripting.repository.password=
577+
scripting.directory.artifacts=
553578
```
554579
555580
Example configuration file:
@@ -594,11 +619,12 @@ is a valid Kotlin `kts` script. Plain and simple, no `main`, no `companion`, jus
594619
595620
### Does `kscript` also work for regular kotlin `.kt` source files with a `main` as entry point?
596621
597-
Yes, (since kscript v1.6) you can run kotlin source files through `kscript`. By default, it will assume a top-level `main` method
622+
Yes, (since kscript v1.6) you can run kotlin source files through `kscript`. By default, it will assume a
623+
top-level `main` method
598624
as entry-point.
599625
600-
However, in case you're using a companion object to declare the entry point, you need to indicate this via the `@file:Entry`.
601-
626+
However, in case you're using a companion object to declare the entry point, you need to indicate this via
627+
the `@file:Entry`.
602628
603629
### What are performance and resource usage difference between scripting with kotlin and python?
604630

TODO.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# kscript 4.2 features:
22

33
* Release kscript to Maven Central
4-
* Change a way of executing .kts files (investigate if we can get rid of reflections)
5-
* Fix the bug on ArchLinux
6-
* Onboard on brew
74
* Test local artifacts directory
85

6+
* Change a way of executing .kts files (investigate if we can get rid of reflections)
7+
* Onboard on brew
98
* Deprecate KotlinOptions
109
* New package for Windows e.g. scoop
1110
* Release scripts in Kotlin

src/integration/kotlin/io/github/kscripting/kscript/integration/KtSupportTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class KtSupportTest : TestBase {
1111
@Test
1212
@Tag("posix")
1313
fun `Run kt via interpreter mode`() {
14-
verify(resolvePath("$projectDir/test/resources/kt_tests/simple_app.kt"), 0, "main was called\n", any())
14+
verify(resolvePath("$projectDir/test/resources/kt_tests/simple_app.kt").stringPath(), 0, "main was called\n", any())
1515
}
1616

1717
@Test
@@ -43,6 +43,6 @@ class KtSupportTest : TestBase {
4343
@Test
4444
@Tag("posix")
4545
fun `Also make sure that kts in package can be run via kscript`() {
46-
verify(resolvePath("$projectDir/test/resources/script_in_pckg.kts"), 0, "I live in a package!\n", any())
46+
verify(resolvePath("$projectDir/test/resources/script_in_pckg.kts").stringPath(), 0, "I live in a package!\n", any())
4747
}
4848
}

src/integration/kotlin/io/github/kscripting/kscript/integration/MiscTest.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.github.kscripting.kscript.integration.tools.TestAssertion.any
44
import io.github.kscripting.kscript.integration.tools.TestAssertion.contains
55
import io.github.kscripting.kscript.integration.tools.TestAssertion.verify
66
import io.github.kscripting.kscript.integration.tools.TestContext.projectDir
7+
import io.github.kscripting.kscript.integration.tools.TestContext.resolvePath
78
import io.github.kscripting.kscript.integration.tools.TestContext.testDir
89
import org.junit.jupiter.api.Tag
910
import org.junit.jupiter.api.Test
@@ -31,7 +32,11 @@ class MiscTest : TestBase {
3132
@Tag("windows")
3233
fun `Prevent regressions of #98 (it fails to process empty or space-containing arguments)`() {
3334
verify("""kscript "print(args.size)" foo bar""", 0, "2") //regular args
34-
verify("""kscript "print(args.size)" "--params foo"""", 0, "1") //make sure dash args are not confused with options
35+
verify(
36+
"""kscript "print(args.size)" "--params foo"""",
37+
0,
38+
"1"
39+
) //make sure dash args are not confused with options
3540
verify("""kscript "print(args.size)" "foo bar"""", 0, "1") //allow for spaces
3641
}
3742

@@ -77,4 +82,17 @@ class MiscTest : TestBase {
7782
//real test
7883
verify("kscript $projectDir/test/resources/invalid_script.kts", 1, "", contains("error: expecting ')'"))
7984
}
85+
86+
@Test
87+
@Tag("posix")
88+
@Tag("windows")
89+
fun `Test local jar dir referenced in ENV variable`() {
90+
val shellPath = resolvePath("$projectDir/test/resources/config/")
91+
verify(
92+
"KSCRIPT_DIRECTORY_ARTIFACTS=${shellPath.resolve("jarFiles")} kscript ${shellPath.resolve("script_with_local_jars.kts")}",
93+
0,
94+
"I am living in Test1 class...\nAnd I come from Test2 class...\n",
95+
""
96+
)
97+
}
8098
}

src/integration/kotlin/io/github/kscripting/kscript/integration/tools/TestContext.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ object TestContext {
3333
testPath.createDirectories()
3434
}
3535

36-
fun resolvePath(path: String): String {
37-
return OsPath.createOrThrow(osType, path).stringPath()
36+
fun resolvePath(path: String): OsPath {
37+
return OsPath.createOrThrow(osType, path)
3838
}
3939

4040
fun runProcess(command: String): GobbledProcessResult {

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,13 @@ class KscriptHandler(
7070
warnMsg("There are deprecated features in scripts. Use --report option to print full report.")
7171
}
7272

73-
val localArtifacts = if (config.scriptingConfig.artifactsDir != null) {
74-
getArtifactsRecursively(config.scriptingConfig.artifactsDir)
75-
} else emptyList()
76-
7773
val resolvedDependencies = cache.getOrCreateDependencies(script.digest) {
78-
DependencyResolver(script.repositories).resolve(script.dependencies)
79-
} + localArtifacts
74+
val localArtifacts = if (config.scriptingConfig.artifactsDir != null) {
75+
getArtifactsRecursively(config.scriptingConfig.artifactsDir)
76+
} else emptyList()
77+
78+
DependencyResolver(script.repositories).resolve(script.dependencies) + localArtifacts
79+
}
8080

8181
// Create temporary dev environment
8282
if (options.containsKey("idea")) {

src/main/kotlin/io/github/kscripting/kscript/model/ConfigBuilder.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class ConfigBuilder(
6363
val configFile: OsPath = configFile ?: kscriptDir?.resolve("kscript.properties") ?: when {
6464
osType.isWindowsLike() -> environment.getEnvVariableOrNull("LOCALAPPDATA")?.toOsPathFromNative()
6565
?: userHomeDir.resolve(".config")
66-
6766
osType == OsType.MACOS -> userHomeDir.resolve("Library", "Application Support")
6867
else -> environment.getEnvVariableOrNull("XDG_CONFIG_DIR")?.toOsPathFromNative()
6968
?: userHomeDir.resolve(".config")
@@ -110,7 +109,7 @@ class ConfigBuilder(
110109
?: configProperties.getPropertyOrNull("scripting.repository.password") ?: ""
111110

112111
val artifactsDir: OsPath? =
113-
artifactsDir ?: environment.getEnvVariableOrNull("KSCRIPT_DIRECTORY_ARTIFACTS")?.toOsPathFromNative()
112+
artifactsDir ?: environment.getEnvVariableOrNull("KSCRIPT_DIRECTORY_ARTIFACTS")?.toOsPathFromOsSpecific(osType)
114113
?: configProperties.getPropertyOrNull("scripting.directory.artifacts")?.toOsPathFromOsSpecific(osType)
115114

116115
val scriptingConfig = ScriptingConfig(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ object FileUtils {
5959
fun getArtifactsRecursively(osPath: OsPath): List<OsPath> {
6060
val artifacts = mutableListOf<OsPath>()
6161

62-
osPath.toNativeFile().walk().forEach {
62+
osPath.toNativeFile().absoluteFile.walk().forEach {
6363
if (it.isFile && (it.extension == "jar" || it.extension == "aar")) {
6464
artifacts.add(it.toOsPath())
6565
}
Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
package io.github.kscripting.kscript.util
22

3+
import assertk.assertThat
4+
import assertk.assertions.isEqualTo
35
import io.github.kscripting.shell.model.OsPath
46
import io.github.kscripting.shell.model.OsType
7+
import io.github.kscripting.shell.model.readText
58
import io.github.kscripting.shell.model.toNativeFile
69
import org.junit.jupiter.api.BeforeEach
7-
import org.junit.jupiter.api.Disabled
810
import org.junit.jupiter.api.Test
911
import org.apache.commons.io.FileUtils as ApacheFileUtils
1012

11-
@Disabled
1213
class FileUtilsTest {
1314
private val path = OsPath.createOrThrow(OsType.native, "build/tmp/file_utils_test")
15+
private val newFile1 = path.resolve("test1.txt")
16+
private val newFile2 = path.resolve("test2.txt")
17+
private val newFile3 = path.resolve("firstDir", "secondDir", "test3.txt")
18+
private val newFile4 = path.resolve("dir1", "dir2", "test4.txt")
19+
private val content1 = "Test\nContent\n"
1420

1521
@BeforeEach
1622
fun setUp() {
@@ -19,18 +25,32 @@ class FileUtilsTest {
1925

2026
@Test
2127
fun `Test create file`() {
22-
FileUtils.createFile(path.resolve("test1"), "Test")
28+
FileUtils.createFile(newFile1, content1)
29+
assertThat(newFile1.readText()).isEqualTo(content1)
2330
}
2431

2532
@Test
2633
fun `Test symlink file`() {
27-
FileUtils.createFile(path.resolve("test1"), "Test")
28-
FileUtils.symLinkOrCopy(path.resolve("test2"), path.resolve("test1"))
34+
FileUtils.createFile(newFile1, content1)
35+
FileUtils.symLinkOrCopy(newFile2, newFile1)
36+
37+
assertThat(newFile2.readText()).isEqualTo(content1)
2938
}
3039

3140
@Test
3241
fun `Create dirs if needed`() {
33-
FileUtils.createFile(path.resolve("test1"), "Test")
34-
FileUtils.symLinkOrCopy(path.resolve("test2"), path.resolve("test1"))
42+
FileUtils.createFile(newFile3, content1)
43+
FileUtils.symLinkOrCopy(newFile4, newFile3)
44+
45+
assertThat(newFile4.readText()).isEqualTo(content1)
46+
}
47+
48+
@Test
49+
fun `Assert that getArtifactsRecursively finds all the artifacts in the path`() {
50+
val artifactsPath = OsPath.createOrThrow(OsType.native, "test/resources/config/jarfiles/")
51+
52+
assertThat(FileUtils.getArtifactsRecursively(artifactsPath)).transform {
53+
it.map { it.stringPath().substringAfterLast("jarfiles").replace("\\", "/") }
54+
}.isEqualTo(listOf("/jar_file_1.jar", "/subdir/jar_file_2.jar"))
3555
}
3656
}

0 commit comments

Comments
 (0)