1+ /*
2+ * Copyright 2026 Morphe.
3+ * https://github.com/MorpheApp/morphe-cli
4+ *
5+ * Original hard forked code:
6+ * https://github.com/revanced/revanced-cli
7+ */
8+
19package app.morphe.cli.command
210
311import app.morphe.patcher.patch.Package
412import app.morphe.patcher.patch.Patch
513import app.morphe.patcher.patch.loadPatchesFromJar
6- import picocli.CommandLine.*
14+ import picocli.CommandLine.Command
15+ import picocli.CommandLine.Option
716import picocli.CommandLine.Help.Visibility.ALWAYS
817import java.io.File
918import java.util.logging.Logger
@@ -16,11 +25,20 @@ import app.morphe.patcher.patch.Option as PatchOption
1625internal object ListPatchesCommand : Runnable {
1726 private val logger = Logger .getLogger(this ::class .java.name)
1827
19- @Parameters(
20- description = [" Paths to MPP files." ],
28+ // Patches is now flag based rather than position based
29+ @Option(
30+ names = [" --patches" ],
31+ description = [" One or more paths to MPP files." ],
2132 arity = " 1..*" ,
33+ required = true
34+ )
35+ private lateinit var patchFiles: Set <File >
36+
37+ @Option(
38+ names = [" --out" ],
39+ description = [" Path to the output text file. Writes patch list to this file instead of stdout." ],
2240 )
23- private lateinit var patchesFiles : Set < File >
41+ private var outputFile : File ? = null
2442
2543 @Option(
2644 names = [" -d" , " --with-descriptions" ],
@@ -135,14 +153,33 @@ internal object ListPatchesCommand : Runnable {
135153 }
136154
137155 fun Patch <* >.filterCompatiblePackages (name : String ) =
138- compatiblePackages?.any { (compatiblePackageName, _) -> compatiblePackageName == name }
139- ? : withUniversalPatches
156+ compatiblePackages?.any { (compatiblePackageName, _) ->
157+ compatiblePackageName == name
158+ } ? : withUniversalPatches
140159
141- val patches = loadPatchesFromJar(patchesFiles ).withIndex().toList()
160+ val patches = loadPatchesFromJar(patchFiles ).withIndex().toList()
142161
143- val filtered =
144- packageName?.let { patches.filter { (_, patch) -> patch.filterCompatiblePackages(it) } } ? : patches
145-
146- if (filtered.isNotEmpty()) logger.info(filtered.joinToString(" \n\n " ) { it.buildString() })
162+ val filtered = packageName?.let {
163+ patches.filter { (_, patch) ->
164+ patch.filterCompatiblePackages(
165+ it
166+ )
167+ }
168+ } ? : patches
169+
170+ // Extracted the final output that we get into this variable. Now we just call this based
171+ // on what the user wants. In the console or as an external text file.
172+ val finalOutput = filtered.joinToString(" \n\n " ) {it.buildString()}
173+
174+ if (filtered.isEmpty()) {
175+ logger.warning(" No compatible patches found in: $patchFiles " )
176+ } else {
177+ if (outputFile == null ) {
178+ logger.info(finalOutput)
179+ } else {
180+ logger.info(" Created new output file at ${outputFile!! .path} " )
181+ outputFile!! .writeText(finalOutput)
182+ }
183+ }
147184 }
148185}
0 commit comments