Skip to content

Commit 0601fc0

Browse files
committed
fix multiple publications in a single project not overwriting each other
1 parent c5e4fc0 commit 0601fc0

File tree

9 files changed

+426
-42
lines changed

9 files changed

+426
-42
lines changed

api/dev-publish-plugin.api

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public abstract class dev/adamko/gradle/dev_publish/DevPublishPluginExtension {
2929
public fun <init> ()V
3030
public abstract fun getChecksumsStore ()Lorg/gradle/api/file/DirectoryProperty;
3131
public abstract fun getDevMavenRepo ()Lorg/gradle/api/file/DirectoryProperty;
32+
public abstract fun getStagingDevMavenRepo ()Lorg/gradle/api/file/DirectoryProperty;
3233
public abstract fun getStagingTestMavenRepo ()Lorg/gradle/api/file/DirectoryProperty;
3334
}
3435

@@ -49,3 +50,12 @@ public abstract class dev/adamko/gradle/dev_publish/tasks/GeneratePublicationHas
4950
public abstract fun getPublicationData ()Lorg/gradle/api/NamedDomainObjectContainer;
5051
}
5152

53+
public abstract class dev/adamko/gradle/dev_publish/tasks/UpdateDevRepoTask : org/gradle/api/DefaultTask {
54+
public fun <init> (Lorg/gradle/api/file/FileSystemOperations;)V
55+
public fun from (Lorg/gradle/api/provider/Provider;)V
56+
public abstract fun getDevRepo ()Lorg/gradle/api/file/DirectoryProperty;
57+
public abstract fun getRepositoryContents ()Lorg/gradle/api/file/ConfigurableFileCollection;
58+
public abstract fun getStagingRepo ()Lorg/gradle/api/file/DirectoryProperty;
59+
public final fun updateDevRepo ()V
60+
}
61+

src/main/kotlin/DevPublishPlugin.kt

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import dev.adamko.gradle.dev_publish.data.PublicationData
44
import dev.adamko.gradle.dev_publish.internal.DevPublishConfigurationAttributes
55
import dev.adamko.gradle.dev_publish.internal.DevPublishConfigurationAttributes.Companion.DEV_PUB_USAGE
66
import dev.adamko.gradle.dev_publish.tasks.GeneratePublicationHashTask
7+
import dev.adamko.gradle.dev_publish.tasks.UpdateDevRepoTask
78
import dev.adamko.gradle.dev_publish.utils.asConsumer
89
import dev.adamko.gradle.dev_publish.utils.asProvider
910
import org.gradle.api.Plugin
@@ -18,7 +19,6 @@ import org.gradle.api.publish.PublishingExtension
1819
import org.gradle.api.publish.maven.MavenPublication
1920
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
2021
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
21-
import org.gradle.api.tasks.Sync
2222
import org.gradle.api.tasks.TaskProvider
2323
import org.gradle.kotlin.dsl.*
2424
import org.gradle.language.base.plugins.LifecycleBasePlugin
@@ -100,38 +100,34 @@ class DevPublishPlugin @Inject constructor(
100100
generatePublicationHashTask,
101101
)
102102

103-
val prepChecksumStoreTask = project.tasks.register("prepareDevPubChecksumStore") {
104-
// hacky workaround to make sure that the checksumsStore directory exists before
105-
// PublishToMavenRepository tasks are configured
106-
outputs.dir(devPubExtension.checksumsStore)
107-
.withPropertyName("checksumStore")
108-
}
109-
110103
project.tasks.withType<PublishToMavenRepository>().configureEach {
111104

112105
// need to determine the repo lazily because the repo isn't set immediately
113106
val repoIsDevPub = providers.provider { repository?.name == DEV_PUB__MAVEN_REPO_NAME }.orElse(false)
114107
inputs.property("repoIsDevPub", repoIsDevPub)
115108

109+
116110
inputs
117-
.files(prepChecksumStoreTask.map { it.outputs.files })
118-
.withPropertyName("devPubChecksumsStore")
111+
// must convert to FileTree, because the directory might not exist, and
112+
// Gradle won't accept directories that don't exist as inputs.
113+
.files(devPubExtension.checksumsStore.asFileTree)
114+
.withPropertyName("devPubChecksumsStoreFiles")
119115

120116
val publicationData = providers.provider {
121117
createPublicationData(publication)
122118
}
123-
val currentChecksum: Provider<String> = publicationData.flatMap { data ->
124-
providers.provider {
125-
data.createChecksumContent()
126-
}
119+
val currentChecksum: Provider<String> = publicationData.map { data ->
120+
data.createChecksumContent()
127121
}
128-
val storedChecksum: Provider<String> = publicationData.flatMap { data ->
129-
providers.provider {
130-
devPubExtension.checksumsStore.asFile.get()
131-
.resolve(data.checksumFilename)
132-
.takeIf(File::exists)
133-
?.readText()
134-
}
122+
123+
val storedChecksum: Provider<String> = providers.zip(
124+
publicationData,
125+
devPubExtension.checksumsStore,
126+
) { data, checksumStore ->
127+
checksumStore.asFile
128+
.resolve(data?.checksumFilename ?: "unknown")
129+
.takeIf(File::exists)
130+
?.readText()
135131
}
136132

137133
onlyIf("current checksums don't match stored checksum") {
@@ -142,22 +138,13 @@ class DevPublishPlugin @Inject constructor(
142138

143139
currentChecksum.orNull != storedChecksum.orNull
144140
}
145-
146-
// clean up dir before publishing to prevent SNAPSHOT spam
147-
doFirst {
148-
if (repoIsDevPub.get()) {
149-
files.delete {
150-
delete(devPubExtension.stagingTestMavenRepo)
151-
}
152-
}
153-
}
154141
}
155142
}
156143

157144
private fun createExtension(project: Project): DevPublishPluginExtension {
158145
return project.extensions.create<DevPublishPluginExtension>(DEV_PUB__EXTENSION_NAME).apply {
159146
devMavenRepo.convention(layout.buildDirectory.dir(DEV_PUB__MAVEN_REPO_DIR))
160-
stagingTestMavenRepo.convention(layout.buildDirectory.dir("tmp/.$DEV_PUB__MAVEN_REPO_DIR/staging"))
147+
stagingDevMavenRepo.convention(layout.buildDirectory.dir("tmp/.$DEV_PUB__MAVEN_REPO_DIR/staging"))
161148
checksumsStore.convention(layout.buildDirectory.dir("tmp/.$DEV_PUB__MAVEN_REPO_DIR/checksum-store"))
162149
}
163150
}
@@ -170,7 +157,7 @@ class DevPublishPlugin @Inject constructor(
170157
group = DEV_PUB__TASK_GROUP
171158
description = "Publishes all Maven publications to the dev Maven repository"
172159

173-
outputs.dir(devPubExtension.stagingTestMavenRepo)
160+
outputs.dir(devPubExtension.stagingDevMavenRepo)
174161

175162
dependsOn(
176163
// I would like to check using repository.name == DEV_PUB__MAVEN_REPO_NAME, but the task's
@@ -192,11 +179,11 @@ class DevPublishPlugin @Inject constructor(
192179
private fun createUpdateDevRepoTask(
193180
project: Project,
194181
devPubExtension: DevPublishPluginExtension,
195-
): TaskProvider<Sync> =
196-
project.tasks.register<Sync>(DEV_PUB__UPDATE_DEV_REPO_TASK_NAME) {
182+
): TaskProvider<UpdateDevRepoTask> =
183+
project.tasks.register<UpdateDevRepoTask>(DEV_PUB__UPDATE_DEV_REPO_TASK_NAME) {
197184
group = DEV_PUB__TASK_GROUP
198-
from(devPubExtension.stagingTestMavenRepo)
199-
into(devPubExtension.devMavenRepo)
185+
stagingRepo.set(devPubExtension.stagingDevMavenRepo)
186+
devRepo.set(devPubExtension.devMavenRepo)
200187
}
201188

202189
private fun configureMavenPublishingPlugin(
@@ -206,7 +193,7 @@ class DevPublishPlugin @Inject constructor(
206193
) {
207194
project.plugins.withType<MavenPublishPlugin>().configureEach {
208195
project.extensions.configure<PublishingExtension> {
209-
repositories.maven(devPubExtension.stagingTestMavenRepo) {
196+
repositories.maven(devPubExtension.stagingDevMavenRepo) {
210197
name = DEV_PUB__MAVEN_REPO_NAME
211198
}
212199

src/main/kotlin/DevPublishPluginExtension.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ abstract class DevPublishPluginExtension {
2020
*
2121
* This value should not typically be configured or used.
2222
*/
23+
abstract val stagingDevMavenRepo: DirectoryProperty
24+
25+
@Deprecated("renamed to tempStagingMavenRepo", ReplaceWith("stagingDevMavenRepo"))
2326
abstract val stagingTestMavenRepo: DirectoryProperty
2427

2528
/**

src/main/kotlin/data/PublicationData.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ abstract class PublicationData @Inject constructor(
2020

2121
/**
2222
* The artifacts inside a [MavenPublication]
23+
*
2324
* @see MavenPublication.getArtifacts
2425
*/
2526
@get:InputFiles
@@ -51,9 +52,9 @@ abstract class PublicationData @Inject constructor(
5152
val identifier = identifier.get()
5253

5354
return /* language=TEXT */ """
54-
|$identifier
55-
|---
56-
|$md5
57-
""".trimMargin()
55+
|$identifier
56+
|---
57+
|$md5
58+
""".trimMargin()
5859
}
5960
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package dev.adamko.gradle.dev_publish.tasks
2+
3+
import dev.adamko.gradle.dev_publish.internal.DevPublishInternalApi
4+
import org.gradle.api.DefaultTask
5+
import org.gradle.api.file.*
6+
import org.gradle.api.provider.Provider
7+
import org.gradle.api.tasks.*
8+
import org.gradle.api.tasks.PathSensitivity.RELATIVE
9+
import java.io.File
10+
import javax.inject.Inject
11+
12+
@CacheableTask
13+
abstract class UpdateDevRepoTask
14+
@Inject
15+
constructor(
16+
private val fs: FileSystemOperations,
17+
) : DefaultTask() {
18+
19+
/**
20+
* Input repo
21+
*
22+
* @see dev.adamko.gradle.dev_publish.DevPublishPluginExtension.stagingDevMavenRepo
23+
*/
24+
@get:Internal
25+
abstract val stagingRepo: DirectoryProperty
26+
27+
/**
28+
* [stagingRepo] is marked as [Internal] as a workaround for 'input directory does not exist' problem.
29+
*
30+
* https://docs.gradle.org/current/userguide/validation_problems.html#input_file_does_not_exist
31+
*
32+
* This property exists so Gradle will still be able to detect the inputs using [InputFiles].
33+
*/
34+
@get:InputFiles
35+
@get:PathSensitive(RELATIVE)
36+
@DevPublishInternalApi
37+
protected val stagingRepoFiles: FileCollection
38+
get() = stagingRepo.asFileTree
39+
40+
@get:InputFiles
41+
@get:PathSensitive(RELATIVE)
42+
abstract val repositoryContents: ConfigurableFileCollection
43+
44+
/**
45+
* Output dev-repo
46+
*
47+
* @see dev.adamko.gradle.dev_publish.DevPublishPluginExtension.devMavenRepo
48+
*/
49+
@get:OutputDirectory
50+
abstract val devRepo: DirectoryProperty
51+
52+
open fun from(files: Provider<Iterable<File>>) {
53+
repositoryContents.from(files)
54+
}
55+
56+
@TaskAction
57+
fun updateDevRepo() {
58+
val syncResult = fs.sync {
59+
from(stagingRepo)
60+
from(repositoryContents)
61+
into(devRepo)
62+
}
63+
64+
// clean up dir after syncing to prevent SNAPSHOT spam
65+
if (syncResult.didWork) {
66+
fs.delete {
67+
delete(stagingRepo)
68+
}
69+
}
70+
}
71+
}

src/main/kotlin/utils/md5.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import java.security.MessageDigest
1313
//import java.util.*
1414

1515

16-
internal fun File.md5(): String = inputStream().md5()
16+
internal fun File.md5(): String = if (exists()) inputStream().md5() else "missing"
1717
//internal fun ByteArray.md5(): String = inputStream().md5()
1818
//internal fun Iterable<File>.md5(): String =
1919
// SequenceInputStream(toEnumeration { it.inputStream() }).md5()

src/test/kotlin/MultiProjectTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class MultiProjectTest : FunSpec({
1717

1818
project.runner.withArguments(
1919
":project-gamma:updateDevRepo",
20+
"--stacktrace",
2021
"--configuration-cache",
2122
"--build-cache",
2223
).build {

0 commit comments

Comments
 (0)