Compare commits

..

2 Commits

Author SHA1 Message Date
semantic-release-bot
369c44e03b chore: Release v21.1.0 [skip ci]
# [21.1.0](https://github.com/ReVanced/revanced-patcher/compare/v21.0.0...v21.1.0) (2025-10-16)

### Bug Fixes

* Add back missing log by naming logger correctly ([#332](https://github.com/ReVanced/revanced-patcher/issues/332)) ([e4e66b0](e4e66b0d8b))
* Correctly save XML files in UTF-8 by using a bufferedWriter ([#356](https://github.com/ReVanced/revanced-patcher/issues/356)) ([33fadcb](33fadcbd0c))
* Encode XML files as UTF-8 to fix compilation of resources ([#339](https://github.com/ReVanced/revanced-patcher/issues/339)) ([4f2ef3c](4f2ef3c47c))
* Support UTF-8 chars when compiling instructions in Smali in non UTF-8 environments ([#331](https://github.com/ReVanced/revanced-patcher/issues/331)) ([bb8771b](bb8771bb8b))

### Features

* Add identity hash code to unnamed patches ([88a3252](88a3252574))
* Use option name as key for simplicity and consistency ([754b02e](754b02e4ca))

### Performance Improvements

* Use a buffered writer to reduce IO overhead ([#347](https://github.com/ReVanced/revanced-patcher/issues/347)) ([99f4318](99f431897e))
2025-10-16 15:06:56 +00:00
oSumAtrIX
028a54f39d chore: Merge branch dev to main (#377) 2025-10-16 17:05:34 +02:00
5 changed files with 74 additions and 100 deletions

View File

@@ -1,3 +1,24 @@
# [21.1.0](https://github.com/ReVanced/revanced-patcher/compare/v21.0.0...v21.1.0) (2025-10-16)
### Bug Fixes
* Add back missing log by naming logger correctly ([#332](https://github.com/ReVanced/revanced-patcher/issues/332)) ([e4e66b0](https://github.com/ReVanced/revanced-patcher/commit/e4e66b0d8bb0986b79fb150b9c15da35b8e11561))
* Correctly save XML files in UTF-8 by using a bufferedWriter ([#356](https://github.com/ReVanced/revanced-patcher/issues/356)) ([33fadcb](https://github.com/ReVanced/revanced-patcher/commit/33fadcbd0c7076b848bdca4d62a9c684d5781232))
* Encode XML files as UTF-8 to fix compilation of resources ([#339](https://github.com/ReVanced/revanced-patcher/issues/339)) ([4f2ef3c](https://github.com/ReVanced/revanced-patcher/commit/4f2ef3c47cea76a26c464cfb45d4bb57fe7198b5))
* Support UTF-8 chars when compiling instructions in Smali in non UTF-8 environments ([#331](https://github.com/ReVanced/revanced-patcher/issues/331)) ([bb8771b](https://github.com/ReVanced/revanced-patcher/commit/bb8771bb8b8ab1724d957e56f4de88c02684d87b))
### Features
* Add identity hash code to unnamed patches ([88a3252](https://github.com/ReVanced/revanced-patcher/commit/88a325257494939a79fb30dd51d60c5c52546755))
* Use option name as key for simplicity and consistency ([754b02e](https://github.com/ReVanced/revanced-patcher/commit/754b02e4ca66ec10764d5205c6643f2d86d0c6a2))
### Performance Improvements
* Use a buffered writer to reduce IO overhead ([#347](https://github.com/ReVanced/revanced-patcher/issues/347)) ([99f4318](https://github.com/ReVanced/revanced-patcher/commit/99f431897eb9e607987fd5d09b879d7eda442f3e))
# [21.1.0-dev.5](https://github.com/ReVanced/revanced-patcher/compare/v21.1.0-dev.4...v21.1.0-dev.5) (2025-10-16)
# [21.1.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v21.1.0-dev.3...v21.1.0-dev.4) (2025-07-18)

View File

@@ -342,12 +342,8 @@ public final class app/revanced/patcher/patch/PatchKt {
public static final fun bytecodePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun bytecodePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun loadPatchesFromDex (Ljava/util/Set;Ljava/io/File;)Lapp/revanced/patcher/patch/PatchLoader$Dex;
public static final fun loadPatchesFromDex (Ljava/util/Set;Ljava/io/File;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/PatchLoader$Dex;
public static synthetic fun loadPatchesFromDex$default (Ljava/util/Set;Ljava/io/File;ILjava/lang/Object;)Lapp/revanced/patcher/patch/PatchLoader$Dex;
public static synthetic fun loadPatchesFromDex$default (Ljava/util/Set;Ljava/io/File;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/PatchLoader$Dex;
public static final fun loadPatchesFromJar (Ljava/util/Set;)Lapp/revanced/patcher/patch/PatchLoader$Jar;
public static final fun loadPatchesFromJar (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/PatchLoader$Jar;
public static synthetic fun loadPatchesFromJar$default (Ljava/util/Set;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/PatchLoader$Jar;
public static final fun rawResourcePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/RawResourcePatch;
public static synthetic fun rawResourcePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/RawResourcePatch;
public static final fun resourcePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch;
@@ -356,7 +352,7 @@ public final class app/revanced/patcher/patch/PatchKt {
public abstract class app/revanced/patcher/patch/PatchLoader : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
public synthetic fun <init> (Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/util/Set;Lkotlin/jvm/functions/Function1;Ljava/lang/ClassLoader;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/util/Set;Lkotlin/jvm/functions/Function1;Ljava/lang/ClassLoader;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun add (Lapp/revanced/patcher/patch/Patch;)Z
public synthetic fun add (Ljava/lang/Object;)Z
public fun addAll (Ljava/util/Collection;)Z
@@ -377,9 +373,12 @@ public abstract class app/revanced/patcher/patch/PatchLoader : java/util/Set, ko
}
public final class app/revanced/patcher/patch/PatchLoader$Dex : app/revanced/patcher/patch/PatchLoader {
public fun <init> (Ljava/util/Set;Ljava/io/File;)V
public synthetic fun <init> (Ljava/util/Set;Ljava/io/File;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/PatchLoader$Jar : app/revanced/patcher/patch/PatchLoader {
public fun <init> (Ljava/util/Set;)V
}
public final class app/revanced/patcher/patch/PatchResult {

View File

@@ -1,3 +1,3 @@
org.gradle.parallel = true
org.gradle.caching = true
version = 21.1.0-dev.5
version = 21.1.0

View File

@@ -87,7 +87,8 @@ sealed class Patch<C : PatchContext<*>>(
finalizeBlock?.invoke(context)
}
override fun toString() = name ?: "Patch@${System.identityHashCode(this)}"
override fun toString() = name ?:
"Patch@${System.identityHashCode(this)}"
}
internal fun Patch<*>.anyRecursively(
@@ -528,11 +529,11 @@ fun resourcePatch(
/**
* An exception thrown when patching.
*
* @param message The exception message.
* @param cause The cause of the exception.
* @param errorMessage The exception message.
* @param cause The corresponding [Throwable].
*/
class PatchException(message: String?, cause: Throwable?) : Exception(message, cause) {
constructor(message: String) : this(message, null)
class PatchException(errorMessage: String?, cause: Throwable?) : Exception(errorMessage, cause) {
constructor(errorMessage: String) : this(errorMessage, null)
constructor(cause: Throwable) : this(cause.message, cause)
}
@@ -542,7 +543,6 @@ class PatchException(message: String?, cause: Throwable?) : Exception(message, c
* @param patch The [Patch] that was executed.
* @param exception The [PatchException] thrown, if any.
*/
@Deprecated("This class is not used anymore. Instead a callback is used")
class PatchResult internal constructor(val patch: Patch<*>, val exception: PatchException? = null)
/**
@@ -553,47 +553,36 @@ class PatchResult internal constructor(val patch: Patch<*>, val exception: Patch
*
* @param byPatchesFile The patches associated by the patches file they were loaded from.
*/
sealed class PatchLoader(
sealed class PatchLoader private constructor(
val byPatchesFile: Map<File, Set<Patch<*>>>,
) : Set<Patch<*>> by byPatchesFile.values.flatten().toSet() {
/**
* @param patchesFiles A set of JAR or DEX files to load the patches from.
* @param getBinaryClassNames A function that returns the binary names of all classes accessible by the class loader.
* @param classLoader The [ClassLoader] to use for loading the classes.
* @param onLoadPatchesException The callback for patches that could not be loaded.
*/
constructor(
private constructor(
patchesFiles: Set<File>,
getBinaryClassNames: (patchesFile: File) -> List<String>,
classLoader: ClassLoader,
onLoadPatchesException: (message: String, cause: Throwable) -> Unit
) : this(
classLoader.loadPatches(
patchesFiles.associateWith { getBinaryClassNames(it).toSet() },
onLoadPatchesException
)
)
) : this(classLoader.loadPatches(patchesFiles.associateWith { getBinaryClassNames(it).toSet() }))
/**
* A [PatchLoader] for JAR files.
*
* @param patchesFiles The JAR files to load the patches from.
* @param onLoadPatchesException The callback for patches that could not be loaded.
*
* @constructor Create a new [PatchLoader] for JAR files.
*/
class Jar internal constructor(
patchesFiles: Set<File>,
onLoadPatchesException: (message: String, cause: Throwable) -> Unit
) : PatchLoader(
patchesFiles,
{ file ->
JarFile(file).entries().toList().filter { it.name.endsWith(".class") }
.map { it.name.substringBeforeLast('.').replace('/', '.') }
},
URLClassLoader(patchesFiles.map { it.toURI().toURL() }.toTypedArray()),
onLoadPatchesException
)
class Jar(patchesFiles: Set<File>) :
PatchLoader(
patchesFiles,
{ file ->
JarFile(file).entries().toList().filter { it.name.endsWith(".class") }
.map { it.name.substringBeforeLast('.').replace('/', '.') }
},
URLClassLoader(patchesFiles.map { it.toURI().toURL() }.toTypedArray()),
)
/**
* A [PatchLoader] for [Dex] files.
@@ -601,30 +590,25 @@ sealed class PatchLoader(
* @param patchesFiles The DEX files to load the patches from.
* @param optimizedDexDirectory The directory to store optimized DEX files in.
* This parameter is deprecated and has no effect since API level 26.
* @param onLoadPatchesException The callback for patches that could not be loaded.
*
* @constructor Create a new [PatchLoader] for [Dex] files.
*/
class Dex internal constructor(
patchesFiles: Set<File>,
optimizedDexDirectory: File? = null,
onLoadPatchesException: (message: String, cause: Throwable) -> Unit
) : PatchLoader(
patchesFiles,
{ patchBundle ->
MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes
.map { classDef ->
classDef.type.substring(1, classDef.length - 1)
}
},
DexClassLoader(
patchesFiles.joinToString(File.pathSeparator) { it.absolutePath },
optimizedDexDirectory?.absolutePath,
null,
this::class.java.classLoader,
),
onLoadPatchesException
)
class Dex(patchesFiles: Set<File>, optimizedDexDirectory: File? = null) :
PatchLoader(
patchesFiles,
{ patchBundle ->
MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes
.map { classDef ->
classDef.type.substring(1, classDef.length - 1)
}
},
DexClassLoader(
patchesFiles.joinToString(File.pathSeparator) { it.absolutePath },
optimizedDexDirectory?.absolutePath,
null,
this::class.java.classLoader,
),
)
// Companion object required for unit tests.
private companion object {
@@ -656,24 +640,19 @@ sealed class PatchLoader(
*
* @param binaryClassNamesByPatchesFile The binary class name of the classes to load the patches from
* associated by the patches file.
* @param onLoadPatchesException The callback for patches that could not be loaded.
*
* @return The loaded patches associated by the patches file.
*/
private fun ClassLoader.loadPatches(
binaryClassNamesByPatchesFile: Map<File, Set<String>>,
onLoadPatchesException: (message: String, cause: Throwable) -> Unit
) = binaryClassNamesByPatchesFile.mapValues { (_, binaryClassNames) ->
binaryClassNames.asSequence().mapNotNull {
runCatching { loadClass(it) }.onFailure { exception ->
onLoadPatchesException("Failed to load patch class $it", exception)
}.getOrNull()
}.flatMap {
it.patchFields + it.patchMethods
}.filter {
it.name != null
}.toSet()
}
private fun ClassLoader.loadPatches(binaryClassNamesByPatchesFile: Map<File, Set<String>>) =
binaryClassNamesByPatchesFile.mapValues { (_, binaryClassNames) ->
binaryClassNames.asSequence().map {
loadClass(it)
}.flatMap {
it.patchFields + it.patchMethods
}.filter {
it.name != null
}.toSet()
}
private fun Member.canAccess(): Boolean {
if (this is Method && parameterCount != 0) return false
@@ -689,22 +668,11 @@ sealed class PatchLoader(
* Patches with no name are not loaded.
*
* @param patchesFiles The JAR files to load the patches from.
* @param onLoadPatchesException The callback for patches that could not be loaded.
*
* @return The loaded patches.
*/
fun loadPatchesFromJar(
patchesFiles: Set<File>,
onLoadPatchesException: ((message: String, cause: Throwable) -> Unit)? = null
) = PatchLoader.Jar(patchesFiles, onLoadPatchesException ?: { message, cause -> })
@Deprecated(
"Use the function with the onLoadPatchesException overload",
replaceWith = ReplaceWith("loadPatchesFromJar(patchesFiles, null)")
)
fun loadPatchesFromJar(
patchesFiles: Set<File>
) = loadPatchesFromJar(patchesFiles, null)
fun loadPatchesFromJar(patchesFiles: Set<File>) =
PatchLoader.Jar(patchesFiles)
/**
* Loads patches from DEX files declared as public static fields
@@ -712,21 +680,8 @@ fun loadPatchesFromJar(
* Patches with no name are not loaded.
*
* @param patchesFiles The DEX files to load the patches from.
* @param onLoadPatchesException The callback for patches that could not be loaded.
*
* @return The loaded patches.
*/
fun loadPatchesFromDex(
patchesFiles: Set<File>,
optimizedDexDirectory: File? = null,
onLoadPatchesException: ((message: String, cause: Throwable) -> Unit)? = null
) = PatchLoader.Dex(patchesFiles, optimizedDexDirectory, onLoadPatchesException ?: { message, cause -> })
@Deprecated(
"Use the function with the onLoadPatchesException overload",
replaceWith = ReplaceWith("loadPatchesFromJar(patchesFiles, optimizedDexDirectory, null)")
)
fun loadPatchesFromDex(
patchesFiles: Set<File>,
optimizedDexDirectory: File? = null,
) = loadPatchesFromDex(patchesFiles, optimizedDexDirectory, null)
fun loadPatchesFromDex(patchesFiles: Set<File>, optimizedDexDirectory: File? = null) =
PatchLoader.Dex(patchesFiles, optimizedDexDirectory)

View File

@@ -71,7 +71,6 @@ internal object PatchLoaderTest {
patchLoaderCompanionObject,
TEST_PATCHES_CLASS_LOADER,
mapOf(File("patchesFile") to setOf(TEST_PATCHES_CLASS)),
null
).values.first()
assertEquals(