Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions formats/api/formats.api
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -100,6 +105,7 @@ class ArchiveFile(
@JvmName("fromJarName")
fun String.toJarFileType() =
when {
endsWith("/") -> Dir
endsWith(".class") -> Class
else -> Other
}
Expand Down
11 changes: 11 additions & 0 deletions reports/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

apply plugin: 'org.jetbrains.kotlin.jvm'
apply plugin: 'com.vanniktech.maven.publish'
apply plugin: 'org.jetbrains.dokka'

def friends = configurations.register('friends')

dependencies {
api projects.formats
implementation libs.picnic
implementation libs.diffUtils

add(friends.name, projects.formats)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Can't call friends projects.formats 😅

A problem occurred evaluating project ':reports'.
> Could not find method call() for arguments [project ':formats'] on provider(configuration 'friends', interface org.gradle.api.artifacts.LegacyConfiguration) of type org.gradle.api.internal.AbstractNamedDomainObjectContainer$NamedDomainObjectCreatingProvider_Decorated.


testImplementation libs.junit
testImplementation libs.assertk
}

tasks.withType(KotlinCompile).configureEach { task ->
// https://www.liutikas.net/2025/01/12/Kotlin-Library-Friends.html
task.friendPaths.from(friends.map { it.incoming.artifactView {}.files })
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ internal class ArchiveFilesDiff(
internal fun ArchiveFilesDiff.toSummaryTable(
name: String,
displayTypes: List<Type>,
skipIfEmptyTypes: Set<Type> = emptySet(),
skipIfEmptyTypes: Set<Type> = setOf(Type.Dir),
) = diffuseTable {
header {
if (includeCompressed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import me.saket.bytesize.binaryBytes
internal fun ArchiveFiles.toSummaryTable(
name: String,
displayTypes: List<ArchiveFile.Type>,
skipIfEmptyTypes: Set<ArchiveFile.Type> = emptySet(),
skipIfEmptyTypes: Set<ArchiveFile.Type> = setOf(ArchiveFile.Type.Dir),
includeCompressed: Boolean = true,
) = diffuseTable {
header {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
)
}
}