diff --git a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextEditTask.kt b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextEditTask.kt index 8bf69f2..e16cfb2 100644 --- a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextEditTask.kt +++ b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextEditTask.kt @@ -24,7 +24,7 @@ import java.io.File import java.nio.charset.StandardCharsets import javax.inject.Inject -open class BaseGettextEditTask @Inject constructor( +abstract class BaseGettextEditTask @Inject constructor( objects: ObjectFactory ) : BaseGettextTask(objects) { @Input diff --git a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextTask.kt b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextTask.kt index 31419d0..b649498 100644 --- a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextTask.kt +++ b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/BaseGettextTask.kt @@ -20,11 +20,15 @@ import org.gradle.api.DefaultTask import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.Input import org.gradle.kotlin.dsl.property +import org.gradle.process.ExecOperations import javax.inject.Inject -open class BaseGettextTask @Inject constructor( +abstract class BaseGettextTask @Inject constructor( objects: ObjectFactory ) : DefaultTask() { @Input val executable = objects.property() + + @get:Inject + protected abstract val execOperations: ExecOperations } diff --git a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/GettextTask.kt b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/GettextTask.kt index 3135fd7..2e7eaf2 100644 --- a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/GettextTask.kt +++ b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/GettextTask.kt @@ -76,7 +76,7 @@ abstract class GettextTask @Inject constructor( } val cmd = executable.get() - project.exec { + execOperations.exec { executable = cmd for (keyword in keywords.get()) { args("-k$keyword") diff --git a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgAttribTask.kt b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgAttribTask.kt index 323c127..9a1664f 100644 --- a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgAttribTask.kt +++ b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgAttribTask.kt @@ -31,7 +31,7 @@ import org.gradle.work.InputChanges import java.io.File import javax.inject.Inject -open class MsgAttribTask @Inject constructor( +abstract class MsgAttribTask @Inject constructor( objects: ObjectFactory ) : BaseGettextEditTask(objects) { @InputFiles @@ -67,7 +67,7 @@ open class MsgAttribTask @Inject constructor( continue } logger.debug("Processing {} with {} {}", po.file, cmd, arg) - project.exec { + execOperations.exec { executable = cmd args("--output-file=${outFile.absolutePath}") args(arg) diff --git a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgFmtTask.kt b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgFmtTask.kt index 94d49cf..316add3 100644 --- a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgFmtTask.kt +++ b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgFmtTask.kt @@ -36,7 +36,7 @@ import java.io.File import java.nio.charset.Charset import javax.inject.Inject -open class MsgFmtTask @Inject constructor( +abstract class MsgFmtTask @Inject constructor( objects: ObjectFactory ) : BaseGettextTask(objects) { @InputFiles @@ -102,7 +102,7 @@ open class MsgFmtTask @Inject constructor( logger.debug("Processing {} with {} {}", po.file, cmd, arg) project.delete(tmpDir) tmpDir.mkdirs() - project.exec { + execOperations.exec { executable = cmd if (format.get() == OutputFormat.JAVA) { args("--java2") diff --git a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgMergeTask.kt b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgMergeTask.kt index 7ecee60..bd5c198 100644 --- a/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgMergeTask.kt +++ b/plugins/gettext-plugin/src/main/kotlin/com/github/vlsi/gradle/gettext/MsgMergeTask.kt @@ -32,7 +32,7 @@ import org.gradle.work.InputChanges import java.io.File import javax.inject.Inject -open class MsgMergeTask @Inject constructor( +abstract class MsgMergeTask @Inject constructor( objects: ObjectFactory ) : BaseGettextEditTask(objects) { @InputFiles @@ -72,7 +72,7 @@ open class MsgMergeTask @Inject constructor( continue } logger.debug("Processing {} with {} {}", po.file, cmd, arg) - project.exec { + execOperations.exec { executable = cmd args("--output-file=${outFile.absolutePath}") args("--quiet") diff --git a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/PromoteSvnRelease.kt b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/PromoteSvnRelease.kt index 6d0cb1e..11efa7c 100644 --- a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/PromoteSvnRelease.kt +++ b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/PromoteSvnRelease.kt @@ -17,8 +17,8 @@ package com.github.vlsi.gradle.release import com.github.vlsi.gradle.release.svn.LsDepth -import com.github.vlsi.gradle.release.svn.Svn import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.the import org.gradle.work.InputChanges @@ -31,6 +31,8 @@ abstract class PromoteSvnRelease : SvnmuccTask() { @Input val useCpWorkaround = project.objects.property().convention(true) + private val ext = project.the() + override fun message() = project.the().run { "Promoting ${componentName.get()} ${rcTag.get()} -> ${releaseTag.get()} to release area" @@ -38,14 +40,13 @@ abstract class PromoteSvnRelease : SvnmuccTask() { override fun operations(inputChanges: InputChanges): List { return mutableListOf().apply { - val ext = project.the() val svnDist = ext.svnDist val stageFolder = svnDist.stageFolder.get() val releaseFolder = svnDist.releaseFolder.get() val subfolders = svnDist.releaseSubfolder.get() - val entries = Svn(project, repository.get()).ls { + val entries = svnClient(repository.get()).ls { withCredentials() folders.add(stageFolder) depth = LsDepth.INFINITY diff --git a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/RemoveStaleArtifactsTask.kt b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/RemoveStaleArtifactsTask.kt index 7063fdc..d2d1531 100644 --- a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/RemoveStaleArtifactsTask.kt +++ b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/RemoveStaleArtifactsTask.kt @@ -68,7 +68,7 @@ abstract class RemoveStaleArtifactsTask @Inject constructor( override fun operations(inputChanges: InputChanges): List { val svnUri = repository.get() - val entries = Svn(project, svnUri).ls { + val entries = svnClient(svnUri).ls { withCredentials() folders.addAll(foldersToList.get()) } diff --git a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/StageVoteReleasePlugin.kt b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/StageVoteReleasePlugin.kt index 5d849a6..f761766 100644 --- a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/StageVoteReleasePlugin.kt +++ b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/StageVoteReleasePlugin.kt @@ -32,6 +32,7 @@ import org.gradle.api.GradleException import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.logging.Logger import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.plugins.MavenPublishPlugin import org.gradle.api.publish.maven.tasks.GenerateMavenPom @@ -55,12 +56,16 @@ import org.gradle.kotlin.dsl.withType import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.plugins.signing.SigningExtension import org.gradle.plugins.signing.SigningPlugin +import org.gradle.process.ExecOperations import java.io.File import java.net.URI import java.nio.charset.StandardCharsets import javax.inject.Inject -class StageVoteReleasePlugin @Inject constructor(private val instantiator: Instantiator) : +class StageVoteReleasePlugin @Inject constructor( + private val instantiator: Instantiator, + private val execOperations: ExecOperations, +) : Plugin { companion object { @Deprecated(replaceWith = ReplaceWith("StageVoteReleasePlugin.RELEASE_PARAMS_EXTENSION_NAME"), message = "There are multiple extensions, so prefer clarified name") @@ -653,6 +658,7 @@ class StageVoteReleasePlugin @Inject constructor(private val instantiator: Insta val releaseExt = project.the() val voteMailFile = layout.buildDirectory.file("$PREPARE_VOTE_TASK_NAME/mail.txt") + val projectDir = layout.projectDirectory outputs.file(file(voteMailFile)) doLast { val nexusPublish = project.the() @@ -670,7 +676,7 @@ class StageVoteReleasePlugin @Inject constructor(private val instantiator: Insta .let { it.replacePath(it.path + "/" + svnDist.stageFolder.get()) } val (stagedFiles, checksums) = if (releaseExt.svnDistEnabled.get()) { - fetchSvnArtifacts(project, svnStagingUri, svnDist) + fetchSvnArtifacts(project, execOperations, logger, projectDir.asFile, svnStagingUri, svnDist) } else { Pair(listOf(), mapOf()) } @@ -708,10 +714,13 @@ class StageVoteReleasePlugin @Inject constructor(private val instantiator: Insta private fun fetchSvnArtifacts( project: Project, + execOperations: ExecOperations, + logger: Logger, + projectDir: File, svnStagingUri: URI, svnDist: SvnDistConfig ): Pair, Map> { - val svn = Svn(project, svnStagingUri).apply { + val svn = Svn(execOperations, logger, projectDir, svnStagingUri).apply { username = svnDist.credentials.username(project) password = svnDist.credentials.password(project) } diff --git a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/SvnmuccTask.kt b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/SvnmuccTask.kt index b04e98e..15cbba1 100644 --- a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/SvnmuccTask.kt +++ b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/SvnmuccTask.kt @@ -16,33 +16,41 @@ */ package com.github.vlsi.gradle.release -import com.github.vlsi.gradle.properties.dsl.stringProperty import com.github.vlsi.gradle.properties.dsl.toBool +import com.github.vlsi.gradle.release.svn.Svn import com.github.vlsi.gradle.release.svn.SvnCredentials import java.io.ByteArrayOutputStream import java.io.File import java.net.URI import javax.inject.Inject import org.gradle.api.DefaultTask -import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.the +import org.gradle.process.ExecOperations import org.gradle.process.ExecSpec import org.gradle.work.InputChanges abstract class SvnmuccTask @Inject constructor() : DefaultTask() { + @get:Inject + abstract val execOperations: ExecOperations + @Input val repository = project.objects.property() .convention(project.provider { project.the().svnDist.url.get() }) + @InputDirectory + protected val projectDir = project.layout.projectDirectory + abstract fun operations(inputChanges: InputChanges): List abstract fun message(): String + // TODO: remove project access at execution time protected fun SvnCredentials.withCredentials() { project.the().svnDist.credentials { this@withCredentials.username = username(project) @@ -50,6 +58,7 @@ abstract class SvnmuccTask @Inject constructor() : DefaultTask() { } } + // TODO: remove project access at execution time protected fun ExecSpec.svnCredentials() { project.the().svnDist.credentials { username(project)?.let { args("--username", it) } @@ -60,24 +69,24 @@ abstract class SvnmuccTask @Inject constructor() : DefaultTask() { fun exists(path: String): Boolean { val os = ByteArrayOutputStream() val absolutePath = "${repository.get()}/$path" - val result = project.exec { - workingDir = project.projectDir + val result = execOperations.exec { + workingDir = projectDir.asFile commandLine("svn", "ls", "--depth", "empty", absolutePath) svnCredentials() isIgnoreExitValue = true errorOutput = os } if (result.exitValue == 0) { - project.logger.debug("Directory {} exists in SVN", absolutePath) + logger.debug("Directory {} exists in SVN", absolutePath) return true } val message = os.toString() // Default encoding is expected if (message.contains("E200009")) { // E200009: Could not list all targets because some targets don't exist - project.logger.debug("Directory {} does not exist in SVN", absolutePath) + logger.debug("Directory {} does not exist in SVN", absolutePath) } else { - project.logger.warn("Unable to check existence of {}. Error: {}", absolutePath, message) + logger.warn("Unable to check existence of {}. Error: {}", absolutePath, message) } return false } @@ -85,6 +94,13 @@ abstract class SvnmuccTask @Inject constructor() : DefaultTask() { @Internal protected val commandsFile = project.layout.buildDirectory.file("svnmucc/$name.txt") + @Input + protected val asfDryRun = project.objects.property() + .convention(project.providers.gradleProperty("asfDryRun").map { it.toBool() }) + + protected fun svnClient(uri: URI) = + Svn(execOperations, logger, projectDir.asFile, uri) + @TaskAction fun mucc(inputChanges: InputChanges) { logger.debug( @@ -120,7 +136,7 @@ abstract class SvnmuccTask @Inject constructor() : DefaultTask() { commandsFile.writeText(commands) val commitMessage = message() - if (project.stringProperty("asfDryRun").toBool()) { + if (asfDryRun.get()) { logger.lifecycle( "Dry run svnmucc. root={}, message={}, commands:\n{}", repository.get(), @@ -139,8 +155,8 @@ abstract class SvnmuccTask @Inject constructor() : DefaultTask() { commitMessage, commands ) - project.exec { - workingDir = project.projectDir + execOperations.exec { + workingDir = projectDir.asFile commandLine("svnmucc", "--non-interactive", "--root-url", repository.get()) svnCredentials() args("--extra-args", commandsFile) diff --git a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/svn/Svn.kt b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/svn/Svn.kt index 9af1e65..9281042 100644 --- a/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/svn/Svn.kt +++ b/plugins/stage-vote-release-plugin/src/main/kotlin/com/github/vlsi/gradle/release/svn/Svn.kt @@ -26,8 +26,11 @@ import java.net.URI import java.time.OffsetDateTime import org.gradle.api.GradleException import org.gradle.api.Project +import org.gradle.api.logging.Logger +import org.gradle.process.ExecOperations +import java.io.File -class Svn(val project: Project, val uri: URI) : SvnCredentials { +class Svn(val execOperations: ExecOperations, val logger: Logger, val projectDir: File, val uri: URI) : SvnCredentials { override var username: String? = null override var password: String? = null @@ -64,12 +67,12 @@ class Svn(val project: Project, val uri: URI) : SvnCredentials { val file = opts.file val revisionSuffix = opts.revision?.let { "@$it" } ?: "" - project.logger.lifecycle("Fetching {}/{}{}", uri, file, revisionSuffix) + logger.lifecycle("Fetching {}/{}{}", uri, file, revisionSuffix) val stdout = ByteArrayOutputStream() val stderr = ByteArrayOutputStream() - val result = project.exec { - workingDir = project.projectDir + val result = execOperations.exec { + workingDir = projectDir commandLine("svn", "cat") opts.username?.let { args("--username", it) } opts.password?.let { args("--password", it) } @@ -97,12 +100,12 @@ class Svn(val project: Project, val uri: URI) : SvnCredentials { } else { "contents" } - project.logger.lifecycle("Listing SVN {} at {}{}", contents, uri, revisionSuffix) + logger.lifecycle("Listing SVN {} at {}{}", contents, uri, revisionSuffix) val stdout = ByteArrayOutputStream() val stderr = ByteArrayOutputStream() - val result = project.exec { - workingDir = project.projectDir + val result = execOperations.exec { + workingDir = projectDir commandLine("svn", "ls", "--xml", "--depth", opts.depth.name.toLowerCase()) for (folder in opts.folders) { args("$uri/$folder/")