Skip to content

优化 Java 下载#5859

Open
Glavo wants to merge 10 commits intoHMCL-dev:mainfrom
Glavo:java-download
Open

优化 Java 下载#5859
Glavo wants to merge 10 commits intoHMCL-dev:mainfrom
Glavo:java-download

Conversation

@Glavo
Copy link
Copy Markdown
Member

@Glavo Glavo commented Mar 26, 2026

  1. 清理代码;
  2. 先将文件下载至临时文件夹,下载完毕后再移动至目标目录。

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

此 PR 旨在优化 Mojang Java 运行时下载流程:清理数据结构代码,并将运行时文件先下载到临时目录,完成校验后再整体落盘到目标安装目录,以减少半成品文件污染目标目录的风险。

Changes:

  • MojangJavaDownloads 及其内部数据结构改为 record,并使用 @JsonSerializable 标注。
  • MojangJavaDownloadTask 增加临时目录参数,下载/解压输出改写入 tempDir,并在 postExecute() 中校验后再迁移到 target
  • HMCLJavaRepository 调整为创建并传入 .tmp 临时目录,并适配 record 访问方式。

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java 结构体清理:从普通类迁移到 record,简化字段/访问器并保持 Gson 适配器逻辑。
HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloadTask.java 下载落盘策略调整:新增 tempDir,下载/解压后做 SHA-1 校验,再迁移到 target
HMCL/src/main/java/org/jackhuang/hmcl/java/HMCLJavaRepository.java 调整 Java 下载任务构造参数:为每个平台/组件提供固定临时目录并适配 record API。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +154 to +166
DownloadInfo raw = remoteFile.getDownloads().get("raw");
if (raw != null && raw.getSha1() != null) {
Path dest = tempDir.resolve(entry.getKey());
String actual = DigestUtils.digestToString("SHA-1", dest);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

doPostExecute() returns true, so postExecute() will run even when dependency downloads fail (the task framework passes a non-null dependenciesException but still invokes postExecute). Currently postExecute() will verify/checksum, clean target, and move/copy tempDir regardless, which can wipe a working Java runtime after a failed/partial download. Add an early guard like if (!isDependenciesSucceeded()) return; (or throw) before any filesystem mutations.

Copilot uses AI. Check for mistakes.
} else if (entry.getValue() instanceof MojangJavaRemoteFiles.RemoteLink) {
MojangJavaRemoteFiles.RemoteLink link = ((MojangJavaRemoteFiles.RemoteLink) entry.getValue());
} else if (entry.getValue() instanceof MojangJavaRemoteFiles.RemoteLink link) {
Files.deleteIfExists(dest);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

Creating RemoteLink entries doesn’t ensure the parent directory exists. Since javaDownloadsTask.getResult().getFiles() is a Map with no guaranteed iteration order, a link may be processed before its parent RemoteDirectory, causing Files.createSymbolicLink(dest, ...) to fail with NoSuchFileException. Create dest.getParent() directories before creating the symlink (when parent is non-null).

Suggested change
Files.deleteIfExists(dest);
Files.deleteIfExists(dest);
Path parent = dest.getParent();
if (parent != null) {
Files.createDirectories(parent);
}

Copilot uses AI. Check for mistakes.
Comment on lines +175 to +179
FileUtils.cleanDirectory(target);

public Result(MojangJavaDownloads.JavaDownload download, MojangJavaRemoteFiles remoteFiles) {
this.download = download;
this.remoteFiles = remoteFiles;
if (Files.getFileStore(target).equals(Files.getFileStore(tempDir))) {
Files.move(tempDir, target, StandardCopyOption.REPLACE_EXISTING);
} else {
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

postExecute() deletes the existing installation (FileUtils.cleanDirectory(target)) before the final move/copy succeeds. If the subsequent Files.move / copyDirectory fails (I/O error, permissions, antivirus locks, etc.), the user can end up with an empty/broken target. To make this safer, avoid mutating target until the new runtime is fully in place (e.g., move target aside to a backup name, move tempDir into place, then delete the backup; or move tempDir to a sibling target.tmp and swap).

Copilot uses AI. Check for mistakes.
@Hylfrd
Copy link
Copy Markdown

Hylfrd commented Mar 27, 2026

帅诶 清理底层代码(?)

@Glavo
Copy link
Copy Markdown
Member Author

Glavo commented Mar 28, 2026

@sourcery-ai review

1 similar comment
@Glavo
Copy link
Copy Markdown
Member Author

Glavo commented Mar 29, 2026

@sourcery-ai review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants