From c2ee6fca8b41378d00c899562024a4b7a63d76c4 Mon Sep 17 00:00:00 2001 From: comp500 Date: Mon, 23 May 2022 17:38:01 +0100 Subject: [PATCH] Improve handling of manual downloads; "Continue" now rechecks files --- .../infra/packwiz/installer/DownloadTask.kt | 2 +- .../infra/packwiz/installer/UpdateManager.kt | 83 ++++++++++++------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/link/infra/packwiz/installer/DownloadTask.kt b/src/main/kotlin/link/infra/packwiz/installer/DownloadTask.kt index 311365a..5dd022f 100644 --- a/src/main/kotlin/link/infra/packwiz/installer/DownloadTask.kt +++ b/src/main/kotlin/link/infra/packwiz/installer/DownloadTask.kt @@ -292,7 +292,7 @@ internal class DownloadTask private constructor(val metadata: IndexFile.File, de companion object { @JvmStatic - fun createTasksFromIndex(index: IndexFile, defaultFormat: String, downloadSide: Side): List { + fun createTasksFromIndex(index: IndexFile, defaultFormat: String, downloadSide: Side): MutableList { val tasks = ArrayList() for (file in Objects.requireNonNull(index.files)) { tasks.add(DownloadTask(file, defaultFormat, downloadSide)) diff --git a/src/main/kotlin/link/infra/packwiz/installer/UpdateManager.kt b/src/main/kotlin/link/infra/packwiz/installer/UpdateManager.kt index 800320a..3cb2e3d 100644 --- a/src/main/kotlin/link/infra/packwiz/installer/UpdateManager.kt +++ b/src/main/kotlin/link/infra/packwiz/installer/UpdateManager.kt @@ -314,8 +314,8 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse } // TODO: task failed function? - val nonFailedFirstTasks = tasks.filter { t -> !t.failed() }.toList() - val optionTasks = nonFailedFirstTasks.filter(DownloadTask::correctSide).filter(DownloadTask::isOptional).toList() + tasks.removeAll { it.failed() } + val optionTasks = tasks.filter(DownloadTask::correctSide).filter(DownloadTask::isOptional).toList() val optionsChanged = optionTasks.any(DownloadTask::isNewOptional) if (optionTasks.isNotEmpty() && !optionsChanged) { if (!ui.optionsButtonPressed) { @@ -339,35 +339,11 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse // TODO: keep this enabled? then apply changes after download process? ui.disableOptionsButton(optionTasks.isNotEmpty()) - ui.submitProgress(InstallProgress("Validating existing files...")) - - // Validate existing files - for (downloadTask in nonFailedFirstTasks.filter(DownloadTask::correctSide)) { - downloadTask.validateExistingFile(opts.packFolder) - } - - // Resolve CurseForge metadata - val cfFiles = nonFailedFirstTasks.asSequence().filter { !it.alreadyUpToDate } - .filter(DownloadTask::correctSide) - .map { it.metadata } - .filter { it.linkedFile != null } - .filter { it.linkedFile?.download?.mode == "metadata:curseforge" }.toList() - if (cfFiles.isNotEmpty()) { - ui.submitProgress(InstallProgress("Resolving CurseForge metadata...")) - val resolveFailures = resolveCfMetadata(cfFiles) - if (resolveFailures.isNotEmpty()) { - errorsOccurred = true - when (ui.showExceptions(resolveFailures, cfFiles.size, true)) { - ExceptionListResult.CONTINUE -> {} - ExceptionListResult.CANCEL -> { - cancelled = true - return - } - ExceptionListResult.IGNORE -> { - cancelledStartGame = true - return - } - } + while (true) { + when (validateAndResolve(tasks)) { + ResolveResult.RETRY -> {} + ResolveResult.QUIT -> return + ResolveResult.SUCCESS -> break } } @@ -418,7 +394,7 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse // Shut down the thread pool when the update is done threadPool.shutdown() - val failedTasks2ElectricBoogaloo = nonFailedFirstTasks.asSequence().map(DownloadTask::exceptionDetails).filterNotNull().toList() + val failedTasks2ElectricBoogaloo = tasks.asSequence().map(DownloadTask::exceptionDetails).filterNotNull().toList() if (failedTasks2ElectricBoogaloo.isNotEmpty()) { errorsOccurred = true when (ui.showExceptions(failedTasks2ElectricBoogaloo, tasks.size, false)) { @@ -429,6 +405,49 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse } } + enum class ResolveResult { + RETRY, + QUIT, + SUCCESS; + } + + private fun validateAndResolve(nonFailedFirstTasks: List): ResolveResult { + ui.submitProgress(InstallProgress("Validating existing files...")) + + // Validate existing files + for (downloadTask in nonFailedFirstTasks.filter(DownloadTask::correctSide)) { + downloadTask.validateExistingFile(opts.packFolder) + } + + // Resolve CurseForge metadata + val cfFiles = nonFailedFirstTasks.asSequence().filter { !it.alreadyUpToDate } + .filter(DownloadTask::correctSide) + .map { it.metadata } + .filter { it.linkedFile != null } + .filter { it.linkedFile?.download?.mode == "metadata:curseforge" }.toList() + if (cfFiles.isNotEmpty()) { + ui.submitProgress(InstallProgress("Resolving CurseForge metadata...")) + val resolveFailures = resolveCfMetadata(cfFiles) + if (resolveFailures.isNotEmpty()) { + errorsOccurred = true + return when (ui.showExceptions(resolveFailures, cfFiles.size, true)) { + ExceptionListResult.CONTINUE -> { + ResolveResult.RETRY + } + ExceptionListResult.CANCEL -> { + cancelled = true + ResolveResult.QUIT + } + ExceptionListResult.IGNORE -> { + cancelledStartGame = true + ResolveResult.QUIT + } + } + } + } + return ResolveResult.SUCCESS + } + private fun showCancellationDialog() { when (ui.showCancellationDialog()) { CancellationResult.QUIT -> cancelled = true