mirror of
https://github.com/revanced/revanced-cli.git
synced 2024-12-24 02:55:48 +01:00
feat: --uninstall
switch (#84)
This moves the move unmount script to a command
This commit is contained in:
parent
8e91c12c5e
commit
131100ef00
@ -33,6 +33,20 @@ internal object MainCommand : Runnable {
|
||||
lateinit var args: Args
|
||||
|
||||
class Args {
|
||||
@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 {
|
||||
@Option(names = ["-b", "--bundles"], description = ["One or more bundles of patches"], required = true)
|
||||
var patchBundles = arrayOf<String>()
|
||||
|
||||
@ -58,9 +72,6 @@ internal object MainCommand : Runnable {
|
||||
}
|
||||
|
||||
class PatchingArgs {
|
||||
@Option(names = ["-a", "--apk"], description = ["Input file to be patched"], required = true)
|
||||
lateinit var inputFile: File
|
||||
|
||||
@Option(names = ["-o", "--out"], description = ["Output file path"], required = true)
|
||||
lateinit var outputPath: String
|
||||
|
||||
@ -94,9 +105,6 @@ internal object MainCommand : Runnable {
|
||||
@Option(names = ["-p", "--password"], description = ["Overwrite the default password for the signed file"])
|
||||
var password = "ReVanced"
|
||||
|
||||
@Option(names = ["-d", "--deploy-on"], description = ["If specified, deploy to adb device with given name"])
|
||||
var deploy: String? = null
|
||||
|
||||
@Option(names = ["-t", "--temp-dir"], description = ["Temporal resource cache directory"])
|
||||
var cacheDirectory = "revanced-cache"
|
||||
|
||||
@ -108,16 +116,37 @@ internal object MainCommand : Runnable {
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if (args.lArgs?.listOnly == true) {
|
||||
if (args.sArgs?.lArgs?.listOnly == true) {
|
||||
printListOfPatches()
|
||||
return
|
||||
}
|
||||
|
||||
val args = args.pArgs ?: return
|
||||
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
|
||||
|
||||
val patcher = app.revanced.patcher.Patcher(
|
||||
PatcherOptions(
|
||||
args.inputFile,
|
||||
_args.inputFile,
|
||||
args.cacheDirectory,
|
||||
!args.disableResourcePatching,
|
||||
logger = PatcherLogger
|
||||
@ -126,10 +155,9 @@ internal object MainCommand : Runnable {
|
||||
|
||||
val outputFile = File(args.outputPath)
|
||||
|
||||
val adb: Adb? = args.deploy?.let {
|
||||
Adb(outputFile, patcher.data.packageMetadata.packageName, args.deploy!!, !args.mount)
|
||||
val adb: Adb? = _args.deploy?.let {
|
||||
Adb(outputFile, patcher.data.packageMetadata.packageName, _args.deploy!!, !args.mount)
|
||||
}
|
||||
|
||||
val patchedFile = if (args.mount) outputFile
|
||||
else File(args.cacheDirectory).resolve("${outputFile.nameWithoutExtension}_raw.apk")
|
||||
|
||||
@ -153,17 +181,17 @@ internal object MainCommand : Runnable {
|
||||
|
||||
adb?.deploy()
|
||||
|
||||
if (args.clean && args.deploy != null) Files.delete(outputFile.toPath())
|
||||
if (args.clean && _args.deploy != null) Files.delete(outputFile.toPath())
|
||||
|
||||
logger.info("Finished")
|
||||
}
|
||||
|
||||
private fun printListOfPatches() {
|
||||
for (patchBundlePath in args.patchBundles) for (patch in JarPatchBundle(patchBundlePath).loadPatches()) {
|
||||
for (patchBundlePath in args.sArgs?.patchBundles!!) for (patch in JarPatchBundle(patchBundlePath).loadPatches()) {
|
||||
for (compatiblePackage in patch.compatiblePackages!!) {
|
||||
val packageEntryStr = buildString {
|
||||
// Add package if flag is set
|
||||
if (args.lArgs?.withPackages == true) {
|
||||
if (args.sArgs?.lArgs?.withPackages == true) {
|
||||
val packageName = compatiblePackage.name.substringAfterLast(".").padStart(10)
|
||||
append(packageName)
|
||||
append("\t")
|
||||
@ -172,12 +200,12 @@ internal object MainCommand : Runnable {
|
||||
val patchName = patch.patchName.padStart(25)
|
||||
append(patchName)
|
||||
// Add description if flag is set.
|
||||
if (args.lArgs?.withDescriptions == true) {
|
||||
if (args.sArgs?.lArgs?.withDescriptions == true) {
|
||||
append("\t")
|
||||
append(patch.description)
|
||||
}
|
||||
// Add compatible versions, if flag is set
|
||||
if (args.lArgs?.withVersions == true) {
|
||||
if (args.sArgs?.lArgs?.withVersions == true) {
|
||||
val compatibleVersions = compatiblePackage.versions.joinToString(separator = ", ")
|
||||
append("\t")
|
||||
append(compatibleVersions)
|
||||
|
@ -11,7 +11,8 @@ import java.nio.file.Files
|
||||
|
||||
internal object Patcher {
|
||||
internal fun start(patcher: app.revanced.patcher.Patcher, output: File) {
|
||||
val args = args.pArgs!!
|
||||
val inputFile = args.inputFile
|
||||
val args = args.sArgs?.pArgs!!
|
||||
|
||||
// merge files like necessary integrations
|
||||
patcher.mergeFiles()
|
||||
@ -22,7 +23,7 @@ internal object Patcher {
|
||||
|
||||
// write output file
|
||||
if (output.exists()) Files.delete(output.toPath())
|
||||
args.inputFile.copyTo(output)
|
||||
inputFile.copyTo(output)
|
||||
|
||||
val result = patcher.save()
|
||||
ZipFileSystemUtils(output).use { outputFileSystem ->
|
||||
|
@ -8,7 +8,7 @@ import java.io.File
|
||||
|
||||
object Signing {
|
||||
fun start(inputFile: File, outputFile: File, signingOptions: SigningOptions) {
|
||||
val cacheDirectory = File(args.pArgs!!.cacheDirectory)
|
||||
val cacheDirectory = File(args.sArgs?.pArgs?.cacheDirectory)
|
||||
val alignedOutput = cacheDirectory.resolve("${outputFile.nameWithoutExtension}_aligned.apk")
|
||||
val signedOutput = cacheDirectory.resolve("${outputFile.nameWithoutExtension}_signed.apk")
|
||||
|
||||
|
@ -21,7 +21,7 @@ internal class Adb(
|
||||
?: throw IllegalArgumentException("No such device with name $deviceName")
|
||||
|
||||
if (!modeInstall && device.run("su -h", false) != 0)
|
||||
throw IllegalArgumentException("Root required on $deviceName. Deploying failed")
|
||||
throw IllegalArgumentException("Root required on $deviceName. Task failed")
|
||||
}
|
||||
|
||||
private fun String.replacePlaceholder(with: String? = null): String {
|
||||
@ -39,7 +39,7 @@ internal class Adb(
|
||||
// push patched file
|
||||
device.copy(Constants.PATH_INIT_PUSH, file)
|
||||
|
||||
// create revanced path
|
||||
// create revanced folder path
|
||||
device.run("${Constants.COMMAND_CREATE_DIR} ${Constants.PATH_REVANCED}")
|
||||
|
||||
// prepare mounting the apk
|
||||
@ -53,16 +53,8 @@ internal class Adb(
|
||||
// install mount script
|
||||
device.run(Constants.COMMAND_INSTALL_MOUNT.replacePlaceholder())
|
||||
|
||||
// push umount script
|
||||
device.createFile(
|
||||
Constants.PATH_INIT_PUSH,
|
||||
Constants.CONTENT_UMOUNT_SCRIPT.replacePlaceholder()
|
||||
)
|
||||
// install unmount script
|
||||
device.run(Constants.COMMAND_INSTALL_UMOUNT.replacePlaceholder())
|
||||
|
||||
// unmount the apk for sanity
|
||||
device.run(Constants.PATH_UMOUNT.replacePlaceholder())
|
||||
device.run(Constants.COMMAND_UMOUNT.replacePlaceholder())
|
||||
// mount the apk
|
||||
device.run(Constants.PATH_MOUNT.replacePlaceholder())
|
||||
|
||||
@ -74,6 +66,21 @@ internal class Adb(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun uninstall() {
|
||||
logger.info("Uninstalling by unmounting")
|
||||
|
||||
// unmount the apk
|
||||
device.run(Constants.COMMAND_UMOUNT.replacePlaceholder())
|
||||
|
||||
// delete revanced app
|
||||
device.run(Constants.COMMAND_DELETE.replacePlaceholder(Constants.PATH_REVANCED_APP).replacePlaceholder())
|
||||
|
||||
// delete mount script
|
||||
device.run(Constants.COMMAND_DELETE.replacePlaceholder(Constants.PATH_MOUNT).replacePlaceholder())
|
||||
|
||||
logger.info("Finished uninstalling")
|
||||
}
|
||||
|
||||
private fun log() {
|
||||
val executor = Executors.newSingleThreadExecutor()
|
||||
val pipe = if (logging) {
|
||||
|
@ -21,31 +21,25 @@ internal object Constants {
|
||||
internal const val PATH_REVANCED = "/data/adb/revanced/"
|
||||
|
||||
// revanced apk path
|
||||
private const val PATH_REVANCED_APP = "$PATH_REVANCED$PLACEHOLDER.apk"
|
||||
internal const val PATH_REVANCED_APP = "$PATH_REVANCED$PLACEHOLDER.apk"
|
||||
|
||||
// (un)mount script paths
|
||||
// delete command
|
||||
internal const val COMMAND_DELETE = "rm -rf $PLACEHOLDER"
|
||||
|
||||
// mount script path
|
||||
internal const val PATH_MOUNT = "/data/adb/service.d/$NAME_MOUNT_SCRIPT"
|
||||
internal const val PATH_UMOUNT = "/data/adb/post-fs-data.d/un$NAME_MOUNT_SCRIPT"
|
||||
|
||||
// move to revanced apk path & set permissions
|
||||
internal const val COMMAND_PREPARE_MOUNT_APK =
|
||||
"base_path=\"$PATH_REVANCED_APP\" && mv $PATH_INIT_PUSH ${'$'}base_path && chmod 644 ${'$'}base_path && chown system:system ${'$'}base_path && chcon u:object_r:apk_data_file:s0 ${'$'}base_path"
|
||||
|
||||
// unmount command
|
||||
internal const val COMMAND_UMOUNT =
|
||||
"stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' ) && umount -l ${'$'}stock_path"
|
||||
|
||||
// install mount script & set permissions
|
||||
internal const val COMMAND_INSTALL_MOUNT = "mv $PATH_INIT_PUSH $PATH_MOUNT && $COMMAND_CHMOD_MOUNT $PATH_MOUNT"
|
||||
|
||||
// install umount script & set permissions
|
||||
internal const val COMMAND_INSTALL_UMOUNT = "mv $PATH_INIT_PUSH $PATH_UMOUNT && $COMMAND_CHMOD_MOUNT $PATH_UMOUNT"
|
||||
|
||||
// unmount script
|
||||
internal val CONTENT_UMOUNT_SCRIPT =
|
||||
"""
|
||||
#!/system/bin/sh
|
||||
|
||||
stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
|
||||
umount -l ${'$'}stock_path
|
||||
""".trimIndent()
|
||||
|
||||
// mount script
|
||||
internal val CONTENT_MOUNT_SCRIPT =
|
||||
"""
|
||||
|
@ -15,7 +15,7 @@ fun Patcher.addPatchesFiltered() {
|
||||
val packageName = this.data.packageMetadata.packageName
|
||||
val packageVersion = this.data.packageMetadata.packageVersion
|
||||
|
||||
args.patchBundles.forEach { bundle ->
|
||||
args.sArgs?.patchBundles!!.forEach { bundle ->
|
||||
val includedPatches = mutableListOf<Class<out Patch<Data>>>()
|
||||
JarPatchBundle(bundle).loadPatches().forEach patch@{ patch ->
|
||||
val compatiblePackages = patch.compatiblePackages
|
||||
@ -23,7 +23,7 @@ fun Patcher.addPatchesFiltered() {
|
||||
|
||||
val prefix = "Skipping $patchName"
|
||||
|
||||
val args = MainCommand.args.pArgs!!
|
||||
val args = MainCommand.args.sArgs?.pArgs!!
|
||||
|
||||
if (excludePatches && args.excludedPatches.contains(patchName)) {
|
||||
logger.info("$prefix: Explicitely excluded")
|
||||
@ -72,7 +72,7 @@ fun Patcher.applyPatchesVerbose() {
|
||||
}
|
||||
|
||||
fun Patcher.mergeFiles() {
|
||||
this.addFiles(args.pArgs!!.mergeFiles) { file ->
|
||||
this.addFiles(args.sArgs?.pArgs!!.mergeFiles) { file ->
|
||||
logger.info("Merging $file")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user