feat: load patches dynamically & use kotlinx.cli

Patches are now loaded dynamically and the CLI now links to the patches library. Also decided to use the CLI library from kotlinx, since that's friendlier than whatever we had before.
This commit is contained in:
Lucaskyy
2022-04-10 22:21:57 +02:00
parent e50071aa61
commit 4624384f28
6 changed files with 156 additions and 26 deletions

View File

@@ -1,32 +1,92 @@
package app.revanced.cli
import app.revanced.cli.utils.PatchLoader
import app.revanced.cli.utils.Patches
import app.revanced.cli.utils.Preconditions
import app.revanced.cli.utils.SignatureParser
import app.revanced.patcher.Patcher
import app.revanced.patches.Index.patches
import org.jf.dexlib2.writer.io.MemoryDataStore
import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.cli.required
import java.io.File
import java.nio.file.Files
fun main(args: Array<String>) {
val patcher = Patcher(
File(args[0]), // in.apk
SignatureParser.parse(args[2]).toTypedArray() // signatures.json
)
private const val CLI_NAME = "ReVanced CLI"
private val CLI_VERSION = Main::class.java.`package`.implementationVersion ?: "0.0.0-unknown"
// add integrations dex container
patcher.addFiles(File(args[3]))
class Main {
companion object {
private fun runCLI(
inApk: String,
inSignatures: String,
inPatches: String,
inOutput: String,
) {
val apk = Preconditions.isFile(inApk)
val signatures = Preconditions.isFile(inSignatures)
val patchesFile = Preconditions.isFile(inPatches)
val output = Preconditions.isDirectory(inOutput)
for (patch in patches) {
patcher.addPatches(patch())
}
val patcher = Patcher(
apk,
SignatureParser
.parse(signatures.readText())
.toTypedArray()
)
patcher.applyPatches().forEach { (name, result) ->
println("$name: $result")
}
PatchLoader.injectPatches(patchesFile)
val patches = Patches.loadPatches()
patcher.addPatches(*patches.map { it() }.toTypedArray())
// save patched apk
val dexFiles: Map<String, MemoryDataStore> = patcher.save()
dexFiles.forEach { (t, p) ->
Files.write(File(args[1], t).toPath(), p.buffer)
val results = patcher.applyPatches()
for ((name, result) in results) {
println("$name: $result")
}
val dexFiles = patcher.save()
dexFiles.forEach { (dexName, dexData) ->
Files.write(File(output, dexName).toPath(), dexData.buffer)
}
}
@JvmStatic
fun main(args: Array<String>) {
println("$CLI_NAME version $CLI_VERSION")
val parser = ArgParser(CLI_NAME)
val apk by parser.option(
ArgType.String,
fullName = "apk",
shortName = "a",
description = "APK file"
).required()
val signatures by parser.option(
ArgType.String,
fullName = "signatures",
shortName = "s",
description = "Signatures JSON file"
).required()
val patches by parser.option(
ArgType.String,
fullName = "patches",
shortName = "p",
description = "Patches JAR file"
).required()
val output by parser.option(
ArgType.String,
fullName = "output",
shortName = "o",
description = "Output directory"
).required()
// TODO: merge dex file
parser.parse(args)
runCLI(
apk,
signatures,
patches,
output,
)
}
}
}