2022-06-11 06:40:59 +02:00
|
|
|
package app.revanced.cli.command
|
|
|
|
|
2022-07-21 16:26:23 +02:00
|
|
|
import app.revanced.cli.aligning.Aligning
|
2022-06-23 02:10:11 +02:00
|
|
|
import app.revanced.cli.logging.impl.DefaultCliLogger
|
2022-06-11 06:40:59 +02:00
|
|
|
import app.revanced.cli.patcher.Patcher
|
2022-06-23 02:10:11 +02:00
|
|
|
import app.revanced.cli.patcher.logging.impl.PatcherLogger
|
2022-06-11 06:40:59 +02:00
|
|
|
import app.revanced.cli.signing.Signing
|
2022-06-22 14:58:12 +02:00
|
|
|
import app.revanced.cli.signing.SigningOptions
|
2022-06-11 06:40:59 +02:00
|
|
|
import app.revanced.patcher.PatcherOptions
|
2022-07-03 15:57:25 +02:00
|
|
|
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
2022-06-21 23:54:34 +02:00
|
|
|
import app.revanced.patcher.extensions.PatchExtensions.description
|
2022-06-22 12:23:14 +02:00
|
|
|
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
2022-06-11 06:40:59 +02:00
|
|
|
import app.revanced.patcher.util.patch.implementation.JarPatchBundle
|
|
|
|
import app.revanced.utils.adb.Adb
|
2022-06-21 01:02:41 +02:00
|
|
|
import picocli.CommandLine.*
|
2022-06-11 06:40:59 +02:00
|
|
|
import java.io.File
|
|
|
|
import java.nio.file.Files
|
|
|
|
|
2022-06-22 16:51:29 +02:00
|
|
|
private class CLIVersionProvider : IVersionProvider {
|
|
|
|
override fun getVersion() = arrayOf(
|
|
|
|
MainCommand::class.java.`package`.implementationVersion ?: "unknown"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-06-11 06:40:59 +02:00
|
|
|
@Command(
|
2022-06-22 16:51:29 +02:00
|
|
|
name = "ReVanced-CLI",
|
|
|
|
mixinStandardHelpOptions = true,
|
|
|
|
versionProvider = CLIVersionProvider::class
|
2022-06-11 06:40:59 +02:00
|
|
|
)
|
|
|
|
internal object MainCommand : Runnable {
|
2022-06-23 02:10:11 +02:00
|
|
|
val logger = DefaultCliLogger()
|
|
|
|
|
2022-06-21 01:02:41 +02:00
|
|
|
@ArgGroup(exclusive = false, multiplicity = "1")
|
|
|
|
lateinit var args: Args
|
|
|
|
|
|
|
|
class Args {
|
2022-07-10 12:17:47 +02:00
|
|
|
@Option(names = ["-a", "--apk"], description = ["Input file to be patched"], required = true)
|
|
|
|
lateinit var inputFile: File
|
|
|
|
|
|
|
|
@Option(names = ["--uninstall"], description = ["Uninstall the mount variant"])
|
|
|
|
var uninstall: Boolean = false
|
|
|
|
|
|
|
|
@Option(names = ["-d", "--deploy-on"], description = ["If specified, deploy to adb device with given name"])
|
|
|
|
var deploy: String? = null
|
|
|
|
|
|
|
|
@ArgGroup(exclusive = false)
|
|
|
|
var sArgs: StartPatcherArgs? = null
|
|
|
|
}
|
|
|
|
|
|
|
|
class StartPatcherArgs {
|
2022-06-21 01:02:41 +02:00
|
|
|
@Option(names = ["-b", "--bundles"], description = ["One or more bundles of patches"], required = true)
|
|
|
|
var patchBundles = arrayOf<String>()
|
|
|
|
|
|
|
|
@ArgGroup(exclusive = false)
|
2022-06-21 17:35:59 +02:00
|
|
|
var lArgs: ListingArgs? = null
|
2022-06-21 01:02:41 +02:00
|
|
|
|
|
|
|
@ArgGroup(exclusive = false)
|
2022-06-21 17:35:59 +02:00
|
|
|
var pArgs: PatchingArgs? = null
|
2022-06-21 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class ListingArgs {
|
|
|
|
@Option(names = ["-l", "--list"], description = ["List patches only"], required = true)
|
|
|
|
var listOnly: Boolean = false
|
2022-07-03 15:57:25 +02:00
|
|
|
|
|
|
|
@Option(names = ["--with-versions"], description = ["List patches with compatible versions"])
|
|
|
|
var withVersions: Boolean = false
|
|
|
|
|
|
|
|
@Option(names = ["--with-packages"], description = ["List patches with compatible packages"])
|
|
|
|
var withPackages: Boolean = false
|
|
|
|
|
|
|
|
@Option(names = ["--with-descriptions"], description = ["List patches with their descriptions"])
|
|
|
|
var withDescriptions: Boolean = true
|
2022-06-21 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class PatchingArgs {
|
|
|
|
@Option(names = ["-o", "--out"], description = ["Output file path"], required = true)
|
|
|
|
lateinit var outputPath: String
|
|
|
|
|
2022-06-21 18:30:10 +02:00
|
|
|
@Option(names = ["-e", "--exclude"], description = ["Explicitly exclude patches"])
|
|
|
|
var excludedPatches = arrayOf<String>()
|
2022-06-21 01:02:41 +02:00
|
|
|
|
2022-07-10 20:04:47 +02:00
|
|
|
@Option(names = ["--exclusive"], description = ["Only installs the patches you include, not including any patch by default"])
|
2022-07-10 12:15:28 +02:00
|
|
|
var defaultExclude = false
|
|
|
|
|
2022-07-03 15:49:25 +02:00
|
|
|
@Option(names = ["-i", "--include"], description = ["Include patches"])
|
|
|
|
var includedPatches = arrayOf<String>()
|
|
|
|
|
2022-06-21 01:02:41 +02:00
|
|
|
@Option(names = ["-r", "--resource-patcher"], description = ["Disable patching resources"])
|
|
|
|
var disableResourcePatching: Boolean = false
|
|
|
|
|
2022-06-21 19:04:32 +02:00
|
|
|
@Option(names = ["--experimental"], description = ["Disable patch version compatibility patch"])
|
2022-06-21 18:40:34 +02:00
|
|
|
var experimental: Boolean = false
|
2022-06-21 01:02:41 +02:00
|
|
|
|
|
|
|
@Option(names = ["-m", "--merge"], description = ["One or more dex file containers to merge"])
|
|
|
|
var mergeFiles = listOf<File>()
|
|
|
|
|
2022-06-21 18:30:10 +02:00
|
|
|
@Option(names = ["--mount"], description = ["If specified, instead of installing, mount"])
|
|
|
|
var mount: Boolean = false
|
2022-06-21 01:02:41 +02:00
|
|
|
|
|
|
|
@Option(names = ["--cn"], description = ["Overwrite the default CN for the signed file"])
|
|
|
|
var cn = "ReVanced"
|
|
|
|
|
2022-06-22 14:58:12 +02:00
|
|
|
@Option(names = ["--keystore"], description = ["File path to your keystore"])
|
|
|
|
var keystorePath: String? = null
|
|
|
|
|
2022-06-21 01:02:41 +02:00
|
|
|
@Option(names = ["-p", "--password"], description = ["Overwrite the default password for the signed file"])
|
|
|
|
var password = "ReVanced"
|
|
|
|
|
|
|
|
@Option(names = ["-t", "--temp-dir"], description = ["Temporal resource cache directory"])
|
|
|
|
var cacheDirectory = "revanced-cache"
|
|
|
|
|
|
|
|
@Option(
|
|
|
|
names = ["-c", "--clean"],
|
|
|
|
description = ["Clean the temporal resource cache directory. This will be done anyways when running the patcher"]
|
|
|
|
)
|
|
|
|
var clean: Boolean = false
|
2022-07-21 14:11:26 +02:00
|
|
|
|
|
|
|
@Option(names = ["--custom-aapt2-binary"], description = ["Path to custom aapt2 binary"])
|
|
|
|
var aaptPath: String = ""
|
2022-06-21 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun run() {
|
2022-07-10 12:17:47 +02:00
|
|
|
if (args.sArgs?.lArgs?.listOnly == true) {
|
2022-07-03 15:57:25 +02:00
|
|
|
printListOfPatches()
|
2022-06-21 17:35:59 +02:00
|
|
|
return
|
2022-06-21 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2022-07-10 12:17:47 +02:00
|
|
|
if (args.uninstall) {
|
|
|
|
// temporarily get package name using Patcher method
|
|
|
|
// fix: abstract options in patcher
|
|
|
|
val patcher = app.revanced.patcher.Patcher(
|
|
|
|
PatcherOptions(
|
|
|
|
args.inputFile,
|
|
|
|
"uninstaller-cache",
|
|
|
|
false
|
|
|
|
)
|
|
|
|
)
|
|
|
|
File("uninstaller-cache").deleteRecursively()
|
|
|
|
|
|
|
|
val adb: Adb? = args.deploy?.let {
|
|
|
|
Adb(File("placeholder_file"), patcher.data.packageMetadata.packageName, args.deploy!!, false)
|
|
|
|
}
|
|
|
|
adb?.uninstall()
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
val _args = args
|
|
|
|
val args = args.sArgs?.pArgs ?: return
|
2022-06-21 01:02:41 +02:00
|
|
|
|
|
|
|
val patcher = app.revanced.patcher.Patcher(
|
|
|
|
PatcherOptions(
|
2022-07-10 12:17:47 +02:00
|
|
|
_args.inputFile,
|
2022-06-22 16:25:04 +02:00
|
|
|
args.cacheDirectory,
|
|
|
|
!args.disableResourcePatching,
|
2022-07-21 14:11:26 +02:00
|
|
|
args.aaptPath,
|
2022-06-22 16:25:04 +02:00
|
|
|
logger = PatcherLogger
|
2022-06-21 01:02:41 +02:00
|
|
|
)
|
|
|
|
)
|
2022-06-21 00:53:36 +02:00
|
|
|
|
|
|
|
val outputFile = File(args.outputPath)
|
|
|
|
|
2022-07-10 12:17:47 +02:00
|
|
|
val adb: Adb? = _args.deploy?.let {
|
|
|
|
Adb(outputFile, patcher.data.packageMetadata.packageName, _args.deploy!!, !args.mount)
|
2022-06-11 06:40:59 +02:00
|
|
|
}
|
2022-07-21 16:26:23 +02:00
|
|
|
val patchedFile = File(args.cacheDirectory).resolve("${outputFile.nameWithoutExtension}_raw.apk")
|
2022-06-11 06:40:59 +02:00
|
|
|
|
|
|
|
Patcher.start(patcher, patchedFile)
|
|
|
|
|
2022-06-21 22:19:12 +02:00
|
|
|
if (!args.mount) {
|
2022-06-11 06:40:59 +02:00
|
|
|
Signing.start(
|
2022-06-22 14:36:38 +02:00
|
|
|
patchedFile,
|
|
|
|
outputFile,
|
2022-06-22 14:58:12 +02:00
|
|
|
SigningOptions(
|
|
|
|
args.cn,
|
|
|
|
args.password,
|
2022-06-22 15:57:15 +02:00
|
|
|
args.keystorePath ?: outputFile.absoluteFile.parentFile
|
2022-06-22 14:58:12 +02:00
|
|
|
.resolve("${outputFile.nameWithoutExtension}.keystore")
|
2022-06-28 00:44:12 +02:00
|
|
|
.canonicalPath
|
2022-06-22 14:58:12 +02:00
|
|
|
)
|
2022-06-11 06:40:59 +02:00
|
|
|
)
|
|
|
|
}
|
2022-07-21 16:26:23 +02:00
|
|
|
else {
|
|
|
|
Aligning.align(patchedFile, outputFile)
|
|
|
|
}
|
2022-06-11 06:40:59 +02:00
|
|
|
|
2022-06-21 00:53:36 +02:00
|
|
|
if (args.clean) File(args.cacheDirectory).deleteRecursively()
|
2022-06-11 06:40:59 +02:00
|
|
|
|
2022-06-23 02:10:11 +02:00
|
|
|
adb?.deploy()
|
2022-06-11 06:40:59 +02:00
|
|
|
|
2022-07-10 12:17:47 +02:00
|
|
|
if (args.clean && _args.deploy != null) Files.delete(outputFile.toPath())
|
2022-06-11 06:40:59 +02:00
|
|
|
|
2022-06-23 02:10:11 +02:00
|
|
|
logger.info("Finished")
|
2022-06-11 06:40:59 +02:00
|
|
|
}
|
2022-07-03 15:57:25 +02:00
|
|
|
|
|
|
|
private fun printListOfPatches() {
|
2022-07-10 12:17:47 +02:00
|
|
|
for (patchBundlePath in args.sArgs?.patchBundles!!) for (patch in JarPatchBundle(patchBundlePath).loadPatches()) {
|
2022-07-03 15:57:25 +02:00
|
|
|
for (compatiblePackage in patch.compatiblePackages!!) {
|
|
|
|
val packageEntryStr = buildString {
|
|
|
|
// Add package if flag is set
|
2022-07-10 12:17:47 +02:00
|
|
|
if (args.sArgs?.lArgs?.withPackages == true) {
|
2022-07-03 15:57:25 +02:00
|
|
|
val packageName = compatiblePackage.name.substringAfterLast(".").padStart(10)
|
|
|
|
append(packageName)
|
|
|
|
append("\t")
|
|
|
|
}
|
|
|
|
// Add patch name
|
|
|
|
val patchName = patch.patchName.padStart(25)
|
|
|
|
append(patchName)
|
|
|
|
// Add description if flag is set.
|
2022-07-10 12:17:47 +02:00
|
|
|
if (args.sArgs?.lArgs?.withDescriptions == true) {
|
2022-07-03 15:57:25 +02:00
|
|
|
append("\t")
|
|
|
|
append(patch.description)
|
|
|
|
}
|
|
|
|
// Add compatible versions, if flag is set
|
2022-07-10 12:17:47 +02:00
|
|
|
if (args.sArgs?.lArgs?.withVersions == true) {
|
2022-07-03 15:57:25 +02:00
|
|
|
val compatibleVersions = compatiblePackage.versions.joinToString(separator = ", ")
|
|
|
|
append("\t")
|
|
|
|
append(compatibleVersions)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
logger.info(packageEntryStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-11 06:40:59 +02:00
|
|
|
}
|