diff --git a/CHANGELOG.md b/CHANGELOG.md index 90166cc8..c21b3b23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Add `--summary-only` flag. - Support diffing bytecode versions for classes. - Support diffing Kotlin metadata versions for classes. +- Support diffing directory entry sizes. **Changed** - Replace `com.jakewharton.diffuse.io.Size` with `me.saket.bytesize.ByteSize` in the APIs. diff --git a/formats/api/formats.api b/formats/api/formats.api index 02e95be6..8f14fa83 100644 --- a/formats/api/formats.api +++ b/formats/api/formats.api @@ -114,6 +114,7 @@ public final class com/jakewharton/diffuse/format/ArchiveFile$Type : java/lang/E public static final field Class Lcom/jakewharton/diffuse/format/ArchiveFile$Type; public static final field Companion Lcom/jakewharton/diffuse/format/ArchiveFile$Type$Companion; public static final field Dex Lcom/jakewharton/diffuse/format/ArchiveFile$Type; + public static final field Dir Lcom/jakewharton/diffuse/format/ArchiveFile$Type; public static final field JAR_TYPES Ljava/util/List; public static final field Jar Lcom/jakewharton/diffuse/format/ArchiveFile$Type; public static final field JarLibs Lcom/jakewharton/diffuse/format/ArchiveFile$Type; @@ -141,6 +142,7 @@ public final class com/jakewharton/diffuse/format/ArchiveFile$Type$Companion { public final class com/jakewharton/diffuse/format/ArchiveFiles : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Lcom/jakewharton/diffuse/format/ArchiveFiles$Companion; + public fun (Ljava/util/Map;)V public fun clear ()V public synthetic fun compute (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; public fun compute (Ljava/lang/String;Ljava/util/function/BiFunction;)Lcom/jakewharton/diffuse/format/ArchiveFile; diff --git a/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFile.kt b/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFile.kt index 9191abe8..606af0a1 100644 --- a/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFile.kt +++ b/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFile.kt @@ -42,24 +42,27 @@ class ArchiveFile( Res, Asset, Native, + Dir, Other; open val displayName get() = name.lowercase(Locale.US) companion object { - @JvmField val APK_TYPES = listOf(Dex, Arsc, Manifest, Res, Native, Asset, Other) + @JvmField val APK_TYPES = listOf(Dex, Arsc, Manifest, Res, Native, Asset, Dir, Other) - @JvmField val AAB_TYPES = listOf(Dex, Manifest, Res, Native, Asset, Other) + @JvmField val AAB_TYPES = listOf(Dex, Manifest, Res, Native, Asset, Dir, Other) - @JvmField val AAR_TYPES = listOf(Jar, Manifest, Res, Native, JarLibs, ApiJar, LintJar, Other) + @JvmField + val AAR_TYPES = listOf(Jar, Manifest, Res, Native, JarLibs, ApiJar, LintJar, Dir, Other) - @JvmField val JAR_TYPES = listOf(Class, Other) + @JvmField val JAR_TYPES = listOf(Class, Dir, Other) @JvmStatic @JvmName("fromApkName") fun String.toApkFileType() = when { + endsWith("/") -> Dir matches(Apk.classesDexRegex) -> Dex equals(AndroidManifest.NAME) -> Manifest equals(ArscFormat.NAME) -> Arsc @@ -73,6 +76,7 @@ class ArchiveFile( @JvmName("fromAabName") fun String.toAabFileType() = when { + endsWith("/") -> Dir equals(Aab.Module.MANIFEST_FILE_PATH) -> Manifest startsWith("dex/") -> Dex startsWith("lib/") -> Native @@ -85,6 +89,7 @@ class ArchiveFile( @JvmName("fromAarName") fun String.toAarFileType() = when { + endsWith("/") -> Dir equals("classes.jar") -> Jar equals("api.jar") -> ApiJar equals("lint.jar") -> LintJar @@ -100,6 +105,7 @@ class ArchiveFile( @JvmName("fromJarName") fun String.toJarFileType() = when { + endsWith("/") -> Dir endsWith(".class") -> Class else -> Other } diff --git a/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFiles.kt b/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFiles.kt index e6977fdf..ec11fa9a 100644 --- a/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFiles.kt +++ b/formats/src/main/kotlin/com/jakewharton/diffuse/format/ArchiveFiles.kt @@ -5,7 +5,7 @@ import com.jakewharton.diffuse.format.ArchiveFile.Type.Other import com.jakewharton.diffuse.io.Zip import me.saket.bytesize.binaryBytes -class ArchiveFiles internal constructor(private val files: Map) : +class ArchiveFiles(private val files: Map) : Map by files { override fun hashCode() = files.hashCode() diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/diff/ArchiveFilesDiff.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/diff/ArchiveFilesDiff.kt index ed250556..c549f204 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/diff/ArchiveFilesDiff.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/diff/ArchiveFilesDiff.kt @@ -96,7 +96,7 @@ internal class ArchiveFilesDiff( internal fun ArchiveFilesDiff.toSummaryTable( name: String, displayTypes: List, - skipIfEmptyTypes: Set = emptySet(), + skipIfEmptyTypes: Set = setOf(Type.Dir), ) = diffuseTable { header { if (includeCompressed) { diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/info/ArchiveFilesInfo.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/info/ArchiveFilesInfo.kt index 8a0a9a4e..78dbd5db 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/info/ArchiveFilesInfo.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/info/ArchiveFilesInfo.kt @@ -11,7 +11,7 @@ import me.saket.bytesize.binaryBytes internal fun ArchiveFiles.toSummaryTable( name: String, displayTypes: List, - skipIfEmptyTypes: Set = emptySet(), + skipIfEmptyTypes: Set = setOf(ArchiveFile.Type.Dir), includeCompressed: Boolean = true, ) = diffuseTable { header { diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AabInfoTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AabInfoTextReport.kt index ea8afaf9..21edfc98 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AabInfoTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AabInfoTextReport.kt @@ -44,7 +44,7 @@ internal class AabInfoTextReport(private val aab: Aab) : Report { module.files.toSummaryTable( "AAB", ArchiveFile.Type.AAB_TYPES, - skipIfEmptyTypes = setOf(ArchiveFile.Type.Native), + skipIfEmptyTypes = setOf(ArchiveFile.Type.Native, ArchiveFile.Type.Dir), ) ) appendLine(module.dexes.toSummaryTable()) diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt index 6fc27335..8102ca23 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarDiffTextReport.kt @@ -21,7 +21,8 @@ internal class AarDiffTextReport(private val aarDiff: AarDiff, private val summa aarDiff.archive.toSummaryTable( "AAR", Type.AAR_TYPES, - skipIfEmptyTypes = setOf(Type.JarLibs, Type.ApiJar, Type.LintJar, Type.Native, Type.Res), + skipIfEmptyTypes = + setOf(Type.JarLibs, Type.ApiJar, Type.LintJar, Type.Native, Type.Res, Type.Dir), ) ) appendLine() diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarInfoTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarInfoTextReport.kt index fc40c072..6158070a 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarInfoTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/AarInfoTextReport.kt @@ -14,7 +14,8 @@ internal class AarInfoTextReport(private val aar: Aar) : Report { aar.files.toSummaryTable( "AAR", Type.AAR_TYPES, - skipIfEmptyTypes = setOf(Type.JarLibs, Type.ApiJar, Type.LintJar, Type.Native, Type.Res), + skipIfEmptyTypes = + setOf(Type.JarLibs, Type.ApiJar, Type.LintJar, Type.Native, Type.Res, Type.Dir), ) ) appendLine() diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkDiffTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkDiffTextReport.kt index 36dfef51..04a174ca 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkDiffTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkDiffTextReport.kt @@ -53,7 +53,11 @@ internal class ApkDiffTextReport(private val apkDiff: ApkDiff, private val summa appendLine() } appendLine( - apkDiff.archive.toSummaryTable("APK", Type.APK_TYPES, skipIfEmptyTypes = setOf(Type.Native)) + apkDiff.archive.toSummaryTable( + "APK", + Type.APK_TYPES, + skipIfEmptyTypes = setOf(Type.Native, Type.Dir), + ) ) appendLine() appendLine(apkDiff.dex.toSummaryTable()) diff --git a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkInfoTextReport.kt b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkInfoTextReport.kt index c798dc9f..80843aa5 100644 --- a/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkInfoTextReport.kt +++ b/reports/src/main/kotlin/com/jakewharton/diffuse/report/text/ApkInfoTextReport.kt @@ -19,7 +19,7 @@ class ApkInfoTextReport(private val apk: Apk) : Report { apk.files.toSummaryTable( "APK", ArchiveFile.Type.APK_TYPES, - skipIfEmptyTypes = setOf(ArchiveFile.Type.Native), + skipIfEmptyTypes = setOf(ArchiveFile.Type.Native, ArchiveFile.Type.Dir), ) ) appendLine() diff --git a/reports/src/test/kotlin/com/jakewharton/diffuse/ArchiveFilesDiffTest.kt b/reports/src/test/kotlin/com/jakewharton/diffuse/ArchiveFilesDiffTest.kt new file mode 100644 index 00000000..3e820edc --- /dev/null +++ b/reports/src/test/kotlin/com/jakewharton/diffuse/ArchiveFilesDiffTest.kt @@ -0,0 +1,91 @@ +package com.jakewharton.diffuse + +import assertk.assertThat +import assertk.assertions.isEqualTo +import com.jakewharton.diffuse.diff.ArchiveFilesDiff +import com.jakewharton.diffuse.diff.toSummaryTable +import com.jakewharton.diffuse.format.ArchiveFile +import com.jakewharton.diffuse.format.ArchiveFile.Type +import com.jakewharton.diffuse.format.ArchiveFiles +import me.saket.bytesize.binaryBytes +import org.junit.Test + +class ArchiveFilesDiffTest { + @Test + fun summaryTableWithDirType() { + val base = + mapOf( + "com/example/Main.class" to + ArchiveFile( + "com/example/Main.class", + Type.Class, + 100.binaryBytes, + 200.binaryBytes, + true, + ), + "META-INF/MANIFEST.MF" to + ArchiveFile("META-INF/MANIFEST.MF", Type.Other, 30.binaryBytes, 40.binaryBytes, true), + ) + val oldFiles = + ArchiveFiles( + base + + mapOf( + "com/example/" to + ArchiveFile("com/example/", Type.Dir, 50.binaryBytes, 0.binaryBytes, true) + ) + ) + val newFiles = ArchiveFiles(base) + val diff = ArchiveFilesDiff(oldFiles, newFiles) + val table = diff.toSummaryTable("JAR", Type.JAR_TYPES) + assertThat(table) + .isEqualTo( + """ + | │ compressed │ uncompressed + | ├───────┬───────┬───────┼───────┬───────┬────── + | JAR │ old │ new │ diff │ old │ new │ diff + |───────┼───────┼───────┼───────┼───────┼───────┼────── + | class │ 100 B │ 100 B │ 0 B │ 200 B │ 200 B │ 0 B + | dir │ 50 B │ 0 B │ -50 B │ 0 B │ 0 B │ 0 B + | other │ 30 B │ 30 B │ 0 B │ 40 B │ 40 B │ 0 B + |───────┼───────┼───────┼───────┼───────┼───────┼────── + | total │ 180 B │ 130 B │ -50 B │ 240 B │ 240 B │ 0 B + """ + .trimMargin() + ) + } + + @Test + fun summaryTableSkipsEmptyDirType() { + val base = + mapOf( + "com/example/Main.class" to + ArchiveFile( + "com/example/Main.class", + Type.Class, + 100.binaryBytes, + 200.binaryBytes, + true, + ), + "META-INF/MANIFEST.MF" to + ArchiveFile("META-INF/MANIFEST.MF", Type.Other, 30.binaryBytes, 40.binaryBytes, true), + ) + val oldFiles = ArchiveFiles(base) + val newFiles = ArchiveFiles(base) + val diff = ArchiveFilesDiff(oldFiles, newFiles) + val table = diff.toSummaryTable("JAR", Type.JAR_TYPES) + assertThat(table) + .isEqualTo( + """ + | │ compressed │ uncompressed + | ├───────┬───────┬──────┼───────┬───────┬────── + | JAR │ old │ new │ diff │ old │ new │ diff + |───────┼───────┼───────┼──────┼───────┼───────┼────── + | class │ 100 B │ 100 B │ 0 B │ 200 B │ 200 B │ 0 B + | other │ 30 B │ 30 B │ 0 B │ 40 B │ 40 B │ 0 B + |───────┼───────┼───────┼──────┼───────┼───────┼────── + | total │ 130 B │ 130 B │ 0 B │ 240 B │ 240 B │ 0 B + """ + .trimMargin() + ) + } +}