Clean up fall-back logic in IncrementalCompilerRunner
Make it clear that there 3 distinct cases:
1. Incremental compilation completed with an ExitCode.
2. Incremental compilation was not possible for some valid reason
(e.g., for a clean build), and we will perform non-incremental
compilation.
3. Incremental compilation failed with an exception.
In this case, we will:
- Print a warning with a stack trace
- Ask the user to file a bug
- Collect rebuild reason enum for analytics
+ TODO: Collect the stack trace too
- Fall back to non-incremental compilation
Test: Existing BaseIncrementalCompilationMultiProjectIT.testFailureHandling_UserError,
Updated BaseIncrementalCompilationMultiProjectIT.testFailureHandling_ToolError
^KT-53015: In progress
This commit is contained in:
committed by
Andrey Uskov
parent
57bbc335f4
commit
def886cd31
+2
-1
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.build.report.metrics.BuildAttribute
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
|
||||
import org.jetbrains.kotlin.gradle.testbase.*
|
||||
import org.jetbrains.kotlin.gradle.util.checkedReplace
|
||||
@@ -735,7 +736,7 @@ abstract class BaseIncrementalCompilationMultiProjectIT : IncrementalCompilation
|
||||
|
||||
// In the next build, compilation should be incremental and fail, then fall back to non-incremental compilation and succeed
|
||||
build(":lib:compileKotlin") {
|
||||
assertIncrementalCompilationFellBackToNonIncremental()
|
||||
assertIncrementalCompilationFellBackToNonIncremental(BuildAttribute.IC_FAILED_TO_COMPILE_INCREMENTALLY)
|
||||
// Also check that the output is not deleted (regression test for KT-49780)
|
||||
assertFileExists(lookupFile)
|
||||
}
|
||||
|
||||
+21
-7
@@ -96,8 +96,10 @@ fun BuildResult.assertNonIncrementalCompilation(reason: BuildAttribute? = null)
|
||||
} else {
|
||||
assertOutputContains(NON_INCREMENTAL_COMPILATION_WILL_BE_PERFORMED)
|
||||
}
|
||||
// Also check that incremental compilation was not attempted, failed, and fell back to non-incremental compilation
|
||||
assertOutputDoesNotContain(PERFORMING_INCREMENTAL_COMPILATION)
|
||||
|
||||
// Also check that the other cases didn't happen
|
||||
assertOutputDoesNotContain(INCREMENTAL_COMPILATION_COMPLETED)
|
||||
assertOutputDoesNotContain(FALLING_BACK_TO_NON_INCREMENTAL_COMPILATION)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +110,11 @@ fun BuildResult.assertNonIncrementalCompilation(reason: BuildAttribute? = null)
|
||||
* Note: Log level of output must be set to [LogLevel.DEBUG].
|
||||
*/
|
||||
fun BuildResult.assertIncrementalCompilation(expectedCompiledKotlinFiles: Iterable<Path>? = null) {
|
||||
assertOutputContains(PERFORMING_INCREMENTAL_COMPILATION)
|
||||
// Also check that incremental compilation did not fail and fall back to non-incremental compilation
|
||||
assertOutputContains(INCREMENTAL_COMPILATION_COMPLETED)
|
||||
|
||||
// Also check that the other cases didn't happen
|
||||
assertOutputDoesNotContain(NON_INCREMENTAL_COMPILATION_WILL_BE_PERFORMED)
|
||||
assertOutputDoesNotContain(FALLING_BACK_TO_NON_INCREMENTAL_COMPILATION)
|
||||
|
||||
expectedCompiledKotlinFiles?.let {
|
||||
assertSameFiles(expected = it, actual = extractCompiledKotlinFiles(output), "Compiled Kotlin files differ:\n")
|
||||
@@ -122,9 +126,19 @@ fun BuildResult.assertIncrementalCompilation(expectedCompiledKotlinFiles: Iterab
|
||||
*
|
||||
* Note: Log level of output must be set to [LogLevel.DEBUG].
|
||||
*/
|
||||
fun BuildResult.assertIncrementalCompilationFellBackToNonIncremental() {
|
||||
assertOutputContains("$NON_INCREMENTAL_COMPILATION_WILL_BE_PERFORMED: ${BuildAttribute.INCREMENTAL_COMPILATION_FAILED.name}")
|
||||
fun BuildResult.assertIncrementalCompilationFellBackToNonIncremental(reason: BuildAttribute? = null) {
|
||||
if (reason != null) {
|
||||
assertOutputContains("$FALLING_BACK_TO_NON_INCREMENTAL_COMPILATION (reason = ${reason.name})")
|
||||
} else {
|
||||
assertOutputContains(FALLING_BACK_TO_NON_INCREMENTAL_COMPILATION)
|
||||
}
|
||||
|
||||
// Also check that the other cases didn't happen
|
||||
assertOutputDoesNotContain(INCREMENTAL_COMPILATION_COMPLETED)
|
||||
assertOutputDoesNotContain(NON_INCREMENTAL_COMPILATION_WILL_BE_PERFORMED)
|
||||
}
|
||||
|
||||
private const val PERFORMING_INCREMENTAL_COMPILATION = "Performing incremental compilation"
|
||||
// Each of the following messages should uniquely correspond to a case in `IncrementalCompilerRunner.ICResult`
|
||||
private const val INCREMENTAL_COMPILATION_COMPLETED = "Incremental compilation completed"
|
||||
const val NON_INCREMENTAL_COMPILATION_WILL_BE_PERFORMED = "Non-incremental compilation will be performed"
|
||||
private const val FALLING_BACK_TO_NON_INCREMENTAL_COMPILATION = "Falling back to non-incremental compilation"
|
||||
|
||||
+12
-13
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileSystemOperations
|
||||
import org.gradle.api.logging.Logging
|
||||
@@ -18,9 +17,7 @@ import org.gradle.workers.WorkerExecutor
|
||||
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
||||
import org.jetbrains.kotlin.build.report.metrics.BuildTime
|
||||
import org.jetbrains.kotlin.build.report.metrics.measure
|
||||
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
|
||||
import org.jetbrains.kotlin.gradle.tasks.TaskOutputsBackup
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -43,7 +40,7 @@ internal class GradleCompilerRunnerWithWorkers(
|
||||
workQueue.submit(GradleKotlinCompilerWorkAction::class.java) { params ->
|
||||
params.compilerWorkArguments.set(workArgs)
|
||||
if (taskOutputsBackup != null) {
|
||||
params.taskOutputs.set(taskOutputsBackup.outputs)
|
||||
params.taskOutputsToRestore.set(taskOutputsBackup.outputsToRestore)
|
||||
params.buildDir.set(taskOutputsBackup.buildDirectory)
|
||||
params.snapshotsDir.set(taskOutputsBackup.snapshotsDir)
|
||||
params.metricsReporter.set(buildMetrics)
|
||||
@@ -64,8 +61,7 @@ internal class GradleCompilerRunnerWithWorkers(
|
||||
fileSystemOperations,
|
||||
parameters.buildDir,
|
||||
parameters.snapshotsDir,
|
||||
parameters.taskOutputs.get(),
|
||||
outputsToExclude = emptyList(),
|
||||
parameters.taskOutputsToRestore.get(),
|
||||
logger
|
||||
)
|
||||
} else {
|
||||
@@ -76,11 +72,14 @@ internal class GradleCompilerRunnerWithWorkers(
|
||||
GradleKotlinCompilerWork(
|
||||
parameters.compilerWorkArguments.get()
|
||||
).run()
|
||||
} catch (e: GradleException) {
|
||||
// Currently, metrics are not reported as in the worker we are getting new instance of [BuildMetricsReporter]
|
||||
// [BuildDataRecorder] knows nothing about this new instance. Possibly could be fixed in the future by migrating
|
||||
// [BuildMetricsReporter] to be shared Gradle service.
|
||||
if (taskOutputsBackup != null) {
|
||||
} catch (e: FailedCompilationException) {
|
||||
// Restore outputs only in cases where we expect that the user will make some changes to their project:
|
||||
// - For a compilation error, the user will need to fix their source code
|
||||
// - For an OOM error, the user will need to increase their memory settings
|
||||
// In the other cases where there is nothing the user can fix in their project, we should not restore the outputs.
|
||||
// Otherwise, the next build(s) will likely fail in exactly the same way as this build because their inputs and outputs are
|
||||
// the same.
|
||||
if (taskOutputsBackup != null && (e is CompilationErrorException || e is OOMErrorException)) {
|
||||
parameters.metricsReporter.get().measure(BuildTime.RESTORE_OUTPUT_FROM_BACKUP) {
|
||||
logger.info("Restoring task outputs to pre-compilation state")
|
||||
taskOutputsBackup.restoreOutputs()
|
||||
@@ -96,7 +95,7 @@ internal class GradleCompilerRunnerWithWorkers(
|
||||
|
||||
internal interface GradleKotlinCompilerWorkParameters : WorkParameters {
|
||||
val compilerWorkArguments: Property<GradleKotlinCompilerWorkArguments>
|
||||
val taskOutputs: ListProperty<File>
|
||||
val taskOutputsToRestore: ListProperty<File>
|
||||
val snapshotsDir: DirectoryProperty
|
||||
val buildDir: DirectoryProperty
|
||||
val metricsReporter: Property<BuildMetricsReporter>
|
||||
|
||||
+4
-8
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.invocation.Gradle
|
||||
import org.gradle.api.logging.Logger
|
||||
@@ -33,11 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.utils.IsolatedKotlinClasspathClassCastException
|
||||
import org.jetbrains.kotlin.gradle.utils.archivePathCompatible
|
||||
import org.jetbrains.kotlin.gradle.utils.findByType
|
||||
import org.jetbrains.kotlin.gradle.utils.newTmpFile
|
||||
import org.jetbrains.kotlin.gradle.utils.relativeOrCanonical
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.incremental.IncrementalModuleEntry
|
||||
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
|
||||
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||
@@ -223,8 +218,9 @@ internal open class GradleCompilerRunner(
|
||||
try {
|
||||
val kotlinCompilerRunnable = GradleKotlinCompilerWork(workArgs)
|
||||
kotlinCompilerRunnable.run()
|
||||
} catch (e: GradleException) {
|
||||
if (taskOutputsBackup != null) {
|
||||
} catch (e: FailedCompilationException) {
|
||||
// Restore outputs only for CompilationErrorException or OOMErrorException (see GradleKotlinCompilerWorkAction.execute)
|
||||
if (taskOutputsBackup != null && (e is CompilationErrorException || e is OOMErrorException)) {
|
||||
buildMetrics.measure(BuildTime.RESTORE_OUTPUT_FROM_BACKUP) {
|
||||
taskOutputsBackup.restoreOutputs()
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
||||
import org.jetbrains.kotlin.gradle.report.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
|
||||
import org.jetbrains.kotlin.gradle.tasks.cleanOutputsAndLocalState
|
||||
import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError
|
||||
import org.jetbrains.kotlin.gradle.tasks.throwExceptionIfCompilationFailed
|
||||
import org.jetbrains.kotlin.gradle.utils.stackTraceAsString
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
||||
@@ -125,7 +125,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
incrementalCompilationEnvironment.multiModuleICSettings.buildHistoryFile.delete()
|
||||
}
|
||||
|
||||
throwGradleExceptionIfError(exitCode, executionStrategy)
|
||||
throwExceptionIfCompilationFailed(exitCode, executionStrategy)
|
||||
} finally {
|
||||
val taskInfo = TaskExecutionInfo(
|
||||
changedFiles = incrementalCompilationEnvironment?.changedFiles,
|
||||
|
||||
-2
@@ -424,9 +424,7 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
||||
taskExecutionResult?.buildMetrics?.buildPerformanceMetrics?.asMap()?.filterValues { value -> value != 0L } ?: emptyMap()
|
||||
val changes = when (val changedFiles = taskExecutionResult?.taskInfo?.changedFiles) {
|
||||
is ChangedFiles.Known -> changedFiles.modified.map { it.absolutePath } + changedFiles.removed.map { it.absolutePath }
|
||||
is ChangedFiles.Dependencies -> changedFiles.modified.map { it.absolutePath } + changedFiles.removed.map { it.absolutePath }
|
||||
else -> emptyList<String>()
|
||||
|
||||
}
|
||||
return CompileStatisticsData(
|
||||
durationMs = durationMs,
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ abstract class KotlinJsDce @Inject constructor(
|
||||
buildDir.get().asFile,
|
||||
jvmArgs
|
||||
)
|
||||
throwGradleExceptionIfError(exitCode, KotlinCompilerExecutionStrategy.OUT_OF_PROCESS)
|
||||
throwExceptionIfCompilationFailed(exitCode, KotlinCompilerExecutionStrategy.OUT_OF_PROCESS)
|
||||
}
|
||||
|
||||
private fun isDceCandidate(file: File): Boolean {
|
||||
|
||||
+2
-4
@@ -363,7 +363,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
|
||||
|
||||
private val systemPropertiesService = CompilerSystemPropertiesService.registerIfAbsent(project.gradle)
|
||||
|
||||
/** Task outputs that we don't want to include in [TaskOutputsBackup] (see [TaskOutputsBackup]'s kdoc for more info). */
|
||||
/** Task outputs that we don't want to include in [TaskOutputsBackup] (see [TaskOutputsBackup.outputsToRestore] for more info). */
|
||||
@get:Internal
|
||||
protected open val taskOutputsBackupExcludes: List<File> = emptyList()
|
||||
|
||||
@@ -391,8 +391,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
|
||||
fileSystemOperations,
|
||||
layout.buildDirectory,
|
||||
layout.buildDirectory.dir("snapshot/kotlin/$name"),
|
||||
allOutputFiles(),
|
||||
taskOutputsBackupExcludes,
|
||||
outputsToRestore = allOutputFiles() - taskOutputsBackupExcludes,
|
||||
logger
|
||||
).also {
|
||||
it.createSnapshot()
|
||||
@@ -596,7 +595,6 @@ abstract class KotlinCompile @Inject constructor(
|
||||
classpathSnapshotProperties.classpathSnapshot
|
||||
)
|
||||
|
||||
// Exclude classpathSnapshotDir from TaskOutputsBackup (see TaskOutputsBackup's kdoc for more info). */
|
||||
override val taskOutputsBackupExcludes: List<File>
|
||||
get() = classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { listOf(it) } ?: emptyList()
|
||||
|
||||
|
||||
+16
-18
@@ -5,7 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.file.*
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileSystemOperations
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.provider.Provider
|
||||
import java.io.File
|
||||
@@ -14,35 +16,31 @@ import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.zip.*
|
||||
import java.util.zip.Deflater
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
internal class TaskOutputsBackup(
|
||||
val fileSystemOperations: FileSystemOperations,
|
||||
private val fileSystemOperations: FileSystemOperations,
|
||||
val buildDirectory: DirectoryProperty,
|
||||
val snapshotsDir: Provider<Directory>,
|
||||
|
||||
allOutputs: List<File>,
|
||||
|
||||
/**
|
||||
* Task outputs that we don't want to back up for performance reasons (e.g., if (1) they are too big, and (2) they are usually updated
|
||||
* only at the end of the task execution--in a failed task run, they are usually unchanged and therefore don't need to be restored).
|
||||
* Task outputs to back up and restore.
|
||||
*
|
||||
* NOTE: In `IncrementalCompilerRunner`, if incremental compilation fails, it will try again by cleaning all the outputs and perform
|
||||
* non-incremental compilation. It is important that `IncrementalCompilerRunner` do not clean [outputsToExclude] immediately but only
|
||||
* right before [outputsToExclude] are updated (which is usually at the end of the task execution). This is so that if the fallback
|
||||
* compilation fails, [outputsToExclude] will remain unchanged and the other outputs will be restored, and the next task run can be
|
||||
* incremental.
|
||||
* Note that this could be a subset of all the outputs of a task because there could be task outputs that we don't want to back up and
|
||||
* restore (e.g., if (1) they are too big and (2) they are updated only at the end of the task execution so in a failed task run, they
|
||||
* are usually unchanged and therefore don't need to be restored).
|
||||
*/
|
||||
outputsToExclude: List<File> = emptyList(),
|
||||
val outputsToRestore: List<File>,
|
||||
|
||||
val logger: Logger
|
||||
) {
|
||||
/** The outputs to back up and restore. Note that this may be a subset of all the outputs of a task (see `outputsToExclude`). */
|
||||
val outputs: List<File> = allOutputs - outputsToExclude.toSet()
|
||||
|
||||
fun createSnapshot() {
|
||||
// Kotlin JS compilation task declares one file from 'destinationDirectory' output as task `@OutputFile'
|
||||
// property. To avoid snapshot sync collisions, each snapshot output directory has also 'index' as prefix.
|
||||
outputs.toSortedSet().forEachIndexed { index, outputPath ->
|
||||
outputsToRestore.toSortedSet().forEachIndexed { index, outputPath ->
|
||||
if (outputPath.isDirectory && !outputPath.isEmptyDirectory) {
|
||||
compressDirectoryToZip(
|
||||
File(snapshotsDir.get().asFile, index.asSnapshotArchiveName),
|
||||
@@ -59,10 +57,10 @@ internal class TaskOutputsBackup(
|
||||
|
||||
fun restoreOutputs() {
|
||||
fileSystemOperations.delete {
|
||||
it.delete(outputs)
|
||||
it.delete(outputsToRestore)
|
||||
}
|
||||
|
||||
outputs.toSortedSet().forEachIndexed { index, outputPath ->
|
||||
outputsToRestore.toSortedSet().forEachIndexed { index, outputPath ->
|
||||
val snapshotDir = snapshotsDir.get().file(index.asSnapshotDirectoryName).asFile
|
||||
if (snapshotDir.isDirectory) {
|
||||
fileSystemOperations.copy { spec ->
|
||||
|
||||
+17
-8
@@ -1,6 +1,5 @@
|
||||
package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
||||
import org.jetbrains.kotlin.build.report.metrics.BuildTime
|
||||
import org.jetbrains.kotlin.build.report.metrics.measure
|
||||
@@ -10,18 +9,19 @@ import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||
import org.jetbrains.kotlin.incremental.cleanDirectoryContents
|
||||
import org.jetbrains.kotlin.incremental.deleteDirectoryContents
|
||||
import org.jetbrains.kotlin.incremental.deleteRecursivelyOrThrow
|
||||
import java.io.File
|
||||
|
||||
fun throwGradleExceptionIfError(
|
||||
/** Throws [FailedCompilationException] if compilation completed with [exitCode] != [ExitCode.OK]. */
|
||||
fun throwExceptionIfCompilationFailed(
|
||||
exitCode: ExitCode,
|
||||
executionStrategy: KotlinCompilerExecutionStrategy
|
||||
) {
|
||||
when (exitCode) {
|
||||
ExitCode.COMPILATION_ERROR -> throw GradleException("Compilation error. See log for more details")
|
||||
ExitCode.INTERNAL_ERROR -> throw GradleException("Internal compiler error. See log for more details")
|
||||
ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException("Script execution error. See log for more details")
|
||||
ExitCode.COMPILATION_ERROR -> throw CompilationErrorException("Compilation error. See log for more details")
|
||||
ExitCode.INTERNAL_ERROR -> throw FailedCompilationException("Internal compiler error. See log for more details")
|
||||
ExitCode.SCRIPT_EXECUTION_ERROR -> throw FailedCompilationException("Script execution error. See log for more details")
|
||||
ExitCode.OOM_ERROR -> {
|
||||
var exceptionMessage = "Not enough memory to run compilation."
|
||||
when (executionStrategy) {
|
||||
@@ -31,13 +31,22 @@ fun throwGradleExceptionIfError(
|
||||
exceptionMessage += " Try to increase it via 'gradle.properties':\norg.gradle.jvmargs=-Xmx<size>"
|
||||
KotlinCompilerExecutionStrategy.OUT_OF_PROCESS -> Unit
|
||||
}
|
||||
throw GradleException(exceptionMessage)
|
||||
throw OOMErrorException(exceptionMessage)
|
||||
}
|
||||
ExitCode.OK -> Unit
|
||||
else -> throw IllegalStateException("Unexpected exit code: $exitCode")
|
||||
}
|
||||
}
|
||||
|
||||
/** Exception thrown when [ExitCode] != [ExitCode.OK]. */
|
||||
internal open class FailedCompilationException(message: String) : RuntimeException(message)
|
||||
|
||||
/** Exception thrown when [ExitCode] == [ExitCode.COMPILATION_ERROR]. */
|
||||
internal class CompilationErrorException(message: String) : FailedCompilationException(message)
|
||||
|
||||
/** Exception thrown when [ExitCode] == [ExitCode.OOM_ERROR]. */
|
||||
internal class OOMErrorException(message: String) : FailedCompilationException(message)
|
||||
|
||||
internal fun TaskWithLocalState.cleanOutputsAndLocalState(reason: String? = null) {
|
||||
val log = GradleKotlinLogger(logger)
|
||||
cleanOutputsAndLocalState(allOutputFiles(), log, metrics.get(), reason)
|
||||
@@ -59,7 +68,7 @@ internal fun cleanOutputsAndLocalState(
|
||||
when {
|
||||
file.isDirectory -> {
|
||||
log.debug("Deleting contents of output directory: $file")
|
||||
file.cleanDirectoryContents()
|
||||
file.deleteDirectoryContents()
|
||||
}
|
||||
file.isFile -> {
|
||||
log.debug("Deleting output file: $file")
|
||||
|
||||
Reference in New Issue
Block a user