Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
14 changes: 13 additions & 1 deletion src/main/kotlin/app/morphe/cli/command/CommandUtils.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package app.morphe.cli.command

import picocli.CommandLine
import kotlin.text.iterator
import picocli.CommandLine.Model.CommandSpec
import java.io.File

internal fun checkFileExistsOrIsUrl(files: Set<File>, spec: CommandSpec) : Set<File> {
files.firstOrNull {
!it.exists() && !it.toString().let {
it.startsWith("http://") || it.startsWith("https://")
}
}?.let {
throw CommandLine.ParameterException(spec.commandLine(), "${it.name} can not be found")
}
return files
}

class OptionKeyConverter : CommandLine.ITypeConverter<String> {
override fun convert(value: String): String = value
Expand Down
56 changes: 49 additions & 7 deletions src/main/kotlin/app/morphe/cli/command/ListCompatibleVersions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ import app.morphe.patcher.patch.VersionMap
import app.morphe.patcher.patch.loadPatchesFromJar
import app.morphe.patcher.patch.mostCommonCompatibleVersions
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Help.Visibility.ALWAYS
import picocli.CommandLine.Model.CommandSpec
import picocli.CommandLine.Option
import picocli.CommandLine.Spec
import java.io.File
import java.util.logging.Logger

@CommandLine.Command(
@Command(
name = "list-versions",
description = [
"List the most common compatible versions of apps that are compatible " +
Expand All @@ -18,25 +23,47 @@ import java.util.logging.Logger
internal class ListCompatibleVersions : Runnable {
private val logger = Logger.getLogger(this::class.java.name)

@CommandLine.Parameters(
description = ["Paths to MPP files."],
@Option(
names = ["--patches"],
description = ["Path to a MPP file or a GitHub repo url such as https://github.com/MorpheApp/morphe-patches"],
arity = "1..*",
required = true
)
private lateinit var patchesFiles: Set<File>
@Suppress("unused")
private fun setPatchesFile(patchesFiles: Set<File>) {
this.patchesFiles = checkFileExistsOrIsUrl(patchesFiles, spec)
}
private var patchesFiles = emptySet<File>()

@Option(
names = ["--prerelease"],
description = ["Fetch the latest dev pre-release instead of the stable main release from the repo provided in --patches."],
showDefaultValue = ALWAYS,
)
private var prerelease: Boolean = false

@CommandLine.Option(
@Option(
names = ["-f", "--filter-package-names"],
description = ["Filter patches by package name."],
)
private var packageNames: Set<String>? = null

@CommandLine.Option(
@Option(
names = ["-u", "--count-unused-patches"],
description = ["Count patches that are not used by default."],
showDefaultValue = CommandLine.Help.Visibility.ALWAYS,
showDefaultValue = ALWAYS,
)
private var countUnusedPatches: Boolean = false

@Option(
names = ["-t", "--temporary-files-path"],
description = ["Path to store temporary files."],
)
private var temporaryFilesPath: File? = null

@Spec
private lateinit var spec: CommandSpec

override fun run() {
fun VersionMap.buildVersionsString(): String {
if (isEmpty()) return "Any"
Expand All @@ -56,6 +83,21 @@ internal class ListCompatibleVersions : Runnable {
appendLine(versions.buildVersionsString().prependIndent("\t"))
}

val temporaryFilesPath = temporaryFilesPath ?: File("").absoluteFile.resolve("morphe-temporary-files")

try {
patchesFiles = PatchFileResolver.resolve(
patchesFiles,
prerelease,
temporaryFilesPath
)
Comment on lines +89 to +93
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is passing an empty set (patchesFiles field) to the method. Is this the desired behavior?

} catch (e: IllegalArgumentException) {
throw CommandLine.ParameterException(
spec.commandLine(),
e.message ?: "Failed to resolve patch URL"
)
}

val patches = loadPatchesFromJar(patchesFiles)

patches.mostCommonCompatibleVersions(
Expand Down
49 changes: 44 additions & 5 deletions src/main/kotlin/app/morphe/cli/command/ListPatchesCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
* https://github.com/MorpheApp/morphe-cli
*
* Original hard forked code:
* https://github.com/revanced/revanced-cli
* https://github.com/ReVanced/revanced-cli/tree/731865e167ee449be15fff3dde7a476faea0c2de
*/

package app.morphe.cli.command

import app.morphe.patcher.patch.Package
import app.morphe.patcher.patch.Patch
import app.morphe.patcher.patch.loadPatchesFromJar
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Option
import picocli.CommandLine.Spec
import picocli.CommandLine.Model.CommandSpec
import picocli.CommandLine.Help.Visibility.ALWAYS
import java.io.File
import java.util.logging.Logger
Expand All @@ -28,11 +31,22 @@ internal object ListPatchesCommand : Runnable {
// Patches is now flag based rather than position based
@Option(
names = ["--patches"],
description = ["One or more paths to MPP files."],
description = ["Path to a MPP file or a GitHub repo url such as https://github.com/MorpheApp/morphe-patches"],
arity = "1..*",
required = true
)
private lateinit var patchFiles: Set<File>
@Suppress("unused")
private fun setPatchesFile(patchesFiles: Set<File>) {
this.patchesFiles = checkFileExistsOrIsUrl(patchesFiles, spec)
}
private var patchesFiles = emptySet<File>()

@Option(
names = ["--prerelease"],
description = ["Fetch the latest dev pre-release instead of the stable main release from the repo provided in --patches."],
showDefaultValue = ALWAYS,
)
private var prerelease: Boolean = false

@Option(
names = ["--out"],
Expand All @@ -47,6 +61,12 @@ internal object ListPatchesCommand : Runnable {
)
private var withDescriptions: Boolean = true

@Option(
names = ["-t", "--temporary-files-path"],
description = ["Path to store temporary files."],
)
private var temporaryFilesPath: File? = null

@Option(
names = ["-p", "--with-packages"],
description = ["List the packages the patches are compatible with."],
Expand Down Expand Up @@ -88,6 +108,9 @@ internal object ListPatchesCommand : Runnable {
)
private var packageName: String? = null

@Spec
private lateinit var spec: CommandSpec

override fun run() {
fun Package.buildString(): String {
val (name, versions) = this
Expand Down Expand Up @@ -157,7 +180,23 @@ internal object ListPatchesCommand : Runnable {
compatiblePackageName == name
} ?: withUniversalPatches

val patches = loadPatchesFromJar(patchFiles).withIndex().toList()

val temporaryFilesPath = temporaryFilesPath ?: File("").absoluteFile.resolve("morphe-temporary-files")

try {
patchesFiles = PatchFileResolver.resolve(
patchesFiles,
prerelease,
temporaryFilesPath
)
} catch (e: IllegalArgumentException) {
throw CommandLine.ParameterException(
spec.commandLine(),
e.message ?: "Failed to resolve patch URL"
)
}

val patches = loadPatchesFromJar(patchesFiles).withIndex().toList()

val filtered = packageName?.let {
patches.filter { (_, patch) ->
Expand All @@ -172,7 +211,7 @@ internal object ListPatchesCommand : Runnable {
val finalOutput = filtered.joinToString("\n\n") {it.buildString()}

if (filtered.isEmpty()) {
logger.warning("No compatible patches found in: $patchFiles")
logger.warning("No compatible patches found in: $patchesFiles")
} else {
if (outputFile == null) {
logger.info(finalOutput)
Expand Down
43 changes: 35 additions & 8 deletions src/main/kotlin/app/morphe/cli/command/OptionsCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import app.morphe.patcher.patch.loadPatchesFromJar
import kotlinx.serialization.json.Json
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Option
import picocli.CommandLine.Help.Visibility.ALWAYS
import picocli.CommandLine.Model.CommandSpec
import picocli.CommandLine.Spec
import java.io.File
Expand All @@ -28,29 +30,39 @@ internal object OptionsCommand : Callable<Int> {
@Spec
private lateinit var spec: CommandSpec

@CommandLine.Option(
@Option(
names = ["-p", "--patches"],
description = ["One or more paths to MPP files."],
description = ["Path to a MPP file or a GitHub repo url such as https://github.com/MorpheApp/morphe-patches"],
required = true,
)
@Suppress("unused")
private fun setPatchesFile(patchesFiles: Set<File>) {
patchesFiles.firstOrNull { !it.exists() }?.let {
throw CommandLine.ParameterException(spec.commandLine(), "${it.name} can't be found")
}
this.patchesFiles = patchesFiles
this.patchesFiles = checkFileExistsOrIsUrl(patchesFiles, spec)
}

private var patchesFiles = emptySet<File>()

@CommandLine.Option(
@Option(
names = ["-o", "--out"],
description = ["Path to the output JSON file."],
required = true,
)
private lateinit var outputFile: File

@CommandLine.Option(
@Option(
names = ["--prerelease"],
description = ["Fetch the latest dev pre-release instead of the stable main release from the repo provided in --patches."],
showDefaultValue = ALWAYS,
)
private var prerelease: Boolean = false

@Option(
names = ["-t", "--temporary-files-path"],
description = ["Path to store temporary files."],
)
private var temporaryFilesPath: File? = null

@Option(
names = ["-f", "--filter-package-name"],
description = ["Filter patches by compatible package name."],
)
Expand All @@ -59,6 +71,21 @@ internal object OptionsCommand : Callable<Int> {
private val json = Json { prettyPrint = true }

override fun call(): Int {
val temporaryFilesPath = temporaryFilesPath ?: File("").absoluteFile.resolve("morphe-temporary-files")

try {
patchesFiles = PatchFileResolver.resolve(
patchesFiles,
prerelease,
temporaryFilesPath
)
} catch (e: IllegalArgumentException) {
throw CommandLine.ParameterException(
spec.commandLine(),
e.message ?: "Failed to resolve patch URL"
)
}

return try {
logger.info("Loading patches")

Expand Down
30 changes: 21 additions & 9 deletions src/main/kotlin/app/morphe/cli/command/PatchCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* https://github.com/MorpheApp/morphe-cli
*
* Original hard forked code:
* https://github.com/revanced/revanced-cli
* https://github.com/ReVanced/revanced-cli/tree/731865e167ee449be15fff3dde7a476faea0c2de
*/

package app.morphe.cli.command
Expand Down Expand Up @@ -45,6 +45,7 @@ import java.io.PrintWriter
import java.io.StringWriter
import java.util.concurrent.Callable
import java.util.logging.Logger
import kotlin.collections.plus

@OptIn(ExperimentalSerializationApi::class)
@VisibleForTesting
Expand Down Expand Up @@ -244,19 +245,23 @@ internal object PatchCommand : Callable<Int> {

@CommandLine.Option(
names = ["-p", "--patches"],
description = ["One or more path to MPP files."],
description = ["Path to a MPP file or a GitHub repo url such as https://github.com/MorpheApp/morphe-patches"],
required = true,
)
@Suppress("unused")
private fun setPatchesFile(patchesFiles: Set<File>) {
patchesFiles.firstOrNull { !it.exists() }?.let {
throw CommandLine.ParameterException(spec.commandLine(), "${it.name} can't be found")
}
this.patchesFiles = patchesFiles
this.patchesFiles = checkFileExistsOrIsUrl(patchesFiles, spec)
}

private var patchesFiles = emptySet<File>()

@CommandLine.Option(
names = ["--prerelease"],
description = ["Fetch the latest dev pre-release instead of the stable main release from the repo provided in --patches."],
showDefaultValue = ALWAYS,
)
private var prerelease: Boolean = false

@CommandLine.Option(
names = ["--custom-aapt2-binary"],
description = ["Path to a custom AAPT binary to compile resources with. Only valid when --use-arsclib is not specified."],
Expand Down Expand Up @@ -326,9 +331,7 @@ internal object PatchCommand : Callable<Int> {
)

val temporaryFilesPath =
temporaryFilesPath ?: outputFilePath.parentFile.resolve(
"${outputFilePath.nameWithoutExtension}-temporary-files",
)
temporaryFilesPath ?: File("").absoluteFile.resolve("morphe-temporary-files")

val keystoreFilePath =
keyStoreFilePath ?: outputFilePath.parentFile
Expand Down Expand Up @@ -372,6 +375,15 @@ internal object PatchCommand : Callable<Int> {
// The heavy Patch objects hold DEX classloaders and must not leak into finally.
var patchesSnapshot: PatchBundle? = null

try {
patchesFiles = PatchFileResolver.resolve(patchesFiles, prerelease, temporaryFilesPath)
} catch (e: IllegalArgumentException) {
throw CommandLine.ParameterException(
spec.commandLine(),
e.message ?: "Failed to resolve patch URL"
)
}

try {
logger.info("Loading patches")
val patches: MutableSet<Patch<*>> = loadPatchesFromJar(patchesFiles).toMutableSet()
Expand Down
Loading
Loading