diff --git a/docs/1_usage.md b/docs/1_usage.md index a3226de2..2b81de64 100644 --- a/docs/1_usage.md +++ b/docs/1_usage.md @@ -30,12 +30,15 @@ Learn how to ReVanced CLI. java -jar revanced-cli.jar -h ``` -- ### 📃 List all available patches from supplied patch bundles +- ### 📃 List patches from supplied patch bundles ```bash - java -jar revanced-cli.jar - -b revanced-patches.jar \ - -l # Names of all patches will be in kebab-case + java -jar revanced-cli.jar \ + list-patches \ + --with-packages \ + --with-versions \ + --with-options \ + revanced-patches.jar ``` - ### 💉 Use ReVanced CLI to patch an APK file but deploy without root permissions diff --git a/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt b/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt new file mode 100644 index 00000000..9c42595b --- /dev/null +++ b/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt @@ -0,0 +1,94 @@ +package app.revanced.cli.command + +import app.revanced.patcher.PatchBundleLoader +import app.revanced.patcher.annotation.Package +import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages +import app.revanced.patcher.extensions.PatchExtensions.description +import app.revanced.patcher.extensions.PatchExtensions.options +import app.revanced.patcher.extensions.PatchExtensions.patchName +import app.revanced.patcher.patch.PatchClass +import app.revanced.patcher.patch.PatchOption +import picocli.CommandLine +import picocli.CommandLine.Help.Visibility.ALWAYS +import java.io.File + + +@CommandLine.Command(name = "list-patches", description = ["List patches from supplied patch bundles"]) +class ListPatchesCommand : Runnable { + @CommandLine.Parameters( + description = ["Paths to patch bundles"], + arity = "1..*" + ) + lateinit var patchBundles: Array + + @CommandLine.Option( + names = ["-d", "--with-descriptions"], + description = ["List their descriptions"], + showDefaultValue = ALWAYS + ) + var withDescriptions: Boolean = true + + @CommandLine.Option( + names = ["-p", "--with-packages"], + description = ["List the packages the patches are compatible with"], + showDefaultValue = ALWAYS + ) + var withPackages: Boolean = false + + @CommandLine.Option( + names = ["-v", "--with-versions"], + description = ["List the versions of the packages the patches are compatible with"], + showDefaultValue = ALWAYS + ) + var withVersions: Boolean = false + + @CommandLine.Option( + names = ["-o", "--with-options"], + description = ["List the options of the patches"], + showDefaultValue = ALWAYS + ) + var withOptions: Boolean = false + + override fun run() { + fun Package.buildString() = buildString { + if (withVersions && versions.isNotEmpty()) { + appendLine("Package name: $name") + appendLine("Compatible versions:") + append(versions.joinToString("\n") { version -> version }.prependIndent("\t")) + } else + append("Package name: $name") + } + + fun PatchOption<*>.buildString() = buildString { + appendLine("Title: $title") + appendLine("Description: $description") + + value?.let { + appendLine("Key: $key") + append("Value: $it") + } ?: append("Key: $key") + } + + fun PatchClass.buildString() = buildString { + append("Name: $patchName") + + if (withDescriptions) append("\nDescription: $description") + + if (withOptions && options != null) { + appendLine("\nOptions:") + append( + options!!.joinToString("\n\n") { option -> option.buildString() }.prependIndent("\t") + ) + } + + if (withPackages && compatiblePackages != null) { + appendLine("\nCompatible packages:") + append( + compatiblePackages!!.joinToString("\n") { it.buildString() }.prependIndent("\t") + ) + } + } + + MainCommand.logger.info(PatchBundleLoader.Jar(*patchBundles).joinToString("\n\n") { it.buildString() }) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/cli/command/MainCommand.kt b/src/main/kotlin/app/revanced/cli/command/MainCommand.kt index 5ef13f0c..8394a7ba 100644 --- a/src/main/kotlin/app/revanced/cli/command/MainCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/MainCommand.kt @@ -9,7 +9,6 @@ import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherOptions import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages -import app.revanced.patcher.extensions.PatchExtensions.description import app.revanced.patcher.extensions.PatchExtensions.include import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.patch.PatchClass @@ -17,9 +16,13 @@ import app.revanced.utils.Options import app.revanced.utils.Options.setOptions import app.revanced.utils.adb.AdbManager import kotlinx.coroutines.runBlocking +import picocli.CommandLine import picocli.CommandLine.* import java.io.File +fun main(args: Array) { + CommandLine(MainCommand).execute(*args) +} internal typealias PatchList = List @@ -31,13 +34,15 @@ private class CLIVersionProvider : IVersionProvider { @Command( name = "ReVanced CLI", + description = ["Command line application to use ReVanced"], mixinStandardHelpOptions = true, - versionProvider = CLIVersionProvider::class + versionProvider = CLIVersionProvider::class, + subcommands = [ListPatchesCommand::class] ) internal object MainCommand : Runnable { val logger = DefaultCliLogger() - @ArgGroup(exclusive = false, multiplicity = "1") + // @ArgGroup(exclusive = false, multiplicity = "1") lateinit var args: Args /** @@ -63,9 +68,6 @@ internal object MainCommand : Runnable { @Option(names = ["-b", "--bundle"], description = ["One or more bundles of patches"], required = true) var patchBundles = emptyList() - @ArgGroup(exclusive = false) - var listingArgs: ListingArgs? = null - @ArgGroup(exclusive = false) var patchingArgs: PatchingArgs? = null @@ -140,27 +142,12 @@ internal object MainCommand : Runnable { ) var aaptBinaryPath = File("") } - - /** - * Arguments for printing patches to the console. - */ - class ListingArgs { - @Option(names = ["-l", "--list"], description = ["List patches"], required = true) - var listOnly: Boolean = false - - @Option(names = ["--with-versions"], description = ["List patches and their compatible versions"]) - var withVersions: Boolean = false - - @Option(names = ["--with-packages"], description = ["List patches and their compatible packages"]) - var withPackages: Boolean = false - } } } override fun run() { val patchArgs = args.patchArgs - if (patchArgs?.listingArgs?.listOnly == true) return printListOfPatches() if (args.packageName != null) return uninstall() val patchingArgs = patchArgs?.patchingArgs ?: return @@ -266,41 +253,6 @@ internal object MainCommand : Runnable { }.uninstall(args.packageName!!) } ?: logger.error("No device serial specified") - private fun printListOfPatches() { - val logged = mutableListOf() - for (patch in PatchBundleLoader.Jar(*args.patchArgs!!.patchBundles.toTypedArray())) { - if (patch.patchName in logged) continue - for (compatiblePackage in patch.compatiblePackages ?: continue) { - val packageEntryStr = buildString { - // Add package if flag is set - if (args.patchArgs?.listingArgs?.withPackages == true) { - val packageName = compatiblePackage.name.padStart(25) - append(packageName) - append("\t") - } - - // Add patch name - val patchName = patch.patchName.lowercase().replace(" ", "-").padStart(25) - append(patchName) - - // Add description if flag is set. - append("\t") - append(patch.description) - - // Add compatible versions, if flag is set - if (args.patchArgs?.listingArgs?.withVersions == true) { - val compatibleVersions = compatiblePackage.versions.joinToString(separator = ", ") - append("\t") - append(compatibleVersions) - } - } - - logged.add(patch.patchName) - logger.info(packageEntryStr) - } - } - } - private fun Patcher.filterPatchSelection(patches: PatchList) = buildList { val packageName = context.packageMetadata.packageName val packageVersion = context.packageMetadata.packageVersion @@ -374,4 +326,8 @@ 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/main/Main.kt b/src/main/kotlin/app/revanced/cli/main/Main.kt deleted file mode 100644 index 3fc7b3d0..00000000 --- a/src/main/kotlin/app/revanced/cli/main/Main.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.cli.main - -import app.revanced.cli.command.MainCommand -import picocli.CommandLine - -internal fun main(args: Array) { - CommandLine(MainCommand).execute(*args) -} \ No newline at end of file