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