Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,27 @@ class MicrofilmPluginFunctionalTest {
.isFalse()
}

@Test
fun `compress task succeeds when image pattern is provided`() {
val project = androidLibProject()
PNG_FIXTURE.copyToDirectory(directory = project.libResourcesDrawableDirectory)
PNG_FIXTURE.copyToDirectory(
directory = project.libResourcesDrawableDirectory,
name = PNG_LOSSY_NAME,
)

val result = project.build(":lib:compressMicrofilm", "--images=**/$PNG_NAME")

assertThat(result).task(":lib:compressMicrofilm").succeeded()
assertThat(project.libResourcesDrawableDirectory.containsPng()).isFalse()
assertThat(project.libResourcesDrawableDirectory.containsWebp()).isTrue()
assertThat(project.libResourcesDrawableDirectory.containsFile(PNG_LOSSY_NAME)).isTrue()
assertThat(project.libResourcesDrawableDirectory.containsFile(WEBP_LOSSY_NAME)).isFalse()
assertThat(project.libMicrofilmDirectory.containsManifest()).isTrue()
assertThat(project.libMicrofilmDrawableDirectory.containsPng()).isTrue()
assertThat(project.libMicrofilmDrawableDirectory.containsFile(PNG_LOSSY_NAME)).isFalse()
}

@Test
fun `compress task is compatible with configuration cache`() {
val project = androidLibProject()
Expand Down Expand Up @@ -332,6 +353,28 @@ class MicrofilmPluginFunctionalTest {
assertThat(project.libMicrofilmDrawableDirectory.containsPng()).isFalse()
}

@Test
fun `decompress task succeeds when image pattern is provided`() {
val project = androidLibProject()
PNG_FIXTURE.copyToDirectory(directory = project.libResourcesDrawableDirectory)
PNG_FIXTURE.copyToDirectory(
directory = project.libResourcesDrawableDirectory,
name = PNG_LOSSY_NAME,
)

project.build(":lib:compressMicrofilm")
val result = project.build(":lib:decompressMicrofilm", "--images=**/$PNG_LOSSY_NAME")

assertThat(result).task(":lib:decompressMicrofilm").succeeded()
assertThat(project.libResourcesDrawableDirectory.containsPng()).isFalse()
assertThat(project.libResourcesDrawableDirectory.containsWebp()).isTrue()
assertThat(project.libResourcesDrawableDirectory.containsFile(PNG_LOSSY_NAME)).isTrue()
assertThat(project.libResourcesDrawableDirectory.containsFile(WEBP_LOSSY_NAME)).isFalse()
assertThat(project.libMicrofilmDirectory.containsManifest()).isTrue()
assertThat(project.libMicrofilmDrawableDirectory.containsPng()).isTrue()
assertThat(project.libMicrofilmDrawableDirectory.containsFile(PNG_LOSSY_NAME)).isFalse()
}

@Test
fun `decompress task is compatible with configuration cache`() {
val project = androidLibProject()
Expand Down Expand Up @@ -470,6 +513,22 @@ class MicrofilmPluginFunctionalTest {
assertThat(result).task(":lib:verifyMicrofilmMain").failed()
}

@Test
fun `verify task succeeds when image pattern is provided`() {
val project = androidLibProject()
MANIFEST_FIXTURE.copyToDirectory(directory = project.libMicrofilmDirectory)
PNG_FIXTURE.copyToDirectory(directory = project.libMicrofilmDrawableDirectory)
PNG_FIXTURE.copyToDirectory(
directory = project.libResourcesDrawableDirectory,
name = PNG_LOSSY_NAME,
)
WEBP_FIXTURE.copyToDirectory(directory = project.libResourcesDrawableDirectory)

val result = project.build(":lib:verifyMicrofilm", "--images=**/$PNG_NAME")

assertThat(result).task(":lib:verifyMicrofilm").succeeded()
}

@Test
fun `verify task is compatible with configuration cache`() {
val project = androidLibProject()
Expand Down
45 changes: 45 additions & 0 deletions plugin/src/main/kotlin/xyz/block/microfilm/ImagesLifecycleTask.kt

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that we could also do to take this a step further is have CompressTask, DecompressTask, and VerifyTask all extend this base class instead of DefaultTask, so they're all guaranteed to share the same --images option.

Or instead of extending ImagesLifecycleTask directly, we could make something like a HasImagesOption interface that the lifecycle and source set tasks all implement.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2026 Block, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.block.microfilm

import org.gradle.api.DefaultTask
import org.gradle.api.provider.ListProperty
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.options.Option
import org.gradle.work.DisableCachingByDefault

/**
* An empty task that acts as an aggregator for a group of source set tasks.
*
* Gradle binds options to the exact task named on the command line. So if you run something like:
* ```
* ./gradlew compressMicrofilm --images drawable-mdpi/my_image.png
* ```
*
* The --images argument will not automatically be passed on to the `compressMicrofilmMain` or
* `compressMicrofilmDebug` tasks. [ImagesLifecycleTask] exists to capture the arguments and expose
* them to the source set tasks
*/
@DisableCachingByDefault(because = "This task has no outputs of its own")
internal abstract class ImagesLifecycleTask : DefaultTask() {
@get:Internal
@get:Option(
option = "images",
description =
"Restrict the task to the images matching these glob patterns, relative to the res directory.",
)
abstract val imagePatterns: ListProperty<String>
}
15 changes: 9 additions & 6 deletions plugin/src/main/kotlin/xyz/block/microfilm/MicrofilmPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,17 @@ public class MicrofilmPlugin : Plugin<Project> {

// Register the tasks
val compress =
tasks.register("compressMicrofilm") { task ->
tasks.register("compressMicrofilm", ImagesLifecycleTask::class.java) { task ->
task.description = "Compresses source images and updates the manifest for all source sets"
task.group = "microfilm"
}
val decompress =
tasks.register("decompressMicrofilm") { task ->
tasks.register("decompressMicrofilm", ImagesLifecycleTask::class.java) { task ->
task.description = "Decompresses source images and removes the manifest for all source sets"
task.group = "microfilm"
}
val verify =
tasks.register("verifyMicrofilm") { task ->
tasks.register("verifyMicrofilm", ImagesLifecycleTask::class.java) { task ->
task.description = "Verifies that the manifest is up to date for all source sets"
task.group = "microfilm"
}
Expand Down Expand Up @@ -140,9 +140,9 @@ public class MicrofilmPlugin : Plugin<Project> {
private fun Project.configureSourceSets(
extension: MicrofilmExtension,
cwebpDirectory: FileCollection,
compress: TaskProvider<*>,
decompress: TaskProvider<*>,
verify: TaskProvider<*>,
compress: TaskProvider<ImagesLifecycleTask>,
decompress: TaskProvider<ImagesLifecycleTask>,
verify: TaskProvider<ImagesLifecycleTask>,
) {
extensions.getByType(CommonExtension::class.java).sourceSets.configureEach { sourceSet ->
val name = sourceSet.name
Expand All @@ -163,6 +163,7 @@ public class MicrofilmPlugin : Plugin<Project> {
task.group = "microfilm"
task.cwebpDirectory.from(cwebpDirectory)
task.imageRules.set(extension.imageRules)
task.imagePatterns.convention(compress.flatMap { it.imagePatterns })
task.microfilmDirectory.set(microfilmDirectory)
task.resourcesDirectory.set(resourcesDirectory)
task.outputs.upToDateWhen { false }
Expand All @@ -172,6 +173,7 @@ public class MicrofilmPlugin : Plugin<Project> {
tasks.register("decompressMicrofilm$nameCapitalized", DecompressTask::class.java) { task ->
task.description = "Decompresses source images for the '$name' source set"
task.group = "microfilm"
task.imagePatterns.convention(decompress.flatMap { it.imagePatterns })
task.microfilmDirectory.set(microfilmDirectory)
task.resourcesDirectory.set(resourcesDirectory)
task.outputs.upToDateWhen { false }
Expand All @@ -182,6 +184,7 @@ public class MicrofilmPlugin : Plugin<Project> {
task.description = "Verifies that the manifest is up to date for the '$name' source set"
task.group = "microfilm"
task.cwebpDirectory.from(cwebpDirectory)
task.imagePatterns.convention(verify.flatMap { it.imagePatterns })
task.imageRules.set(extension.imageRules)
task.microfilmDirectory.set(microfilmDirectory)
task.resourcesDirectory.set(resourcesDirectory)
Expand Down