Skip to content
Merged
Show file tree
Hide file tree
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
41 changes: 41 additions & 0 deletions src/main/java/me/itzg/helpers/errors/ExceptionDetailer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package me.itzg.helpers.errors;

import java.util.ArrayList;
import java.util.Iterator;

public class ExceptionDetailer {

private static class CauseIterator implements Iterator<Throwable> {
private Throwable current;

CauseIterator(Throwable initial) {
this.current = initial;
}

@Override
public boolean hasNext() {
return current != null;
}

public Throwable next() {
if (current == null) {
return null;
}
Throwable result = current;
current = current.getCause();
return result;
}
}

public static String buildCausalMessages(Throwable throwable) {
final CauseIterator causeIterator = new CauseIterator(throwable);
final ArrayList<String> parts = new ArrayList<>();
while (causeIterator.hasNext()) {
final Throwable cause = causeIterator.next();
if (cause != null) {
parts.add(cause.getClass().getSimpleName() + ": " + cause.getMessage());
}
}
return String.join("; ", parts);
}
}
18 changes: 16 additions & 2 deletions src/main/java/me/itzg/helpers/sync/SynchronizingFileVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.nio.file.attribute.FileTime;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import me.itzg.helpers.errors.ExceptionDetailer;
import me.itzg.helpers.errors.InvalidParameterException;

@Slf4j
class SynchronizingFileVisitor implements FileVisitor<Path> {
Expand All @@ -24,9 +26,21 @@ public SynchronizingFileVisitor(Path src, Path dest, boolean skipNewerInDestinat
this.fileProcessor = fileProcessor;
}

/**
* Convenience method that processes each source path into the destination path by applying a {@link SynchronizingFileVisitor}
* to each source.
* @param srcDest source... dest
* @param skipNewerInDestination provided to {@link SynchronizingFileVisitor}
* @param fileProcessor provided to {@link SynchronizingFileVisitor}
* @return exit code style of 1 for failure, 0 for success
*/
static int walkDirectories(List<Path> srcDest, boolean skipNewerInDestination,
FileProcessor fileProcessor
) {
if (srcDest.size() < 2) {
throw new InvalidParameterException("At least one source and destination path is required");
}

// TODO can use getLast() with java 21
final Path dest = srcDest.get(srcDest.size() - 1);

Expand All @@ -35,7 +49,7 @@ static int walkDirectories(List<Path> srcDest, boolean skipNewerInDestination,
try {
Files.walkFileTree(src, new SynchronizingFileVisitor(src, dest, skipNewerInDestination, fileProcessor));
} catch (IOException e) {
log.error("Failed to sync and interpolate {} into {} : {}", src, dest, e.getMessage());
log.error("Failed to sync and interpolate {} into {}: {}", src, dest, ExceptionDetailer.buildCausalMessages(e));
log.debug("Details", e);
return 1;
}
Expand Down Expand Up @@ -104,7 +118,7 @@ private boolean shouldProcessFile(Path srcFile, Path destFile) throws IOExceptio

@Override
public FileVisitResult visitFileFailed(Path file, IOException e) {
log.warn("Failed to visit file {} due to {}:{}", file, e.getClass(), e.getMessage());
log.warn("Failed to visit file {} due to {}", file, ExceptionDetailer.buildCausalMessages(e));
log.debug("Details", e);
return FileVisitResult.CONTINUE;
}
Expand Down