diff --git a/core/src/main/java/com/threerings/getdown/data/Application.java b/core/src/main/java/com/threerings/getdown/data/Application.java index 7943d38..9b6f650 100644 --- a/core/src/main/java/com/threerings/getdown/data/Application.java +++ b/core/src/main/java/com/threerings/getdown/data/Application.java @@ -362,6 +362,13 @@ public class Application return _digest.getDigest(resource); } + /** + * Returns a list of the cleanup patterns used by application. + */ + public List cleanupPatterns() { + return _cleanupPatterns; + } + /** * Returns a list of all the active {@link Resource} objects used by this application (code and * non-code). @@ -594,6 +601,7 @@ public class Application initJava(config); initTracking(config); initResources(config); + initCleanupPatterns(config); initArgs(config); return config; } @@ -753,6 +761,22 @@ public class Application } } + /** + * Reads the cleanup patterns from {@code config} into this instance. + */ + public void initCleanupPatterns (Config config) { + // clear our arrays as we may be reinitializing + _cleanupPatterns.clear(); + + // parse cleanup patterns + String[] patterns = config.getMultiValue("cleanup_pattern"); + if (patterns == null) { + return; + } + + _cleanupPatterns.addAll(Arrays.asList(patterns)); + } + /** * Reads the command line arg info from {@code config} into this instance. */ @@ -1771,6 +1795,7 @@ public class Application protected List _codes = new ArrayList<>(); protected List _resources = new ArrayList<>(); + protected List _cleanupPatterns = new ArrayList<>(); protected List _cpdirs = new ArrayList<>(); protected int _verifyTimeout = 60; diff --git a/core/src/main/java/com/threerings/getdown/util/FileUtil.java b/core/src/main/java/com/threerings/getdown/util/FileUtil.java index d7de78b..38dd1c3 100644 --- a/core/src/main/java/com/threerings/getdown/util/FileUtil.java +++ b/core/src/main/java/com/threerings/getdown/util/FileUtil.java @@ -6,6 +6,8 @@ package com.threerings.getdown.util; import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; import java.util.*; import java.util.jar.*; import java.util.zip.*; @@ -236,4 +238,44 @@ public final class FileUtil } } } + + /** + * Returns files as Paths from path {@code basePath}, filtered Glob pattern {@code globPattern}. + */ + public static Set getFilePathsByGlob(String basePath, String globPattern) { + + //massaging glob pattern + final String globPatternUnixSeparator = globPattern.replace("\\", "/"); + final String glob = String.format("glob:%s%s%s", + basePath.replace("\\", "/"), + globPatternUnixSeparator.startsWith("/") ? "" : "/", + globPatternUnixSeparator); + + final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(glob); + final Set foundFilePaths = new HashSet<>(); + + try { + Files.walkFileTree(Paths.get(basePath), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path path, + BasicFileAttributes attrs) { + if (pathMatcher.matches(path) && !Files.isDirectory(path)) { + foundFilePaths.add(path); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + return FileVisitResult.CONTINUE; + } + }); + } catch (Exception e) { + log.warning(String.format("Failed to get file list with path %s with glob %s", + basePath, globPattern), "error", e); + return Collections.emptySet(); + } + + return foundFilePaths; + } } diff --git a/launcher/src/main/java/com/threerings/getdown/launcher/Getdown.java b/launcher/src/main/java/com/threerings/getdown/launcher/Getdown.java index 1cc6922..b6f2a5f 100644 --- a/launcher/src/main/java/com/threerings/getdown/launcher/Getdown.java +++ b/launcher/src/main/java/com/threerings/getdown/launcher/Getdown.java @@ -22,6 +22,7 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -424,6 +425,12 @@ public abstract class Getdown _readyToInstall = true; install(); + // do resource cleanup + final List cleanupPatterns = _app.cleanupPatterns(); + if (!cleanupPatterns.isEmpty()) { + cleanupResources(cleanupPatterns); + } + // Only launch if we aren't in silent mode. Some mystery program starting out // of the blue would be disconcerting. if (!_silent || _launchInSilent) { @@ -679,6 +686,37 @@ public abstract class Getdown } } + /** + * Removes files/resources by glob pattern with exclusion of resources defined in Getdown.txt + */ + void cleanupResources(List cleanupPatterns) { + //get list of files from glob patterns + final String applicationPath = _app.getAppDir().getAbsolutePath(); + final Set filesFromGlob = new HashSet<>(); + for (String cleanupPattern : cleanupPatterns) { + filesFromGlob.addAll(FileUtil.getFilePathsByGlob(applicationPath, cleanupPattern)); + } + + //filter out files contained in resources + Set rsrcs = new HashSet<>(); + for (Resource resource : _app.getAllActiveResources()) { + rsrcs.add(resource.getLocal().toPath().toAbsolutePath()); + } + + final Set cleanupSet = new HashSet<>(); + for (Path path : filesFromGlob) { + if (!rsrcs.contains(path)) { + cleanupSet.add(path); + } + } + + if (!cleanupSet.isEmpty()) { + for (Path path : cleanupSet) { + path.toFile().delete(); + } + } + } + /** * Called to launch the application if everything is determined to be ready to go. */