mirror of
https://github.com/revanced/revanced-cli.git
synced 2024-12-27 04:25:48 +01:00
build: Bump ReVanced Patcher (#335)
This commit is contained in:
parent
0a2e99c1c0
commit
54ae01cd76
2
.gitignore
vendored
2
.gitignore
vendored
@ -121,5 +121,5 @@ node_modules/
|
||||
revanced-cache/
|
||||
options.toml
|
||||
|
||||
# Generated by an Android project (such as ReVanced Integrations)
|
||||
# Generated by Android projects
|
||||
local.properties
|
175
docs/1_usage.md
175
docs/1_usage.md
@ -1,129 +1,100 @@
|
||||
# π οΈ Using ReVanced CLI
|
||||
|
||||
Learn how to use ReVanced CLI.
|
||||
The following examples will show you how to perform basic operations.
|
||||
You can list patches, patch an app, uninstall, and install an app.
|
||||
|
||||
## π¨ Usage
|
||||
## π Show all commands
|
||||
|
||||
ReVanced CLI is divided into the following fundamental commands:
|
||||
```bash
|
||||
java -jar revanced-cli.jar -h
|
||||
```
|
||||
|
||||
- ### π Show all available options for ReVanced CLI
|
||||
## π List patches
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar -h
|
||||
```
|
||||
```bash
|
||||
java -jar revanced-cli.jar list-patches --with-descriptions --with-packages --with-versions --with-options --with-universal-patches revanced-patches.rvp
|
||||
```
|
||||
|
||||
- ### π List patches
|
||||
## π Patch an app with the default list of patches
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar list-patches \
|
||||
--with-packages \
|
||||
--with-versions \
|
||||
--with-options \
|
||||
revanced-patches.jar [<patch-bundle> ...]
|
||||
```
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch -b revanced-patches.rvp input.apk
|
||||
```
|
||||
|
||||
- ### βοΈ Generate options
|
||||
You can also use multiple patch bundles:
|
||||
|
||||
This will generate an `options.json` file for the patches from a list of supplied patch bundles.
|
||||
The file can be supplied to ReVanced CLI later on.
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch -b revanced-patches.rvp -b another-patches.rvp input.apk
|
||||
```
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar options \
|
||||
--path options.json \
|
||||
--overwrite \
|
||||
revanced-patches.jar [<patch-bundle> ...]
|
||||
```
|
||||
To manually include or exclude patches, use the options `-i` and `-e`.
|
||||
Keep in mind the name of the patch must be an exact match.
|
||||
You can also use the options `--ii` and `--ie` to include or exclude patches by their index
|
||||
if two patches have the same name.
|
||||
To know the indices of patches, use the option `--with-indices` when listing patches:
|
||||
|
||||
> **βΉοΈ Note**
|
||||
> A default `options.json` file will be automatically created if it does not exist
|
||||
> without any need for intervention when using the `patch` command.
|
||||
```bash
|
||||
java -jar revanced-cli.jar list-patches --with-indices revanced-patches.rvp
|
||||
```
|
||||
|
||||
- ### π Patch an app
|
||||
Then you can use the indices to include or exclude patches:
|
||||
|
||||
You can patch apps by supplying patch bundles and the app to patch.
|
||||
After patching, ReVanced CLI can install the patched app on your device using two methods:
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch -b revanced-patches.rvp --ii 123 --ie 456 input.apk
|
||||
```
|
||||
|
||||
> **π‘ Tip**
|
||||
> For ReVanced CLI to be able to install the patched app on your device, make sure ADB is working:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell exit
|
||||
> ```
|
||||
>
|
||||
> If you want to mount the patched app on top of the un-patched app, make sure you have root permissions:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell su -c exit
|
||||
> ```
|
||||
> [!TIP]
|
||||
> You can use the option `-d` to automatically install the patched app after patching.
|
||||
> Make sure ADB is working:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell exit
|
||||
> ```
|
||||
|
||||
> **β οΈ Warning**
|
||||
> Some patches may require integrations
|
||||
> such as [ReVanced Integrations](https://github.com/revanced/revanced-integrations).
|
||||
> Supply them with the option `--merge`. ReVanced Patcher will automatically determine if they are necessary.
|
||||
|
||||
- #### πΎ Patch an app and install it on your device regularly
|
||||
> [!TIP]
|
||||
> You can use the option `--mount` to mount the patched app on top of the un-patched app.
|
||||
> Make sure you have root permissions and the same app you are patching and mounting over is installed on your device:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell su -c exit
|
||||
> adb install input.apk
|
||||
> ```
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch \
|
||||
--patch-bundle revanced-patches.jar \
|
||||
-d \
|
||||
input.apk
|
||||
```
|
||||
## π¦ Install an app manually
|
||||
|
||||
- #### πΎ Patch an app and mount it on top of the un-patched app with root permissions
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility install -a input.apk
|
||||
```
|
||||
|
||||
> **β Caution**
|
||||
> Ensure that the same app you are patching and mounting over is installed on your device:
|
||||
>
|
||||
> ```bash
|
||||
> adb install app.apk
|
||||
> ```
|
||||
> [!TIP]
|
||||
> You can use the option `--mount` to mount the patched app on top of the un-patched app.
|
||||
> Make sure you have root permissions and the same app you are patching and mounting over is installed on your device:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell su -c exit
|
||||
> adb install input.apk
|
||||
> ```
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch \
|
||||
--patch-bundle revanced-patches.jar \
|
||||
--include "Some patch" \
|
||||
--ii 123 \
|
||||
--exclude "Some other patch" \
|
||||
-d \
|
||||
--mount \
|
||||
app.apk
|
||||
```
|
||||
## ποΈ Uninstall an app manually
|
||||
|
||||
> **π‘ Tip**
|
||||
> You can use the option `--ii` to include or `--ie` to exclude
|
||||
> patches by their index in relation to supplied patch bundles,
|
||||
> similarly to the option `--include` and `--exclude`.
|
||||
>
|
||||
> This is useful in case two patches have the same name, and you must include or exclude one.
|
||||
> The patch index is calculated by the position of the patch in the list of patches
|
||||
> from patch bundles supplied using the option `--patch-bundle`.
|
||||
>
|
||||
> You can list all patches with their indices using the command `list-patches`.
|
||||
>
|
||||
> Keep in mind that the indices can change based on the order of the patch bundles supplied,
|
||||
> as well if the patch bundles are updated because patches can be added or removed.
|
||||
Here `<package-name>` is the package name of the app you want to uninstall:
|
||||
|
||||
- ### ποΈ Uninstall an app
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility uninstall --package-name <package-name>
|
||||
```
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility uninstall \
|
||||
--package-name <package-name> \
|
||||
[<device-serial>]
|
||||
```
|
||||
If the app is mounted, you need to unmount it by using the option `--unmount`:
|
||||
|
||||
> **π‘ Tip**
|
||||
> You can unmount an APK file
|
||||
> by adding the option `--unmount`.
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility uninstall --package-name <package-name> --unmount
|
||||
```
|
||||
|
||||
- ### οΈ π¦ Install an app
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility install \
|
||||
-a input.apk \
|
||||
[<device-serial>]
|
||||
```
|
||||
|
||||
> **π‘ Tip**
|
||||
> You can mount an APK file
|
||||
> by supplying the app's package name to mount the supplied APK file over the option `--mount`.
|
||||
> [!TIP]
|
||||
> By default, the app is installed or uninstalled to the first connected device.
|
||||
> You can append one or more devices by their serial to install or uninstall an app on your selected choice of devices:
|
||||
>
|
||||
> ```bash
|
||||
> java -jar revanced-cli.jar utility uninstall --package-name <package-name> [<device-serial> ...]
|
||||
> ```
|
||||
|
@ -1,17 +1,17 @@
|
||||
[versions]
|
||||
shadow = "8.1.1"
|
||||
kotlin = "2.0.0"
|
||||
kotlinx-coroutines-core = "1.8.0"
|
||||
picocli = "4.7.5"
|
||||
revanced-patcher = "19.3.1"
|
||||
revanced-library = "2.3.0"
|
||||
kotlinx = "1.8.1"
|
||||
picocli = "4.7.6"
|
||||
revanced-patcher = "20.0.0"
|
||||
revanced-library = "3.0.0"
|
||||
|
||||
[libraries]
|
||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx" }
|
||||
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
|
||||
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
||||
revanced-library = { module = "app.revanced:revanced-library", version.ref = "revanced-library" }
|
||||
revanced-library = { module = "app.revanced:revanced-library-jvm", version.ref = "revanced-library" }
|
||||
|
||||
[plugins]
|
||||
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
@ -3,7 +3,7 @@ package app.revanced.cli.command
|
||||
import app.revanced.library.PackageName
|
||||
import app.revanced.library.PatchUtils
|
||||
import app.revanced.library.VersionMap
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import app.revanced.patcher.patch.loadPatchesFromJar
|
||||
import picocli.CommandLine
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
@ -12,7 +12,7 @@ import java.util.logging.Logger
|
||||
name = "list-versions",
|
||||
description = [
|
||||
"List the most common compatible versions of apps that are compatible " +
|
||||
"with the patches in the supplied patch bundles.",
|
||||
"with the patches in the supplied patch bundles.",
|
||||
],
|
||||
)
|
||||
internal class ListCompatibleVersions : Runnable {
|
||||
@ -22,7 +22,7 @@ internal class ListCompatibleVersions : Runnable {
|
||||
description = ["Paths to patch bundles."],
|
||||
arity = "1..*",
|
||||
)
|
||||
private lateinit var patchBundles: Array<File>
|
||||
private lateinit var patchBundles: Set<File>
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-f", "--filter-package-names"],
|
||||
@ -38,8 +38,6 @@ internal class ListCompatibleVersions : Runnable {
|
||||
private var countUnusedPatches: Boolean = false
|
||||
|
||||
override fun run() {
|
||||
val patches = PatchBundleLoader.Jar(*patchBundles)
|
||||
|
||||
fun VersionMap.buildVersionsString(): String {
|
||||
if (isEmpty()) return "Any"
|
||||
|
||||
@ -58,6 +56,8 @@ internal class ListCompatibleVersions : Runnable {
|
||||
appendLine(versions.buildVersionsString().prependIndent("\t"))
|
||||
}
|
||||
|
||||
val patches = loadPatchesFromJar(patchBundles)
|
||||
|
||||
PatchUtils.getMostCommonCompatibleVersions(
|
||||
patches,
|
||||
packageNames,
|
||||
|
@ -1,12 +1,13 @@
|
||||
package app.revanced.cli.command
|
||||
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import app.revanced.patcher.patch.Package
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
import app.revanced.patcher.patch.loadPatchesFromJar
|
||||
import picocli.CommandLine.*
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
import app.revanced.patcher.patch.Option as PatchOption
|
||||
|
||||
@Command(
|
||||
name = "list-patches",
|
||||
@ -19,7 +20,7 @@ internal object ListPatchesCommand : Runnable {
|
||||
description = ["Paths to patch bundles."],
|
||||
arity = "1..*",
|
||||
)
|
||||
private lateinit var patchBundles: Array<File>
|
||||
private lateinit var patchBundles: Set<File>
|
||||
|
||||
@Option(
|
||||
names = ["-d", "--with-descriptions"],
|
||||
@ -70,16 +71,19 @@ internal object ListPatchesCommand : Runnable {
|
||||
private var packageName: String? = null
|
||||
|
||||
override fun run() {
|
||||
fun Patch.CompatiblePackage.buildString() =
|
||||
buildString {
|
||||
fun Package.buildString(): String {
|
||||
val (name, versions) = this
|
||||
|
||||
return buildString {
|
||||
if (withVersions && versions != null) {
|
||||
appendLine("Package name: $name")
|
||||
appendLine("Compatible versions:")
|
||||
append(versions!!.joinToString("\n") { version -> version }.prependIndent("\t"))
|
||||
append(versions.joinToString("\n") { version -> version }.prependIndent("\t"))
|
||||
} else {
|
||||
append("Package name: $name")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun PatchOption<*>.buildString() =
|
||||
buildString {
|
||||
@ -126,10 +130,10 @@ internal object ListPatchesCommand : Runnable {
|
||||
}
|
||||
|
||||
fun Patch<*>.filterCompatiblePackages(name: String) =
|
||||
compatiblePackages?.any { it.name == name }
|
||||
compatiblePackages?.any { (compatiblePackageName, _) -> compatiblePackageName == name }
|
||||
?: withUniversalPatches
|
||||
|
||||
val patches = PatchBundleLoader.Jar(*patchBundles).withIndex().toList()
|
||||
val patches = loadPatchesFromJar(patchBundles).withIndex().toList()
|
||||
|
||||
val filtered =
|
||||
packageName?.let { patches.filter { (_, patch) -> patch.filterCompatiblePackages(it) } } ?: patches
|
||||
|
@ -2,7 +2,7 @@ package app.revanced.cli.command
|
||||
|
||||
import app.revanced.library.Options
|
||||
import app.revanced.library.Options.setOptions
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import app.revanced.patcher.patch.loadPatchesFromJar
|
||||
import picocli.CommandLine
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import java.io.File
|
||||
@ -19,7 +19,7 @@ internal object OptionsCommand : Runnable {
|
||||
description = ["Paths to patch bundles."],
|
||||
arity = "1..*",
|
||||
)
|
||||
private lateinit var patchBundles: Array<File>
|
||||
private lateinit var patchBundles: Set<File>
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-p", "--path"],
|
||||
@ -44,7 +44,7 @@ internal object OptionsCommand : Runnable {
|
||||
|
||||
override fun run() =
|
||||
try {
|
||||
PatchBundleLoader.Jar(*patchBundles).let { patches ->
|
||||
loadPatchesFromJar(patchBundles).let { patches ->
|
||||
val exists = filePath.exists()
|
||||
if (!exists || overwrite) {
|
||||
if (exists && update) patches.setOptions(filePath)
|
||||
|
@ -4,11 +4,11 @@ import app.revanced.library.ApkUtils
|
||||
import app.revanced.library.ApkUtils.applyTo
|
||||
import app.revanced.library.Options
|
||||
import app.revanced.library.Options.setOptions
|
||||
import app.revanced.library.adb.AdbManager
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import app.revanced.patcher.PatchSet
|
||||
import app.revanced.library.installation.installer.*
|
||||
import app.revanced.patcher.Patcher
|
||||
import app.revanced.patcher.PatcherConfig
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.loadPatchesFromJar
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import picocli.CommandLine
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
@ -31,8 +31,6 @@ internal object PatchCommand : Runnable {
|
||||
|
||||
private lateinit var apk: File
|
||||
|
||||
private var integrations = setOf<File>()
|
||||
|
||||
private var patchBundles = emptySet<File>()
|
||||
|
||||
@CommandLine.Option(
|
||||
@ -121,16 +119,6 @@ internal object PatchCommand : Runnable {
|
||||
)
|
||||
private var keyStorePassword: String? = null // Empty password by default
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--alias"],
|
||||
description = ["The alias of the keystore entry to sign the patched APK file with."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private fun setKeyStoreEntryAlias(alias: String = "ReVanced Key") {
|
||||
logger.warning("The --alias option is deprecated. Use --keystore-entry-alias instead.")
|
||||
keyStoreEntryAlias = alias
|
||||
}
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--keystore-entry-alias"],
|
||||
description = ["The alias of the keystore entry to sign the patched APK file with."],
|
||||
@ -193,11 +181,8 @@ internal object PatchCommand : Runnable {
|
||||
description = ["One or more DEX files or containers to merge into the APK."],
|
||||
)
|
||||
@Suppress("unused")
|
||||
private fun setIntegrations(integrations: Array<File>) {
|
||||
integrations.firstOrNull { !it.exists() }?.let {
|
||||
throw CommandLine.ParameterException(spec.commandLine(), "Integrations file ${it.path} does not exist.")
|
||||
}
|
||||
this.integrations += integrations
|
||||
private fun setIntegrations(integrations: Set<File>) {
|
||||
logger.warning("The --merge option is not used anymore.")
|
||||
}
|
||||
|
||||
@CommandLine.Option(
|
||||
@ -256,7 +241,7 @@ internal object PatchCommand : Runnable {
|
||||
|
||||
logger.info("Loading patches")
|
||||
|
||||
val patches = PatchBundleLoader.Jar(*patchBundles.toTypedArray())
|
||||
val patches = loadPatchesFromJar(patchBundles)
|
||||
|
||||
// Warn if a patch can not be found in the supplied patch bundles.
|
||||
if (warn) {
|
||||
@ -271,6 +256,7 @@ internal object PatchCommand : Runnable {
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
val patcherTemporaryFilesPath = temporaryFilesPath.resolve("patcher")
|
||||
val (packageName, patcherResult) = Patcher(
|
||||
PatcherConfig(
|
||||
@ -292,28 +278,27 @@ internal object PatchCommand : Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
// region Patch
|
||||
patcher += filteredPatches
|
||||
|
||||
patcher.context.packageMetadata.packageName to patcher.apply {
|
||||
acceptIntegrations(integrations)
|
||||
acceptPatches(filteredPatches)
|
||||
// Execute patches.
|
||||
runBlocking {
|
||||
patcher().collect { patchResult ->
|
||||
val exception = patchResult.exception
|
||||
?: return@collect logger.info("\"${patchResult.patch}\" succeeded")
|
||||
|
||||
// Execute patches.
|
||||
runBlocking {
|
||||
apply(false).collect { patchResult ->
|
||||
patchResult.exception?.let {
|
||||
StringWriter().use { writer ->
|
||||
it.printStackTrace(PrintWriter(writer))
|
||||
logger.severe("${patchResult.patch.name} failed:\n$writer")
|
||||
}
|
||||
} ?: logger.info("${patchResult.patch.name} succeeded")
|
||||
StringWriter().use { writer ->
|
||||
exception.printStackTrace(PrintWriter(writer))
|
||||
|
||||
logger.severe("\"${patchResult.patch}\" failed:\n$writer")
|
||||
}
|
||||
}
|
||||
}.get()
|
||||
// endregion
|
||||
}
|
||||
|
||||
patcher.context.packageMetadata.packageName to patcher.get()
|
||||
}
|
||||
|
||||
// region Save
|
||||
|
||||
apk.copyTo(temporaryFilesPath.resolve(apk.name), overwrite = true).apply {
|
||||
patcherResult.applyTo(this)
|
||||
}.let { patchedApkFile ->
|
||||
@ -340,9 +325,23 @@ internal object PatchCommand : Runnable {
|
||||
|
||||
// region Install
|
||||
|
||||
deviceSerial?.let { serial ->
|
||||
AdbManager.getAdbManager(deviceSerial = serial.ifEmpty { null }, mount)
|
||||
}?.install(AdbManager.Apk(outputFilePath, packageName))
|
||||
deviceSerial?.let { it ->
|
||||
val deviceSerial = it.ifEmpty { null }
|
||||
|
||||
runBlocking {
|
||||
val result = if (mount) {
|
||||
AdbRootInstaller(deviceSerial)
|
||||
} else {
|
||||
AdbInstaller(deviceSerial)
|
||||
}.install(Installer.Apk(outputFilePath, packageName))
|
||||
|
||||
when (result) {
|
||||
RootInstallerResult.FAILURE -> logger.severe("Failed to mount the patched APK file")
|
||||
is AdbInstallerResult.Failure -> logger.severe(result.exception.toString())
|
||||
else -> logger.info("Installed the patched APK file")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@ -358,7 +357,7 @@ internal object PatchCommand : Runnable {
|
||||
* @param patches The patches to filter.
|
||||
* @return The filtered patches.
|
||||
*/
|
||||
private fun Patcher.filterPatchSelection(patches: PatchSet): PatchSet =
|
||||
private fun Patcher.filterPatchSelection(patches: Set<Patch<*>>): Set<Patch<*>> =
|
||||
buildSet {
|
||||
val packageName = context.packageMetadata.packageName
|
||||
val packageVersion = context.packageMetadata.packageVersion
|
||||
@ -367,33 +366,36 @@ internal object PatchCommand : Runnable {
|
||||
val patchName = patch.name!!
|
||||
|
||||
val explicitlyExcluded = excludedPatches.contains(patchName) || excludedPatchesByIndex.contains(i)
|
||||
if (explicitlyExcluded) return@patch logger.info("Excluding $patchName")
|
||||
if (explicitlyExcluded) return@patch logger.info("\"$patchName\" excluded manually")
|
||||
|
||||
// Make sure the patch is compatible with the supplied APK files package name and version.
|
||||
patch.compatiblePackages?.let { packages ->
|
||||
packages.singleOrNull { it.name == packageName }?.let { `package` ->
|
||||
val matchesVersion =
|
||||
force || `package`.versions?.let {
|
||||
it.any { version -> version == packageVersion }
|
||||
} ?: true
|
||||
packages.singleOrNull { (name, _) -> name == packageName }?.let { (_, versions) ->
|
||||
if (versions?.isEmpty() == true) {
|
||||
return@patch logger.warning("\"$patchName\" incompatible with \"$packageName\"")
|
||||
}
|
||||
|
||||
val matchesVersion = force ||
|
||||
versions?.let { it.any { version -> version == packageVersion } }
|
||||
?: true
|
||||
|
||||
if (!matchesVersion) {
|
||||
return@patch logger.warning(
|
||||
"$patchName is incompatible with version $packageVersion. " +
|
||||
"This patch is only compatible with version " +
|
||||
packages.joinToString(";") { pkg ->
|
||||
pkg.versions!!.joinToString(", ")
|
||||
"\"$patchName\" incompatible with $packageName $packageVersion " +
|
||||
"but compatible with " +
|
||||
packages.joinToString("; ") { (packageName, versions) ->
|
||||
packageName + " " + versions!!.joinToString(", ")
|
||||
},
|
||||
)
|
||||
}
|
||||
} ?: return@patch logger.fine(
|
||||
"$patchName is incompatible with $packageName. " +
|
||||
"This patch is only compatible with " +
|
||||
packages.joinToString(", ") { `package` -> `package`.name },
|
||||
"\"$patchName\" incompatible with $packageName. " +
|
||||
"It is only compatible with " +
|
||||
packages.joinToString(", ") { (name, _) -> name },
|
||||
)
|
||||
|
||||
return@let
|
||||
} ?: logger.fine("$patchName has no constraint on packages.")
|
||||
} ?: logger.fine("\"$patchName\" has no package constraints")
|
||||
|
||||
// If the patch is implicitly used, it will be only included if [exclusive] is false.
|
||||
val implicitlyIncluded = !exclusive && patch.use
|
||||
@ -401,11 +403,11 @@ internal object PatchCommand : Runnable {
|
||||
val explicitlyIncluded = includedPatches.contains(patchName) || includedPatchesByIndex.contains(i)
|
||||
|
||||
val included = implicitlyIncluded || explicitlyIncluded
|
||||
if (!included) return@patch logger.info("$patchName excluded") // Case 1.
|
||||
|
||||
logger.fine("Adding $patchName")
|
||||
if (!included) return@patch logger.info("\"$patchName\" excluded") // Case 1.
|
||||
|
||||
add(patch)
|
||||
|
||||
logger.fine("\"$patchName\" added")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package app.revanced.cli.command.utility
|
||||
|
||||
import app.revanced.library.adb.AdbManager
|
||||
import app.revanced.library.installation.installer.*
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import picocli.CommandLine.*
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
@ -32,13 +35,29 @@ internal object InstallCommand : Runnable {
|
||||
private var packageName: String? = null
|
||||
|
||||
override fun run() {
|
||||
fun install(deviceSerial: String? = null) =
|
||||
try {
|
||||
AdbManager.getAdbManager(deviceSerial, packageName != null).install(AdbManager.Apk(apk, packageName))
|
||||
} catch (e: AdbManager.DeviceNotFoundException) {
|
||||
suspend fun install(deviceSerial: String? = null) {
|
||||
val result = try {
|
||||
if (packageName != null) {
|
||||
AdbRootInstaller(deviceSerial)
|
||||
} else {
|
||||
AdbInstaller(deviceSerial)
|
||||
}.install(Installer.Apk(apk, packageName))
|
||||
} catch (e: Exception) {
|
||||
logger.severe(e.toString())
|
||||
}
|
||||
|
||||
deviceSerials?.forEach(::install) ?: install()
|
||||
when (result) {
|
||||
RootInstallerResult.FAILURE ->
|
||||
logger.severe("Failed to mount the APK file")
|
||||
is AdbInstallerResult.Failure ->
|
||||
logger.severe(result.exception.toString())
|
||||
else ->
|
||||
logger.info("Installed the APK file")
|
||||
}
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
deviceSerials?.map { async { install(it) } }?.awaitAll() ?: install()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package app.revanced.cli.command.utility
|
||||
|
||||
import app.revanced.library.adb.AdbManager
|
||||
import app.revanced.library.installation.installer.*
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import picocli.CommandLine.*
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import java.util.logging.Logger
|
||||
@ -33,13 +36,28 @@ internal object UninstallCommand : Runnable {
|
||||
private var unmount: Boolean = false
|
||||
|
||||
override fun run() {
|
||||
fun uninstall(deviceSerial: String? = null) =
|
||||
try {
|
||||
AdbManager.getAdbManager(deviceSerial, unmount).uninstall(packageName)
|
||||
} catch (e: AdbManager.DeviceNotFoundException) {
|
||||
suspend fun uninstall(deviceSerial: String? = null) {
|
||||
val result = try {
|
||||
if (unmount) {
|
||||
AdbRootInstaller(deviceSerial)
|
||||
} else {
|
||||
AdbInstaller(deviceSerial)
|
||||
}.uninstall(packageName)
|
||||
} catch (e: Exception) {
|
||||
logger.severe(e.toString())
|
||||
}
|
||||
|
||||
deviceSerials?.forEach { uninstall(it) } ?: uninstall()
|
||||
when (result) {
|
||||
RootInstallerResult.FAILURE ->
|
||||
logger.severe("Failed to unmount the patched APK file")
|
||||
is AdbInstallerResult.Failure ->
|
||||
logger.severe(result.exception.toString())
|
||||
else -> logger.info("Uninstalled the patched APK file")
|
||||
}
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
deviceSerials?.map { async { uninstall(it) } }?.awaitAll() ?: uninstall()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loadingβ¦
Reference in New Issue
Block a user