From 03aa9b8129fa38be0d0c9e311d6787417de4203e Mon Sep 17 00:00:00 2001 From: Josh Feinberg Date: Thu, 7 Jul 2022 14:30:14 -0500 Subject: [PATCH 1/2] Make config cacheable: --- .../AffectedModuleDetector.kt | 17 +--- .../affectedmoduledetector/ToStringLogger.kt | 83 ++++++++++++++----- .../AttachLogsTestRule.kt | 4 +- .../mocks/MockCommandRunner.kt | 2 +- 4 files changed, 71 insertions(+), 35 deletions(-) diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt index 115e6a01..f5ea60b0 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt @@ -151,19 +151,10 @@ abstract class AffectedModuleDetector { val logger = ToStringLogger.createWithLifecycle( - gradle - ) { log -> - config.logFolder?.let { - val distDir = File(it) - if (!distDir.exists()) { - distDir.mkdirs() - } - val outputFile = - distDir.resolve(config.logFilename) - outputFile.appendText(log) - println("Wrote dependency log to ${outputFile.absolutePath}") - } - } + rootProject, + config.logFilename, + config.logFolder + ) val modules = getModulesProperty( diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt index 30d39d6d..25d96cfb 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt @@ -20,52 +20,95 @@ package com.dropbox.affectedmoduledetector -import org.gradle.BuildAdapter -import org.gradle.BuildResult -import org.gradle.api.invocation.Gradle +import org.gradle.api.Project +import org.gradle.api.file.RegularFileProperty import org.gradle.api.logging.LogLevel import org.gradle.api.logging.Logger +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters +import org.gradle.internal.build.event.BuildEventListenerRegistryInternal import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLoggerContext +import org.gradle.internal.operations.* import org.gradle.internal.time.Clock +import org.gradle.invocation.DefaultGradle +import java.io.File /** * Gradle logger that logs to a string. */ -class ToStringLogger( - private val stringBuilder: StringBuilder = StringBuilder() +internal open class ToStringLogger( + private val stringBuilder: Provider? ) : OutputEventListenerBackedLogger( "amd", - OutputEventListenerBackedLoggerContext( - Clock { - System.currentTimeMillis() - } - ).also { + OutputEventListenerBackedLoggerContext { + System.currentTimeMillis() + }.also { it.level = LogLevel.DEBUG - it.setOutputEventListener { - stringBuilder.appendln(it.toString()) + it.setOutputEventListener { outputEvent -> + stringBuilder?.get()?.parameters?.getStringBuilderProperty()?.get()?.appendLine(outputEvent.toString()) } }, Clock { System.currentTimeMillis() } ) { + /** * Returns the current log. */ - fun buildString() = stringBuilder.toString() + fun buildString() = stringBuilder?.get()?.parameters?.getStringBuilderProperty()?.get()?.toString() + @Suppress("UnstableApiUsage") // BuildService is not yet stable companion object { + internal abstract class ToStringLoggerBuildService : BuildService, BuildOperationListener, AutoCloseable { + interface ToStringLoggerBuildServiceParameters : BuildServiceParameters { + fun getStringBuilderProperty(): Property + fun getOutputFileProperty(): RegularFileProperty + } + + override fun started(p0: BuildOperationDescriptor, p1: OperationStartEvent) { } + + override fun progress(p0: OperationIdentifier, p1: OperationProgressEvent) { } + + override fun finished(buildOperationDescriptor: BuildOperationDescriptor, operationFinishEvent: OperationFinishEvent) { } + + override fun close() { + val outputFile = parameters.getOutputFileProperty().orNull?.asFile ?: return + outputFile.appendText(parameters.getStringBuilderProperty().get().toString()) + println("Wrote dependency log to ${outputFile.absolutePath}") + } + } + + /** + * Creates the [ToStringLogger] + * + * @param project the current project to apply to + * @param logFilename the filename for the logs to go + * @param logFolder the path to where the log should output. if null doesn't output + */ fun createWithLifecycle( - gradle: Gradle, - onComplete: (String) -> Unit + project: Project, + logFilename: String, + logFolder: String? = null ): Logger { - val logger = ToStringLogger() - gradle.addBuildListener(object : BuildAdapter() { - override fun buildFinished(result: BuildResult) { - onComplete(logger.buildString()) + val gradle = project.gradle + val stringBuilder = StringBuilder() + val toStringLoggerBuildService = gradle.sharedServices.registerIfAbsent("to-string-logger-build-listener", ToStringLoggerBuildService::class.java) { service -> + service.parameters.getStringBuilderProperty().set(stringBuilder) + if (logFolder != null) { + val distDir = File(logFolder) + if (!distDir.exists()) { + distDir.mkdirs() + } + val outputFile = distDir.resolve(logFilename) + service.parameters.getOutputFileProperty().set(outputFile) } - }) + } + val logger = ToStringLogger(toStringLoggerBuildService) + (gradle as DefaultGradle).services[BuildEventListenerRegistryInternal::class.java].onOperationCompletion(toStringLoggerBuildService) return logger } } diff --git a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AttachLogsTestRule.kt b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AttachLogsTestRule.kt index a775de27..3dc91a75 100644 --- a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AttachLogsTestRule.kt +++ b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AttachLogsTestRule.kt @@ -1,5 +1,7 @@ package com.dropbox.affectedmoduledetector +import com.nhaarman.mockito_kotlin.mock +import org.gradle.api.provider.Provider import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement @@ -8,7 +10,7 @@ import org.junit.runners.model.Statement * Special rule for dependency detector tests that will attach logs to a failure. */ class AttachLogsTestRule : TestRule { - val logger = ToStringLogger() + internal val logger = mock { } override fun apply(base: Statement, description: Description): Statement { return object : Statement() { override fun evaluate() { diff --git a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt index 3607f3d4..435df919 100644 --- a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt +++ b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt @@ -3,7 +3,7 @@ package com.dropbox.affectedmoduledetector.mocks import com.dropbox.affectedmoduledetector.GitClient import com.dropbox.affectedmoduledetector.ToStringLogger -class MockCommandRunner(private val logger: ToStringLogger) : GitClient.CommandRunner { +internal class MockCommandRunner(private val logger: ToStringLogger) : GitClient.CommandRunner { private val replies = mutableMapOf>() fun addReply(command: String, response: String) { From 37705031b565b8d9d7fa0bdd3c9beb4fc72c6c88 Mon Sep 17 00:00:00 2001 From: Josh Feinberg Date: Fri, 15 Jul 2022 13:29:43 -0500 Subject: [PATCH 2/2] Rename variable --- .../com/dropbox/affectedmoduledetector/ToStringLogger.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt index 25d96cfb..edcdd479 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/ToStringLogger.kt @@ -40,7 +40,7 @@ import java.io.File * Gradle logger that logs to a string. */ internal open class ToStringLogger( - private val stringBuilder: Provider? + private val loggerProvider: Provider? ) : OutputEventListenerBackedLogger( "amd", OutputEventListenerBackedLoggerContext { @@ -48,7 +48,7 @@ internal open class ToStringLogger( }.also { it.level = LogLevel.DEBUG it.setOutputEventListener { outputEvent -> - stringBuilder?.get()?.parameters?.getStringBuilderProperty()?.get()?.appendLine(outputEvent.toString()) + loggerProvider?.get()?.parameters?.getStringBuilderProperty()?.get()?.appendLine(outputEvent.toString()) } }, Clock { @@ -59,7 +59,7 @@ internal open class ToStringLogger( /** * Returns the current log. */ - fun buildString() = stringBuilder?.get()?.parameters?.getStringBuilderProperty()?.get()?.toString() + fun buildString() = loggerProvider?.get()?.parameters?.getStringBuilderProperty()?.get()?.toString() @Suppress("UnstableApiUsage") // BuildService is not yet stable companion object {