Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,18 @@
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;

public class DownloadPage extends DecoratorAnimatedPage implements DecoratorPage {
private final ReadOnlyObjectWrapper<DecoratorPage.State> state = new ReadOnlyObjectWrapper<>(DecoratorPage.State.fromTitle(i18n("download"), -1));
Expand Down Expand Up @@ -134,6 +139,19 @@ public static void download(DownloadProvider downloadProvider, Profile profile,

Path runDirectory = profile.getRepository().hasVersion(version) ? profile.getRepository().getRunDirectory(version) : profile.getRepository().getBaseDirectory();

Set<String> existingFiles;

try (var list = Files.list(runDirectory.resolve(subdirectoryName))) {
existingFiles = list.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toSet());
} catch (IOException e) {
LOG.warning("Failed to list files in " + runDirectory.resolve(subdirectoryName), e);
existingFiles = Set.of();
}
Comment on lines +144 to +151
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

建议在调用 Files.list 之前先检查目录是否存在。如果子目录(如 mods)尚未创建,Files.list 会抛出 NoSuchFileException,导致 catch 块记录不必要的警告日志。此外,预先解析路径可以提高代码可读性并避免重复解析。同时,为了支持跨平台的文件名冲突检查(如 Windows/macOS 默认不区分大小写),建议将文件名统一转换为小写存储。

        Path dir = runDirectory.resolve(subdirectoryName);
        if (Files.isDirectory(dir)) {
            try (var list = Files.list(dir)) {
                existingFiles = list.map(path -> path.getFileName().toString().toLowerCase(Locale.ROOT))
                        .collect(Collectors.toSet());
            } catch (IOException e) {
                LOG.warning("Failed to list files in " + dir, e);
                existingFiles = Set.of();
            }
        } else {
            existingFiles = Set.of();
        }


Set<String> finalExistingFiles = existingFiles;

Controllers.prompt(i18n("archive.file.name"), (result, handler) -> {
Path dest = runDirectory.resolve(subdirectoryName).resolve(result);

Expand All @@ -153,7 +171,7 @@ public static void download(DownloadProvider downloadProvider, Profile profile,
}
}), i18n("message.downloading"), TaskCancellationAction.NORMAL);
handler.resolve();
}, file.getFile().getFilename(), new Validator(i18n("install.new_game.malformed"), FileUtils::isNameValid));
}, file.getFile().getFilename(), new Validator(i18n("install.new_game.malformed"), FileUtils::isNameValid), new Validator(i18n("profile.already_exists"), (it) -> !finalExistingFiles.contains(it)));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

由于 existingFiles 现在存储的是小写文件名,校验器在比较时也应将输入值转换为小写。这可以确保在不区分大小写的文件系统上也能正确识别文件名冲突。

Suggested change
}, file.getFile().getFilename(), new Validator(i18n("install.new_game.malformed"), FileUtils::isNameValid), new Validator(i18n("profile.already_exists"), (it) -> !finalExistingFiles.contains(it)));
}, file.getFile().getFilename(), new Validator(i18n("install.new_game.malformed"), FileUtils::isNameValid), new Validator(i18n("profile.already_exists"), (it) -> !finalExistingFiles.contains(it.toLowerCase(Locale.ROOT))));


}

Expand Down