Skip to content

Commit 036faba

Browse files
authored
fix: continue-on-error fix + force windows to FULL (#120)
Fixed an issue where continue-on-error would fail sometimes even though it is not supposed to. Windows now forces `FULL` BytecodeMode. (Temp fix until wchill's permanent fix)
1 parent 4b946dd commit 036faba

4 files changed

Lines changed: 39 additions & 5 deletions

File tree

src/main/kotlin/app/morphe/cli/command/PatchCommand.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package app.morphe.cli.command
1010

1111
import app.morphe.cli.command.model.*
1212
import app.morphe.engine.PatchEngine
13+
import app.morphe.engine.isWindows
1314
import app.morphe.engine.PatchEngine.Config.Companion.DEFAULT_KEYSTORE_ALIAS
1415
import app.morphe.engine.PatchEngine.Config.Companion.DEFAULT_KEYSTORE_PASSWORD
1516
import app.morphe.engine.PatchEngine.Config.Companion.DEFAULT_SIGNER_NAME
@@ -542,7 +543,11 @@ internal object PatchCommand : Callable<Int> {
542543
patcherTemporaryFilesPath.absolutePath,
543544
useArsclib = if (aaptBinaryPath != null) { false } else { !forceApktool },
544545
keepArchitectures = keepArchitectures,
545-
useBytecodeMode = bytecodeMode,
546+
/*
547+
TODO: Remove Windows override once the patcher ships its proper fix
548+
(reflection-based MappedByteBuffer release + copy-instead-of-rename for output DEX files).
549+
*/
550+
useBytecodeMode = if (isWindows()) { BytecodeMode.FULL } else { bytecodeMode },
546551
verifier = verifier
547552
),
548553
).use { patcher ->
@@ -694,9 +699,9 @@ internal object PatchCommand : Callable<Int> {
694699
writer.toString()
695700
)
696701
)
697-
patchingResult.success = false
698702

699703
if (!continueOnError) {
704+
patchingResult.success = false
700705
throw PatchFailedException(
701706
"\"${patchResult.patch}\" failed",
702707
exception

src/main/kotlin/app/morphe/engine/PatchEngine.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ object PatchEngine {
5757
val aaptBinaryPath: File? = null,
5858
val tempDir: File? = null,
5959
val failOnError: Boolean = true,
60+
val bytecodeMode: BytecodeMode = BytecodeMode.STRIP_FAST
6061
) {
6162
companion object {
6263
internal const val DEFAULT_KEYSTORE_ALIAS = "Morphe"
@@ -127,7 +128,11 @@ object PatchEngine {
127128
patcherTempDir.absolutePath,
128129
useArsclib = true,
129130
keepArchitectures = config.architecturesToKeep,
130-
useBytecodeMode = BytecodeMode.STRIP_FAST
131+
/*
132+
TODO: Remove Windows override once the patcher ships its proper fix
133+
(reflection-based MappedByteBuffer release + copy-instead-of-rename for output DEX files).
134+
*/
135+
useBytecodeMode = if (isWindows()) { BytecodeMode.FULL } else { config.bytecodeMode }
131136
)
132137

133138
Patcher(patcherConfig).use { patcher ->
@@ -281,8 +286,13 @@ object PatchEngine {
281286

282287
onProgress("Patching complete!")
283288

289+
// When failOnError=false (user asked to continue on error), reaching this
290+
// line means the APK was successfully rebuilt from the patches that worked,
291+
// treat the run as a success. Individual failures are still reported via
292+
// `failedPatches` for the UI to display. Only strict mode (failOnError=true)
293+
// treats any failure as an overall failure.
284294
return Result(
285-
success = failedPatches.isEmpty(),
295+
success = if (config.failOnError) failedPatches.isEmpty() else true,
286296
outputPath = config.outputApk.absolutePath,
287297
packageName = packageName,
288298
packageVersion = packageVersion,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package app.morphe.engine
2+
3+
internal fun isWindows(): Boolean {
4+
return System.getProperty("os.name").startsWith("Windows", ignoreCase = true)
5+
}

src/main/kotlin/app/morphe/gui/ui/screens/patching/PatchingViewModel.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,21 @@ class PatchingViewModel(
8484
result.fold(
8585
onSuccess = { patchResult ->
8686
if (patchResult.success) {
87-
addLog("Patching completed successfully!", LogLevel.SUCCESS)
87+
// Distinguish clean success from "continue-on-error" partial success:
88+
// the APK was built, but some patches were skipped. Log the skipped
89+
// ones as a warning so the user sees what didn't apply.
90+
if (patchResult.failedPatches.isNotEmpty()) {
91+
addLog(
92+
"Patching completed with ${patchResult.failedPatches.size} patches skipped",
93+
LogLevel.WARNING
94+
)
95+
addLog(
96+
"Skipped patches: ${patchResult.failedPatches.joinToString(", ")}",
97+
LogLevel.WARNING
98+
)
99+
} else {
100+
addLog("Patching completed successfully!", LogLevel.SUCCESS)
101+
}
88102
addLog("Applied ${patchResult.appliedPatches.size} patches", LogLevel.SUCCESS)
89103
_uiState.value = _uiState.value.copy(
90104
status = PatchingStatus.COMPLETED,

0 commit comments

Comments
 (0)