From 93d4917ed88bf48b23ac5698eda81b798c8d3468 Mon Sep 17 00:00:00 2001 From: CalbootOnceMore Date: Sun, 3 May 2026 12:49:56 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/setting/Config.java | 15 ++++++++++ .../jackhuang/hmcl/ui/main/SettingsPage.java | 29 +++++++++++++++---- .../jackhuang/hmcl/upgrade/RemoteVersion.java | 28 ++++++++++++++++-- .../jackhuang/hmcl/upgrade/UpdateChannel.java | 2 +- .../jackhuang/hmcl/upgrade/UpdateChecker.java | 5 ++-- .../jackhuang/hmcl/upgrade/UpdateHandler.java | 29 +++++++++++-------- .../resources/assets/lang/I18N.properties | 2 ++ .../resources/assets/lang/I18N_zh.properties | 2 ++ .../assets/lang/I18N_zh_CN.properties | 2 ++ 9 files changed, 91 insertions(+), 23 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index 0a845929b50..7ad231457e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -237,6 +237,21 @@ public void setDisableAutoShowUpdateDialog(boolean disableAutoShowUpdateDialog) this.disableAutoShowUpdateDialog.set(disableAutoShowUpdateDialog); } + @SerializedName("autoDownloadUpdate") + private final BooleanProperty autoDownloadUpdate = new SimpleBooleanProperty(false); + + public BooleanProperty autoDownloadUpdateProperty() { + return autoDownloadUpdate; + } + + public boolean isAutoDownloadUpdate() { + return autoDownloadUpdate.get(); + } + + public void setAutoDownloadUpdate(boolean autoDownloadUpdate) { + this.autoDownloadUpdate.set(autoDownloadUpdate); + } + @SerializedName("disableAprilFools") private final BooleanProperty disableAprilFools = new SimpleBooleanProperty(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index 9d80ebcefd0..4e00ff0d01f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -21,6 +21,7 @@ import javafx.beans.InvalidationListener; import javafx.beans.WeakInvalidationListener; import javafx.beans.binding.Bindings; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.StringProperty; import javafx.css.PseudoClass; @@ -173,17 +174,13 @@ protected int getTrailingTextIndex() { settingsPane.getContent().add(updatePane); } + BooleanProperty preview; { LineToggleButton previewPane = new LineToggleButton(); previewPane.setTitle(i18n("update.preview")); previewPane.setSubtitle(i18n("update.preview.subtitle")); previewPane.selectedProperty().bindBidirectional(config().acceptPreviewUpdateProperty()); - - InvalidationListener checkUpdateListener = e -> { - UpdateChecker.requestCheckUpdate(updateChannel.get(), previewPane.isSelected()); - }; - updateChannel.addListener(checkUpdateListener); - previewPane.selectedProperty().addListener(checkUpdateListener); + preview = previewPane.selectedProperty(); settingsPane.getContent().add(previewPane); } @@ -196,6 +193,26 @@ protected int getTrailingTextIndex() { settingsPane.getContent().add(disableAutoShowUpdateDialogPane); } + BooleanProperty autoDownloadUpdate; + { + LineToggleButton autoDownloadUpdatePane = new LineToggleButton(); + autoDownloadUpdatePane.setTitle(i18n("update.auto_download")); + autoDownloadUpdatePane.setSubtitle(i18n("update.auto_download.subtitle")); + autoDownloadUpdatePane.selectedProperty().bindBidirectional(config().autoDownloadUpdateProperty()); + autoDownloadUpdate = autoDownloadUpdatePane.selectedProperty(); + + settingsPane.getContent().add(autoDownloadUpdatePane); + } + + { + InvalidationListener checkUpdateListener = e -> { + UpdateChecker.requestCheckUpdate(updateChannel.get(), preview.get(), autoDownloadUpdate.get()); + }; + updateChannel.addListener(checkUpdateListener); + preview.addListener(checkUpdateListener); + autoDownloadUpdate.addListener(checkUpdateListener); + } + if (AprilFools.isShowAprilFoolsSettings()) { LineToggleButton disableAprilFools = new LineToggleButton(); disableAprilFools.setTitle(i18n("settings.launcher.disable_april_fools")); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java index b24ce19491a..5e0a1602e7a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java @@ -24,12 +24,17 @@ import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Optional; +import static org.jackhuang.hmcl.util.logging.Logger.LOG; + public record RemoteVersion(UpdateChannel channel, String version, String url, Type type, IntegrityCheck integrityCheck, - boolean preview, boolean force) { + boolean preview, boolean force, @Nullable Path downloadedFile) { public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String url) throws IOException { try { @@ -39,7 +44,7 @@ public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String String jarHash = Optional.ofNullable(response.get("jarsha1")).map(JsonElement::getAsString).orElse(null); boolean force = Optional.ofNullable(response.get("force")).map(JsonElement::getAsBoolean).orElse(false); if (jarUrl != null && jarHash != null) { - return new RemoteVersion(channel, version, jarUrl, Type.JAR, new IntegrityCheck("SHA-1", jarHash), preview, force); + return new RemoteVersion(channel, version, jarUrl, Type.JAR, new IntegrityCheck("SHA-1", jarHash), preview, force, null); } else { throw new IOException("No download url is available"); } @@ -53,6 +58,25 @@ public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String return "[" + version + " from " + url + "]"; } + public RemoteVersion tryDownload() { + if (downloadedFile() != null) return this; + Path downloaded; + try { + downloaded = Files.createTempFile("hmcl-update-", ".jar"); + } catch (IOException e) { + LOG.warning("Failed to create temp file", e); + return this; + } + + var executor = new HMCLDownloadTask(this, downloaded).executor(); + if (executor.test()) { + return new RemoteVersion(channel(), version(), url(), type(), integrityCheck(), preview(), force(), downloaded); + } else { + LOG.warning("Failed to download update for " + this, executor.getException()); + return this; + } + } + public enum Type { JAR } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChannel.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChannel.java index 998a3da7d2e..b040ac9ba5d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChannel.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChannel.java @@ -22,7 +22,7 @@ public enum UpdateChannel { STABLE("stable"), DEVELOPMENT("dev"), - NIGHTLY("nightly"); + NIGHTLY("dev"); public final String channelName; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java index df15a3fac11..f8f5b767daf 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java @@ -56,7 +56,7 @@ private UpdateChecker() { private static final ReadOnlyBooleanWrapper checkingUpdate = new ReadOnlyBooleanWrapper(false); public static void init() { - requestCheckUpdate(UpdateChannel.getChannel(), config().isAcceptPreviewUpdate()); + requestCheckUpdate(UpdateChannel.getChannel(), config().isAcceptPreviewUpdate(), config().isAutoDownloadUpdate()); } public static RemoteVersion getLatestVersion() { @@ -101,7 +101,7 @@ private static boolean isDevelopmentVersion(String version) { version.contains("SNAPSHOT"); // eg. 3.5.SNAPSHOT } - public static void requestCheckUpdate(UpdateChannel channel, boolean preview) { + public static void requestCheckUpdate(UpdateChannel channel, boolean preview, boolean download) { Platform.runLater(() -> { if (isCheckingUpdate()) return; @@ -112,6 +112,7 @@ public static void requestCheckUpdate(UpdateChannel channel, boolean preview) { try { result = checkUpdate(channel, preview); LOG.info("Latest version (" + channel + ", preview=" + preview + ") is " + result); + if (download) result = result.tryDownload(); } catch (Throwable e) { LOG.warning("Failed to check for update", e); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index 95c8f1b772c..769b025fa23 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -106,18 +106,23 @@ public static void updateFrom(RemoteVersion version) { } Controllers.dialog(new UpgradeDialog(version, () -> { - Path downloaded; - try { - downloaded = Files.createTempFile("hmcl-update-", ".jar"); - } catch (IOException e) { - LOG.warning("Failed to create temp file", e); - return; - } - - Task task = new HMCLDownloadTask(version, downloaded); + Path downloaded = version.downloadedFile(); + TaskExecutor executor; + if (downloaded != null && Files.isRegularFile(downloaded)) { + executor = Task.completed(null).executor(); + } else { + try { + downloaded = Files.createTempFile("hmcl-update-", ".jar"); + } catch (IOException e) { + LOG.warning("Failed to create temp file", e); + return; + } - TaskExecutor executor = task.executor(); - Controllers.taskDialog(executor, i18n("message.downloading"), TaskCancellationAction.NORMAL); + Task task = new HMCLDownloadTask(version, downloaded); + executor = task.executor(); + Controllers.taskDialog(executor, i18n("message.downloading"), TaskCancellationAction.NORMAL); + } + final Path finalDownloaded = downloaded; thread(() -> { boolean success = executor.test(); @@ -150,7 +155,7 @@ public static void updateFrom(RemoteVersion version) { // Ignore } - requestUpdate(downloaded, getCurrentLocation()); + requestUpdate(finalDownloaded, getCurrentLocation()); EntryPoint.exit(0); } catch (IOException e) { LOG.warning("Failed to update to " + version, e); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index e13e61bd67b..6f33c43ad45 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1627,6 +1627,8 @@ unofficial.hint=You are using an unofficial build of HMCL. We cannot guarantee i update=Update update.accept=Update +update.auto_download=Auto download update +update.auto_download.subtitle=Automatically download (but not installing) launcher update in the background. update.changelog=Changelog update.channel.dev=Beta update.channel.dev.hint=You are currently using a Beta channel build of the launcher. While it may include some extra features, it is also sometimes less stable than the Stable channel builds.\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 555f135af8d..2b6a3328cb0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1417,6 +1417,8 @@ unofficial.hint=你正在使用第三方提供的 HMCL。我們無法保證其 update=啟動器更新 update.accept=更新 +update.auto_download=自動下載更新 +update.auto_download.subtitle=自動在後臺下載更新(但不安裝) update.changelog=更新日誌 update.channel.dev=開發版 update.channel.dev.hint=你正在使用 HMCL 開發版。開發版包含一些未在穩定版中包含的測試性功能,僅用於體驗新功能。開發版功能未受充分驗證,使用起來可能不穩定!\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index b251db3d68a..cbd381a6b64 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1422,6 +1422,8 @@ unofficial.hint=你正在使用非官方构建的 HMCL。我们无法保证其 update=启动器更新 update.accept=更新 +update.auto_download=自动下载更新 +update.auto_download.subtitle=自动在后台下载更新(但不安装) update.changelog=更新日志 update.channel.dev=开发版 update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ From e8f258c5c8ae78b1167f32ddc56033700a0cca81 Mon Sep 17 00:00:00 2001 From: CalbootOnceMore Date: Sun, 3 May 2026 13:29:09 +0800 Subject: [PATCH 2/5] update --- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 2b6a3328cb0..b436335d08a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1418,7 +1418,7 @@ unofficial.hint=你正在使用第三方提供的 HMCL。我們無法保證其 update=啟動器更新 update.accept=更新 update.auto_download=自動下載更新 -update.auto_download.subtitle=自動在後臺下載更新(但不安裝) +update.auto_download.subtitle=自動在後臺下載更新 (但不安裝) update.changelog=更新日誌 update.channel.dev=開發版 update.channel.dev.hint=你正在使用 HMCL 開發版。開發版包含一些未在穩定版中包含的測試性功能,僅用於體驗新功能。開發版功能未受充分驗證,使用起來可能不穩定!\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index cbd381a6b64..5b6d0f85efc 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1423,7 +1423,7 @@ unofficial.hint=你正在使用非官方构建的 HMCL。我们无法保证其 update=启动器更新 update.accept=更新 update.auto_download=自动下载更新 -update.auto_download.subtitle=自动在后台下载更新(但不安装) +update.auto_download.subtitle=自动在后台下载更新 (但不安装) update.changelog=更新日志 update.channel.dev=开发版 update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ From 38c1abe2f80acddf12718539b7b182ccb0125afe Mon Sep 17 00:00:00 2001 From: CalbootOnceMore Date: Mon, 4 May 2026 10:48:11 +0800 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 6f33c43ad45..65b88f7d1f4 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1628,7 +1628,7 @@ unofficial.hint=You are using an unofficial build of HMCL. We cannot guarantee i update=Update update.accept=Update update.auto_download=Auto download update -update.auto_download.subtitle=Automatically download (but not installing) launcher update in the background. +update.auto_download.subtitle=Automatically download launcher updates and notify when ready to install. update.changelog=Changelog update.channel.dev=Beta update.channel.dev.hint=You are currently using a Beta channel build of the launcher. While it may include some extra features, it is also sometimes less stable than the Stable channel builds.\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index b436335d08a..d58a6da30b5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1418,7 +1418,7 @@ unofficial.hint=你正在使用第三方提供的 HMCL。我們無法保證其 update=啟動器更新 update.accept=更新 update.auto_download=自動下載更新 -update.auto_download.subtitle=自動在後臺下載更新 (但不安裝) +update.auto_download.subtitle=自動在背景下載更新,下載完成後顯示通知 update.changelog=更新日誌 update.channel.dev=開發版 update.channel.dev.hint=你正在使用 HMCL 開發版。開發版包含一些未在穩定版中包含的測試性功能,僅用於體驗新功能。開發版功能未受充分驗證,使用起來可能不穩定!\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 5b6d0f85efc..e17ea940286 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1423,7 +1423,7 @@ unofficial.hint=你正在使用非官方构建的 HMCL。我们无法保证其 update=启动器更新 update.accept=更新 update.auto_download=自动下载更新 -update.auto_download.subtitle=自动在后台下载更新 (但不安装) +update.auto_download.subtitle=自动在后台下载更新,下载完成后显示通知 update.changelog=更新日志 update.channel.dev=开发版 update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ From 43a7ee1e93e5195417bc03a3f2e3e11d41cd8157 Mon Sep 17 00:00:00 2001 From: CalbootOnceMore Date: Mon, 4 May 2026 12:24:07 +0800 Subject: [PATCH 4/5] using cache --- .../jackhuang/hmcl/upgrade/RemoteVersion.java | 22 +++++++++++-------- .../jackhuang/hmcl/upgrade/UpdateChecker.java | 2 +- .../jackhuang/hmcl/upgrade/UpdateHandler.java | 10 ++++----- .../jackhuang/hmcl/util/CacheRepository.java | 10 +-------- .../org/jackhuang/hmcl/util/io/FileUtils.java | 14 ++++++++++++ 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java index 5e0a1602e7a..8fa744fba7b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java @@ -22,19 +22,23 @@ import com.google.gson.JsonParseException; import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public record RemoteVersion(UpdateChannel channel, String version, String url, Type type, IntegrityCheck integrityCheck, - boolean preview, boolean force, @Nullable Path downloadedFile) { + boolean preview, boolean force) { + + public static final Map downloadCache = new HashMap<>(); public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String url) throws IOException { try { @@ -44,7 +48,7 @@ public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String String jarHash = Optional.ofNullable(response.get("jarsha1")).map(JsonElement::getAsString).orElse(null); boolean force = Optional.ofNullable(response.get("force")).map(JsonElement::getAsBoolean).orElse(false); if (jarUrl != null && jarHash != null) { - return new RemoteVersion(channel, version, jarUrl, Type.JAR, new IntegrityCheck("SHA-1", jarHash), preview, force, null); + return new RemoteVersion(channel, version, jarUrl, Type.JAR, new IntegrityCheck("SHA-1", jarHash), preview, force); } else { throw new IOException("No download url is available"); } @@ -58,22 +62,22 @@ public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String return "[" + version + " from " + url + "]"; } - public RemoteVersion tryDownload() { - if (downloadedFile() != null) return this; - Path downloaded; + public void tryDownload() { + Path downloaded = downloadCache.get(this); + if (downloaded != null && FileUtils.verifyHash(downloaded, integrityCheck().algorithm(), integrityCheck().checksum())) return; + try { downloaded = Files.createTempFile("hmcl-update-", ".jar"); } catch (IOException e) { LOG.warning("Failed to create temp file", e); - return this; + return; } var executor = new HMCLDownloadTask(this, downloaded).executor(); if (executor.test()) { - return new RemoteVersion(channel(), version(), url(), type(), integrityCheck(), preview(), force(), downloaded); + downloadCache.put(this, downloaded); } else { LOG.warning("Failed to download update for " + this, executor.getException()); - return this; } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java index f8f5b767daf..a86f1624f2f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java @@ -112,7 +112,7 @@ public static void requestCheckUpdate(UpdateChannel channel, boolean preview, bo try { result = checkUpdate(channel, preview); LOG.info("Latest version (" + channel + ", preview=" + preview + ") is " + result); - if (download) result = result.tryDownload(); + if (download) result.tryDownload(); } catch (Throwable e) { LOG.warning("Failed to check for update", e); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index 769b025fa23..3a682470e7a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -33,6 +33,7 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.SwingUtils; import org.jackhuang.hmcl.util.TaskCancellationAction; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.JarUtils; import org.jackhuang.hmcl.util.platform.OperatingSystem; @@ -106,9 +107,9 @@ public static void updateFrom(RemoteVersion version) { } Controllers.dialog(new UpgradeDialog(version, () -> { - Path downloaded = version.downloadedFile(); + Path downloaded = RemoteVersion.downloadCache.get(version); TaskExecutor executor; - if (downloaded != null && Files.isRegularFile(downloaded)) { + if (downloaded != null && FileUtils.verifyHash(downloaded, version.integrityCheck().algorithm(), version.integrityCheck().checksum())) { executor = Task.completed(null).executor(); } else { try { @@ -124,9 +125,8 @@ public static void updateFrom(RemoteVersion version) { } final Path finalDownloaded = downloaded; thread(() -> { - boolean success = executor.test(); - - if (success) { + if (executor.test()) { + RemoteVersion.downloadCache.put(version, finalDownloaded); try { if (!IntegrityChecker.isSelfVerified() && !IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK) { throw new IOException("Current JAR is not verified"); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java index 3e08b993b2b..1e2659af3bc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java @@ -103,15 +103,7 @@ protected Path getFile(String algorithm, String hash) { protected boolean fileExists(String algorithm, String hash) { if (hash == null) return false; Path file = getFile(algorithm, hash); - if (Files.exists(file)) { - try { - return DigestUtils.digestToString(algorithm, file).equalsIgnoreCase(hash); - } catch (IOException e) { - return false; - } - } else { - return false; - } + return FileUtils.verifyHash(file, algorithm, hash); } public void tryCacheFile(Path path, String algorithm, String hash) throws IOException { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java index bce609927db..dd3070f39e9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java @@ -20,6 +20,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import org.glavo.chardet.DetectedCharset; import org.glavo.chardet.UniversalDetector; +import org.jackhuang.hmcl.util.DigestUtils; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.function.ExceptionalConsumer; import org.jackhuang.hmcl.util.platform.OperatingSystem; @@ -559,4 +560,17 @@ public static EnumSet parsePosixFilePermission(int unixMode return permissions; } + + public static boolean verifyHash(Path file, String algorithm, String hash) { + if (Files.exists(file)) { + try { + return DigestUtils.digestToString(algorithm, file).equalsIgnoreCase(hash); + } catch (IOException e) { + LOG.warning("Failed to verify hash for file " + file, e); + return false; + } + } else { + return false; + } + } } From 34360346793be3a874e92f1add2c18dae0800b40 Mon Sep 17 00:00:00 2001 From: CalbootOnceMore Date: Mon, 4 May 2026 19:34:41 +0800 Subject: [PATCH 5/5] update --- .../src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java index 8fa744fba7b..ab286a81425 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java @@ -63,7 +63,7 @@ public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String } public void tryDownload() { - Path downloaded = downloadCache.get(this); + Path downloaded = downloadCache.get(this); if (downloaded != null && FileUtils.verifyHash(downloaded, integrityCheck().algorithm(), integrityCheck().checksum())) return; try {