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 gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ protobufJava = { module = "com.google.protobuf:protobuf-java", version.ref = "pr
clikt = "com.github.ajalt.clikt:clikt:4.4.0"
junit = "junit:junit:4.13.2"
assertk = "com.willowtreeapps.assertk:assertk:0.28.1"
kotlinxHtml = "org.jetbrains.kotlinx:kotlinx-html:0.11.0"
okio = "com.squareup.okio:okio:3.9.0"
byteunits = "com.jakewharton.byteunits:byteunits:0.9.1"
asm = "org.ow2.asm:asm:9.7"
Expand Down
1 change: 1 addition & 0 deletions reports/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ apply plugin: 'org.jetbrains.dokka'
dependencies {
api projects.formats
implementation libs.picnic
implementation libs.kotlinxHtml
implementation libs.diffUtils

testImplementation libs.junit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.jakewharton.diffuse.diff

import com.jakewharton.diffuse.format.Aab
import com.jakewharton.diffuse.report.Report
import com.jakewharton.diffuse.report.html.AabDiffHtmlReport
import com.jakewharton.diffuse.report.text.AabDiffTextReport

internal class AabDiff(
Expand Down Expand Up @@ -33,4 +34,5 @@ internal class AabDiff(
}

override fun toTextReport(): Report = AabDiffTextReport(this)
override fun toHtmlReport(): Report = AabDiffHtmlReport(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.jakewharton.diffuse.diff
import com.jakewharton.diffuse.format.Aar
import com.jakewharton.diffuse.format.ApiMapping
import com.jakewharton.diffuse.report.Report
import com.jakewharton.diffuse.report.html.AarDiffHtmlReport
import com.jakewharton.diffuse.report.text.AarDiffTextReport

internal class AarDiff(
Expand All @@ -16,4 +17,5 @@ internal class AarDiff(
val manifest = ManifestDiff(oldAar.manifest, newAar.manifest)

override fun toTextReport(): Report = AarDiffTextReport(this)
override fun toHtmlReport(): Report = AarDiffHtmlReport(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.jakewharton.diffuse.diff.lint.resourcesArscCompression
import com.jakewharton.diffuse.format.ApiMapping
import com.jakewharton.diffuse.format.Apk
import com.jakewharton.diffuse.report.Report
import com.jakewharton.diffuse.report.html.ApkDiffHtmlReport
import com.jakewharton.diffuse.report.text.ApkDiffTextReport

internal class ApkDiff(
Expand All @@ -26,4 +27,5 @@ internal class ApkDiff(
)

override fun toTextReport(): Report = ApkDiffTextReport(this)
override fun toHtmlReport(): Report = ApkDiffHtmlReport(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,24 @@ import com.jakewharton.diffuse.diffuseTable
import com.jakewharton.diffuse.format.ArchiveFile.Type
import com.jakewharton.diffuse.format.ArchiveFiles
import com.jakewharton.diffuse.io.Size
import com.jakewharton.diffuse.report.htmlEncoded
import com.jakewharton.diffuse.report.toDiffString
import com.jakewharton.picnic.TableSectionDsl
import com.jakewharton.picnic.TextAlignment.BottomCenter
import com.jakewharton.picnic.TextAlignment.BottomLeft
import com.jakewharton.picnic.TextAlignment.MiddleCenter
import com.jakewharton.picnic.TextAlignment.MiddleRight
import com.jakewharton.picnic.renderText
import kotlinx.html.FlowContent
import kotlinx.html.TR
import kotlinx.html.style
import kotlinx.html.table
import kotlinx.html.tbody
import kotlinx.html.td
import kotlinx.html.tfoot
import kotlinx.html.thead
import kotlinx.html.tr
import kotlinx.html.unsafe

internal class ArchiveFilesDiff(
val oldFiles: ArchiveFiles,
Expand Down Expand Up @@ -120,7 +131,7 @@ internal fun ArchiveFilesDiff.toSummaryTable(
}
}

fun TableSectionDsl.addApkRow(name: String, type: Type? = null) {
fun TableSectionDsl.addArchiveRow(name: String, type: Type? = null) {
val old = if (type != null) oldFiles.filterValues { it.type == type } else oldFiles
val new = if (type != null) newFiles.filterValues { it.type == type } else newFiles
val oldSize = old.values.fold(Size.ZERO) { acc, file -> acc + file.size }
Expand Down Expand Up @@ -150,15 +161,15 @@ internal fun ArchiveFilesDiff.toSummaryTable(
alignment = MiddleRight
}
for (type in displayTypes) {
addApkRow(type.displayName, type)
addArchiveRow(type.displayName, type)
}
}

footer {
cellStyle {
alignment = MiddleRight
}
addApkRow("total")
addArchiveRow("total")
}
}.renderText()

Expand Down Expand Up @@ -243,3 +254,190 @@ internal fun ArchiveFilesDiff.toDetailReport() = buildString {
}.renderText(),
)
}

internal fun FlowContent.toSummaryTable(
name: String,
diff: ArchiveFilesDiff,
displayTypes: List<Type>,
skipIfEmptyTypes: Set<Type> = emptySet(),
) {
table {
thead {
if (diff.includeCompressed) {
tr {
td {
rowSpan = "2"
style = "text-align: left; vertical-align: bottom;"
+name
}
td {
colSpan = "3"
style = "text-align: center; vertical-align: bottom;"
+"compressed"
}
td {
colSpan = "3"
style = "text-align: center; vertical-align: bottom;"
+"uncompressed"
}
}
tr {
td { +"old" }
td { +"new" }
td { +"diff" }
td { +"old" }
td { +"new" }
td { +"diff" }
}
} else {
tr {
td {
style = "text-align: left; vertical-align: bottom;"
+name
}
td { +"old" }
td { +"new" }
td { +"diff" }
}
}
}

fun TR.addArchiveRow(name: String, type: Type? = null) {
val old = if (type != null) diff.oldFiles.filterValues { it.type == type } else diff.oldFiles
val new = if (type != null) diff.newFiles.filterValues { it.type == type } else diff.newFiles
val oldSize = old.values.fold(Size.ZERO) { acc, file -> acc + file.size }
val newSize = new.values.fold(Size.ZERO) { acc, file -> acc + file.size }
val oldUncompressedSize = old.values.fold(Size.ZERO) { acc, file -> acc + file.uncompressedSize }
val newUncompressedSize = new.values.fold(Size.ZERO) { acc, file -> acc + file.uncompressedSize }
if (oldSize != Size.ZERO || newSize != Size.ZERO || type !in skipIfEmptyTypes) {
val uncompressedDiff = (newUncompressedSize - oldUncompressedSize).toDiffString()
if (diff.includeCompressed) {
td { +name }
td { +oldSize.toString() }
td { +newSize.toString() }
td { +(newSize - oldSize).toString() }
td { +oldUncompressedSize.toString() }
td { +newUncompressedSize.toString() }
td { +uncompressedDiff }
} else {
td { +name }
td { +oldUncompressedSize.toString() }
td { +newUncompressedSize.toString() }
td { +uncompressedDiff }
}
}
}

tbody {
style = "text-align: right; vertical-align: middle;"

for (type in displayTypes) {
tr {
addArchiveRow(type.displayName, type)
}
}
}

tfoot {
style = "text-align: right; vertical-align: middle;"
tr { addArchiveRow("total") }
}
}
}

internal fun FlowContent.toDetailReport(diff: ArchiveFilesDiff) {
table {
thead {
if (diff.includeCompressed) {
tr {
td {
style = "text-align: center; vertical-align: middle;"
colSpan = "2"
+"compressed"
}
td {
style = "text-align: center; vertical-align: middle;"
colSpan = "2"
+"uncompressed"
}

td {
style = "text-align: left; vertical-align: bottom;"
rowSpan = "2"
+"path"
}
}
tr {
td { +"size" }
td { +"diff" }
td { +"size" }
td { +"diff" }
}
} else {
tr {
td { +"size" }
td { +"diff" }
td {
style = "text-align: left; vertical-align: bottom;"
+"path"
}
}
}
}
tfoot {
tr {
if (diff.includeCompressed) {
val totalSize = diff.changes.fold(Size.ZERO) { acc, change -> acc + change.size }
val totalDiff = diff.changes.fold(Size.ZERO) { acc, change -> acc + change.sizeDiff }
td {
style = "text-align: right; vertical-align: middle;"
+totalSize.toString()
}
td {
style = "text-align: right; vertical-align: middle;"
+totalDiff.toDiffString()
}
}
val totalUncompressedSize = diff.changes.fold(Size.ZERO) { acc, change -> acc + change.uncompressedSize }
val totalUncompressedDiff = diff.changes.fold(Size.ZERO) { acc, change -> acc + change.uncompressedSizeDiff }
td {
style = "text-align: right; vertical-align: middle;"
+totalUncompressedSize.toString()
}
td {
style = "text-align: right; vertical-align: middle;"
+totalUncompressedDiff.toDiffString()
}
td { +"(total)" }
}
}
for ((path, size, sizeDiff, uncompressedSize, uncompressedSizeDiff, type) in diff.changes) {
val typeChar = when (type) {
Change.Type.Added -> '+'
Change.Type.Removed -> '-'
Change.Type.Changed -> '∆'
}
tr {
if (diff.includeCompressed) {
td {
style = "text-align: right; vertical-align: middle;"
if (type != Change.Type.Removed) +size.toString() else +""
}
td {
style = "text-align: right; vertical-align: middle;"
+sizeDiff.toDiffString()
}
}
td {
style = "text-align: right; vertical-align: middle;"
if (type != Change.Type.Removed) +uncompressedSize.toString() else +""
}
td {
style = "text-align: right; vertical-align: middle;"
+uncompressedSizeDiff.toDiffString()
}
td { unsafe { raw("$typeChar $path".htmlEncoded) } }
}
}
}
}
Loading