mirror of
https://github.com/revanced/revanced-patcher.git
synced 2025-05-02 14:04:24 +02:00
fix: Merge extension only when patch executes (#315)
This commit is contained in:
parent
ab624f04f6
commit
aa472eb985
@ -91,19 +91,15 @@ class Patcher(private val config: PatcherConfig) : Closeable {
|
|||||||
}.also { executedPatches[this] = it }
|
}.also { executedPatches[this] = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent from decoding the app manifest twice if it is not needed.
|
// Prevent decoding the app manifest twice if it is not needed.
|
||||||
if (config.resourceMode != ResourcePatchContext.ResourceMode.NONE) {
|
if (config.resourceMode != ResourcePatchContext.ResourceMode.NONE) {
|
||||||
context.resourceContext.decodeResources(config.resourceMode)
|
context.resourceContext.decodeResources(config.resourceMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Merging extensions")
|
logger.info("Initializing lookup maps")
|
||||||
|
|
||||||
with(context.bytecodeContext) {
|
// Accessing the lazy lookup maps to initialize them.
|
||||||
context.executablePatches.mergeExtensions()
|
context.bytecodeContext.lookupMaps
|
||||||
|
|
||||||
// Initialize lookup maps.
|
|
||||||
lookupMaps
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Executing patches")
|
logger.info("Executing patches")
|
||||||
|
|
||||||
|
@ -59,42 +59,33 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
|
|||||||
internal val lookupMaps by lazy { LookupMaps(classes) }
|
internal val lookupMaps by lazy { LookupMaps(classes) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge the extensions for this set of patches.
|
* Merge the extension of this patch.
|
||||||
*/
|
*/
|
||||||
internal fun Set<Patch<*>>.mergeExtensions() {
|
internal fun BytecodePatch.mergeExtension() {
|
||||||
// Lookup map to check if a class exists by its type quickly.
|
extension?.use { extensionStream ->
|
||||||
val classesByType = mutableMapOf<String, ClassDef>().apply {
|
RawDexIO.readRawDexFile(extensionStream, 0, null).classes.forEach { classDef ->
|
||||||
classes.forEach { classDef -> put(classDef.type, classDef) }
|
val existingClass = lookupMaps.classesByType[classDef.type] ?: run {
|
||||||
}
|
logger.fine("Adding class \"$classDef\"")
|
||||||
|
|
||||||
forEachRecursively { patch ->
|
classes += classDef
|
||||||
if (patch !is BytecodePatch) return@forEachRecursively
|
lookupMaps.classesByType[classDef.type] = classDef
|
||||||
|
|
||||||
patch.extension?.use { extensionStream ->
|
return@forEach
|
||||||
RawDexIO.readRawDexFile(extensionStream, 0, null).classes.forEach { classDef ->
|
}
|
||||||
val existingClass = classesByType[classDef.type] ?: run {
|
|
||||||
logger.fine("Adding class \"$classDef\"")
|
|
||||||
|
|
||||||
classes += classDef
|
logger.fine("Class \"$classDef\" exists already. Adding missing methods and fields.")
|
||||||
classesByType[classDef.type] = classDef
|
|
||||||
|
|
||||||
return@forEach
|
existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass ->
|
||||||
|
// If the class was merged, replace the original class with the merged class.
|
||||||
|
if (mergedClass === existingClass) {
|
||||||
|
return@let
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.fine("Class \"$classDef\" exists already. Adding missing methods and fields.")
|
classes -= existingClass
|
||||||
|
classes += mergedClass
|
||||||
existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass ->
|
|
||||||
// If the class was merged, replace the original class with the merged class.
|
|
||||||
if (mergedClass === existingClass) {
|
|
||||||
return@let
|
|
||||||
}
|
|
||||||
|
|
||||||
classes -= existingClass
|
|
||||||
classes += mergedClass
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} ?: return logger.fine("No extension to merge")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -185,6 +176,11 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
|
|||||||
*/
|
*/
|
||||||
internal val methodsByStrings = MethodClassPairsLookupMap()
|
internal val methodsByStrings = MethodClassPairsLookupMap()
|
||||||
|
|
||||||
|
// Lookup map for fast checking if a class exists by its type.
|
||||||
|
val classesByType = mutableMapOf<String, ClassDef>().apply {
|
||||||
|
classes.forEach { classDef -> put(classDef.type, classDef) }
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
classes.forEach { classDef ->
|
classes.forEach { classDef ->
|
||||||
classDef.methods.forEach { method ->
|
classDef.methods.forEach { method ->
|
||||||
@ -231,6 +227,7 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
|
|||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
methodsByStrings.clear()
|
methodsByStrings.clear()
|
||||||
|
classesByType.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +158,13 @@ class BytecodePatch internal constructor(
|
|||||||
finalizeBlock,
|
finalizeBlock,
|
||||||
) {
|
) {
|
||||||
override fun execute(context: PatcherContext) = with(context.bytecodeContext) {
|
override fun execute(context: PatcherContext) = with(context.bytecodeContext) {
|
||||||
fingerprints.forEach { it.match(this) }
|
with(context.bytecodeContext) {
|
||||||
|
mergeExtension()
|
||||||
|
}
|
||||||
|
|
||||||
|
fingerprints.forEach {
|
||||||
|
it.match(this)
|
||||||
|
}
|
||||||
|
|
||||||
execute(this)
|
execute(this)
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ internal object PatcherTest {
|
|||||||
private operator fun Set<Patch<*>>.invoke(): List<PatchResult> {
|
private operator fun Set<Patch<*>>.invoke(): List<PatchResult> {
|
||||||
every { patcher.context.executablePatches } returns toMutableSet()
|
every { patcher.context.executablePatches } returns toMutableSet()
|
||||||
every { patcher.context.bytecodeContext.lookupMaps } returns LookupMaps(patcher.context.bytecodeContext.classes)
|
every { patcher.context.bytecodeContext.lookupMaps } returns LookupMaps(patcher.context.bytecodeContext.classes)
|
||||||
every { with(patcher.context.bytecodeContext) { any<Set<Patch<*>>>().mergeExtensions() } } just runs
|
every { with(patcher.context.bytecodeContext) { any<BytecodePatch>().mergeExtension() } } just runs
|
||||||
|
|
||||||
return runBlocking { patcher().toList() }
|
return runBlocking { patcher().toList() }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user