From 893274074bfeeb0239576c560292e3dc16d3ada2 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 00:21:58 +0100 Subject: [PATCH 1/9] refactor: Do not escape unnecessary --- src/main/kotlin/app/revanced/library/adb/Constants.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/app/revanced/library/adb/Constants.kt b/src/main/kotlin/app/revanced/library/adb/Constants.kt index 94caabc..74641a0 100644 --- a/src/main/kotlin/app/revanced/library/adb/Constants.kt +++ b/src/main/kotlin/app/revanced/library/adb/Constants.kt @@ -21,21 +21,21 @@ internal object Constants { "chcon u:object_r:apk_data_file:s0 ${'$'}base_path" internal const val UMOUNT = - "grep $PLACEHOLDER /proc/mounts | while read -r line; do echo ${'$'}line | cut -d \" \" -f 2 | sed 's/apk.*/apk/' | xargs -r umount -l; done" + "grep $PLACEHOLDER /proc/mounts | while read -r line; do echo ${'$'}line | cut -d ' ' -f 2 | sed 's/apk.*/apk/' | xargs -r umount -l; done" internal const val INSTALL_MOUNT = "mv $TMP_PATH $MOUNT_PATH && chmod +x $MOUNT_PATH" internal val MOUNT_SCRIPT = """ #!/system/bin/sh - MAGISKTMP="${'$'}(magisk --path)" || MAGISKTMP=/sbin + MAGISKTMP="$( magisk --path )" || MAGISKTMP=/sbin MIRROR="${'$'}MAGISKTMP/.magisk/mirror" - until [ "${'$'}(getprop sys.boot_completed)" = 1 ]; do sleep 3; done + until [ "$( getprop sys.boot_completed )" = 1 ]; do sleep 3; done until [ -d "/sdcard/Android" ]; do sleep 1; done base_path="$PATCHED_APK_PATH" - stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' ) + stock_path=$( pm path $PLACEHOLDER | grep base | sed 's/package://g' ) chcon u:object_r:apk_data_file:s0 ${'$'}base_path mount -o bind ${'$'}MIRROR${'$'}base_path ${'$'}stock_path From c5f3536cbb6997766076595dc0b2b5d2e861ca73 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 02:23:47 +0100 Subject: [PATCH 2/9] feat: Add `PatchUtils#getMostCommonCompatibleVersions` utility function --- api/revanced-library.api | 3 + .../kotlin/app/revanced/library/PatchUtils.kt | 46 +++++++ .../app/revanced/library/PatchUtilsTest.kt | 113 +++++++++++++++++- 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/api/revanced-library.api b/api/revanced-library.api index 2d0cddb..e020e1e 100644 --- a/api/revanced-library.api +++ b/api/revanced-library.api @@ -63,6 +63,8 @@ public final class app/revanced/library/Options$Patch$Option { public final class app/revanced/library/PatchUtils { public static final field INSTANCE Lapp/revanced/library/PatchUtils; public final fun getMostCommonCompatibleVersion (Ljava/util/Set;Ljava/lang/String;)Ljava/lang/String; + public final fun getMostCommonCompatibleVersions (Ljava/util/Set;Ljava/util/Set;Z)Ljava/util/Map; + public static synthetic fun getMostCommonCompatibleVersions$default (Lapp/revanced/library/PatchUtils;Ljava/util/Set;Ljava/util/Set;ZILjava/lang/Object;)Ljava/util/Map; } public abstract class app/revanced/library/adb/AdbManager { @@ -87,6 +89,7 @@ public final class app/revanced/library/adb/AdbManager$Companion { } public final class app/revanced/library/adb/AdbManager$DeviceNotFoundException : java/lang/Exception { + public fun ()V } public final class app/revanced/library/adb/AdbManager$FailedToFindInstalledPackageException : java/lang/Exception { diff --git a/src/main/kotlin/app/revanced/library/PatchUtils.kt b/src/main/kotlin/app/revanced/library/PatchUtils.kt index 716814c..de04dcd 100644 --- a/src/main/kotlin/app/revanced/library/PatchUtils.kt +++ b/src/main/kotlin/app/revanced/library/PatchUtils.kt @@ -1,6 +1,14 @@ package app.revanced.library import app.revanced.patcher.PatchSet +import java.util.* + +private typealias PackageName = String +private typealias Version = String +private typealias Count = Int + +private typealias VersionMap = SortedMap +internal typealias PackageNameMap = Map /** * Utility functions for working with patches. @@ -14,6 +22,13 @@ object PatchUtils { * @param packageName The name of the compatible package. * @return The most common version of. */ + @Deprecated( + "Use getMostCommonCompatibleVersions instead.", + ReplaceWith( + "getMostCommonCompatibleVersions(patches, setOf(packageName))" + + ".entries.firstOrNull()?.value?.keys?.firstOrNull()", + ), + ) fun getMostCommonCompatibleVersion( patches: PatchSet, packageName: String, @@ -28,4 +43,35 @@ object PatchUtils { .groupingBy { it } .eachCount() .maxByOrNull { it.value }?.key + + /** + * Get the count of versions for each compatible package from a supplied set of [patches] ordered by the most common version. + * + * @param patches The set of patches to check. + * @param packageNames The names of the compatible packages. + * @param countUnusedPatches Whether to count patches that are not used. + * @return A map of package names to a map of versions to their count. + */ + fun getMostCommonCompatibleVersions( + patches: PatchSet, + packageNames: Set, + countUnusedPatches: Boolean = false, + ): PackageNameMap { + val wantedPackages = packageNames.toHashSet() + return buildMap { + patches + .filter { it.use || countUnusedPatches } + .flatMap { it.compatiblePackages ?: emptyList() } + .filter { it.name in wantedPackages } + .forEach { compatiblePackage -> + compatiblePackage.versions?.let { versions -> + val versionMap = getOrPut(compatiblePackage.name) { sortedMapOf() } + + versions.forEach { version -> + versionMap[version] = versionMap.getOrDefault(version, 0) + 1 + } + } + } + } + } } diff --git a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt index 9b8ada2..669c214 100644 --- a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt +++ b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt @@ -8,6 +8,83 @@ import org.junit.jupiter.api.Test import kotlin.test.assertEquals internal object PatchUtilsTest { + private val patches = + arrayOf( + newPatch("some.package", "a"), + newPatch("some.package", "a", "b", use = false), + newPatch("some.package", "a", "b", "c", use = false), + newPatch("some.other.package", "b", use = false), + newPatch("some.other.package", "b", "c"), + newPatch("some.other.package", "b", "c", "d"), + newPatch("some.other.other.package"), + newPatch("some.other.other.package", "a"), + newPatch("some.other.other.package", "b"), + newPatch("some.other.other.other.package", use = false), + newPatch("some.other.other.other.package", use = false), + ).toSet() + + @Test + fun `return common versions correctly ordered for each package`() { + assertEqualsVersions( + expected = + mapOf( + "some.package" to sortedMapOf("a" to 3, "b" to 2, "c" to 1), + "some.other.package" to sortedMapOf("b" to 3, "c" to 2, "d" to 1), + "some.other.other.package" to sortedMapOf("a" to 1, "b" to 1), + "some.other.other.other.package" to sortedMapOf(), + ), + patches, + compatiblePackageNames = + setOf( + "some.package", + "some.other.package", + "some.other.other.package", + "some.other.other.other.package", + ), + countUnusedPatches = true, + ) + } + + @Test + fun `return common versions correctly ordered for each package without counting unused patches`() { + assertEqualsVersions( + expected = + mapOf( + "some.package" to sortedMapOf("a" to 1), + "some.other.package" to sortedMapOf("b" to 2, "c" to 2, "d" to 1), + "some.other.other.package" to sortedMapOf("a" to 1, "b" to 1), + ), + patches, + compatiblePackageNames = + setOf( + "some.package", + "some.other.package", + "some.other.other.package", + "some.other.other.other.package", + ), + countUnusedPatches = false, + ) + } + + @Test + fun `return an empty map because no known package was supplied`() { + assertEqualsVersions( + expected = emptyMap(), + patches, + compatiblePackageNames = setOf("unknown.package"), + ) + } + + @Test + fun `return empty set of versions because no compatible package is constrained to a version`() { + assertEqualsVersions( + expected = mapOf("some.package" to sortedMapOf()), + patches = setOf(newPatch("some.package")), + compatiblePackageNames = setOf("some.package"), + countUnusedPatches = true, + ) + } + @Test fun `return 'a' because it is the most common version`() { val patches = @@ -31,7 +108,7 @@ internal object PatchUtilsTest { } @Test - fun `return null because no patch compatible package is constrained to a version`() { + fun `return null because no compatible package is constrained to a version`() { val patches = setOf( newPatch("other.package"), @@ -41,15 +118,39 @@ internal object PatchUtilsTest { assertEqualsVersion(null, patches, "other.package") } + private fun assertEqualsVersions( + expected: PackageNameMap, + patches: PatchSet, + compatiblePackageNames: Set, + countUnusedPatches: Boolean = false, + ) = assertEquals( + expected, + PatchUtils.getMostCommonCompatibleVersions(patches, compatiblePackageNames, countUnusedPatches), + ) + private fun assertEqualsVersion( expected: String?, patches: PatchSet, compatiblePackageName: String, - ) = assertEquals(expected, PatchUtils.getMostCommonCompatibleVersion(patches, compatiblePackageName)) + ) { + // Test both the deprecated and the new method. + + assertEquals( + expected, + PatchUtils.getMostCommonCompatibleVersion(patches, compatiblePackageName), + ) + + assertEquals( + expected, + PatchUtils.getMostCommonCompatibleVersions(patches, setOf(compatiblePackageName)) + .entries.firstOrNull()?.value?.keys?.firstOrNull(), + ) + } private fun newPatch( packageName: String, vararg versions: String, + use: Boolean = true, ) = object : BytecodePatch() { init { // Set the compatible packages field to the supplied package name and versions reflectively, @@ -58,8 +159,16 @@ internal object PatchUtilsTest { compatiblePackagesField.isAccessible = true compatiblePackagesField.set(this, setOf(CompatiblePackage(packageName, versions.toSet()))) + + val useField = Patch::class.java.getDeclaredField("use") + + useField.isAccessible = true + useField.set(this, use) } override fun execute(context: BytecodeContext) {} + + // Needed to make the patches unique. + override fun equals(other: Any?) = false } } From 34171b534b69d4cb1cd1d5fbc69942a5779ffce4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 27 Nov 2023 01:26:17 +0000 Subject: [PATCH 3/9] chore(release): 1.4.0-dev.1 [skip ci] # [1.4.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v1.3.0...v1.4.0-dev.1) (2023-11-27) ### Features * Add `PatchUtils#getMostCommonCompatibleVersions` utility function ([c5f3536](https://github.com/ReVanced/revanced-library/commit/c5f3536cbb6997766076595dc0b2b5d2e861ca73)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 590ccb2..af17947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.4.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v1.3.0...v1.4.0-dev.1) (2023-11-27) + + +### Features + +* Add `PatchUtils#getMostCommonCompatibleVersions` utility function ([c5f3536](https://github.com/ReVanced/revanced-library/commit/c5f3536cbb6997766076595dc0b2b5d2e861ca73)) + # [1.3.0](https://github.com/ReVanced/revanced-library/compare/v1.2.0...v1.3.0) (2023-11-26) diff --git a/gradle.properties b/gradle.properties index f621b40..99db55e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true kotlin.code.style = official -version = 1.3.0 +version = 1.4.0-dev.1 From 96845ba265e6dc208c7ac96f5e58734209cd1720 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 21:03:23 +0100 Subject: [PATCH 4/9] feat: Allow getting most common compatible versions for all packages --- .../kotlin/app/revanced/library/PatchUtils.kt | 48 ++++++++------- .../app/revanced/library/PatchUtilsTest.kt | 61 +++++++++++-------- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/main/kotlin/app/revanced/library/PatchUtils.kt b/src/main/kotlin/app/revanced/library/PatchUtils.kt index de04dcd..83140c6 100644 --- a/src/main/kotlin/app/revanced/library/PatchUtils.kt +++ b/src/main/kotlin/app/revanced/library/PatchUtils.kt @@ -1,14 +1,14 @@ package app.revanced.library import app.revanced.patcher.PatchSet -import java.util.* +import app.revanced.patcher.patch.Patch -private typealias PackageName = String -private typealias Version = String -private typealias Count = Int +typealias PackageName = String +typealias Version = String +typealias Count = Int -private typealias VersionMap = SortedMap -internal typealias PackageNameMap = Map +typealias VersionMap = LinkedHashMap +typealias PackageNameMap = Map /** * Utility functions for working with patches. @@ -26,7 +26,7 @@ object PatchUtils { "Use getMostCommonCompatibleVersions instead.", ReplaceWith( "getMostCommonCompatibleVersions(patches, setOf(packageName))" + - ".entries.firstOrNull()?.value?.keys?.firstOrNull()", + ".entries.firstOrNull()?.value?.keys?.firstOrNull()", ), ) fun getMostCommonCompatibleVersion( @@ -48,30 +48,32 @@ object PatchUtils { * Get the count of versions for each compatible package from a supplied set of [patches] ordered by the most common version. * * @param patches The set of patches to check. - * @param packageNames The names of the compatible packages. + * @param packageNames The names of the compatible packages to include. If null, all packages will be included. * @param countUnusedPatches Whether to count patches that are not used. * @return A map of package names to a map of versions to their count. */ fun getMostCommonCompatibleVersions( patches: PatchSet, - packageNames: Set, + packageNames: Set? = null, countUnusedPatches: Boolean = false, - ): PackageNameMap { - val wantedPackages = packageNames.toHashSet() - return buildMap { - patches - .filter { it.use || countUnusedPatches } - .flatMap { it.compatiblePackages ?: emptyList() } - .filter { it.name in wantedPackages } - .forEach { compatiblePackage -> - compatiblePackage.versions?.let { versions -> - val versionMap = getOrPut(compatiblePackage.name) { sortedMapOf() } + ): PackageNameMap = buildMap { + fun filterWantedPackages(compatiblePackages: Iterable): Iterable { + val wantedPackages = packageNames?.toHashSet() ?: return compatiblePackages + return compatiblePackages.filter { it.name in wantedPackages } + } - versions.forEach { version -> - versionMap[version] = versionMap.getOrDefault(version, 0) + 1 - } + patches + .filter { it.use || countUnusedPatches } + .flatMap { it.compatiblePackages ?: emptyList() } + .let(::filterWantedPackages) + .forEach { compatiblePackage -> + val versionMap = getOrPut(compatiblePackage.name) { linkedMapOf() } + + compatiblePackage.versions?.let { versions -> + versions.forEach { version -> + versionMap[version] = versionMap.getOrDefault(version, 0) + 1 } } - } + } } } diff --git a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt index 669c214..03e462e 100644 --- a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt +++ b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt @@ -25,43 +25,50 @@ internal object PatchUtilsTest { @Test fun `return common versions correctly ordered for each package`() { - assertEqualsVersions( + fun assertEqualsExpected(compatiblePackageNames: Set?) = assertEqualsVersions( expected = - mapOf( - "some.package" to sortedMapOf("a" to 3, "b" to 2, "c" to 1), - "some.other.package" to sortedMapOf("b" to 3, "c" to 2, "d" to 1), - "some.other.other.package" to sortedMapOf("a" to 1, "b" to 1), - "some.other.other.other.package" to sortedMapOf(), - ), + mapOf( + "some.package" to linkedMapOf("a" to 3, "b" to 2, "c" to 1), + "some.other.package" to linkedMapOf("b" to 3, "c" to 2, "d" to 1), + "some.other.other.package" to linkedMapOf("a" to 1, "b" to 1), + "some.other.other.other.package" to linkedMapOf(), + ), patches, - compatiblePackageNames = - setOf( - "some.package", - "some.other.package", - "some.other.other.package", - "some.other.other.other.package", - ), + compatiblePackageNames, countUnusedPatches = true, ) + + assertEqualsExpected( + compatiblePackageNames = setOf( + "some.package", + "some.other.package", + "some.other.other.package", + "some.other.other.other.package", + ), + ) + + assertEqualsExpected( + compatiblePackageNames = null + ) } @Test fun `return common versions correctly ordered for each package without counting unused patches`() { assertEqualsVersions( expected = - mapOf( - "some.package" to sortedMapOf("a" to 1), - "some.other.package" to sortedMapOf("b" to 2, "c" to 2, "d" to 1), - "some.other.other.package" to sortedMapOf("a" to 1, "b" to 1), - ), + mapOf( + "some.package" to linkedMapOf("a" to 1), + "some.other.package" to linkedMapOf("b" to 2, "c" to 2, "d" to 1), + "some.other.other.package" to linkedMapOf("a" to 1, "b" to 1), + ), patches, compatiblePackageNames = - setOf( - "some.package", - "some.other.package", - "some.other.other.package", - "some.other.other.other.package", - ), + setOf( + "some.package", + "some.other.package", + "some.other.other.package", + "some.other.other.other.package", + ), countUnusedPatches = false, ) } @@ -78,7 +85,7 @@ internal object PatchUtilsTest { @Test fun `return empty set of versions because no compatible package is constrained to a version`() { assertEqualsVersions( - expected = mapOf("some.package" to sortedMapOf()), + expected = mapOf("some.package" to linkedMapOf()), patches = setOf(newPatch("some.package")), compatiblePackageNames = setOf("some.package"), countUnusedPatches = true, @@ -121,7 +128,7 @@ internal object PatchUtilsTest { private fun assertEqualsVersions( expected: PackageNameMap, patches: PatchSet, - compatiblePackageNames: Set, + compatiblePackageNames: Set?, countUnusedPatches: Boolean = false, ) = assertEquals( expected, From e4be6dbccd86700ffafe7cd8395e845bbd3d5138 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 21:21:25 +0100 Subject: [PATCH 5/9] fix: Sort the version maps by the most common version --- src/main/kotlin/app/revanced/library/PatchUtils.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/kotlin/app/revanced/library/PatchUtils.kt b/src/main/kotlin/app/revanced/library/PatchUtils.kt index 83140c6..77a83f5 100644 --- a/src/main/kotlin/app/revanced/library/PatchUtils.kt +++ b/src/main/kotlin/app/revanced/library/PatchUtils.kt @@ -75,5 +75,13 @@ object PatchUtils { } } } + + // Sort the version maps by the most common version. + forEach { (packageName, versionMap) -> + this[packageName] = versionMap + .asIterable() + .sortedWith(compareByDescending { it.value }) + .associate { it.key to it.value } as VersionMap + } } } From 762b7e3bc01e2ca33dfcdbb1b5028d60ef6e0a48 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 22:30:59 +0100 Subject: [PATCH 6/9] fix: Differentiate no package compatibility to any version compatibility --- .../kotlin/app/revanced/library/PatchUtils.kt | 3 + .../app/revanced/library/PatchUtilsTest.kt | 76 +++++++++++-------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/app/revanced/library/PatchUtils.kt b/src/main/kotlin/app/revanced/library/PatchUtils.kt index 77a83f5..4df1bc6 100644 --- a/src/main/kotlin/app/revanced/library/PatchUtils.kt +++ b/src/main/kotlin/app/revanced/library/PatchUtils.kt @@ -67,6 +67,9 @@ object PatchUtils { .flatMap { it.compatiblePackages ?: emptyList() } .let(::filterWantedPackages) .forEach { compatiblePackage -> + if (compatiblePackage.versions?.isEmpty() == true) + return@forEach + val versionMap = getOrPut(compatiblePackage.name) { linkedMapOf() } compatiblePackage.versions?.let { versions -> diff --git a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt index 03e462e..5c260c2 100644 --- a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt +++ b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt @@ -10,21 +10,49 @@ import kotlin.test.assertEquals internal object PatchUtilsTest { private val patches = arrayOf( - newPatch("some.package", "a"), - newPatch("some.package", "a", "b", use = false), - newPatch("some.package", "a", "b", "c", use = false), - newPatch("some.other.package", "b", use = false), - newPatch("some.other.package", "b", "c"), - newPatch("some.other.package", "b", "c", "d"), + newPatch("some.package", setOf("a")), + newPatch("some.package", setOf("a", "b"), use = false), + newPatch("some.package", setOf("a", "b", "c"), use = false), + newPatch("some.other.package", setOf("b"), use = false), + newPatch("some.other.package", setOf("b", "c")), + newPatch("some.other.package", setOf("b", "c", "d")), newPatch("some.other.other.package"), - newPatch("some.other.other.package", "a"), - newPatch("some.other.other.package", "b"), + newPatch("some.other.other.package", setOf("a")), + newPatch("some.other.other.package", setOf("b")), newPatch("some.other.other.other.package", use = false), newPatch("some.other.other.other.package", use = false), ).toSet() @Test - fun `return common versions correctly ordered for each package`() { + fun `empty because package is incompatible with any version`() { + assertEqualsVersions( + expected = emptyMap(), + patches = setOf(newPatch("some.package", emptySet(), use = true)), + compatiblePackageNames = setOf("some.package"), + ) + } + + @Test + fun `empty list of versions because package is unconstrained to any version`() { + assertEqualsVersions( + expected = mapOf("some.package" to linkedMapOf()), + patches = setOf(newPatch("some.package")), + compatiblePackageNames = setOf("some.package"), + countUnusedPatches = true, + ) + } + + @Test + fun `empty because no known package was supplied`() { + assertEqualsVersions( + expected = emptyMap(), + patches, + compatiblePackageNames = setOf("unknown.package"), + ) + } + + @Test + fun `common versions correctly ordered for each package`() { fun assertEqualsExpected(compatiblePackageNames: Set?) = assertEqualsVersions( expected = mapOf( @@ -53,7 +81,7 @@ internal object PatchUtilsTest { } @Test - fun `return common versions correctly ordered for each package without counting unused patches`() { + fun `common versions correctly ordered for each package without counting unused patches`() { assertEqualsVersions( expected = mapOf( @@ -73,30 +101,11 @@ internal object PatchUtilsTest { ) } - @Test - fun `return an empty map because no known package was supplied`() { - assertEqualsVersions( - expected = emptyMap(), - patches, - compatiblePackageNames = setOf("unknown.package"), - ) - } - - @Test - fun `return empty set of versions because no compatible package is constrained to a version`() { - assertEqualsVersions( - expected = mapOf("some.package" to linkedMapOf()), - patches = setOf(newPatch("some.package")), - compatiblePackageNames = setOf("some.package"), - countUnusedPatches = true, - ) - } - @Test fun `return 'a' because it is the most common version`() { val patches = arrayOf("a", "a", "c", "d", "a", "b", "c", "d", "a", "b", "c", "d") - .map { version -> newPatch("some.package", version) } + .map { version -> newPatch("some.package", setOf(version)) } .toSet() assertEqualsVersion("a", patches, "some.package") @@ -109,7 +118,7 @@ internal object PatchUtilsTest { @Test fun `return null because no patch is compatible with the supplied package name`() { - val patches = setOf(newPatch("some.package", "a")) + val patches = setOf(newPatch("some.package", setOf("a"))) assertEqualsVersion(null, patches, "other.package") } @@ -142,6 +151,7 @@ internal object PatchUtilsTest { ) { // Test both the deprecated and the new method. + @Suppress("DEPRECATION") assertEquals( expected, PatchUtils.getMostCommonCompatibleVersion(patches, compatiblePackageName), @@ -156,7 +166,7 @@ internal object PatchUtilsTest { private fun newPatch( packageName: String, - vararg versions: String, + versions: Set? = null, use: Boolean = true, ) = object : BytecodePatch() { init { @@ -165,7 +175,7 @@ internal object PatchUtilsTest { val compatiblePackagesField = Patch::class.java.getDeclaredField("compatiblePackages") compatiblePackagesField.isAccessible = true - compatiblePackagesField.set(this, setOf(CompatiblePackage(packageName, versions.toSet()))) + compatiblePackagesField.set(this, setOf(CompatiblePackage(packageName, versions?.toSet()))) val useField = Patch::class.java.getDeclaredField("use") From 73c97abedd3e27e05177c96955d7d4e78a5f7b94 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 22:40:00 +0100 Subject: [PATCH 7/9] chore: Lint code --- .../kotlin/app/revanced/library/PatchUtils.kt | 61 +++++++++-------- .../app/revanced/library/PatchUtilsTest.kt | 66 ++++++++++--------- 2 files changed, 66 insertions(+), 61 deletions(-) diff --git a/src/main/kotlin/app/revanced/library/PatchUtils.kt b/src/main/kotlin/app/revanced/library/PatchUtils.kt index 4df1bc6..1cc700b 100644 --- a/src/main/kotlin/app/revanced/library/PatchUtils.kt +++ b/src/main/kotlin/app/revanced/library/PatchUtils.kt @@ -26,7 +26,7 @@ object PatchUtils { "Use getMostCommonCompatibleVersions instead.", ReplaceWith( "getMostCommonCompatibleVersions(patches, setOf(packageName))" + - ".entries.firstOrNull()?.value?.keys?.firstOrNull()", + ".entries.firstOrNull()?.value?.keys?.firstOrNull()", ), ) fun getMostCommonCompatibleVersion( @@ -56,35 +56,38 @@ object PatchUtils { patches: PatchSet, packageNames: Set? = null, countUnusedPatches: Boolean = false, - ): PackageNameMap = buildMap { - fun filterWantedPackages(compatiblePackages: Iterable): Iterable { - val wantedPackages = packageNames?.toHashSet() ?: return compatiblePackages - return compatiblePackages.filter { it.name in wantedPackages } - } - - patches - .filter { it.use || countUnusedPatches } - .flatMap { it.compatiblePackages ?: emptyList() } - .let(::filterWantedPackages) - .forEach { compatiblePackage -> - if (compatiblePackage.versions?.isEmpty() == true) - return@forEach - - val versionMap = getOrPut(compatiblePackage.name) { linkedMapOf() } - - compatiblePackage.versions?.let { versions -> - versions.forEach { version -> - versionMap[version] = versionMap.getOrDefault(version, 0) + 1 - } - } + ): PackageNameMap = + buildMap { + fun filterWantedPackages(compatiblePackages: Iterable): Iterable { + val wantedPackages = packageNames?.toHashSet() ?: return compatiblePackages + return compatiblePackages.filter { it.name in wantedPackages } } - // Sort the version maps by the most common version. - forEach { (packageName, versionMap) -> - this[packageName] = versionMap - .asIterable() - .sortedWith(compareByDescending { it.value }) - .associate { it.key to it.value } as VersionMap + patches + .filter { it.use || countUnusedPatches } + .flatMap { it.compatiblePackages ?: emptyList() } + .let(::filterWantedPackages) + .forEach { compatiblePackage -> + if (compatiblePackage.versions?.isEmpty() == true) { + return@forEach + } + + val versionMap = getOrPut(compatiblePackage.name) { linkedMapOf() } + + compatiblePackage.versions?.let { versions -> + versions.forEach { version -> + versionMap[version] = versionMap.getOrDefault(version, 0) + 1 + } + } + } + + // Sort the version maps by the most common version. + forEach { (packageName, versionMap) -> + this[packageName] = + versionMap + .asIterable() + .sortedWith(compareByDescending { it.value }) + .associate { it.key to it.value } as VersionMap + } } - } } diff --git a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt index 5c260c2..fc635cf 100644 --- a/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt +++ b/src/test/kotlin/app/revanced/library/PatchUtilsTest.kt @@ -53,30 +53,32 @@ internal object PatchUtilsTest { @Test fun `common versions correctly ordered for each package`() { - fun assertEqualsExpected(compatiblePackageNames: Set?) = assertEqualsVersions( - expected = - mapOf( - "some.package" to linkedMapOf("a" to 3, "b" to 2, "c" to 1), - "some.other.package" to linkedMapOf("b" to 3, "c" to 2, "d" to 1), - "some.other.other.package" to linkedMapOf("a" to 1, "b" to 1), - "some.other.other.other.package" to linkedMapOf(), - ), - patches, - compatiblePackageNames, - countUnusedPatches = true, + fun assertEqualsExpected(compatiblePackageNames: Set?) = + assertEqualsVersions( + expected = + mapOf( + "some.package" to linkedMapOf("a" to 3, "b" to 2, "c" to 1), + "some.other.package" to linkedMapOf("b" to 3, "c" to 2, "d" to 1), + "some.other.other.package" to linkedMapOf("a" to 1, "b" to 1), + "some.other.other.other.package" to linkedMapOf(), + ), + patches, + compatiblePackageNames, + countUnusedPatches = true, + ) + + assertEqualsExpected( + compatiblePackageNames = + setOf( + "some.package", + "some.other.package", + "some.other.other.package", + "some.other.other.other.package", + ), ) assertEqualsExpected( - compatiblePackageNames = setOf( - "some.package", - "some.other.package", - "some.other.other.package", - "some.other.other.other.package", - ), - ) - - assertEqualsExpected( - compatiblePackageNames = null + compatiblePackageNames = null, ) } @@ -84,19 +86,19 @@ internal object PatchUtilsTest { fun `common versions correctly ordered for each package without counting unused patches`() { assertEqualsVersions( expected = - mapOf( - "some.package" to linkedMapOf("a" to 1), - "some.other.package" to linkedMapOf("b" to 2, "c" to 2, "d" to 1), - "some.other.other.package" to linkedMapOf("a" to 1, "b" to 1), - ), + mapOf( + "some.package" to linkedMapOf("a" to 1), + "some.other.package" to linkedMapOf("b" to 2, "c" to 2, "d" to 1), + "some.other.other.package" to linkedMapOf("a" to 1, "b" to 1), + ), patches, compatiblePackageNames = - setOf( - "some.package", - "some.other.package", - "some.other.other.package", - "some.other.other.other.package", - ), + setOf( + "some.package", + "some.other.package", + "some.other.other.package", + "some.other.other.other.package", + ), countUnusedPatches = false, ) } From 37434cf4a408c9a8f14a9e59c37cfcd376206057 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 27 Nov 2023 22:40:07 +0100 Subject: [PATCH 8/9] build: Bump dependencies --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 55f19ed..8d21415 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ bcpkix-jdk18on = "1.76" jackson-module-kotlin = "2.14.3" jadb = "1.2.1" kotlin-reflect = "1.9.10" -kotlin-test = "1.9.10" +kotlin-test = "1.9.20" revanced-patcher = "19.0.0" binary-compatibility-validator = "0.13.2" From cdf94ffeca8d10ccc769c9f64bba266e75dd0637 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 27 Nov 2023 21:43:22 +0000 Subject: [PATCH 9/9] chore(release): 1.4.0-dev.2 [skip ci] # [1.4.0-dev.2](https://github.com/ReVanced/revanced-library/compare/v1.4.0-dev.1...v1.4.0-dev.2) (2023-11-27) ### Bug Fixes * Differentiate no package compatibility to any version compatibility ([762b7e3](https://github.com/ReVanced/revanced-library/commit/762b7e3bc01e2ca33dfcdbb1b5028d60ef6e0a48)) * Sort the version maps by the most common version ([e4be6db](https://github.com/ReVanced/revanced-library/commit/e4be6dbccd86700ffafe7cd8395e845bbd3d5138)) ### Features * Allow getting most common compatible versions for all packages ([96845ba](https://github.com/ReVanced/revanced-library/commit/96845ba265e6dc208c7ac96f5e58734209cd1720)) --- CHANGELOG.md | 13 +++++++++++++ gradle.properties | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af17947..574e6d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [1.4.0-dev.2](https://github.com/ReVanced/revanced-library/compare/v1.4.0-dev.1...v1.4.0-dev.2) (2023-11-27) + + +### Bug Fixes + +* Differentiate no package compatibility to any version compatibility ([762b7e3](https://github.com/ReVanced/revanced-library/commit/762b7e3bc01e2ca33dfcdbb1b5028d60ef6e0a48)) +* Sort the version maps by the most common version ([e4be6db](https://github.com/ReVanced/revanced-library/commit/e4be6dbccd86700ffafe7cd8395e845bbd3d5138)) + + +### Features + +* Allow getting most common compatible versions for all packages ([96845ba](https://github.com/ReVanced/revanced-library/commit/96845ba265e6dc208c7ac96f5e58734209cd1720)) + # [1.4.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v1.3.0...v1.4.0-dev.1) (2023-11-27) diff --git a/gradle.properties b/gradle.properties index 99db55e..fd63a01 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true kotlin.code.style = official -version = 1.4.0-dev.1 +version = 1.4.0-dev.2