You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:02:15