mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-27 08:38:13 -07:00
Checkpoint.
This commit is contained in:
parent
e93f4ba85f
commit
8882c1cae5
4 changed files with 143 additions and 75 deletions
|
@ -6,65 +6,28 @@ import java.io.InputStream
|
|||
import java.io.InputStreamReader
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class RunCommand(val command: String) {
|
||||
val DEFAULT_SUCCESS = { output: List<String> -> }
|
||||
// val DEFAULT_SUCCESS_VERBOSE = { output: List<String> -> log(2, "Success:\n " + output.joinToString("\n"))}
|
||||
val defaultSuccess = DEFAULT_SUCCESS
|
||||
val DEFAULT_ERROR = {
|
||||
output: List<String> -> error(output.joinToString("\n "))
|
||||
}
|
||||
|
||||
var directory = File(".")
|
||||
var env = hashMapOf<String, String>()
|
||||
class RunCommandInfo {
|
||||
lateinit var command: String
|
||||
var args : List<String> = arrayListOf()
|
||||
var directory : File = File("")
|
||||
var env : Map<String, String> = hashMapOf()
|
||||
|
||||
/**
|
||||
* Some commands fail but return 0, so the only way to find out if they failed is to look
|
||||
* at the error stream. However, some commands succeed but output text on the error stream.
|
||||
* This field is used to specify how errors are caught.
|
||||
*/
|
||||
var useErrorStreamAsErrorIndicator = true
|
||||
var useInputStreamAsErrorIndicator = false
|
||||
var useErrorStreamAsErrorIndicator : Boolean = true
|
||||
var useInputStreamAsErrorIndicator : Boolean = false
|
||||
|
||||
fun useErrorStreamAsErrorIndicator(f: Boolean) : RunCommand {
|
||||
useErrorStreamAsErrorIndicator = f
|
||||
return this
|
||||
}
|
||||
var errorCallback: Function1<List<String>, Unit> = RunCommand.DEFAULT_ERROR
|
||||
var successCallback: Function1<List<String>, Unit> = RunCommand.DEFAULT_SUCCESS
|
||||
|
||||
open fun run(args: List<String>,
|
||||
errorCallback: Function1<List<String>, Unit> = DEFAULT_ERROR,
|
||||
successCallback: Function1<List<String>, Unit> = defaultSuccess) : Int {
|
||||
val allArgs = arrayListOf<String>()
|
||||
allArgs.add(command)
|
||||
allArgs.addAll(args)
|
||||
|
||||
val pb = ProcessBuilder(allArgs)
|
||||
pb.directory(directory)
|
||||
log(2, "Running command in directory ${directory.absolutePath}" +
|
||||
"\n " + allArgs.joinToString(" ").replace("\\", "/"))
|
||||
val process = pb.start()
|
||||
pb.environment().let { pbEnv ->
|
||||
env.forEach {
|
||||
pbEnv.put(it.key, it.value)
|
||||
}
|
||||
}
|
||||
val callSucceeded = process.waitFor(30, TimeUnit.SECONDS)
|
||||
val input = if (process.inputStream.available() > 0) fromStream(process.inputStream)
|
||||
else listOf()
|
||||
val error = if (process.errorStream.available() > 0) fromStream(process.errorStream)
|
||||
else listOf()
|
||||
val isSuccess = isSuccess(callSucceeded, input, error)
|
||||
|
||||
if (isSuccess) {
|
||||
successCallback(fromStream(process.inputStream))
|
||||
} else {
|
||||
errorCallback(error + input)
|
||||
}
|
||||
|
||||
return if (isSuccess) 0 else 1
|
||||
}
|
||||
|
||||
open protected fun isSuccess(callSucceeded: Boolean, input: List<String>, error: List<String>) : Boolean {
|
||||
var hasErrors = ! callSucceeded
|
||||
var isSuccess: (Boolean, List<String>, List<String>) -> Boolean = {
|
||||
isSuccess: Boolean,
|
||||
input: List<String>,
|
||||
error: List<String> ->
|
||||
var hasErrors = ! isSuccess
|
||||
if (useErrorStreamAsErrorIndicator && ! hasErrors) {
|
||||
hasErrors = hasErrors || error.size > 0
|
||||
}
|
||||
|
@ -72,9 +35,83 @@ open class RunCommand(val command: String) {
|
|||
hasErrors = hasErrors || input.size > 0
|
||||
}
|
||||
|
||||
! hasErrors
|
||||
}
|
||||
}
|
||||
|
||||
fun runCommand(init: RunCommandInfo.() -> Unit) = RunCommand(RunCommandInfo().apply { init() }).invoke()
|
||||
|
||||
open class RunCommand(val info: RunCommandInfo) {
|
||||
|
||||
companion object {
|
||||
val DEFAULT_SUCCESS = { output: List<String> -> }
|
||||
// val DEFAULT_SUCCESS_VERBOSE = { output: List<String> -> log(2, "Success:\n " + output.joinToString("\n"))}
|
||||
// val defaultSuccess = DEFAULT_SUCCESS
|
||||
val DEFAULT_ERROR = {
|
||||
output: List<String> ->
|
||||
error(output.joinToString("\n "))
|
||||
}
|
||||
}
|
||||
|
||||
// fun useErrorStreamAsErrorIndicator(f: Boolean) : RunCommand {
|
||||
// useErrorStreamAsErrorIndicator = f
|
||||
// return this
|
||||
// }
|
||||
|
||||
fun invoke() : Int {
|
||||
val allArgs = arrayListOf<String>()
|
||||
allArgs.add(info.command)
|
||||
allArgs.addAll(info.args)
|
||||
|
||||
val pb = ProcessBuilder(allArgs)
|
||||
pb.directory(info.directory)
|
||||
log(2, "Running command in directory ${info.directory.absolutePath}" +
|
||||
"\n " + allArgs.joinToString(" ").replace("\\", "/"))
|
||||
val process = pb.start()
|
||||
pb.environment().let { pbEnv ->
|
||||
info.env.forEach {
|
||||
pbEnv.put(it.key, it.value)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the command and collect the return code and streams
|
||||
val returnCode = process.waitFor(30, TimeUnit.SECONDS)
|
||||
val input = if (process.inputStream.available() > 0) fromStream(process.inputStream)
|
||||
else listOf()
|
||||
val error = if (process.errorStream.available() > 0) fromStream(process.errorStream)
|
||||
else listOf()
|
||||
|
||||
// Check to see if the command succeeded
|
||||
val isSuccess = isSuccess(returnCode, input, error)
|
||||
|
||||
if (isSuccess) {
|
||||
info.successCallback(input)
|
||||
} else {
|
||||
info.errorCallback(error + input)
|
||||
}
|
||||
|
||||
return if (isSuccess) 0 else 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this method to do their own error handling, since commands can
|
||||
* have various ways to signal errors.
|
||||
*/
|
||||
open protected fun isSuccess(isSuccess: Boolean, input: List<String>, error: List<String>) : Boolean {
|
||||
var hasErrors = ! isSuccess
|
||||
if (info.useErrorStreamAsErrorIndicator && ! hasErrors) {
|
||||
hasErrors = hasErrors || error.size > 0
|
||||
}
|
||||
if (info.useInputStreamAsErrorIndicator && ! hasErrors) {
|
||||
hasErrors = hasErrors || input.size > 0
|
||||
}
|
||||
|
||||
return ! hasErrors
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the given InputStream into a list of strings.
|
||||
*/
|
||||
private fun fromStream(ins: InputStream) : List<String> {
|
||||
val result = arrayListOf<String>()
|
||||
val br = BufferedReader(InputStreamReader(ins))
|
||||
|
|
|
@ -1,24 +1,54 @@
|
|||
package com.beust.kobalt.plugin.android
|
||||
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.misc.RunCommand
|
||||
import com.beust.kobalt.misc.log
|
||||
import com.beust.kobalt.misc.runCommand
|
||||
import java.io.File
|
||||
|
||||
open class AndroidCommand(project: Project, androidHome: String, command: String, cwd: File = File(project.directory))
|
||||
: RunCommand(command) {
|
||||
init {
|
||||
env.put("ANDROID_HOME", androidHome)
|
||||
directory = cwd
|
||||
}
|
||||
open class AndroidCommand(project: Project, val androidHome: String, val command: String,
|
||||
val directory: File = File(project.directory),
|
||||
val useErrorStreamAsErrorIndicator : Boolean = true,
|
||||
val args: List<String>)
|
||||
// : RunCommand(command, directory = cwd, args = args
|
||||
// ,
|
||||
// successCallback = { output ->
|
||||
// log(1, "$command succeeded:")
|
||||
// output.forEach {
|
||||
// log(1, " $it")
|
||||
// }
|
||||
// }
|
||||
{
|
||||
|
||||
open fun call(args: List<String>) = run(args,
|
||||
|
||||
// val SUCCESS_CALLBACK : (List<String>) -> Unit = { output ->
|
||||
// log(1, "$command succeeded:")
|
||||
// output.forEach {
|
||||
// log(1, " $it")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val ERROR_CALLBACK : (List<String>) -> Unit = { output ->
|
||||
// with(StringBuilder()) {
|
||||
// append("Error running $command:")
|
||||
// output.forEach {
|
||||
// append(" $it")
|
||||
// }
|
||||
// error(this.toString())
|
||||
// }
|
||||
// }nComman
|
||||
|
||||
open fun call(theseArgs: List<String>) : Int {
|
||||
val rc = runCommand {
|
||||
args = theseArgs
|
||||
useErrorStreamAsErrorIndicator = useErrorStreamAsErrorIndicator
|
||||
directory = directory
|
||||
env = hashMapOf("ANDROID_HOME" to androidHome)
|
||||
successCallback = { output ->
|
||||
log(1, "$command succeeded:")
|
||||
output.forEach {
|
||||
log(1, " $it")
|
||||
}
|
||||
},
|
||||
}
|
||||
errorCallback = { output ->
|
||||
with(StringBuilder()) {
|
||||
append("Error running $command:")
|
||||
|
@ -27,7 +57,10 @@ open class AndroidCommand(project: Project, androidHome: String, command: String
|
|||
}
|
||||
error(this.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return rc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -107,15 +107,12 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
|
|||
* aapt returns 0 even if it fails, so in order to detect whether it failed, we are checking
|
||||
* if its error stream contains anything.
|
||||
*/
|
||||
inner class AaptCommand(project: Project, aapt: String, val aaptCommand: String,
|
||||
cwd: File = File(".")) : AndroidCommand(project, androidHome(project), aapt) {
|
||||
init {
|
||||
directory = cwd
|
||||
useErrorStreamAsErrorIndicator = true
|
||||
}
|
||||
|
||||
override fun call(args: List<String>) = super.run(arrayListOf(aaptCommand) + args)
|
||||
}
|
||||
inner class AaptCommand(project: Project, aapt: String, val aaptCommand: String, cwd: File = File("."),
|
||||
args: List<String>)
|
||||
: AndroidCommand(project, androidHome(project), aapt,
|
||||
directory = cwd,
|
||||
useErrorStreamAsErrorIndicator = true,
|
||||
args = arrayListOf(aaptCommand) + args)
|
||||
|
||||
private fun generateR(project: Project, generated: String, aapt: String) : Boolean {
|
||||
val compileSdkVersion = compileSdkVersion(project)
|
||||
|
@ -132,7 +129,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
|
|||
val variantDir = context.variant.toIntermediateDir()
|
||||
|
||||
val rDirectory = KFiles.joinAndMakeDir(generated, "source", "r", variantDir).toString()
|
||||
val result = AaptCommand(project, aapt, "package").call(listOf(
|
||||
val result = AaptCommand(project, aapt, "package", args = listOf(
|
||||
"-f",
|
||||
"--no-crunch",
|
||||
"-I", androidJar.toString(),
|
||||
|
@ -358,7 +355,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
|
|||
* adb has weird ways of signaling errors, that's the best I've found so far.
|
||||
*/
|
||||
class AdbInstall : RunCommand(adb(project)) {
|
||||
override fun isSuccess(callSucceeded: Boolean, input: List<String>, error: List<String>)
|
||||
override fun isSuccess(isSuccess: Boolean, input: List<String>, error: List<String>)
|
||||
= input.filter { it.contains("Success")}.size > 0
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,10 @@ class RetrolambdaPlugin @Inject constructor(val dependencyManager: DependencyMan
|
|||
"-Dretrolambda.bytecodeVersion=${config.byteCodeVersion}",
|
||||
"-jar", JAR.jarFile.get().path)
|
||||
|
||||
val result = RunCommand("java").apply {
|
||||
directory = File(project.directory)
|
||||
}.run(args)
|
||||
val result = RunCommand("java",
|
||||
directory = File(project.directory),
|
||||
args = args)
|
||||
.run()
|
||||
TaskResult(result == 0)
|
||||
} else {
|
||||
TaskResult()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue