Skip to content
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

Argument Files (@argfiles) Fail On Redirects (e.g., @<(echo foo)) #527

Closed
adamsmd opened this issue Jul 8, 2024 · 1 comment · Fixed by #528
Closed

Argument Files (@argfiles) Fail On Redirects (e.g., @<(echo foo)) #527

adamsmd opened this issue Jul 8, 2024 · 1 comment · Fixed by #528

Comments

@adamsmd
Copy link

adamsmd commented Jul 8, 2024

Summary

Using a Bash redirect with an argument file (@argfile) produces an error Error: /dev/fd/63 not found.

Environment

Clikt: 4.4.0
Kotlin: 1.9.22
Platform: Tested on JVM with Linux. Unsure about others.

Code

The following code demonstraits this error:

src/main/kotlin/Main.kt:

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.context
import java.io.File

fun main(args: Array<String>) {
    println(args.toList())
    Main().main(args)
}

class Main : CliktCommand() {
    // init { context { argumentFileReader = { File(it).readText() } } }
    override fun run() {}
}

build.gradle.kts:

repositories {
  mavenCentral()
}

plugins {
  kotlin("jvm") version "1.9.22"
  application
}

dependencies {
  implementation("com.github.ajalt.clikt:clikt:4.4.0")
}

application {
  mainClass = "MainKt"
}

Actual Output

$ ./gradlew build installDist
> Task :checkKotlinGradlePluginConfigurationErrors
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :jar UP-TO-DATE
> Task :startScripts UP-TO-DATE
> Task :distTar UP-TO-DATE
> Task :distZip UP-TO-DATE
> Task :assemble UP-TO-DATE
> Task :compileTestKotlin NO-SOURCE
> Task :compileTestJava NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test NO-SOURCE
> Task :check UP-TO-DATE
> Task :build UP-TO-DATE
> Task :installDist UP-TO-DATE

BUILD SUCCESSFUL in 665ms
7 actionable tasks: 1 executed, 6 up-to-date

$ ./build/install/clikt-bug/bin/clikt-bug @<(echo foo)
[@/dev/fd/63]
Usage: main [<options>]

Error: /dev/fd/63 not found

Expected Output

$ ./build/install/clikt-bug/bin/clikt-bug @<(echo foo)
[@/dev/fd/63]
Usage: main [<options>]

Error: got unexpected extra argument (foo)

Workaround

Uncommenting the init line in Main produces the expected output.

Cause

The default argumentFileReader is at

val argumentFileReader: ((filename: String) -> String)?
get() = readArgumentFile

This calls readArgumentFile in MordantContext.kt at

readArgumentFile = { MultiplatformSystem.readFileAsUtf8(it) ?: throw FileNotFound(it) }

That calls MultiplatformSystem.readFileAsUtf8() at https://github.com/ajalt/mordant/blob/d24d2fa2794d57ac92e8a59445fe408ca0a598f1/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/platform/MultiplatformSystem.kt#L34-L41

That calls readFileIfExists at https://github.com/ajalt/mordant/blob/d24d2fa2794d57ac92e8a59445fe408ca0a598f1/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppInternal.jvm.kt#L151-L155

Which finally calls java.io.File.isFile() which returns false on pipes and devices.

Recommended Fix

In https://github.com/ajalt/mordant/blob/d24d2fa2794d57ac92e8a59445fe408ca0a598f1/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppInternal.jvm.kt#L151-L155, instead of calling isFile(), catch the FileNotFoundException when opening the file.

Note

The following documentation should be updated to reflect whatever fix is made here.

* argumentFileReader = {
* with(Paths.get(it)) {
* if (isRegularFile()) readText() else throw FileNotFound(it)
* }
* }

@ajalt
Copy link
Owner

ajalt commented Jul 9, 2024

Thanks for the detailed write-up! I fixed this in ajalt/mordant#188, and I'll be making a bugfix release of mordant soon, so you can use it without waiting for a clikt release.

I also updated the clikt docs with your recommendation.

@ajalt ajalt closed this as completed in #528 Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants