mirror of
https://github.com/ReVanced/revanced-cli.git
synced 2026-01-28 13:41:05 +00:00
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:
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user