导出日志时允许重名文件 (#4733)
This commit is contained in:
@@ -64,7 +64,7 @@ public final class LogExporter {
|
||||
}
|
||||
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try (Zipper zipper = new Zipper(zipFile)) {
|
||||
try (Zipper zipper = new Zipper(zipFile, true)) {
|
||||
processLogs(runDirectory.resolve("liteconfig"), "*.log", "liteconfig", zipper, logMatcher);
|
||||
processLogs(runDirectory.resolve("logs"), "*.log", "logs", zipper, logMatcher);
|
||||
processLogs(runDirectory, "*.log", "runDirectory", zipper, logMatcher);
|
||||
|
||||
@@ -63,9 +63,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@@ -330,6 +328,19 @@ public final class SettingsPage extends ScrollPane {
|
||||
UpdateHandler.updateFrom(target);
|
||||
}
|
||||
|
||||
private static String getEntryName(Set<String> entryNames, String name) {
|
||||
if (entryNames.add(name)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
for (long i = 1; ; i++) {
|
||||
String newName = name + "." + i;
|
||||
if (entryNames.add(newName)) {
|
||||
return newName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This method guarantees to close both `input` and the current zip entry.
|
||||
///
|
||||
/// If no exception occurs, this method returns `true`;
|
||||
@@ -389,6 +400,8 @@ public final class SettingsPage extends ScrollPane {
|
||||
try (var os = Files.newOutputStream(outputFile);
|
||||
var zos = new ZipOutputStream(os)) {
|
||||
|
||||
Set<String> entryNames = new HashSet<>();
|
||||
|
||||
for (Path path : recentLogFiles) {
|
||||
String fileName = FileUtils.getName(path);
|
||||
String extension = StringUtils.substringAfterLast(fileName, '.');
|
||||
@@ -410,7 +423,7 @@ public final class SettingsPage extends ScrollPane {
|
||||
input = null;
|
||||
}
|
||||
|
||||
String entryName = StringUtils.substringBeforeLast(fileName, ".");
|
||||
String entryName = getEntryName(entryNames, StringUtils.substringBeforeLast(fileName, "."));
|
||||
if (input != null && exportLogFile(zos, path, entryName, input, buffer))
|
||||
continue;
|
||||
}
|
||||
@@ -427,10 +440,10 @@ public final class SettingsPage extends ScrollPane {
|
||||
continue;
|
||||
}
|
||||
|
||||
exportLogFile(zos, path, fileName, input, buffer);
|
||||
exportLogFile(zos, path, getEntryName(entryNames, fileName), input, buffer);
|
||||
}
|
||||
|
||||
zos.putNextEntry(new ZipEntry("hmcl-latest.log"));
|
||||
zos.putNextEntry(new ZipEntry(getEntryName(entryNames, "hmcl-latest.log")));
|
||||
LOG.exportLogs(zos);
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
@@ -39,13 +41,15 @@ public final class Zipper implements Closeable {
|
||||
|
||||
private final ZipOutputStream zos;
|
||||
private final byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
private final Set<String> entryNames;
|
||||
|
||||
public Zipper(Path zipFile) throws IOException {
|
||||
this(zipFile, StandardCharsets.UTF_8);
|
||||
this(zipFile, false);
|
||||
}
|
||||
|
||||
public Zipper(Path zipFile, Charset encoding) throws IOException {
|
||||
this.zos = new ZipOutputStream(Files.newOutputStream(zipFile), encoding);
|
||||
public Zipper(Path zipFile, boolean allowDuplicateEntry) throws IOException {
|
||||
this.zos = new ZipOutputStream(Files.newOutputStream(zipFile), StandardCharsets.UTF_8);
|
||||
this.entryNames = allowDuplicateEntry ? new HashSet<>() : null;
|
||||
}
|
||||
|
||||
private static String normalize(String path) {
|
||||
@@ -57,6 +61,20 @@ public final class Zipper implements Closeable {
|
||||
return path;
|
||||
}
|
||||
|
||||
private ZipEntry newEntry(String name) throws IOException {
|
||||
if (entryNames == null || name.endsWith("/") || entryNames.add(name))
|
||||
return new ZipEntry(name);
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
String newName = name + "." + i;
|
||||
if (entryNames.add(newName)) {
|
||||
return new ZipEntry(newName);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ZipException("duplicate entry: " + name);
|
||||
}
|
||||
|
||||
private static String resolve(String dir, String file) {
|
||||
if (dir.isEmpty()) return file;
|
||||
if (file.isEmpty()) return dir;
|
||||
@@ -118,16 +136,12 @@ public final class Zipper implements Closeable {
|
||||
});
|
||||
}
|
||||
|
||||
public void putFile(File file, String path) throws IOException {
|
||||
putFile(file.toPath(), path);
|
||||
}
|
||||
|
||||
public void putFile(Path file, String path) throws IOException {
|
||||
path = normalize(path);
|
||||
|
||||
BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
|
||||
|
||||
ZipEntry entry = new ZipEntry(attrs.isDirectory() ? path + "/" : path);
|
||||
ZipEntry entry = newEntry(attrs.isDirectory() ? path + "/" : path);
|
||||
entry.setCreationTime(attrs.creationTime());
|
||||
entry.setLastAccessTime(attrs.lastAccessTime());
|
||||
entry.setLastModifiedTime(attrs.lastModifiedTime());
|
||||
@@ -149,13 +163,13 @@ public final class Zipper implements Closeable {
|
||||
}
|
||||
|
||||
public void putStream(InputStream in, String path) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(normalize(path)));
|
||||
zos.putNextEntry(newEntry(normalize(path)));
|
||||
IOUtils.copyTo(in, zos, buffer);
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
public OutputStream putStream(String path) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(normalize(path)));
|
||||
zos.putNextEntry(newEntry(normalize(path)));
|
||||
return new OutputStream() {
|
||||
public void write(int b) throws IOException {
|
||||
zos.write(b);
|
||||
@@ -180,7 +194,7 @@ public final class Zipper implements Closeable {
|
||||
}
|
||||
|
||||
public void putLines(Stream<String> lines, String path) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(normalize(path)));
|
||||
zos.putNextEntry(newEntry(normalize(path)));
|
||||
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(zos));
|
||||
@@ -205,7 +219,7 @@ public final class Zipper implements Closeable {
|
||||
}
|
||||
|
||||
public void putTextFile(String text, Charset encoding, String path) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(normalize(path)));
|
||||
zos.putNextEntry(newEntry(normalize(path)));
|
||||
zos.write(text.getBytes(encoding));
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user