Skip to content

Commit

Permalink
Rewrite StreamGobbler (#1692)
Browse files Browse the repository at this point in the history
  • Loading branch information
nulls authored Jun 13, 2023
1 parent d7d39f0 commit 4f23c71
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 80 deletions.
1 change: 1 addition & 0 deletions diktat-test-framework/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies {
implementation(libs.apache.commons.cli)
implementation(libs.apache.commons.io)
implementation(libs.kotlin.logging)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlin.multiplatform.diff)
testImplementation(libs.junit.jupiter)
testImplementation(libs.assertj.core)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package com.saveourtool.diktat.test.framework.common

import mu.KotlinLogging

import java.io.IOException
import java.io.InputStream
import java.nio.charset.Charset
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.runBlocking

/**
* Class that wraps shell [command] and can execute it
*/
class LocalCommandExecutor internal constructor(private val command: String) {
class LocalCommandExecutor internal constructor(
private val command: String,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
) {
/**
* Execute [command]
*
Expand All @@ -18,17 +29,12 @@ class LocalCommandExecutor internal constructor(private val command: String) {
log.info { "Executing command: $command" }
val process = Runtime.getRuntime().exec(command)
process.outputStream.close()
val inputStream = process.inputStream
val outputGobbler = StreamGobbler(inputStream, "OUTPUT") { msg, ex ->
log.error(ex, msg)
}
outputGobbler.start()
val errorStream = process.errorStream
val errorGobbler = StreamGobbler(errorStream, "ERROR") { msg, ex ->
log.error(ex, msg)
return runBlocking {
ExecutionResult(
process.inputStream.readLinesAsync("OUTPUT", ioDispatcher).toList(),
process.errorStream.readLinesAsync("ERROR", ioDispatcher).toList(),
)
}
errorGobbler.start()
return ExecutionResult(outputGobbler.content, errorGobbler.content)
} catch (ex: IOException) {
log.error("Execution of $command failed", ex)
}
Expand All @@ -37,5 +43,22 @@ class LocalCommandExecutor internal constructor(private val command: String) {

companion object {
private val log = KotlinLogging.logger {}

/**
* @param streamType
* @param ioDispatcher
* @return [Flow] of strings from input stream
*/
fun InputStream.readLinesAsync(streamType: String, ioDispatcher: CoroutineDispatcher): Flow<String> = flow {
try {
val bufferedReader = this@readLinesAsync.bufferedReader(Charset.defaultCharset())
while (true) {
val line = bufferedReader.readLine() ?: break
emit(line)
}
} catch (ex: IOException) {
log.error(ex) { "Failed to consume and display the input stream of type $streamType." }
}
}.flowOn(ioDispatcher)
}
}
5 changes: 4 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ save-cli = "0.3.9"
ktor = "2.2.4"
okio = "3.3.0"
kotlinx-datetime = "0.4.0"
kotlinx-coroutines = "1.6.4"
kotlinx-coroutines = "1.7.1"
assertj = "3.24.2"
diktat = "2.0.0"
jgit = "6.5.0.202303070854-r"
Expand Down Expand Up @@ -102,6 +102,9 @@ kotlinx-serialization-json-jvm = { module = "org.jetbrains.kotlinx:kotlinx-seria
# another serialization
kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "kaml" }

# kotlinx coroutines
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }

#kotlin libs
kotlin-multiplatform-diff = { module = "io.github.petertrr:kotlin-multiplatform-diff", version.ref = "kotlin-multiplatform-diff" }

Expand Down

0 comments on commit 4f23c71

Please sign in to comment.