build: Bump ReVanced Patcher (#335)

This commit is contained in:
oSumAtrIX 2024-08-13 00:05:47 +04:00 committed by GitHub
parent 0a2e99c1c0
commit 54ae01cd76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 210 additions and 196 deletions

2
.gitignore vendored
View File

@ -121,5 +121,5 @@ node_modules/
revanced-cache/ revanced-cache/
options.toml options.toml
# Generated by an Android project (such as ReVanced Integrations) # Generated by Android projects
local.properties local.properties

View File

@ -1,129 +1,100 @@
# πŸ› οΈ Using ReVanced CLI # πŸ› οΈ Using ReVanced CLI
Learn how to use 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 ```bash
java -jar revanced-cli.jar -h 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 ```bash
java -jar revanced-cli.jar list-patches \ java -jar revanced-cli.jar patch -b revanced-patches.rvp input.apk
--with-packages \ ```
--with-versions \
--with-options \
revanced-patches.jar [<patch-bundle> ...]
```
- ### βš™οΈ 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. ```bash
The file can be supplied to ReVanced CLI later on. java -jar revanced-cli.jar patch -b revanced-patches.rvp -b another-patches.rvp input.apk
```
```bash To manually include or exclude patches, use the options `-i` and `-e`.
java -jar revanced-cli.jar options \ Keep in mind the name of the patch must be an exact match.
--path options.json \ You can also use the options `--ii` and `--ie` to include or exclude patches by their index
--overwrite \ if two patches have the same name.
revanced-patches.jar [<patch-bundle> ...] To know the indices of patches, use the option `--with-indices` when listing patches:
```
> **ℹ️ Note** ```bash
> A default `options.json` file will be automatically created if it does not exist java -jar revanced-cli.jar list-patches --with-indices revanced-patches.rvp
> without any need for intervention when using the `patch` command. ```
- ### πŸ’‰ 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. ```bash
After patching, ReVanced CLI can install the patched app on your device using two methods: java -jar revanced-cli.jar patch -b revanced-patches.rvp --ii 123 --ie 456 input.apk
```
> **πŸ’‘ Tip** > [!TIP]
> For ReVanced CLI to be able to install the patched app on your device, make sure ADB is working: > You can use the option `-d` to automatically install the patched app after patching.
> > Make sure ADB is working:
> ```bash >
> adb shell exit > ```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
> ```
> **⚠️ 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 ## πŸ“¦ Install an app manually
java -jar revanced-cli.jar patch \
--patch-bundle revanced-patches.jar \
-d \
input.apk
```
- #### πŸ‘Ύ 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** > [!TIP]
> Ensure that the same app you are patching and mounting over is installed on your device: > 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 install app.apk > ```bash
> ``` > adb shell su -c exit
> adb install input.apk
> ```
```bash ## πŸ—‘οΈ Uninstall an app manually
java -jar revanced-cli.jar patch \
--patch-bundle revanced-patches.jar \
--include "Some patch" \
--ii 123 \
--exclude "Some other patch" \
-d \
--mount \
app.apk
```
> **πŸ’‘ Tip** Here `<package-name>` is the package name of the app you want to uninstall:
> 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.
- ### πŸ—‘οΈ Uninstall an app ```bash
java -jar revanced-cli.jar utility uninstall --package-name <package-name>
```
```bash If the app is mounted, you need to unmount it by using the option `--unmount`:
java -jar revanced-cli.jar utility uninstall \
--package-name <package-name> \
[<device-serial>]
```
> **πŸ’‘ Tip** ```bash
> You can unmount an APK file java -jar revanced-cli.jar utility uninstall --package-name <package-name> --unmount
> by adding the option `--unmount`. ```
- ### ️ πŸ“¦ Install an app > [!TIP]
> By default, the app is installed or uninstalled to the first connected device.
```bash > You can append one or more devices by their serial to install or uninstall an app on your selected choice of devices:
java -jar revanced-cli.jar utility install \ >
-a input.apk \ > ```bash
[<device-serial>] > java -jar revanced-cli.jar utility uninstall --package-name <package-name> [<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`.

View File

@ -1,17 +1,17 @@
[versions] [versions]
shadow = "8.1.1" shadow = "8.1.1"
kotlin = "2.0.0" kotlin = "2.0.0"
kotlinx-coroutines-core = "1.8.0" kotlinx = "1.8.1"
picocli = "4.7.5" picocli = "4.7.6"
revanced-patcher = "19.3.1" revanced-patcher = "20.0.0"
revanced-library = "2.3.0" revanced-library = "3.0.0"
[libraries] [libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } 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" } picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" } 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] [plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -3,7 +3,7 @@ package app.revanced.cli.command
import app.revanced.library.PackageName import app.revanced.library.PackageName
import app.revanced.library.PatchUtils import app.revanced.library.PatchUtils
import app.revanced.library.VersionMap import app.revanced.library.VersionMap
import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.patch.loadPatchesFromJar
import picocli.CommandLine import picocli.CommandLine
import java.io.File import java.io.File
import java.util.logging.Logger import java.util.logging.Logger
@ -12,7 +12,7 @@ import java.util.logging.Logger
name = "list-versions", name = "list-versions",
description = [ description = [
"List the most common compatible versions of apps that are compatible " + "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 { internal class ListCompatibleVersions : Runnable {
@ -22,7 +22,7 @@ internal class ListCompatibleVersions : Runnable {
description = ["Paths to patch bundles."], description = ["Paths to patch bundles."],
arity = "1..*", arity = "1..*",
) )
private lateinit var patchBundles: Array<File> private lateinit var patchBundles: Set<File>
@CommandLine.Option( @CommandLine.Option(
names = ["-f", "--filter-package-names"], names = ["-f", "--filter-package-names"],
@ -38,8 +38,6 @@ internal class ListCompatibleVersions : Runnable {
private var countUnusedPatches: Boolean = false private var countUnusedPatches: Boolean = false
override fun run() { override fun run() {
val patches = PatchBundleLoader.Jar(*patchBundles)
fun VersionMap.buildVersionsString(): String { fun VersionMap.buildVersionsString(): String {
if (isEmpty()) return "Any" if (isEmpty()) return "Any"
@ -58,6 +56,8 @@ internal class ListCompatibleVersions : Runnable {
appendLine(versions.buildVersionsString().prependIndent("\t")) appendLine(versions.buildVersionsString().prependIndent("\t"))
} }
val patches = loadPatchesFromJar(patchBundles)
PatchUtils.getMostCommonCompatibleVersions( PatchUtils.getMostCommonCompatibleVersions(
patches, patches,
packageNames, packageNames,

View File

@ -1,12 +1,13 @@
package app.revanced.cli.command 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.Patch
import app.revanced.patcher.patch.options.PatchOption import app.revanced.patcher.patch.loadPatchesFromJar
import picocli.CommandLine.* import picocli.CommandLine.*
import picocli.CommandLine.Help.Visibility.ALWAYS import picocli.CommandLine.Help.Visibility.ALWAYS
import java.io.File import java.io.File
import java.util.logging.Logger import java.util.logging.Logger
import app.revanced.patcher.patch.Option as PatchOption
@Command( @Command(
name = "list-patches", name = "list-patches",
@ -19,7 +20,7 @@ internal object ListPatchesCommand : Runnable {
description = ["Paths to patch bundles."], description = ["Paths to patch bundles."],
arity = "1..*", arity = "1..*",
) )
private lateinit var patchBundles: Array<File> private lateinit var patchBundles: Set<File>
@Option( @Option(
names = ["-d", "--with-descriptions"], names = ["-d", "--with-descriptions"],
@ -70,16 +71,19 @@ internal object ListPatchesCommand : Runnable {
private var packageName: String? = null private var packageName: String? = null
override fun run() { override fun run() {
fun Patch.CompatiblePackage.buildString() = fun Package.buildString(): String {
buildString { val (name, versions) = this
return buildString {
if (withVersions && versions != null) { if (withVersions && versions != null) {
appendLine("Package name: $name") appendLine("Package name: $name")
appendLine("Compatible versions:") appendLine("Compatible versions:")
append(versions!!.joinToString("\n") { version -> version }.prependIndent("\t")) append(versions.joinToString("\n") { version -> version }.prependIndent("\t"))
} else { } else {
append("Package name: $name") append("Package name: $name")
} }
} }
}
fun PatchOption<*>.buildString() = fun PatchOption<*>.buildString() =
buildString { buildString {
@ -126,10 +130,10 @@ internal object ListPatchesCommand : Runnable {
} }
fun Patch<*>.filterCompatiblePackages(name: String) = fun Patch<*>.filterCompatiblePackages(name: String) =
compatiblePackages?.any { it.name == name } compatiblePackages?.any { (compatiblePackageName, _) -> compatiblePackageName == name }
?: withUniversalPatches ?: withUniversalPatches
val patches = PatchBundleLoader.Jar(*patchBundles).withIndex().toList() val patches = loadPatchesFromJar(patchBundles).withIndex().toList()
val filtered = val filtered =
packageName?.let { patches.filter { (_, patch) -> patch.filterCompatiblePackages(it) } } ?: patches packageName?.let { patches.filter { (_, patch) -> patch.filterCompatiblePackages(it) } } ?: patches

View File

@ -2,7 +2,7 @@ package app.revanced.cli.command
import app.revanced.library.Options import app.revanced.library.Options
import app.revanced.library.Options.setOptions import app.revanced.library.Options.setOptions
import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.patch.loadPatchesFromJar
import picocli.CommandLine import picocli.CommandLine
import picocli.CommandLine.Help.Visibility.ALWAYS import picocli.CommandLine.Help.Visibility.ALWAYS
import java.io.File import java.io.File
@ -19,7 +19,7 @@ internal object OptionsCommand : Runnable {
description = ["Paths to patch bundles."], description = ["Paths to patch bundles."],
arity = "1..*", arity = "1..*",
) )
private lateinit var patchBundles: Array<File> private lateinit var patchBundles: Set<File>
@CommandLine.Option( @CommandLine.Option(
names = ["-p", "--path"], names = ["-p", "--path"],
@ -44,7 +44,7 @@ internal object OptionsCommand : Runnable {
override fun run() = override fun run() =
try { try {
PatchBundleLoader.Jar(*patchBundles).let { patches -> loadPatchesFromJar(patchBundles).let { patches ->
val exists = filePath.exists() val exists = filePath.exists()
if (!exists || overwrite) { if (!exists || overwrite) {
if (exists && update) patches.setOptions(filePath) if (exists && update) patches.setOptions(filePath)

View File

@ -4,11 +4,11 @@ import app.revanced.library.ApkUtils
import app.revanced.library.ApkUtils.applyTo import app.revanced.library.ApkUtils.applyTo
import app.revanced.library.Options import app.revanced.library.Options
import app.revanced.library.Options.setOptions import app.revanced.library.Options.setOptions
import app.revanced.library.adb.AdbManager import app.revanced.library.installation.installer.*
import app.revanced.patcher.PatchBundleLoader
import app.revanced.patcher.PatchSet
import app.revanced.patcher.Patcher import app.revanced.patcher.Patcher
import app.revanced.patcher.PatcherConfig import app.revanced.patcher.PatcherConfig
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.loadPatchesFromJar
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import picocli.CommandLine import picocli.CommandLine
import picocli.CommandLine.Help.Visibility.ALWAYS import picocli.CommandLine.Help.Visibility.ALWAYS
@ -31,8 +31,6 @@ internal object PatchCommand : Runnable {
private lateinit var apk: File private lateinit var apk: File
private var integrations = setOf<File>()
private var patchBundles = emptySet<File>() private var patchBundles = emptySet<File>()
@CommandLine.Option( @CommandLine.Option(
@ -121,16 +119,6 @@ internal object PatchCommand : Runnable {
) )
private var keyStorePassword: String? = null // Empty password by default 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( @CommandLine.Option(
names = ["--keystore-entry-alias"], names = ["--keystore-entry-alias"],
description = ["The alias of the keystore entry to sign the patched APK file with."], 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."], description = ["One or more DEX files or containers to merge into the APK."],
) )
@Suppress("unused") @Suppress("unused")
private fun setIntegrations(integrations: Array<File>) { private fun setIntegrations(integrations: Set<File>) {
integrations.firstOrNull { !it.exists() }?.let { logger.warning("The --merge option is not used anymore.")
throw CommandLine.ParameterException(spec.commandLine(), "Integrations file ${it.path} does not exist.")
}
this.integrations += integrations
} }
@CommandLine.Option( @CommandLine.Option(
@ -256,7 +241,7 @@ internal object PatchCommand : Runnable {
logger.info("Loading patches") 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. // Warn if a patch can not be found in the supplied patch bundles.
if (warn) { if (warn) {
@ -271,6 +256,7 @@ internal object PatchCommand : Runnable {
} }
// endregion // endregion
val patcherTemporaryFilesPath = temporaryFilesPath.resolve("patcher") val patcherTemporaryFilesPath = temporaryFilesPath.resolve("patcher")
val (packageName, patcherResult) = Patcher( val (packageName, patcherResult) = Patcher(
PatcherConfig( PatcherConfig(
@ -292,28 +278,27 @@ internal object PatchCommand : Runnable {
} }
} }
// region Patch patcher += filteredPatches
patcher.context.packageMetadata.packageName to patcher.apply { // Execute patches.
acceptIntegrations(integrations) runBlocking {
acceptPatches(filteredPatches) patcher().collect { patchResult ->
val exception = patchResult.exception
?: return@collect logger.info("\"${patchResult.patch}\" succeeded")
// Execute patches. StringWriter().use { writer ->
runBlocking { exception.printStackTrace(PrintWriter(writer))
apply(false).collect { patchResult ->
patchResult.exception?.let { logger.severe("\"${patchResult.patch}\" failed:\n$writer")
StringWriter().use { writer ->
it.printStackTrace(PrintWriter(writer))
logger.severe("${patchResult.patch.name} failed:\n$writer")
}
} ?: logger.info("${patchResult.patch.name} succeeded")
} }
} }
}.get() }
// endregion
patcher.context.packageMetadata.packageName to patcher.get()
} }
// region Save // region Save
apk.copyTo(temporaryFilesPath.resolve(apk.name), overwrite = true).apply { apk.copyTo(temporaryFilesPath.resolve(apk.name), overwrite = true).apply {
patcherResult.applyTo(this) patcherResult.applyTo(this)
}.let { patchedApkFile -> }.let { patchedApkFile ->
@ -340,9 +325,23 @@ internal object PatchCommand : Runnable {
// region Install // region Install
deviceSerial?.let { serial -> deviceSerial?.let { it ->
AdbManager.getAdbManager(deviceSerial = serial.ifEmpty { null }, mount) val deviceSerial = it.ifEmpty { null }
}?.install(AdbManager.Apk(outputFilePath, packageName))
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 // endregion
@ -358,7 +357,7 @@ internal object PatchCommand : Runnable {
* @param patches The patches to filter. * @param patches The patches to filter.
* @return The filtered patches. * @return The filtered patches.
*/ */
private fun Patcher.filterPatchSelection(patches: PatchSet): PatchSet = private fun Patcher.filterPatchSelection(patches: Set<Patch<*>>): Set<Patch<*>> =
buildSet { buildSet {
val packageName = context.packageMetadata.packageName val packageName = context.packageMetadata.packageName
val packageVersion = context.packageMetadata.packageVersion val packageVersion = context.packageMetadata.packageVersion
@ -367,33 +366,36 @@ internal object PatchCommand : Runnable {
val patchName = patch.name!! val patchName = patch.name!!
val explicitlyExcluded = excludedPatches.contains(patchName) || excludedPatchesByIndex.contains(i) 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. // Make sure the patch is compatible with the supplied APK files package name and version.
patch.compatiblePackages?.let { packages -> patch.compatiblePackages?.let { packages ->
packages.singleOrNull { it.name == packageName }?.let { `package` -> packages.singleOrNull { (name, _) -> name == packageName }?.let { (_, versions) ->
val matchesVersion = if (versions?.isEmpty() == true) {
force || `package`.versions?.let { return@patch logger.warning("\"$patchName\" incompatible with \"$packageName\"")
it.any { version -> version == packageVersion } }
} ?: true
val matchesVersion = force ||
versions?.let { it.any { version -> version == packageVersion } }
?: true
if (!matchesVersion) { if (!matchesVersion) {
return@patch logger.warning( return@patch logger.warning(
"$patchName is incompatible with version $packageVersion. " + "\"$patchName\" incompatible with $packageName $packageVersion " +
"This patch is only compatible with version " + "but compatible with " +
packages.joinToString(";") { pkg -> packages.joinToString("; ") { (packageName, versions) ->
pkg.versions!!.joinToString(", ") packageName + " " + versions!!.joinToString(", ")
}, },
) )
} }
} ?: return@patch logger.fine( } ?: return@patch logger.fine(
"$patchName is incompatible with $packageName. " + "\"$patchName\" incompatible with $packageName. " +
"This patch is only compatible with " + "It is only compatible with " +
packages.joinToString(", ") { `package` -> `package`.name }, packages.joinToString(", ") { (name, _) -> name },
) )
return@let 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. // If the patch is implicitly used, it will be only included if [exclusive] is false.
val implicitlyIncluded = !exclusive && patch.use val implicitlyIncluded = !exclusive && patch.use
@ -401,11 +403,11 @@ internal object PatchCommand : Runnable {
val explicitlyIncluded = includedPatches.contains(patchName) || includedPatchesByIndex.contains(i) val explicitlyIncluded = includedPatches.contains(patchName) || includedPatchesByIndex.contains(i)
val included = implicitlyIncluded || explicitlyIncluded val included = implicitlyIncluded || explicitlyIncluded
if (!included) return@patch logger.info("$patchName excluded") // Case 1. if (!included) return@patch logger.info("\"$patchName\" excluded") // Case 1.
logger.fine("Adding $patchName")
add(patch) add(patch)
logger.fine("\"$patchName\" added")
} }
} }

View File

@ -1,6 +1,9 @@
package app.revanced.cli.command.utility 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.*
import java.io.File import java.io.File
import java.util.logging.Logger import java.util.logging.Logger
@ -32,13 +35,29 @@ internal object InstallCommand : Runnable {
private var packageName: String? = null private var packageName: String? = null
override fun run() { override fun run() {
fun install(deviceSerial: String? = null) = suspend fun install(deviceSerial: String? = null) {
try { val result = try {
AdbManager.getAdbManager(deviceSerial, packageName != null).install(AdbManager.Apk(apk, packageName)) if (packageName != null) {
} catch (e: AdbManager.DeviceNotFoundException) { AdbRootInstaller(deviceSerial)
} else {
AdbInstaller(deviceSerial)
}.install(Installer.Apk(apk, packageName))
} catch (e: Exception) {
logger.severe(e.toString()) 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()
}
} }
} }

View File

@ -1,6 +1,9 @@
package app.revanced.cli.command.utility 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.*
import picocli.CommandLine.Help.Visibility.ALWAYS import picocli.CommandLine.Help.Visibility.ALWAYS
import java.util.logging.Logger import java.util.logging.Logger
@ -33,13 +36,28 @@ internal object UninstallCommand : Runnable {
private var unmount: Boolean = false private var unmount: Boolean = false
override fun run() { override fun run() {
fun uninstall(deviceSerial: String? = null) = suspend fun uninstall(deviceSerial: String? = null) {
try { val result = try {
AdbManager.getAdbManager(deviceSerial, unmount).uninstall(packageName) if (unmount) {
} catch (e: AdbManager.DeviceNotFoundException) { AdbRootInstaller(deviceSerial)
} else {
AdbInstaller(deviceSerial)
}.uninstall(packageName)
} catch (e: Exception) {
logger.severe(e.toString()) 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()
}
} }
} }