Merge remote-tracking branch 'origin/main'

This commit is contained in:
oSumAtrIX 2022-08-02 03:09:02 +02:00
commit 5f7ef2dbff
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
8 changed files with 166 additions and 15 deletions

View File

@ -1,3 +1,15 @@
# [2.8.0](https://github.com/revanced/revanced-patcher/compare/v2.7.0...v2.8.0) (2022-08-01)
### Bug Fixes
* remove requirement for solution [skip ci] ([#80](https://github.com/revanced/revanced-patcher/issues/80)) ([9a4d30e](https://github.com/revanced/revanced-patcher/commit/9a4d30e15234ef62844f035c58a1143674d4c12e))
### Features
* patch options ([#81](https://github.com/revanced/revanced-patcher/issues/81)) ([fbb09f3](https://github.com/revanced/revanced-patcher/commit/fbb09f38dce49adc7f63b71bdf2df2ef0b84db04))
# [2.7.0](https://github.com/revanced/revanced-patcher/compare/v2.6.0...v2.7.0) (2022-08-01) # [2.7.0](https://github.com/revanced/revanced-patcher/compare/v2.6.0...v2.7.0) (2022-08-01)

View File

@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 2.7.0 version = 2.8.0

View File

@ -11,7 +11,6 @@ import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependencyType
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.patch.impl.ResourcePatch import app.revanced.patcher.patch.impl.ResourcePatch
import app.revanced.patcher.util.ListBackedSet import app.revanced.patcher.util.ListBackedSet
@ -265,11 +264,6 @@ class Patcher(private val options: PatcherOptions) {
// recursively apply all dependency patches // recursively apply all dependency patches
patch.dependencies.forEach { patch.dependencies.forEach {
val dependency = it.patch.java val dependency = it.patch.java
if ( // soft dependencies must be included manually.
it.type == DependencyType.SOFT && !data.patches.any { p ->
p.patchName == dependency.patchName
}
) return@forEach
val result = applyPatch(dependency, appliedPatches) val result = applyPatch(dependency, appliedPatches)
if (result.isSuccess()) return@forEach if (result.isSuccess()) return@forEach

View File

@ -17,4 +17,9 @@ abstract class Patch<out T : Data> {
* The main function of the [Patch] which the patcher will call. * The main function of the [Patch] which the patcher will call.
*/ */
abstract fun execute(data: @UnsafeVariance T): PatchResult abstract fun execute(data: @UnsafeVariance T): PatchResult
/**
* A list of [PatchOption]s.
*/
open val options: Iterable<PatchOption<*>> = listOf()
} }

View File

@ -0,0 +1,100 @@
package app.revanced.patcher.patch
/**
* A [Patch] option.
* @param key Unique identifier of the option. Example: _`settings.microg.enabled`_
* @param default The default value of the option.
* @param title A human-readable title of the option. Example: _MicroG Settings_
* @param description A human-readable description of the option. Example: _Settings integration for MicroG._
* @param required Whether the option is required.
*/
@Suppress("MemberVisibilityCanBePrivate")
sealed class PatchOption<T>(
val key: String,
default: T?,
val title: String,
val description: String,
val required: Boolean
) {
var value: T? = default
/**
* A [PatchOption] representing a [String].
* @see PatchOption
*/
class StringOption(
key: String,
default: String?,
title: String,
description: String,
required: Boolean = false
) : PatchOption<String>(
key, default, title, description, required
)
/**
* A [PatchOption] representing a [Boolean].
* @see PatchOption
*/
class BooleanOption(
key: String,
default: Boolean?,
title: String,
description: String,
required: Boolean = false
) : PatchOption<Boolean>(
key, default, title, description, required
)
/**
* A [PatchOption] with a list of allowed options.
* @param options A list of allowed options for the [ListOption].
* @see PatchOption
*/
sealed class ListOption<E>(
key: String,
default: E?,
val options: Iterable<E>,
title: String,
description: String,
required: Boolean = false
) : PatchOption<E>(
key, default, title, description, required
) {
init {
if (default !in options) {
throw IllegalStateException("Default option must be an allowed options")
}
}
}
/**
* A [ListOption] of type [String].
* @see ListOption
*/
class StringListOption(
key: String,
default: String?,
options: Iterable<String>,
title: String,
description: String,
required: Boolean = false
) : ListOption<String>(
key, default, options, title, description, required
)
/**
* A [ListOption] of type [Int].
* @see ListOption
*/
class IntListOption(
key: String,
default: Int?,
options: Iterable<Int>,
title: String,
description: String,
required: Boolean = false
) : ListOption<Int>(
key, default, options, title, description, required
)
}

View File

@ -43,11 +43,5 @@ enum class DependencyType {
/** /**
* Enforces that the dependency is applied, even if it was not selected. * Enforces that the dependency is applied, even if it was not selected.
*/ */
HARD, HARD
/**
* Applies the dependency only if it was selected.
*/
@Deprecated("Will be removed when Patch Options is implemented.")
SOFT
} }

View File

@ -0,0 +1,30 @@
package app.revanced.patcher.usage
import app.revanced.patcher.patch.PatchOption
import app.revanced.patcher.usage.bytecode.ExampleBytecodePatch
fun patchOptionsUsage() {
val options = ExampleBytecodePatch().options
for (option in options) {
when (option) {
is PatchOption.StringOption -> {
option.value = "Hello World"
}
is PatchOption.BooleanOption -> {
option.value = false
}
is PatchOption.StringListOption -> {
option.value = option.options.first()
for (choice in option.options) {
println(choice)
}
}
is PatchOption.IntListOption -> {
option.value = option.options.first()
for (choice in option.options) {
println(choice)
}
}
}
}
}

View File

@ -7,6 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.PatchOption
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependencyType import app.revanced.patcher.patch.annotations.DependencyType
@ -37,7 +38,7 @@ import org.jf.dexlib2.util.Preconditions
@Description("Example demonstration of a bytecode patch.") @Description("Example demonstration of a bytecode patch.")
@ExampleResourceCompatibility @ExampleResourceCompatibility
@Version("0.0.1") @Version("0.0.1")
@DependsOn(ExampleBytecodePatch::class, DependencyType.SOFT) @DependsOn(ExampleBytecodePatch::class, DependencyType.HARD)
class ExampleBytecodePatch : BytecodePatch(listOf(ExampleFingerprint)) { class ExampleBytecodePatch : BytecodePatch(listOf(ExampleFingerprint)) {
// This function will be executed by the patcher. // This function will be executed by the patcher.
// You can treat it as a constructor // You can treat it as a constructor
@ -162,4 +163,19 @@ class ExampleBytecodePatch : BytecodePatch(listOf(ExampleFingerprint)) {
) )
) )
} }
override val options = listOf(
PatchOption.StringOption(
"key", "default", "title", "description", true
),
PatchOption.BooleanOption(
"key", true, "title", "description" // required defaults to false
),
PatchOption.StringListOption(
"key", "TEST", listOf("TEST", "TEST1", "TEST2"), "title", "description"
),
PatchOption.IntListOption(
"key", 1, listOf(1, 2, 3), "title", "description"
),
)
} }