You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-09-06 16:38:50 +02:00
Compare commits
12 Commits
v6.4.3-dev
...
v7.0.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a3ae825e48 | ||
![]() |
146c8504ed | ||
![]() |
2eb125ad69 | ||
![]() |
6e24a85eab | ||
![]() |
e4c3e9ffc5 | ||
![]() |
4c1778a62f | ||
![]() |
d99261cdbb | ||
![]() |
ac1c0f2773 | ||
![]() |
eddd4ec7ac | ||
![]() |
07a2829c65 | ||
![]() |
3d77e299d9 | ||
![]() |
f1336f89e4 |
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -32,11 +32,11 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "latest"
|
node-version: "18"
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
- name: Setup semantic-release
|
- name: Setup semantic-release
|
||||||
run: npm install semantic-release@19.0.5 @saithodev/semantic-release-backmerge @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin@1.7.4 -D
|
run: npm install
|
||||||
- name: Release
|
- name: Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||||
run: npx semantic-release
|
run: npm exec semantic-release
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -117,4 +117,7 @@ gradle-app.setting
|
|||||||
!src/test/resources/*
|
!src/test/resources/*
|
||||||
|
|
||||||
# Dependency directories
|
# Dependency directories
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
# Gradle props, to avoid sharing the gpr key
|
||||||
|
gradle.properties
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
[
|
[
|
||||||
"@saithodev/semantic-release-backmerge",
|
"@saithodev/semantic-release-backmerge",
|
||||||
{
|
{
|
||||||
branches: [{from: "main", to: "dev"}],
|
backmergeBranches: [{"from": "main", "to": "dev"}],
|
||||||
clearWorkspace: true
|
clearWorkspace: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
31
CHANGELOG.md
31
CHANGELOG.md
@@ -1,3 +1,34 @@
|
|||||||
|
# [7.0.0](https://github.com/revanced/revanced-patcher/compare/v6.4.3...v7.0.0) (2023-02-26)
|
||||||
|
|
||||||
|
|
||||||
|
* feat!: merge integrations only when necessary ([6e24a85](https://github.com/revanced/revanced-patcher/commit/6e24a85eabd1e7a1484fad229d5ba55c3ba1f1b4))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`
|
||||||
|
|
||||||
|
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
|
||||||
|
|
||||||
|
# [7.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.3...v7.0.0-dev.1) (2023-02-26)
|
||||||
|
|
||||||
|
|
||||||
|
* feat!: merge integrations only when necessary ([6e24a85](https://github.com/revanced/revanced-patcher/commit/6e24a85eabd1e7a1484fad229d5ba55c3ba1f1b4))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`
|
||||||
|
|
||||||
|
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
|
||||||
|
|
||||||
|
## [6.4.3](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3) (2023-02-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* check `CONST_STRING_JUMP` instructions for matching string ([058d292](https://github.com/revanced/revanced-patcher/commit/058d292ad5e297f4c652ff543c13e77a39f7fb1b))
|
||||||
|
|
||||||
## [6.4.3-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3-dev.1) (2023-02-10)
|
## [6.4.3-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3-dev.1) (2023-02-10)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 6.4.3-dev.1
|
version = 7.0.0
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
727
package-lock.json
generated
727
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@saithodev/semantic-release-backmerge": "^3.1.0",
|
||||||
"@semantic-release/changelog": "^6.0.2",
|
"@semantic-release/changelog": "^6.0.2",
|
||||||
"@semantic-release/git": "^10.0.1",
|
"@semantic-release/git": "^10.0.1",
|
||||||
"gradle-semantic-release-plugin": "^1.7.4",
|
"gradle-semantic-release-plugin": "^1.7.6",
|
||||||
"semantic-release": "^19.0.5"
|
"semantic-release": "^20.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
package app.revanced.patcher
|
package app.revanced.patcher
|
||||||
|
|
||||||
import app.revanced.patcher.data.Context
|
import app.revanced.patcher.data.Context
|
||||||
import app.revanced.patcher.data.findIndexed
|
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.dependencies
|
import app.revanced.patcher.extensions.PatchExtensions.dependencies
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.requiresIntegrations
|
||||||
import app.revanced.patcher.extensions.nullOutputStream
|
import app.revanced.patcher.extensions.nullOutputStream
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
import app.revanced.patcher.patch.*
|
import app.revanced.patcher.patch.*
|
||||||
import app.revanced.patcher.util.ClassMerger.merge
|
|
||||||
import app.revanced.patcher.util.VersionReader
|
import app.revanced.patcher.util.VersionReader
|
||||||
import brut.androlib.Androlib
|
import brut.androlib.Androlib
|
||||||
import brut.androlib.meta.UsesFramework
|
import brut.androlib.meta.UsesFramework
|
||||||
@@ -28,7 +27,7 @@ import org.jf.dexlib2.writer.io.MemoryDataStore
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
private val NAMER = BasicDexFileNamer()
|
internal val NAMER = BasicDexFileNamer()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ReVanced Patcher.
|
* The ReVanced Patcher.
|
||||||
@@ -38,6 +37,7 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
private val logger = options.logger
|
private val logger = options.logger
|
||||||
private val opcodes: Opcodes
|
private val opcodes: Opcodes
|
||||||
private var resourceDecodingMode = ResourceDecodingMode.MANIFEST_ONLY
|
private var resourceDecodingMode = ResourceDecodingMode.MANIFEST_ONLY
|
||||||
|
private var mergeIntegrations = false
|
||||||
val context: PatcherContext
|
val context: PatcherContext
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -64,37 +64,19 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add additional dex file container to the patcher.
|
* Add integrations to be merged by the patcher.
|
||||||
* @param files The dex file containers to add to the patcher.
|
* The integrations will only be merged, if necessary.
|
||||||
* @param process The callback for [files] which are being added.
|
*
|
||||||
|
* @param integrations The integrations, must be dex files or dex file container such as ZIP, APK or DEX files.
|
||||||
|
* @param callback The callback for [integrations] which are being added.
|
||||||
*/
|
*/
|
||||||
fun addFiles(
|
fun addIntegrations(
|
||||||
files: List<File>,
|
integrations: List<File>,
|
||||||
process: (File) -> Unit
|
callback: (File) -> Unit
|
||||||
) {
|
) {
|
||||||
with(context.bytecodeContext.classes) {
|
context.integrations.apply integrations@{
|
||||||
for (file in files) {
|
add(integrations)
|
||||||
process(file)
|
this@integrations.callback = callback
|
||||||
for (classDef in MultiDexIO.readDexFile(true, file, NAMER, null, null).classes) {
|
|
||||||
val type = classDef.type
|
|
||||||
|
|
||||||
val result = classes.findIndexed { it.type == type }
|
|
||||||
if (result == null) {
|
|
||||||
logger.trace("Merging type $type")
|
|
||||||
classes.add(classDef)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val (existingClass, existingClassIndex) = result
|
|
||||||
|
|
||||||
logger.trace("Type $type exists. Adding missing methods and fields.")
|
|
||||||
|
|
||||||
existingClass.merge(classDef, context, logger).let { mergedClass ->
|
|
||||||
if (mergedClass !== existingClass) // referential equality check
|
|
||||||
classes[existingClassIndex] = mergedClass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,18 +165,29 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
*/
|
*/
|
||||||
fun addPatches(patches: Iterable<Class<out Patch<Context>>>) {
|
fun addPatches(patches: Iterable<Class<out Patch<Context>>>) {
|
||||||
/**
|
/**
|
||||||
* Fill the cache with the instances of the [Patch]es for later use.
|
* Returns true if at least one patches or its dependencies matches the given predicate.
|
||||||
* Note: Dependencies of the [Patch] will be cached as well.
|
|
||||||
*/
|
*/
|
||||||
fun Class<out Patch<Context>>.isResource() {
|
fun Class<out Patch<Context>>.anyRecursively(predicate: (Class<out Patch<Context>>) -> Boolean): Boolean =
|
||||||
this.also {
|
predicate(this) || dependencies?.any { it.java.anyRecursively(predicate) } == true
|
||||||
if (!ResourcePatch::class.java.isAssignableFrom(it)) return@also
|
|
||||||
// set the mode to decode all resources before running the patches
|
|
||||||
|
// Determine if resource patching is required.
|
||||||
|
for (patch in patches) {
|
||||||
|
if (patch.anyRecursively { ResourcePatch::class.java.isAssignableFrom(it) }) {
|
||||||
resourceDecodingMode = ResourceDecodingMode.FULL
|
resourceDecodingMode = ResourceDecodingMode.FULL
|
||||||
}.dependencies?.forEach { it.java.isResource() }
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.patches.addAll(patches.onEach(Class<out Patch<Context>>::isResource))
|
// Determine if merging integrations is required.
|
||||||
|
for (patch in patches) {
|
||||||
|
if (patch.anyRecursively { it.requiresIntegrations }) {
|
||||||
|
mergeIntegrations = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.patches.addAll(patches)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,6 +336,8 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sequence {
|
return sequence {
|
||||||
|
if (mergeIntegrations) context.integrations.merge(logger)
|
||||||
|
|
||||||
// prevent from decoding the manifest twice if it is not needed
|
// prevent from decoding the manifest twice if it is not needed
|
||||||
if (resourceDecodingMode == ResourceDecodingMode.FULL) decodeResources(ResourceDecodingMode.FULL)
|
if (resourceDecodingMode == ResourceDecodingMode.FULL) decodeResources(ResourceDecodingMode.FULL)
|
||||||
|
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
package app.revanced.patcher
|
package app.revanced.patcher
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.*
|
||||||
import app.revanced.patcher.data.Context
|
import app.revanced.patcher.logging.Logger
|
||||||
import app.revanced.patcher.data.PackageMetadata
|
|
||||||
import app.revanced.patcher.data.ResourceContext
|
|
||||||
import app.revanced.patcher.patch.Patch
|
import app.revanced.patcher.patch.Patch
|
||||||
|
import app.revanced.patcher.util.ClassMerger.merge
|
||||||
import org.jf.dexlib2.iface.ClassDef
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -14,6 +13,52 @@ data class PatcherContext(
|
|||||||
) {
|
) {
|
||||||
val packageMetadata = PackageMetadata()
|
val packageMetadata = PackageMetadata()
|
||||||
internal val patches = mutableListOf<Class<out Patch<Context>>>()
|
internal val patches = mutableListOf<Class<out Patch<Context>>>()
|
||||||
|
internal val integrations = Integrations(this)
|
||||||
internal val bytecodeContext = BytecodeContext(classes)
|
internal val bytecodeContext = BytecodeContext(classes)
|
||||||
internal val resourceContext = ResourceContext(resourceCacheDirectory)
|
internal val resourceContext = ResourceContext(resourceCacheDirectory)
|
||||||
|
|
||||||
|
internal class Integrations(val context: PatcherContext) {
|
||||||
|
var callback: ((File) -> Unit)? = null
|
||||||
|
private val integrations: MutableList<File> = mutableListOf()
|
||||||
|
|
||||||
|
fun add(integrations: List<File>) = this@Integrations.integrations.addAll(integrations)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge integrations.
|
||||||
|
* @param logger A logger.
|
||||||
|
*/
|
||||||
|
fun merge(logger: Logger) {
|
||||||
|
with(context.bytecodeContext.classes) {
|
||||||
|
for (integrations in integrations) {
|
||||||
|
callback?.let { it(integrations) }
|
||||||
|
|
||||||
|
for (classDef in lanchon.multidexlib2.MultiDexIO.readDexFile(
|
||||||
|
true,
|
||||||
|
integrations,
|
||||||
|
NAMER,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
).classes) {
|
||||||
|
val type = classDef.type
|
||||||
|
|
||||||
|
val result = classes.findIndexed { it.type == type }
|
||||||
|
if (result == null) {
|
||||||
|
logger.trace("Merging type $type")
|
||||||
|
classes.add(classDef)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val (existingClass, existingClassIndex) = result
|
||||||
|
|
||||||
|
logger.trace("Type $type exists. Adding missing methods and fields.")
|
||||||
|
|
||||||
|
existingClass.merge(classDef, context, logger).let { mergedClass ->
|
||||||
|
if (mergedClass !== existingClass) // referential equality check
|
||||||
|
classes[existingClassIndex] = mergedClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -7,8 +7,6 @@ import app.revanced.patcher.patch.Patch
|
|||||||
* @param compatiblePackages A list of packages a [Patch] is compatible with.
|
* @param compatiblePackages A list of packages a [Patch] is compatible with.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class Compatibility(
|
annotation class Compatibility(
|
||||||
val compatiblePackages: Array<Package>,
|
val compatiblePackages: Array<Package>,
|
||||||
)
|
)
|
||||||
@@ -19,8 +17,6 @@ annotation class Compatibility(
|
|||||||
* @param versions The versions of the package the [Patch] is compatible with.
|
* @param versions The versions of the package the [Patch] is compatible with.
|
||||||
*/
|
*/
|
||||||
@Target()
|
@Target()
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class Package(
|
annotation class Package(
|
||||||
val name: String,
|
val name: String,
|
||||||
val versions: Array<String> = [],
|
val versions: Array<String> = [],
|
||||||
|
@@ -7,8 +7,6 @@ import app.revanced.patcher.patch.Patch
|
|||||||
* @param name A suggestive name for the [Patch].
|
* @param name A suggestive name for the [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class Name(
|
annotation class Name(
|
||||||
val name: String,
|
val name: String,
|
||||||
)
|
)
|
||||||
@@ -18,8 +16,6 @@ annotation class Name(
|
|||||||
* @param description A description for the [Patch].
|
* @param description A description for the [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class Description(
|
annotation class Description(
|
||||||
val description: String,
|
val description: String,
|
||||||
)
|
)
|
||||||
@@ -30,8 +26,6 @@ annotation class Description(
|
|||||||
* @param version The version of a [Patch].
|
* @param version The version of a [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class Version(
|
annotation class Version(
|
||||||
val version: String,
|
val version: String,
|
||||||
)
|
)
|
||||||
|
@@ -8,6 +8,7 @@ import app.revanced.patcher.patch.OptionsContainer
|
|||||||
import app.revanced.patcher.patch.Patch
|
import app.revanced.patcher.patch.Patch
|
||||||
import app.revanced.patcher.patch.PatchOptions
|
import app.revanced.patcher.patch.PatchOptions
|
||||||
import app.revanced.patcher.patch.annotations.DependsOn
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patcher.patch.annotations.RequiresIntegrations
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KVisibility
|
import kotlin.reflect.KVisibility
|
||||||
import kotlin.reflect.full.companionObject
|
import kotlin.reflect.full.companionObject
|
||||||
@@ -58,6 +59,9 @@ object PatchExtensions {
|
|||||||
val Class<out Patch<Context>>.compatiblePackages
|
val Class<out Patch<Context>>.compatiblePackages
|
||||||
get() = findAnnotationRecursively(Compatibility::class)?.compatiblePackages
|
get() = findAnnotationRecursively(Compatibility::class)?.compatiblePackages
|
||||||
|
|
||||||
|
internal val Class<out Patch<Context>>.requiresIntegrations
|
||||||
|
get() = findAnnotationRecursively(RequiresIntegrations::class) != null
|
||||||
|
|
||||||
val Class<out Patch<Context>>.options: PatchOptions?
|
val Class<out Patch<Context>>.options: PatchOptions?
|
||||||
get() = kotlin.companionObject?.let { cl ->
|
get() = kotlin.companionObject?.let { cl ->
|
||||||
if (cl.visibility != KVisibility.PUBLIC) return null
|
if (cl.visibility != KVisibility.PUBLIC) return null
|
||||||
|
@@ -7,7 +7,6 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|||||||
* @param threshold if [threshold] or more of the opcodes do not match, skip.
|
* @param threshold if [threshold] or more of the opcodes do not match, skip.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class FuzzyPatternScanMethod(
|
annotation class FuzzyPatternScanMethod(
|
||||||
val threshold: Int = 1
|
val threshold: Int = 1
|
||||||
)
|
)
|
@@ -5,20 +5,23 @@ import app.revanced.patcher.patch.Patch
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to mark a Class as a patch.
|
* Annotation to mark a class as a patch.
|
||||||
* @param include If false, the patch should be treated as optional by default.
|
* @param include If false, the patch should be treated as optional by default.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class Patch(val include: Boolean = true)
|
annotation class Patch(val include: Boolean = true)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation for dependencies of [Patch]es.
|
* Annotation for dependencies of [Patch]es.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class DependsOn(
|
annotation class DependsOn(
|
||||||
val dependencies: Array<KClass<out Patch<Context>>> = []
|
val dependencies: Array<KClass<out Patch<Context>>> = []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation to mark [Patch]es which depend on integrations.
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class RequiresIntegrations // required because integrations are decoupled from patches
|
@@ -9,6 +9,5 @@ import app.revanced.patcher.annotation.Package
|
|||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
internal annotation class ExampleBytecodeCompatibility
|
internal annotation class ExampleBytecodeCompatibility
|
||||||
|
|
||||||
|
@@ -9,6 +9,5 @@ import app.revanced.patcher.annotation.Package
|
|||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
internal annotation class ExampleResourceCompatibility
|
internal annotation class ExampleResourceCompatibility
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user