build.gradle.kts中ProcessBuilder管道读取输入流挂起求助
解决Gradle脚本执行Git命令挂起并提取版本号的方案
核心问题原因
Gradle中执行外部命令时,若不显式处理标准错误流(stderr),进程可能因输出缓冲区满而挂起。仅用readText()或readLine()处理stdout、忽略stderr的话,极易出现阻塞。
可行实现代码
在build.gradle.kts中添加以下函数,用于获取最新Git标签版本并自增:
fun getNextVersion(): String { // 直接获取最新标签,无需额外过滤,效率更高 val processBuilder = ProcessBuilder("git", "describe", "--abbrev=0", "--tags") .directory(project.rootDir) // 指定项目根目录执行Git命令 .redirectErrorStream(true) // 将stderr合并到stdout,避免缓冲区阻塞 val process = processBuilder.start() // 读取输出并自动关闭流 val output = process.inputStream.bufferedReader().use { it.readText().trim() } process.waitFor() // 等待命令执行完成 // 无标签时返回初始版本 if (output.isEmpty()) { return "2023.11.1" } // 拆分版本号并自增最后一位 val versionParts = output.split(".") if (versionParts.size != 3) { error("版本号格式错误,需为x.y.z格式") } val major = versionParts[0].toInt() val minor = versionParts[1].toInt() val patch = versionParts[2].toInt() + 1 return "$major.$minor.$patch" } // 使用示例 val appVersion = getNextVersion() println("生成的下一个版本号:$appVersion")
关键细节说明
redirectErrorStream(true):将Git的错误输出合并到标准输出,确保所有输出被读取,避免因stderr缓冲区满导致进程挂起。directory(project.rootDir):确保Git命令在项目根目录执行,避免找不到仓库的问题。git describe --abbrev=0 --tags:直接获取最新标签,比git log更高效,无需额外过滤步骤。
适配特殊标签格式的方案
如果标签带前缀(如v2023.11.1),或需要过滤特定格式,可调整Git命令并通过正则提取版本:
fun getNextVersion(): String { val processBuilder = ProcessBuilder("git", "tag", "--list", "v*", "--sort=-v:refname") .directory(project.rootDir) .redirectErrorStream(true) val process = processBuilder.start() val output = process.inputStream.bufferedReader().use { it.readText().trim() } process.waitFor() // 用正则提取x.y.z格式的版本号 val versionRegex = Regex("""(\d+\.\d+\.\d+)""") val latestVersion = versionRegex.find(output)?.groupValues?.get(1) ?: "2023.11.1" // 自增逻辑同前 val versionParts = latestVersion.split(".") val major = versionParts[0].toInt() val minor = versionParts[1].toInt() val patch = versionParts[2].toInt() + 1 return "$major.$minor.$patch" }
内容的提问来源于stack exchange,提问作者toshiomagic
相关产品推荐
相关产品推荐

