KT-57650 run pod install --repo-update if repo is out of date
This commit is contained in:
committed by
Space Team
parent
da4c6dd443
commit
4cdb9301ed
+25
-15
@@ -11,10 +11,10 @@ import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.work.DisableCachingByDefault
|
||||
import org.jetbrains.kotlin.gradle.utils.CommandFallback
|
||||
import org.jetbrains.kotlin.gradle.utils.onlyIfCompat
|
||||
import org.jetbrains.kotlin.gradle.utils.runCommand
|
||||
import org.jetbrains.kotlin.gradle.utils.runCommandWithFallback
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* The task takes the path to the Podfile and calls `pod install`
|
||||
@@ -45,19 +45,7 @@ abstract class AbstractPodInstallTask : CocoapodsTask() {
|
||||
|
||||
@TaskAction
|
||||
open fun doPodInstall() {
|
||||
// env is used here to work around the JVM PATH caching when spawning a child process with custom environment, i.e. LC_ALL
|
||||
// The caching causes the ProcessBuilder to ignore changes in the PATH that may occur on incremental runs of the Gradle daemon
|
||||
// KT-60394
|
||||
val podInstallCommand = listOf("env", "pod", "install")
|
||||
|
||||
runCommand(podInstallCommand,
|
||||
logger,
|
||||
errorHandler = { retCode, output, process -> sharedHandleError(podInstallCommand, retCode, output, process) },
|
||||
processConfiguration = {
|
||||
directory(workingDir.get())
|
||||
// CocoaPods requires to be run with Unicode external encoding
|
||||
environment().putIfAbsent("LC_ALL", "en_US.UTF-8")
|
||||
})
|
||||
runPodInstall(false)
|
||||
|
||||
with(podsXcodeProjDirProvider.get()) {
|
||||
check(exists() && isDirectory) {
|
||||
@@ -66,6 +54,28 @@ abstract class AbstractPodInstallTask : CocoapodsTask() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun runPodInstall(updateRepo: Boolean): String {
|
||||
// env is used here to work around the JVM PATH caching when spawning a child process with custom environment, i.e. LC_ALL
|
||||
// The caching causes the ProcessBuilder to ignore changes in the PATH that may occur on incremental runs of the Gradle daemon
|
||||
// KT-60394
|
||||
val podInstallCommand = listOfNotNull("env", "pod", "install", if (updateRepo) "--repo-update" else null)
|
||||
|
||||
return runCommandWithFallback(podInstallCommand,
|
||||
logger,
|
||||
fallback = { retCode, output, process ->
|
||||
if (output.contains("out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`") && updateRepo.not()) {
|
||||
CommandFallback.Action(runPodInstall(true))
|
||||
} else {
|
||||
CommandFallback.Error(sharedHandleError(podInstallCommand, retCode, output, process))
|
||||
}
|
||||
},
|
||||
processConfiguration = {
|
||||
directory(workingDir.get())
|
||||
// CocoaPods requires to be run with Unicode external encoding
|
||||
environment().putIfAbsent("LC_ALL", "en_US.UTF-8")
|
||||
})
|
||||
}
|
||||
|
||||
private fun sharedHandleError(podInstallCommand: List<String>, retCode: Int, error: String, process: Process): String? {
|
||||
return if (error.contains("No such file or directory")) {
|
||||
val command = podInstallCommand.joinToString(" ")
|
||||
|
||||
+79
-15
@@ -6,15 +6,80 @@
|
||||
package org.jetbrains.kotlin.gradle.utils
|
||||
|
||||
import org.gradle.api.logging.Logger
|
||||
import java.io.IOException
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
/**
|
||||
* Executes a command and returns the input text.
|
||||
*
|
||||
* @param command the command and its arguments to be executed as a list of strings.
|
||||
* @param logger an optional logger to log information about the command execution.
|
||||
* @param errorHandler (Optional) A function that handles any errors that occur during the command execution.
|
||||
* @param processConfiguration a function to configure the process before execution.
|
||||
* @return The input text of the executed command.
|
||||
*/
|
||||
internal fun runCommand(
|
||||
command: List<String>,
|
||||
logger: Logger? = null,
|
||||
errorHandler: ((retCode: Int, output: String, process: Process) -> String?)? = null,
|
||||
processConfiguration: ProcessBuilder.() -> Unit = { }
|
||||
processConfiguration: ProcessBuilder.() -> Unit = { },
|
||||
): String {
|
||||
val runResult = assembleAndRunProcess(command, logger, processConfiguration)
|
||||
check(runResult.retCode == 0) {
|
||||
errorHandler?.invoke(runResult.retCode, runResult.output, runResult.process) ?: createErrorMessage(command, runResult)
|
||||
}
|
||||
|
||||
return runResult.inputText
|
||||
}
|
||||
|
||||
/**
|
||||
* Sealed class representing the fallback behavior for a command.
|
||||
*/
|
||||
sealed class CommandFallback {
|
||||
data class Action(val fallback: String) : CommandFallback()
|
||||
data class Error(val error: String?) : CommandFallback()
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the specified command with fallback behavior in case of non-zero return code.
|
||||
*
|
||||
* @param command the command and its arguments to be executed as a list of strings.
|
||||
* @param logger an optional logger to log information about the command execution.
|
||||
* @param fallback a function that provides the fallback behavior. It takes the return code, output, and process as parameters and returns a [CommandFallback] object.
|
||||
* @param processConfiguration a function to configure the process before execution.
|
||||
* @return the output of the command if the return code is 0, otherwise the fallback action or error.
|
||||
*/
|
||||
internal fun runCommandWithFallback(
|
||||
command: List<String>,
|
||||
logger: Logger? = null,
|
||||
fallback: (retCode: Int, output: String, process: Process) -> CommandFallback,
|
||||
processConfiguration: ProcessBuilder.() -> Unit = { },
|
||||
): String {
|
||||
val runResult = assembleAndRunProcess(command, logger, processConfiguration)
|
||||
return if (runResult.retCode != 0) {
|
||||
when (val fallbackOption = fallback(runResult.retCode, runResult.output, runResult.process)) {
|
||||
is CommandFallback.Action -> fallbackOption.fallback
|
||||
is CommandFallback.Error -> error(fallbackOption.error ?: createErrorMessage(command, runResult))
|
||||
}
|
||||
} else {
|
||||
runResult.inputText
|
||||
}
|
||||
}
|
||||
|
||||
private data class RunProcessResult(
|
||||
val inputText: String,
|
||||
val errorText: String,
|
||||
val retCode: Int,
|
||||
val process: Process,
|
||||
) {
|
||||
val output: String get() = inputText.ifBlank { errorText }
|
||||
}
|
||||
|
||||
private fun assembleAndRunProcess(
|
||||
command: List<String>,
|
||||
logger: Logger? = null,
|
||||
processConfiguration: ProcessBuilder.() -> Unit = { },
|
||||
): RunProcessResult {
|
||||
|
||||
val process = ProcessBuilder(command).apply {
|
||||
this.processConfiguration()
|
||||
}.start()
|
||||
@@ -46,17 +111,16 @@ internal fun runCommand(
|
||||
""".trimMargin()
|
||||
)
|
||||
|
||||
check(retCode == 0) {
|
||||
errorHandler?.invoke(retCode, inputText.ifBlank { errorText }, process)
|
||||
?: """
|
||||
|Executing of '${command.joinToString(" ")}' failed with code $retCode and message:
|
||||
|
|
||||
|$inputText
|
||||
|
|
||||
|$errorText
|
||||
|
|
||||
""".trimMargin()
|
||||
}
|
||||
|
||||
return inputText
|
||||
return RunProcessResult(inputText, errorText, retCode, process)
|
||||
}
|
||||
|
||||
private fun createErrorMessage(command: List<String>, runResult: RunProcessResult): String {
|
||||
return """
|
||||
|Executing of '${command.joinToString(" ")}' failed with code ${runResult.retCode} and message:
|
||||
|
|
||||
|${runResult.inputText}
|
||||
|
|
||||
|${runResult.errorText}
|
||||
|
|
||||
""".trimMargin()
|
||||
}
|
||||
Reference in New Issue
Block a user