将 org.jackhuang.hmcl.mod 从 java.io.File 迁移至 NIO (#4499)

This commit is contained in:
Glavo
2025-09-17 19:29:59 +08:00
committed by GitHub
parent 94994ffdb6
commit e9d7d0a33c
27 changed files with 154 additions and 164 deletions

View File

@@ -30,23 +30,22 @@ import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public final class MinecraftInstanceTask<T> extends Task<ModpackConfiguration<T>> {
private final File zipFile;
private final Path zipFile;
private final Charset encoding;
private final List<String> subDirectories;
private final File jsonFile;
private final Path jsonFile;
private final T manifest;
private final String type;
private final String name;
private final String version;
public MinecraftInstanceTask(File zipFile, Charset encoding, List<String> subDirectories, T manifest, ModpackProvider modpackProvider, String name, String version, File jsonFile) {
public MinecraftInstanceTask(Path zipFile, Charset encoding, List<String> subDirectories, T manifest, ModpackProvider modpackProvider, String name, String version, Path jsonFile) {
this.zipFile = zipFile;
this.encoding = encoding;
this.subDirectories = subDirectories.stream().map(FileUtils::normalizePath).collect(Collectors.toList());
this.subDirectories = subDirectories.stream().map(FileUtils::normalizePath).toList();
this.manifest = manifest;
this.jsonFile = jsonFile;
this.type = modpackProvider.getName();
@@ -58,12 +57,12 @@ public final class MinecraftInstanceTask<T> extends Task<ModpackConfiguration<T>
public void execute() throws Exception {
List<ModpackConfiguration.FileInformation> overrides = new ArrayList<>();
try (FileSystem fs = CompressingUtils.readonly(zipFile.toPath()).setEncoding(encoding).build()) {
try (FileSystem fs = CompressingUtils.readonly(zipFile).setEncoding(encoding).build()) {
for (String subDirectory : subDirectories) {
Path root = fs.getPath(subDirectory);
if (Files.exists(root))
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
Files.walkFileTree(root, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String relativePath = root.relativize(file).normalize().toString().replace(File.separatorChar, '/');
@@ -75,9 +74,8 @@ public final class MinecraftInstanceTask<T> extends Task<ModpackConfiguration<T>
}
ModpackConfiguration<T> configuration = new ModpackConfiguration<>(manifest, type, name, version, overrides);
Path jsonPath = jsonFile.toPath();
Files.createDirectories(jsonPath.getParent());
JsonUtils.writeToJsonFile(jsonPath, configuration);
Files.createDirectories(jsonFile.getParent());
JsonUtils.writeToJsonFile(jsonFile, configuration);
setResult(configuration);
}
}

View File

@@ -20,8 +20,8 @@ package org.jackhuang.hmcl.mod;
import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.task.Task;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.List;
/**
@@ -114,7 +114,7 @@ public abstract class Modpack {
return this;
}
public abstract Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name);
public abstract Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name);
public static boolean acceptFile(String path, List<String> blackList, List<String> whiteList) {
if (path.isEmpty())

View File

@@ -21,31 +21,30 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.DigestUtils;
import org.jackhuang.hmcl.util.io.Unzipper;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Predicate;
public class ModpackInstallTask<T> extends Task<Void> {
private final File modpackFile;
private final File dest;
private final Path modpackFile;
private final Path dest;
private final Charset charset;
private final List<String> subDirectories;
private final List<ModpackConfiguration.FileInformation> overrides;
private final Predicate<String> callback;
/**
* Constructor
* @param modpackFile a zip file
* @param dest destination to store unpacked files
* @param charset charset of the zip file
* @param subDirectories the subdirectory of zip file to unpack
* @param callback test whether the file (given full path) in zip file should be unpacked or not
* @param oldConfiguration old modpack information if upgrade
*/
public ModpackInstallTask(File modpackFile, File dest, Charset charset, List<String> subDirectories, Predicate<String> callback, ModpackConfiguration<T> oldConfiguration) {
/// Constructor
///
/// @param modpackFile a zip file
/// @param dest destination to store unpacked files
/// @param charset charset of the zip file
/// @param subDirectories the subdirectory of zip file to unpack
/// @param callback test whether the file (given full path) in zip file should be unpacked or not
/// @param oldConfiguration old modpack information if upgrade
public ModpackInstallTask(Path modpackFile, Path dest, Charset charset, List<String> subDirectories, Predicate<String> callback, ModpackConfiguration<T> oldConfiguration) {
this.modpackFile = modpackFile;
this.dest = dest;
this.charset = charset;
@@ -61,7 +60,7 @@ public class ModpackInstallTask<T> extends Task<Void> {
@Override
public void execute() throws Exception {
Set<String> entries = new HashSet<>();
Files.createDirectories(dest.toPath());
Files.createDirectories(dest);
HashMap<String, ModpackConfiguration.FileInformation> files = new HashMap<>();
for (ModpackConfiguration.FileInformation file : overrides)
@@ -97,9 +96,9 @@ public class ModpackInstallTask<T> extends Task<Void> {
// If old modpack have this entry, and new modpack deleted it. Delete this file.
for (ModpackConfiguration.FileInformation file : overrides) {
File original = new File(dest, file.getPath());
if (original.exists() && !entries.contains(file.getPath()))
original.delete();
Path original = dest.resolve(file.getPath());
if (Files.exists(original) && !entries.contains(file.getPath()))
Files.deleteIfExists(original);
}
}
}

View File

@@ -23,7 +23,6 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.game.LaunchOptions;
import org.jackhuang.hmcl.task.Task;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
@@ -34,7 +33,7 @@ public interface ModpackProvider {
Task<?> createCompletionTask(DefaultDependencyManager dependencyManager, String version);
Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, File zipFile, Modpack modpack) throws MismatchedModpackTypeException;
Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, Path zipFile, Modpack modpack) throws MismatchedModpackTypeException;
/**
* @param zipFile the opened modpack zip file.

View File

@@ -28,7 +28,6 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
@@ -148,12 +147,12 @@ public final class CurseCompletionTask extends Task<Void> {
.filter(f -> f.getFileName() != null)
.flatMap(f -> {
try {
File path = guessFilePath(f, resourcePacksRoot.toFile(), shaderPacksRoot.toFile());
Path path = guessFilePath(f, resourcePacksRoot, shaderPacksRoot);
if (path == null) {
return Stream.empty();
}
var task = new FileDownloadTask(f.getUrl(), path.toPath());
var task = new FileDownloadTask(f.getUrl(), path);
task.setCacheRepository(dependency.getCacheRepository());
task.setCaching(true);
return Stream.of(task.withCounter("hmcl.modpack.download"));
@@ -181,23 +180,23 @@ public final class CurseCompletionTask extends Task<Void> {
* @return ./resourcepacks/$filename or ./shaderpacks/$filename or ./mods/$filename if the file doesn't exist. null if the file existed.
* @throws IOException If IOException was encountered during getting data from CurseForge.
*/
private File guessFilePath(CurseManifestFile file, File resourcePacksRoot, File shaderPacksRoot) throws IOException {
private Path guessFilePath(CurseManifestFile file, Path resourcePacksRoot, Path shaderPacksRoot) throws IOException {
RemoteMod mod = CurseForgeRemoteModRepository.MODS.getModById(Integer.toString(file.getProjectID()));
int classID = ((CurseAddon) mod.getData()).getClassId();
String fileName = file.getFileName();
switch (classID) {
case 12: // Resource pack
case 6552: { // Shader pack
File res = new File(classID == 12 ? resourcePacksRoot : shaderPacksRoot, fileName);
return res.exists() ? null : res;
return switch (classID) {
case 12, // Resource pack
6552 -> { // Shader pack
Path res = (classID == 12 ? resourcePacksRoot : shaderPacksRoot).resolve(fileName);
yield Files.exists(res) ? null : res;
}
default: {
default -> {
if (modManager.hasSimpleMod(fileName)) {
return null;
yield null;
}
return modManager.getSimpleModPath(fileName).toFile();
yield modManager.getSimpleModPath(fileName);
}
}
};
}
@Override

View File

@@ -26,7 +26,6 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -44,11 +43,11 @@ public final class CurseInstallTask extends Task<Void> {
private final DefaultDependencyManager dependencyManager;
private final DefaultGameRepository repository;
private final File zipFile;
private final Path zipFile;
private final Modpack modpack;
private final CurseManifest manifest;
private final String name;
private final File run;
private final Path run;
private final ModpackConfiguration<CurseManifest> config;
private final List<Task<?>> dependents = new ArrayList<>(4);
private final List<Task<?>> dependencies = new ArrayList<>(1);
@@ -61,14 +60,14 @@ public final class CurseInstallTask extends Task<Void> {
* @param manifest The manifest content of given CurseForge modpack.
* @param name the new version name
*/
public CurseInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, CurseManifest manifest, String name) {
public CurseInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, Modpack modpack, CurseManifest manifest, String name) {
this.dependencyManager = dependencyManager;
this.zipFile = zipFile;
this.modpack = modpack;
this.manifest = manifest;
this.name = name;
this.repository = dependencyManager.getGameRepository();
this.run = repository.getRunDirectory(name).toFile();
this.run = repository.getRunDirectory(name);
Path json = repository.getModpackConfiguration(name);
if (repository.hasVersion(name) && Files.notExists(json))
@@ -107,7 +106,7 @@ public final class CurseInstallTask extends Task<Void> {
}
this.config = config;
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), Collections.singletonList(manifest.getOverrides()), any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList(manifest.getOverrides()), manifest, CurseModpackProvider.INSTANCE, manifest.getName(), manifest.getVersion(), repository.getModpackConfiguration(name).toFile()).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList(manifest.getOverrides()), manifest, CurseModpackProvider.INSTANCE, manifest.getName(), manifest.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest));
}
@@ -128,11 +127,10 @@ public final class CurseInstallTask extends Task<Void> {
// For update, remove mods not listed in new manifest
for (CurseManifestFile oldCurseManifestFile : config.getManifest().getFiles()) {
if (StringUtils.isBlank(oldCurseManifestFile.getFileName())) continue;
File oldFile = new File(run, "mods/" + oldCurseManifestFile.getFileName());
if (!oldFile.exists()) continue;
Path oldFile = run.resolve("mods/" + oldCurseManifestFile.getFileName());
if (Files.notExists(oldFile)) continue;
if (manifest.getFiles().stream().noneMatch(oldCurseManifestFile::equals))
if (!oldFile.delete())
throw new IOException("Unable to delete mod file " + oldFile);
Files.deleteIfExists(oldFile);
}
}

View File

@@ -30,7 +30,6 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
@@ -49,11 +48,11 @@ public final class CurseModpackProvider implements ModpackProvider {
}
@Override
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, File zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof CurseManifest))
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, Path zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof CurseManifest curseManifest))
throw new MismatchedModpackTypeException(getName(), modpack.getManifest().getProvider().getName());
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new CurseInstallTask(dependencyManager, zipFile, modpack, (CurseManifest) modpack.getManifest(), name));
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new CurseInstallTask(dependencyManager, zipFile, modpack, curseManifest, name));
}
@Override
@@ -69,7 +68,7 @@ public final class CurseModpackProvider implements ModpackProvider {
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(), description, encoding, manifest) {
@Override
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name) {
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name) {
return new CurseInstallTask(dependencyManager, zipFile, this, manifest, name);
}
};

View File

@@ -32,7 +32,6 @@ import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
@@ -55,7 +54,7 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
private final DefaultGameRepository repository;
private final ModManager modManager;
private final String version;
private final File configurationFile;
private final Path configurationFile;
private ModpackConfiguration<McbbsModpackManifest> configuration;
private McbbsModpackManifest manifest;
private final List<Task<?>> dependencies = new ArrayList<>();
@@ -73,7 +72,7 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
this.repository = dependencyManager.getGameRepository();
this.modManager = repository.getModManager(version);
this.version = version;
this.configurationFile = repository.getModpackConfiguration(version).toFile();
this.configurationFile = repository.getModpackConfiguration(version);
this.configuration = configuration;
setStage("hmcl.modpack.download");
@@ -85,7 +84,7 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
if (configuration == null) {
// Load configuration from disk
try {
configuration = JsonUtils.fromNonNullJson(Files.readString(configurationFile.toPath()), ModpackConfiguration.typeOf(McbbsModpackManifest.class));
configuration = JsonUtils.fromNonNullJson(Files.readString(configurationFile), ModpackConfiguration.typeOf(McbbsModpackManifest.class));
} catch (IOException | JsonParseException e) {
throw new IOException("Malformed modpack configuration");
}
@@ -239,7 +238,7 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
manifest = newManifest;
configuration = configuration.setManifest(newManifest);
JsonUtils.writeToJsonFile(configurationFile.toPath(), configuration);
JsonUtils.writeToJsonFile(configurationFile, configuration);
for (McbbsModpackManifest.File file : newManifest.getFiles())
if (file instanceof McbbsModpackManifest.CurseFile) {

View File

@@ -47,16 +47,22 @@ public class McbbsModpackExportTask extends Task<Void> {
private final DefaultGameRepository repository;
private final String version;
private final ModpackExportInfo info;
private final File modpackFile;
private final Path modpackFile;
public McbbsModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo info, File modpackFile) {
public McbbsModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo info, Path modpackFile) {
this.repository = repository;
this.version = version;
this.info = info.validate();
this.modpackFile = modpackFile;
onDone().register(event -> {
if (event.isFailed()) modpackFile.delete();
if (event.isFailed()) {
try {
Files.deleteIfExists(modpackFile);
} catch (IOException e) {
LOG.warning("Failed to delete modpack file: " + modpackFile, e);
}
}
});
}
@@ -66,7 +72,7 @@ public class McbbsModpackExportTask extends Task<Void> {
blackList.add(version + ".jar");
blackList.add(version + ".json");
LOG.info("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker");
try (Zipper zip = new Zipper(modpackFile.toPath())) {
try (var zip = new Zipper(modpackFile)) {
Path runDirectory = repository.getRunDirectory(version);
List<McbbsModpackManifest.File> files = new ArrayList<>();
zip.putDirectory(runDirectory, "overrides", path -> {

View File

@@ -29,7 +29,6 @@ import org.jackhuang.hmcl.mod.ModpackInstallTask;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -38,10 +37,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class McbbsModpackLocalInstallTask extends Task<Void> {
public final class McbbsModpackLocalInstallTask extends Task<Void> {
private final DefaultDependencyManager dependencyManager;
private final File zipFile;
private final Path zipFile;
private final Modpack modpack;
private final McbbsModpackManifest manifest;
private final String name;
@@ -51,7 +50,7 @@ public class McbbsModpackLocalInstallTask extends Task<Void> {
private final List<Task<?>> dependencies = new ArrayList<>(2);
private final List<Task<?>> dependents = new ArrayList<>(4);
public McbbsModpackLocalInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, McbbsModpackManifest manifest, String name) {
public McbbsModpackLocalInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, Modpack modpack, McbbsModpackManifest manifest, String name) {
this.dependencyManager = dependencyManager;
this.zipFile = zipFile;
this.modpack = modpack;
@@ -87,8 +86,8 @@ public class McbbsModpackLocalInstallTask extends Task<Void> {
}
} catch (JsonParseException | IOException ignore) {
}
dependents.add(new ModpackInstallTask<>(zipFile, run.toFile(), modpack.getEncoding(), Collections.singletonList("/overrides"), any -> true, config).withStage("hmcl.modpack"));
instanceTask = new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList("/overrides"), manifest, McbbsModpackProvider.INSTANCE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name).toFile());
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), Collections.singletonList("/overrides"), any -> true, config).withStage("hmcl.modpack"));
instanceTask = new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList("/overrides"), manifest, McbbsModpackProvider.INSTANCE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name));
dependents.add(instanceTask.withStage("hmcl.modpack"));
}

View File

@@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -423,7 +424,7 @@ public class McbbsModpackManifest implements ModpackManifest, Validation {
.orElseThrow(() -> new IOException("Cannot find game version")).getVersion();
return new Modpack(name, author, version, gameVersion, description, encoding, this) {
@Override
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, java.io.File zipFile, String name) {
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name) {
return new McbbsModpackLocalInstallTask(dependencyManager, zipFile, this, McbbsModpackManifest.this, name);
}
};

View File

@@ -26,7 +26,6 @@ import org.jackhuang.hmcl.mod.*;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
@@ -46,11 +45,11 @@ public final class McbbsModpackProvider implements ModpackProvider {
}
@Override
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, File zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof McbbsModpackManifest))
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, Path zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof McbbsModpackManifest mcbbsModpackManifest))
throw new MismatchedModpackTypeException(getName(), modpack.getManifest().getProvider().getName());
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new McbbsModpackLocalInstallTask(dependencyManager, zipFile, modpack, (McbbsModpackManifest) modpack.getManifest(), name));
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new McbbsModpackLocalInstallTask(dependencyManager, zipFile, modpack, mcbbsModpackManifest, name));
}
@Override

View File

@@ -25,7 +25,6 @@ import org.jackhuang.hmcl.mod.*;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -35,23 +34,23 @@ public class ModrinthInstallTask extends Task<Void> {
private final DefaultDependencyManager dependencyManager;
private final DefaultGameRepository repository;
private final File zipFile;
private final Path zipFile;
private final Modpack modpack;
private final ModrinthManifest manifest;
private final String name;
private final File run;
private final Path run;
private final ModpackConfiguration<ModrinthManifest> config;
private final List<Task<?>> dependents = new ArrayList<>(4);
private final List<Task<?>> dependencies = new ArrayList<>(1);
public ModrinthInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, ModrinthManifest manifest, String name) {
public ModrinthInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, Modpack modpack, ModrinthManifest manifest, String name) {
this.dependencyManager = dependencyManager;
this.zipFile = zipFile;
this.modpack = modpack;
this.manifest = manifest;
this.name = name;
this.repository = dependencyManager.getGameRepository();
this.run = repository.getRunDirectory(name).toFile();
this.run = repository.getRunDirectory(name);
Path json = repository.getModpackConfiguration(name);
if (repository.hasVersion(name) && Files.notExists(json))
@@ -103,7 +102,7 @@ public class ModrinthInstallTask extends Task<Void> {
this.config = config;
List<String> subDirectories = Arrays.asList("/client-overrides", "/overrides");
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), subDirectories, any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), subDirectories, manifest, ModrinthModpackProvider.INSTANCE, manifest.getName(), manifest.getVersionId(), repository.getModpackConfiguration(name).toFile()).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), subDirectories, manifest, ModrinthModpackProvider.INSTANCE, manifest.getName(), manifest.getVersionId(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependencies.add(new ModrinthCompletionTask(dependencyManager, name, manifest));
}
@@ -123,7 +122,7 @@ public class ModrinthInstallTask extends Task<Void> {
if (config != null) {
// For update, remove mods not listed in new manifest
for (ModrinthManifest.File oldManifestFile : config.getManifest().getFiles()) {
Path oldFile = run.toPath().resolve(oldManifestFile.getPath());
Path oldFile = run.resolve(oldManifestFile.getPath());
if (!Files.exists(oldFile)) continue;
if (manifest.getFiles().stream().noneMatch(oldManifestFile::equals)) {
Files.deleteIfExists(oldFile);

View File

@@ -27,16 +27,22 @@ public class ModrinthModpackExportTask extends Task<Void> {
private final DefaultGameRepository repository;
private final String version;
private final ModpackExportInfo info;
private final File modpackFile;
private final Path modpackFile;
public ModrinthModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo info, File modpackFile) {
public ModrinthModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo info, Path modpackFile) {
this.repository = repository;
this.version = version;
this.info = info.validate();
this.modpackFile = modpackFile;
onDone().register(event -> {
if (event.isFailed()) modpackFile.delete();
if (event.isFailed()) {
try {
Files.deleteIfExists(modpackFile);
} catch (IOException e) {
LOG.warning("Failed to delete modpack file: " + modpackFile, e);
}
}
});
}
@@ -107,7 +113,7 @@ public class ModrinthModpackExportTask extends Task<Void> {
blackList.add(version + ".jar");
blackList.add(version + ".json");
LOG.info("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker");
try (Zipper zip = new Zipper(modpackFile.toPath())) {
try (var zip = new Zipper(modpackFile)) {
Path runDirectory = repository.getRunDirectory(version);
List<ModrinthManifest.File> files = new ArrayList<>();
Set<String> filesInManifest = new HashSet<>();
@@ -139,7 +145,7 @@ public class ModrinthModpackExportTask extends Task<Void> {
}
zip.putDirectory(runDirectory, "client-overrides", path -> {
String relativePath = path.toString().replace(File.separatorChar, '/');
String relativePath = path.replace(File.separatorChar, '/');
if (filesInManifest.contains(relativePath)) {
return false;
}

View File

@@ -28,7 +28,6 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
@@ -47,11 +46,11 @@ public final class ModrinthModpackProvider implements ModpackProvider {
}
@Override
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, File zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof ModrinthManifest))
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, Path zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof ModrinthManifest modrinthManifest))
throw new MismatchedModpackTypeException(getName(), modpack.getManifest().getProvider().getName());
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new ModrinthInstallTask(dependencyManager, zipFile, modpack, (ModrinthManifest) modpack.getManifest(), name));
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new ModrinthInstallTask(dependencyManager, zipFile, modpack, modrinthManifest, name));
}
@Override
@@ -59,7 +58,7 @@ public final class ModrinthModpackProvider implements ModpackProvider {
ModrinthManifest manifest = JsonUtils.fromNonNullJson(CompressingUtils.readTextZipEntry(zip, "modrinth.index.json"), ModrinthManifest.class);
return new Modpack(manifest.getName(), "", manifest.getVersionId(), manifest.getGameVersion(), manifest.getSummary(), encoding, manifest) {
@Override
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, java.io.File zipFile, String name) {
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name) {
return new ModrinthInstallTask(dependencyManager, zipFile, this, manifest, name);
}
};

View File

@@ -26,9 +26,10 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.Zipper;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -44,13 +45,13 @@ public class MultiMCModpackExportTask extends Task<Void> {
private final String versionId;
private final List<String> whitelist;
private final MultiMCInstanceConfiguration configuration;
private final File output;
private final Path output;
/**
* @param output mod pack file.
* @param versionId to locate version.json
*/
public MultiMCModpackExportTask(DefaultGameRepository repository, String versionId, List<String> whitelist, MultiMCInstanceConfiguration configuration, File output) {
public MultiMCModpackExportTask(DefaultGameRepository repository, String versionId, List<String> whitelist, MultiMCInstanceConfiguration configuration, Path output) {
this.repository = repository;
this.versionId = versionId;
this.whitelist = whitelist;
@@ -58,7 +59,13 @@ public class MultiMCModpackExportTask extends Task<Void> {
this.output = output;
onDone().register(event -> {
if (event.isFailed()) output.delete();
if (event.isFailed()) {
try {
Files.deleteIfExists(output);
} catch (IOException e) {
LOG.warning("Failed to delete modpack file: " + output, e);
}
}
});
}
@@ -68,7 +75,7 @@ public class MultiMCModpackExportTask extends Task<Void> {
blackList.add(versionId + ".jar");
blackList.add(versionId + ".json");
LOG.info("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker");
try (Zipper zip = new Zipper(output.toPath())) {
try (Zipper zip = new Zipper(output)) {
zip.putDirectory(repository.getRunDirectory(versionId), ".minecraft", path -> Modpack.acceptFile(path, blackList, whitelist));
String gameVersion = repository.getGameVersion(versionId)

View File

@@ -39,7 +39,6 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
@@ -77,7 +76,7 @@ import java.util.Objects;
*/
public final class MultiMCModpackInstallTask extends Task<MultiMCInstancePatch.ResolvedInstance> {
private final File zipFile;
private final Path zipFile;
private final Modpack modpack;
private final MultiMCInstanceConfiguration manifest;
private final String name;
@@ -86,7 +85,7 @@ public final class MultiMCModpackInstallTask extends Task<MultiMCInstancePatch.R
private final List<Task<?>> dependencies = new ArrayList<>();
private final DefaultDependencyManager dependencyManager;
public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, MultiMCInstanceConfiguration manifest, String name) {
public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, Modpack modpack, MultiMCInstanceConfiguration manifest, String name) {
this.zipFile = zipFile;
this.modpack = modpack;
this.manifest = manifest;
@@ -133,8 +132,8 @@ public final class MultiMCModpackInstallTask extends Task<MultiMCInstancePatch.R
}
// TODO: Optimize unbearably slow ModpackInstallTask
dependents.add(new ModpackInstallTask<>(zipFile, run.toFile(), modpack.getEncoding(), Collections.singletonList(mcDirectory), any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList(mcDirectory), manifest, MultiMCModpackProvider.INSTANCE, manifest.getName(), null, repository.getModpackConfiguration(name).toFile()).withStage("hmcl.modpack"));
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), Collections.singletonList(mcDirectory), any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList(mcDirectory), manifest, MultiMCModpackProvider.INSTANCE, manifest.getName(), null, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
}
// Stage #1: Load all related Json-Patch from meta maven or local mod pack.
@@ -351,7 +350,7 @@ public final class MultiMCModpackInstallTask extends Task<MultiMCInstancePatch.R
}
private FileSystem openModpack() throws IOException {
return CompressingUtils.readonly(zipFile.toPath()).setAutoDetectEncoding(true).setEncoding(modpack.getEncoding()).build();
return CompressingUtils.readonly(zipFile).setAutoDetectEncoding(true).setEncoding(modpack.getEncoding()).build();
}
private static boolean testPath(Path root) {

View File

@@ -27,7 +27,6 @@ import org.jackhuang.hmcl.mod.ModpackUpdateTask;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
@@ -47,11 +46,11 @@ public final class MultiMCModpackProvider implements ModpackProvider {
}
@Override
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, File zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof MultiMCInstanceConfiguration))
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, Path zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof MultiMCInstanceConfiguration multiMCInstanceConfiguration))
throw new MismatchedModpackTypeException(getName(), modpack.getManifest().getProvider().getName());
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new MultiMCModpackInstallTask(dependencyManager, zipFile, modpack, (MultiMCInstanceConfiguration) modpack.getManifest(), name));
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new MultiMCModpackInstallTask(dependencyManager, zipFile, modpack, multiMCInstanceConfiguration, name));
}
private static String getRootEntryName(ZipArchiveReader file) throws IOException {
@@ -86,7 +85,7 @@ public final class MultiMCModpackProvider implements ModpackProvider {
MultiMCInstanceConfiguration cfg = new MultiMCInstanceConfiguration(name, instanceStream, manifest);
return new Modpack(cfg.getName(), "", "", cfg.getGameVersion(), cfg.getNotes(), encoding, cfg) {
@Override
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name) {
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name) {
return new MultiMCModpackInstallTask(dependencyManager, zipFile, this, cfg, name);
}
};

View File

@@ -43,16 +43,22 @@ public class ServerModpackExportTask extends Task<Void> {
private final DefaultGameRepository repository;
private final String versionId;
private final ModpackExportInfo exportInfo;
private final File modpackFile;
private final Path modpackFile;
public ServerModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo exportInfo, File modpackFile) {
public ServerModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo exportInfo, Path modpackFile) {
this.repository = repository;
this.versionId = version;
this.exportInfo = exportInfo.validate();
this.modpackFile = modpackFile;
onDone().register(event -> {
if (event.isFailed()) modpackFile.delete();
if (event.isFailed()) {
try {
Files.deleteIfExists(modpackFile);
} catch (IOException e) {
LOG.warning("Failed to delete modpack file: " + modpackFile, e);
}
}
});
}
@@ -62,7 +68,7 @@ public class ServerModpackExportTask extends Task<Void> {
blackList.add(versionId + ".jar");
blackList.add(versionId + ".json");
LOG.info("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker");
try (Zipper zip = new Zipper(modpackFile.toPath())) {
try (Zipper zip = new Zipper(modpackFile)) {
Path runDirectory = repository.getRunDirectory(versionId);
List<ModpackConfiguration.FileInformation> files = new ArrayList<>();
zip.putDirectory(runDirectory, "overrides", path -> {

View File

@@ -28,7 +28,6 @@ import org.jackhuang.hmcl.mod.ModpackInstallTask;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -38,7 +37,7 @@ import java.util.List;
public class ServerModpackLocalInstallTask extends Task<Void> {
private final File zipFile;
private final Path zipFile;
private final Modpack modpack;
private final ServerModpackManifest manifest;
private final String name;
@@ -46,7 +45,7 @@ public class ServerModpackLocalInstallTask extends Task<Void> {
private final List<Task<?>> dependencies = new ArrayList<>();
private final List<Task<?>> dependents = new ArrayList<>(4);
public ServerModpackLocalInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, ServerModpackManifest manifest, String name) {
public ServerModpackLocalInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, Modpack modpack, ServerModpackManifest manifest, String name) {
this.zipFile = zipFile;
this.modpack = modpack;
this.manifest = manifest;
@@ -79,8 +78,8 @@ public class ServerModpackLocalInstallTask extends Task<Void> {
}
} catch (JsonParseException | IOException ignore) {
}
dependents.add(new ModpackInstallTask<>(zipFile, run.toFile(), modpack.getEncoding(), Collections.singletonList("/overrides"), any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList("/overrides"), manifest, ServerModpackProvider.INSTANCE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name).toFile()).withStage("hmcl.modpack"));
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), Collections.singletonList("/overrides"), any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), Collections.singletonList("/overrides"), manifest, ServerModpackProvider.INSTANCE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
}
@Override

View File

@@ -27,9 +27,9 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.TolerableValidationException;
import org.jackhuang.hmcl.util.gson.Validation;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
@@ -126,7 +126,7 @@ public class ServerModpackManifest implements ModpackManifest, Validation {
.orElseThrow(() -> new IOException("Cannot find game version")).getVersion();
return new Modpack(name, author, version, gameVersion, description, encoding, this) {
@Override
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name) {
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name) {
return new ServerModpackLocalInstallTask(dependencyManager, zipFile, this, ServerModpackManifest.this, name);
}
};

View File

@@ -28,7 +28,6 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
@@ -47,11 +46,11 @@ public final class ServerModpackProvider implements ModpackProvider {
}
@Override
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, File zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof ServerModpackManifest))
public Task<?> createUpdateTask(DefaultDependencyManager dependencyManager, String name, Path zipFile, Modpack modpack) throws MismatchedModpackTypeException {
if (!(modpack.getManifest() instanceof ServerModpackManifest serverModpackManifest))
throw new MismatchedModpackTypeException(getName(), modpack.getManifest().getProvider().getName());
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new ServerModpackLocalInstallTask(dependencyManager, zipFile, modpack, (ServerModpackManifest) modpack.getManifest(), name));
return new ModpackUpdateTask(dependencyManager.getGameRepository(), name, new ServerModpackLocalInstallTask(dependencyManager, zipFile, modpack, serverModpackManifest, name));
}
@Override

View File

@@ -22,7 +22,6 @@ import kala.compress.archivers.zip.ZipArchiveReader;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
@@ -237,8 +236,8 @@ public final class CompressingUtils {
* @return the plain text content of given file.
* @throws IOException if the file is not a valid zip file.
*/
public static String readTextZipEntry(File zipFile, String name) throws IOException {
try (ZipArchiveReader s = new ZipArchiveReader(zipFile.toPath())) {
public static String readTextZipEntry(Path zipFile, String name) throws IOException {
try (ZipArchiveReader s = new ZipArchiveReader(zipFile)) {
return readTextZipEntry(s, name);
}
}
@@ -269,21 +268,6 @@ public final class CompressingUtils {
}
}
/**
* Read the text content of a file in zip.
*
* @param file the zip file
* @param name the location of the text in zip file, something like A/B/C/D.txt
* @return the plain text content of given file.
*/
public static Optional<String> readTextZipEntryQuietly(File file, String name) {
try {
return Optional.of(readTextZipEntry(file, name));
} catch (IOException | NullPointerException e) {
return Optional.empty();
}
}
/**
* Read the text content of a file in zip.
*