diff --git a/docs/1_usage.md b/docs/1_usage.md index 2b81de6..932fdb2 100644 --- a/docs/1_usage.md +++ b/docs/1_usage.md @@ -41,6 +41,14 @@ Learn how to ReVanced CLI. revanced-patches.jar ``` +- ### ⚙️ Supply options to patches using ReVanced CLI + + Some patches provide options. Currently, ReVanced CLI will generate and consume an `options.json` file at the location that is specified in `-o`. If the option is not specified, the options file will be generated in the current working directory. + + The options file contains all options from supplied patch bundles. + + > **Note**: The `options.json` file will be generated at the first time you use ReVanced CLI to patch an APK file for now. This will be changed in the future. + - ### 💉 Use ReVanced CLI to patch an APK file but deploy without root permissions This will deploy the patched APK file on your device by installing it. @@ -50,7 +58,7 @@ Learn how to ReVanced CLI. -a input.apk \ -o patched-output.apk \ -b revanced-patches.jar \ - -d device-name + -d device-serial ``` - ### 👾 Use ReVanced CLI to patch an APK file but deploy with root permissions @@ -64,16 +72,17 @@ Learn how to ReVanced CLI. -o patched-output.apk \ -b revanced-patches.jar \ -e vanced-microg-support \ - -d device-name \ + -d device-serial \ --mount ``` > **Note**: Some patches from [ReVanced Patches](https://github.com/revanced/revanced-patches) also require [ReVanced Integrations](https://github.com/revanced/revanced-integrations). Supply them with the option `-m`. ReVanced Patcher will merge ReVanced Integrations automatically, depending on if the supplied patches require them. + package -- ### ⚙️ Supply options to patches using ReVanced CLI - - Some patches provide options. Currently, ReVanced CLI will generate and consume an `options.json` file at the location that is specified in `-o`. If the option is not specified, the options file will be generated in the current working directory. - - The options file contains all options from supplied patch bundles. - - > **Note**: The `options.json` file will be generated at the first time you use ReVanced CLI to patch an APK file for now. This will be changed in the future. +- ### 🗑️ Uninstall a patched + ```bash + java -jar revanced-cli.jar \ + uninstall \ + -p package-name \ + device-serial + ``` diff --git a/src/main/kotlin/app/revanced/cli/command/MainCommand.kt b/src/main/kotlin/app/revanced/cli/command/MainCommand.kt index 8394a7b..58774c5 100644 --- a/src/main/kotlin/app/revanced/cli/command/MainCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/MainCommand.kt @@ -37,10 +37,10 @@ private class CLIVersionProvider : IVersionProvider { description = ["Command line application to use ReVanced"], mixinStandardHelpOptions = true, versionProvider = CLIVersionProvider::class, - subcommands = [ListPatchesCommand::class] + subcommands = [ListPatchesCommand::class, UninstallCommand::class] ) internal object MainCommand : Runnable { - val logger = DefaultCliLogger() + internal val logger = DefaultCliLogger() // @ArgGroup(exclusive = false, multiplicity = "1") lateinit var args: Args @@ -145,11 +145,12 @@ internal object MainCommand : Runnable { } } + fun main(args: Array) { + CommandLine(MainCommand).execute(*args) + } + override fun run() { val patchArgs = args.patchArgs - - if (args.packageName != null) return uninstall() - val patchingArgs = patchArgs?.patchingArgs ?: return if (!patchingArgs.inputFile.exists()) return logger.error("Input file ${patchingArgs.inputFile} does not exist.") @@ -241,18 +242,6 @@ internal object MainCommand : Runnable { logger.info(result) } - /** - * Uninstall the specified package from the specified device. - * - */ - private fun uninstall() = args.deviceSerial?.let { serial -> - if (args.mount) { - AdbManager.RootAdbManager(serial, logger) - } else { - AdbManager.UserAdbManager(serial, logger) - }.uninstall(args.packageName!!) - } ?: logger.error("No device serial specified") - private fun Patcher.filterPatchSelection(patches: PatchList) = buildList { val packageName = context.packageMetadata.packageName val packageVersion = context.packageMetadata.packageVersion @@ -326,8 +315,4 @@ internal object MainCommand : Runnable { add(patch) } } - - fun main(args: Array) { - CommandLine(MainCommand).execute(*args) - } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt b/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt new file mode 100644 index 0000000..070adb7 --- /dev/null +++ b/src/main/kotlin/app/revanced/cli/command/UninstallCommand.kt @@ -0,0 +1,44 @@ +package app.revanced.cli.command + +import app.revanced.utils.adb.AdbManager +import picocli.CommandLine +import picocli.CommandLine.Help.Visibility.ALWAYS + + +@CommandLine.Command( + name = "uninstall", + description = ["Uninstall a patched package from the devices with the supplied ADB device serials"] +) +class UninstallCommand : Runnable { + @CommandLine.Parameters( + description = ["ADB device serials"], + arity = "1..*" + ) + lateinit var deviceSerials: Array + + @CommandLine.Option( + names = ["-p", "--package-name"], + description = ["Package name to uninstall"], + required = true + ) + lateinit var packageName: String + + @CommandLine.Option( + names = ["-u", "--unmount"], + description = ["Uninstall by unmounting the patched package"], + showDefaultValue = ALWAYS + ) + var unmount: Boolean = false + + override fun run() = try { + deviceSerials.forEach {deviceSerial -> + if (unmount) { + AdbManager.RootAdbManager(deviceSerial, MainCommand.logger) + } else { + AdbManager.UserAdbManager(deviceSerial, MainCommand.logger) + }.uninstall(packageName) + } + } catch (e: AdbManager.DeviceNotFoundException) { + MainCommand.logger.error(e.toString()) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt b/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt index 1bbc28d..2044f51 100644 --- a/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt +++ b/src/main/kotlin/app/revanced/utils/adb/AdbManager.kt @@ -27,7 +27,7 @@ import java.io.File */ internal sealed class AdbManager(deviceSerial: String? = null, protected val logger: CliLogger? = null) : Closeable { protected val device = JadbConnection().devices.find { device -> device.serial == deviceSerial } - ?: throw IllegalArgumentException("The device with the serial $deviceSerial can not be found.") + ?: throw DeviceNotFoundException(deviceSerial) init { logger?.trace("Established connection to $deviceSerial") @@ -127,4 +127,9 @@ internal sealed class AdbManager(deviceSerial: String? = null, protected val log * @param file The [Apk] file. */ internal class Apk(val file: File, val packageName: String? = null) + + internal class DeviceNotFoundException(deviceSerial: String?) : + Exception(deviceSerial?.let { + "The device with the ADB device serial \"$deviceSerial\" can not be found" + } ?: "No ADB device found") } \ No newline at end of file