-
Notifications
You must be signed in to change notification settings - Fork 499
/
CommandExecutorImpl.kt
49 lines (46 loc) · 1.61 KB
/
CommandExecutorImpl.kt
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
package org.oppia.android.scripts.common
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import java.io.File
import java.util.concurrent.TimeUnit
/**
* The default amount of time that should be waited before considering a process as 'hung', in
* milliseconds.
*/
const val WAIT_PROCESS_TIMEOUT_MS = 60_000L
/** Default implementation of [CommandExecutor]. */
class CommandExecutorImpl(
private val scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher,
private val processTimeout: Long = WAIT_PROCESS_TIMEOUT_MS,
private val processTimeoutUnit: TimeUnit = TimeUnit.MILLISECONDS
) : CommandExecutor {
override fun executeCommand(
workingDir: File,
command: String,
vararg arguments: String,
includeErrorOutput: Boolean
): CommandResult {
check(workingDir.isDirectory) {
"Expected working directory to be an actual directory: $workingDir"
}
val assembledCommand = listOf(command) + arguments.toList()
val process =
ProcessBuilder(assembledCommand)
.directory(workingDir)
.redirectErrorStream(includeErrorOutput)
.start()
val finished = runBlocking {
CoroutineScope(scriptBgDispatcher).async {
process.waitFor(processTimeout, processTimeoutUnit)
}.await()
}
check(finished) { "Process did not finish within the expected timeout" }
return CommandResult(
process.exitValue(),
process.inputStream.bufferedReader().readLines(),
if (!includeErrorOutput) process.errorStream.bufferedReader().readLines() else listOf(),
assembledCommand,
)
}
}