From 2d7221421f920bc4fd8edc8b5e41d32914482d7c Mon Sep 17 00:00:00 2001 From: 5peak2me <461260911@qq.com> Date: Wed, 8 Jan 2025 20:08:32 +0800 Subject: [PATCH] Extract file's operation to FileProvider.kt --- .../com/spotify/ruler/plugin/FileProvider.kt | 93 +++++++++++++++++++ .../com/spotify/ruler/plugin/RulerPlugin.kt | 92 +----------------- 2 files changed, 96 insertions(+), 89 deletions(-) create mode 100644 ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/FileProvider.kt diff --git a/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/FileProvider.kt b/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/FileProvider.kt new file mode 100644 index 0000000..1705eab --- /dev/null +++ b/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/FileProvider.kt @@ -0,0 +1,93 @@ +package com.spotify.ruler.plugin + +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.ApplicationVariant +import org.gradle.api.Project +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.Provider + +/** + * Returns the bundle file that's going to be analyzed. DexGuard produces a separate bundle instead of overriding + * the default one, so we have to handle that separately. + */ +internal fun Project.getBundleFile( + variant: ApplicationVariant +): Provider { + val defaultBundleFile = variant.artifacts.get(SingleArtifact.BUNDLE) + if (!hasDexGuard(project)) { + return defaultBundleFile // No DexGuard means we can use the default bundle + } + + // Bundle can still be in the default location, depending on the DexGuard config + return defaultBundleFile.flatMap { bundle -> + val dexGuardBundle = + bundle.asFile.parentFile.resolve("${bundle.asFile.nameWithoutExtension}-protected.aab") + if (dexGuardBundle.exists()) { + project.layout.buildDirectory.file(dexGuardBundle.absolutePath) // File exists -> use it + } else { + defaultBundleFile // File doesn't exist -> fall back to default + } + } +} + +/** + * Returns the mapping file used for de-obfuscation. Different obfuscation tools like DexGuard and ProGuard place + * their mapping files in different directories, so we have to handle those separately. + */ +internal fun Project.getMappingFile( + variant: ApplicationVariant +): Provider { + val defaultMappingFile = variant.artifacts.get(SingleArtifact.OBFUSCATION_MAPPING_FILE) + val mappingFilePath = when { + hasDexGuard(project) -> "outputs/dexguard/mapping/bundle/${variant.name}/mapping.txt" + hasProGuard(project) -> "outputs/proguard/${variant.name}/mapping/mapping.txt" + else -> return defaultMappingFile // No special obfuscation plugin -> use default path + } + + // Mapping files can also be missing, for example when obfuscation is disabled for a variant + val mappingFileProvider = project.layout.buildDirectory.file(mappingFilePath) + return mappingFileProvider.flatMap { mappingFile -> + if (mappingFile.asFile.exists()) { + mappingFileProvider // File exists -> use it + } else { + defaultMappingFile // File doesn't exist -> fall back to default + } + } +} + +/** + * Returns a mapping file to de-obfuscate resource names. DexGuard supports this feature by default, so we need to + * handle it accordingly. + */ +internal fun Project.getResourceMappingFile( + variant: ApplicationVariant +): Provider { + val defaultResourceMappingFile = project.objects.fileProperty() // Empty by default + @Suppress("SpellCheckingInspection") + val resourceMappingFilePath = when { + hasDexGuard(project) -> "outputs/dexguard/mapping/bundle/${variant.name}/resourcefilenamemapping.txt" + else -> return defaultResourceMappingFile // No DexGuard plugin -> use default empty file + } + + // Mapping file can still be missing, for example if resource obfuscation is disabled for a variant + val resourceMappingFileProvider = + project.layout.buildDirectory.file(resourceMappingFilePath) + return resourceMappingFileProvider.flatMap { resourceMappingFile -> + if (resourceMappingFile.asFile.exists()) { + resourceMappingFileProvider // File exists -> use it + } else { + defaultResourceMappingFile // File doesn't exist -> fall back to default + } + } +} + +/** Checks if the given [project] is using DexGuard for obfuscation, instead of R8. */ +private fun hasDexGuard(project: Project): Boolean { + return project.pluginManager.hasPlugin("dexguard") +} + +/** Checks if the given [project] is using ProGuard for obfuscation, instead of R8. */ +private fun hasProGuard(project: Project): Boolean { + @Suppress("SpellCheckingInspection") + return project.pluginManager.hasPlugin("com.guardsquare.proguard") +} diff --git a/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/RulerPlugin.kt b/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/RulerPlugin.kt index 23cb23e..99b8712 100644 --- a/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/RulerPlugin.kt +++ b/ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/RulerPlugin.kt @@ -57,9 +57,9 @@ class RulerPlugin : Plugin { task.appInfo.set(getAppInfo(project, variant)) task.deviceSpec.set(getDeviceSpec(rulerExtension)) - task.bundleFile.set(getBundleFile(project, variant)) - task.mappingFile.set(getMappingFile(project, variant)) - task.resourceMappingFile.set(getResourceMappingFile(project, variant)) + task.bundleFile.set(project.getBundleFile(variant)) + task.mappingFile.set(project.getMappingFile(variant)) + task.resourceMappingFile.set(project.getResourceMappingFile(variant)) task.ownershipFile.set(rulerExtension.ownershipFile) task.defaultOwner.set(rulerExtension.defaultOwner) @@ -94,83 +94,6 @@ class RulerPlugin : Plugin { sdkVersion = extension.sdkVersion.orNull ?: error("SDK version not specified."), ) - /** - * Returns the bundle file that's going to be analyzed. DexGuard produces a separate bundle instead of overriding - * the default one, so we have to handle that separately. - */ - private fun getBundleFile( - project: Project, - variant: ApplicationVariant - ): Provider { - val defaultBundleFile = variant.artifacts.get(SingleArtifact.BUNDLE) - if (!hasDexGuard(project)) { - return defaultBundleFile // No DexGuard means we can use the default bundle - } - - // Bundle can still be in the default location, depending on the DexGuard config - return defaultBundleFile.flatMap { bundle -> - val dexGuardBundle = - bundle.asFile.parentFile.resolve("${bundle.asFile.nameWithoutExtension}-protected.aab") - if (dexGuardBundle.exists()) { - project.layout.buildDirectory.file(dexGuardBundle.absolutePath) // File exists -> use it - } else { - defaultBundleFile // File doesn't exist -> fall back to default - } - } - } - - /** - * Returns the mapping file used for de-obfuscation. Different obfuscation tools like DexGuard and ProGuard place - * their mapping files in different directories, so we have to handle those separately. - */ - private fun getMappingFile( - project: Project, - variant: ApplicationVariant - ): Provider { - val defaultMappingFile = variant.artifacts.get(SingleArtifact.OBFUSCATION_MAPPING_FILE) - val mappingFilePath = when { - hasDexGuard(project) -> "outputs/dexguard/mapping/bundle/${variant.name}/mapping.txt" - hasProGuard(project) -> "outputs/proguard/${variant.name}/mapping/mapping.txt" - else -> return defaultMappingFile // No special obfuscation plugin -> use default path - } - - // Mapping files can also be missing, for example when obfuscation is disabled for a variant - val mappingFileProvider = project.layout.buildDirectory.file(mappingFilePath) - return mappingFileProvider.flatMap { mappingFile -> - if (mappingFile.asFile.exists()) { - mappingFileProvider // File exists -> use it - } else { - defaultMappingFile // File doesn't exist -> fall back to default - } - } - } - - /** - * Returns a mapping file to de-obfuscate resource names. DexGuard supports this feature by default, so we need to - * handle it accordingly. - */ - private fun getResourceMappingFile( - project: Project, - variant: ApplicationVariant - ): Provider { - val defaultResourceMappingFile = project.objects.fileProperty() // Empty by default - val resourceMappingFilePath = when { - hasDexGuard(project) -> "outputs/dexguard/mapping/bundle/${variant.name}/resourcefilenamemapping.txt" - else -> return defaultResourceMappingFile // No DexGuard plugin -> use default empty file - } - - // Mapping file can still be missing, for example if resource obfuscation is disabled for a variant - val resourceMappingFileProvider = - project.layout.buildDirectory.file(resourceMappingFilePath) - return resourceMappingFileProvider.flatMap { resourceMappingFile -> - if (resourceMappingFile.asFile.exists()) { - resourceMappingFileProvider // File exists -> use it - } else { - defaultResourceMappingFile // File doesn't exist -> fall back to default - } - } - } - private fun getVerificationConfig(extension: RulerVerificationExtension): VerificationConfig { return VerificationConfig( downloadSizeThreshold = extension.downloadSizeThreshold.get(), @@ -178,13 +101,4 @@ class RulerPlugin : Plugin { ) } - /** Checks if the given [project] is using DexGuard for obfuscation, instead of R8. */ - private fun hasDexGuard(project: Project): Boolean { - return project.pluginManager.hasPlugin("dexguard") - } - - /** Checks if the given [project] is using ProGuard for obfuscation, instead of R8. */ - private fun hasProGuard(project: Project): Boolean { - return project.pluginManager.hasPlugin("com.guardsquare.proguard") - } }