-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathProcessUtil.kt
More file actions
77 lines (68 loc) · 2.19 KB
/
Copy pathProcessUtil.kt
File metadata and controls
77 lines (68 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.Reader
import kotlin.time.Duration
import java.util.concurrent.TimeUnit
object ProcessUtil {
data class Result(
val exitCode: Int,
val stdout: String,
val stderr: String,
val isTimeout: Boolean, // true if the process was terminated due to timeout
)
fun run(
command: List<String>,
input: Reader = "".reader(),
timeout: Duration? = null,
builder: ProcessBuilder.() -> Unit = {},
): Result {
val process = ProcessBuilder(command).apply(builder).start()
return communicate(process, input, timeout)
}
private fun communicate(
process: Process,
input: Reader,
timeout: Duration? = null,
): Result {
val stdout = StringBuilder()
val stderr = StringBuilder()
val scope = CoroutineScope(Dispatchers.IO)
// Handle process input
val stdinJob = scope.launch {
process.outputStream.bufferedWriter().use { writer ->
input.copyTo(writer)
}
}
// Launch output capture coroutines
val stdoutJob = scope.launch {
process.inputStream.bufferedReader().useLines { lines ->
lines.forEach { stdout.appendLine(it) }
}
}
val stderrJob = scope.launch {
process.errorStream.bufferedReader().useLines { lines ->
lines.forEach { stderr.appendLine(it) }
}
}
// Wait for completion
val isTimeout = if (timeout != null) {
!process.waitFor(timeout.inWholeNanoseconds, TimeUnit.NANOSECONDS)
} else {
process.waitFor()
false
}
// Wait for all coroutines to finish
runBlocking {
joinAll(stdinJob, stdoutJob, stderrJob)
}
return Result(
exitCode = process.exitValue(),
stdout = stdout.toString(),
stderr = stderr.toString(),
isTimeout = isTimeout,
)
}
}