@@ -17,19 +17,22 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import kala.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.tree.ArchiveFileTree;
|
||||
import org.jackhuang.hmcl.util.tree.ZipFileTree;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class MinecraftInstanceTask<T> extends Task<ModpackConfiguration<T>> {
|
||||
|
||||
@@ -53,26 +56,42 @@ public final class MinecraftInstanceTask<T> extends Task<ModpackConfiguration<T>
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
private static void getOverrides(List<ModpackConfiguration.FileInformation> overrides,
|
||||
ZipFileTree tree,
|
||||
ArchiveFileTree.Dir<ZipArchiveEntry> dir,
|
||||
List<String> names) throws IOException {
|
||||
String prefix = String.join("/", names);
|
||||
if (!prefix.isEmpty())
|
||||
prefix = prefix + "/";
|
||||
|
||||
for (Map.Entry<String, ZipArchiveEntry> entry : dir.getFiles().entrySet()) {
|
||||
String hash;
|
||||
try (InputStream input = tree.getInputStream(entry.getValue())) {
|
||||
hash = DigestUtils.digestToString("SHA-1", input);
|
||||
}
|
||||
overrides.add(new ModpackConfiguration.FileInformation(prefix + entry.getKey(), hash));
|
||||
}
|
||||
|
||||
for (ArchiveFileTree.Dir<ZipArchiveEntry> subDir : dir.getSubDirs().values()) {
|
||||
names.add(subDir.getName());
|
||||
getOverrides(overrides, tree, subDir, names);
|
||||
names.remove(names.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
List<ModpackConfiguration.FileInformation> overrides = new ArrayList<>();
|
||||
|
||||
try (FileSystem fs = CompressingUtils.readonly(zipFile).setEncoding(encoding).build()) {
|
||||
try (var tree = new ZipFileTree(CompressingUtils.openZipFileWithPossibleEncoding(zipFile, encoding))) {
|
||||
for (String subDirectory : subDirectories) {
|
||||
Path root = fs.getPath(subDirectory);
|
||||
|
||||
if (Files.exists(root))
|
||||
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, '/');
|
||||
overrides.add(new ModpackConfiguration.FileInformation(relativePath, DigestUtils.digestToString("SHA-1", file)));
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
ArchiveFileTree.Dir<ZipArchiveEntry> root = tree.getDirectory(subDirectory);
|
||||
if (root == null)
|
||||
continue;
|
||||
var names = new ArrayList<String>();
|
||||
getOverrides(overrides, tree, root, names);
|
||||
}
|
||||
}
|
||||
|
||||
ModpackConfiguration<T> configuration = new ModpackConfiguration<>(manifest, type, name, version, overrides);
|
||||
Files.createDirectories(jsonFile.getParent());
|
||||
JsonUtils.writeToJsonFile(jsonFile, configuration);
|
||||
|
||||
@@ -133,12 +133,28 @@ public final class CompressingUtils {
|
||||
}
|
||||
|
||||
public static ZipArchiveReader openZipFile(Path zipFile) throws IOException {
|
||||
return openZipFileWithPossibleEncoding(zipFile, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static ZipArchiveReader openZipFile(Path zipFile, Charset charset) throws IOException {
|
||||
return new ZipArchiveReader(zipFile, charset);
|
||||
}
|
||||
|
||||
public static ZipArchiveReader openZipFileWithPossibleEncoding(Path zipFile, Charset possibleEncoding) throws IOException {
|
||||
if (possibleEncoding == null)
|
||||
possibleEncoding = StandardCharsets.UTF_8;
|
||||
|
||||
ZipArchiveReader zipReader = new ZipArchiveReader(Files.newByteChannel(zipFile));
|
||||
|
||||
Charset suitableEncoding;
|
||||
try {
|
||||
suitableEncoding = findSuitableEncoding(zipReader);
|
||||
if (suitableEncoding == StandardCharsets.UTF_8)
|
||||
return zipReader;
|
||||
if (possibleEncoding != StandardCharsets.UTF_8 && CompressingUtils.testEncoding(zipReader, possibleEncoding)) {
|
||||
suitableEncoding = possibleEncoding;
|
||||
} else {
|
||||
suitableEncoding = CompressingUtils.findSuitableEncoding(zipReader);
|
||||
if (suitableEncoding == StandardCharsets.UTF_8)
|
||||
return zipReader;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
IOUtils.closeQuietly(zipReader, e);
|
||||
throw e;
|
||||
@@ -148,10 +164,6 @@ public final class CompressingUtils {
|
||||
return new ZipArchiveReader(Files.newByteChannel(zipFile), suitableEncoding);
|
||||
}
|
||||
|
||||
public static ZipArchiveReader openZipFile(Path zipFile, Charset charset) throws IOException {
|
||||
return new ZipArchiveReader(zipFile, charset);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private boolean autoDetectEncoding = false;
|
||||
private Charset encoding = StandardCharsets.UTF_8;
|
||||
|
||||
@@ -80,27 +80,6 @@ public final class Unzipper {
|
||||
return this;
|
||||
}
|
||||
|
||||
private ZipArchiveReader openReader() throws IOException {
|
||||
ZipArchiveReader zipReader = new ZipArchiveReader(Files.newByteChannel(zipFile));
|
||||
|
||||
Charset suitableEncoding;
|
||||
try {
|
||||
if (encoding != StandardCharsets.UTF_8 && CompressingUtils.testEncoding(zipReader, encoding)) {
|
||||
suitableEncoding = encoding;
|
||||
} else {
|
||||
suitableEncoding = CompressingUtils.findSuitableEncoding(zipReader);
|
||||
if (suitableEncoding == StandardCharsets.UTF_8)
|
||||
return zipReader;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
IOUtils.closeQuietly(zipReader, e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
zipReader.close();
|
||||
return new ZipArchiveReader(Files.newByteChannel(zipFile), suitableEncoding);
|
||||
}
|
||||
|
||||
/// Decompress the given zip file to a directory.
|
||||
///
|
||||
/// @throws IOException if zip file is malformed or filesystem error.
|
||||
@@ -113,7 +92,7 @@ public final class Unzipper {
|
||||
: new CopyOption[]{};
|
||||
|
||||
long entryCount = 0L;
|
||||
try (ZipArchiveReader reader = openReader()) {
|
||||
try (ZipArchiveReader reader = CompressingUtils.openZipFileWithPossibleEncoding(zipFile, encoding)) {
|
||||
String pathPrefix = StringUtils.addSuffix(subDirectory, "/");
|
||||
|
||||
for (ZipArchiveEntry entry : reader.getEntries()) {
|
||||
|
||||
@@ -90,6 +90,22 @@ public abstract class ArchiveFileTree<R, E extends ArchiveEntry> implements Clos
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Dir<E> getDirectory(@NotNull String dirPath) {
|
||||
Dir<E> dir = root;
|
||||
if (dirPath.isEmpty()) {
|
||||
return dir;
|
||||
}
|
||||
String[] path = dirPath.split("/");
|
||||
for (String item : path) {
|
||||
if (item.isEmpty())
|
||||
continue;
|
||||
dir = dir.getSubDirs().get(item);
|
||||
if (dir == null)
|
||||
return null;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
protected void addEntry(E entry) throws IOException {
|
||||
String[] path = entry.getName().split("/");
|
||||
List<String> pathList = Arrays.asList(path);
|
||||
|
||||
Reference in New Issue
Block a user