radistao
(radistao)
June 28, 2019, 7:23am
1
I’m migrating to Kotlin DSL.
The old commands look like:
final gitBranch = "git rev-parse --abbrev-ref HEAD".execute().text.trim()
final gitTag = "git tag -l --points-at HEAD".execute().text.trim()
final gitCommitId = "git rev-parse --short=8 HEAD".execute().text.trim()
In Kotlin DSL i have not found the same way.
Tried this approach:https://stackoverflow.com/questions/35421699/how-to-invoke-external-command-from-within-kotlin-code
but is there is any built-in way?
Lance
(uklance)
June 28, 2019, 7:28am
2
Perhaps the kotlin equivalent of
project.exec {
commandLine = "git rev-parse --abbrev-ref HEAD".split(" ")
}
radistao
(radistao)
June 28, 2019, 7:31am
3
But how than i capture the output?
Lance
(uklance)
June 28, 2019, 7:43am
4
String.execute()
is a groovy enhancement which is why it’s not available in Kotlin. It has nothing to do with Gradle. See Groovy String Enhancements
But how than i capture the output?
See Project.exec(ExecSpec)
Eg:
ByteArrayOutputStream byteOut = new ByteArrayOutputStream()
project.exec {
commandLine = "git rev-parse --abbrev-ref HEAD".split(" ")
standardOutput = byteOut
}
String output = new String(byteOut.toByteArray())
radistao
(radistao)
June 28, 2019, 8:45am
5
I hoped to have smth shorter ((. Than i’d better introduce a function, like in this answer:
exec, kotlin
fun String.runCommand(workingDir: File = file("./")): String {
val parts = this.split("\\s".toRegex())
val proc = ProcessBuilder(*parts.toTypedArray())
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
proc.waitFor(1, TimeUnit.MINUTES)
return proc.inputStream.bufferedReader().readText().trim()
}
Lance
(uklance)
June 28, 2019, 8:51am
6
I’d use project.exec
rather than ProcessBuilder
directly. I’m sure there’s some nice error handling etc in the Gradle version
radistao
(radistao)
June 28, 2019, 9:23am
7
unfortunately i’ve not understood how to use that code snippe with project.exec
. Shall i repeat all these 5 lines for each command i want to execute?
with ProcessBuilder
i declare fun runCommand
once and reuse it in the build script:
fun String.runCommand(workingDir: File = file("./")): String {
val parts = this.split("\\s".toRegex())
val proc = ProcessBuilder(*parts.toTypedArray())
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
proc.waitFor(1, TimeUnit.MINUTES)
return proc.inputStream.bufferedReader().readText().trim()
}
val gitBranch = "git rev-parse --abbrev-ref HEAD".runCommand()
val gitTag = "git tag -l --points-at HEAD".runCommand()
val gitCommitId = "git rev-parse --short=8 HEAD".runCommand()
Lance
(uklance)
June 28, 2019, 11:38am
9
Here’s what it might look like in groovy
def runCommand = { Project project, String command ->
ByteArrayOutputStream byteOut = new
ByteArrayOutputStream()
project.exec {
commandLine = command.split(" ")
standardOutput = byteOut
}
return new String(byteOut.toByteArray()).trim()
}
def gitBranch = runCommand(project, "git rev-parse --abbrev-ref HEAD")
def gitTag = runCommand(project, "git tag -l --points-at HEAD")
def gitCommitId = runCommand(project, "git rev-parse --short=8 HEAD")
1 Like
radistao
(radistao)
July 1, 2021, 10:37am
10
ok, for Kotlin DSL it looks like this:
fun String.runCommand(currentWorkingDir: File = file("./")): String {
val byteOut = ByteArrayOutputStream()
project.exec {
workingDir = currentWorkingDir
commandLine = this@runCommand.split("\\s".toRegex())
standardOutput = byteOut
}
return String(byteOut.toByteArray()).trim()
}
val gitBranch = "git branch --show-current".runCommand()
val gitTag = "git tag -l --points-at HEAD".runCommand()
val gitCommitId = "git rev-parse HEAD".runCommand()
1 Like
seal
(seal.wu)
August 20, 2022, 12:17pm
11
There is a kotlin library for easy run external command
Add this gradle dependency:
implementation("com.sealwu:kscript-tools:1.0.1")
And can run comamnd like this:
"cd ~ && ls".runCommand()
Output:
Applications Downloads MavenDep Pictures iOSProjects
Desktop IdeaProjects Movies Public scripts
Documents Library Music StudioProjects
Also you can get the output of command line by using evalBash
val date = "date".evalBash().getOrThrow() //execute shell command `date` and get the command's output and set the content to date variable
println(date) //This will print Fri Aug 19 21:59:56 CEST 2022 on console
val year = date.substringAfterLast(" ") // will get 2022 and assign to
println(year)
Output:
Fri Aug 19 21:59:56 CEST 2022
2022
Vampire
(Björn Kautler)
August 21, 2022, 12:50am
12
And still you shouldn’t use it, but should use Exec
task or exec
methods to call external processes in the Gradle context.