package net.minecraft.server.packs; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; public class DownloadCacheCleaner { private static final Logger LOGGER = LogUtils.getLogger(); public static void vacuumCacheDir(Path path, int maxEntries) { try { List list = listFilesWithModificationTimes(path); int i = list.size() - maxEntries; if (i <= 0) { return; } list.sort(DownloadCacheCleaner.PathAndTime.NEWEST_FIRST); List list2 = prioritizeFilesInDirs(list); Collections.reverse(list2); list2.sort(DownloadCacheCleaner.PathAndPriority.HIGHEST_PRIORITY_FIRST); Set set = new HashSet(); for (int j = 0; j < i; j++) { DownloadCacheCleaner.PathAndPriority pathAndPriority = (DownloadCacheCleaner.PathAndPriority)list2.get(j); Path path2 = pathAndPriority.path; try { Files.delete(path2); if (pathAndPriority.removalPriority == 0) { set.add(path2.getParent()); } } catch (IOException var12) { LOGGER.warn("Failed to delete cache file {}", path2, var12); } } set.remove(path); for (Path path3 : set) { try { Files.delete(path3); } catch (DirectoryNotEmptyException var10) { } catch (IOException var11) { LOGGER.warn("Failed to delete empty(?) cache directory {}", path3, var11); } } } catch (UncheckedIOException | IOException var13) { LOGGER.error("Failed to vacuum cache dir {}", path, var13); } } private static List listFilesWithModificationTimes(Path path) throws IOException { try { final List list = new ArrayList(); Files.walkFileTree(path, new SimpleFileVisitor() { public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { if (attributes.isRegularFile() && !file.getParent().equals(path)) { FileTime fileTime = attributes.lastModifiedTime(); list.add(new DownloadCacheCleaner.PathAndTime(file, fileTime)); } return FileVisitResult.CONTINUE; } }); return list; } catch (NoSuchFileException var2) { return List.of(); } } private static List prioritizeFilesInDirs(List paths) { List list = new ArrayList(); Object2IntOpenHashMap object2IntOpenHashMap = new Object2IntOpenHashMap<>(); for (DownloadCacheCleaner.PathAndTime pathAndTime : paths) { int i = object2IntOpenHashMap.addTo(pathAndTime.path.getParent(), 1); list.add(new DownloadCacheCleaner.PathAndPriority(pathAndTime.path, i)); } return list; } record PathAndPriority(Path path, int removalPriority) { public static final Comparator HIGHEST_PRIORITY_FIRST = Comparator.comparing( DownloadCacheCleaner.PathAndPriority::removalPriority ) .reversed(); } record PathAndTime(Path path, FileTime modifiedTime) { public static final Comparator NEWEST_FIRST = Comparator.comparing(DownloadCacheCleaner.PathAndTime::modifiedTime) .reversed(); } }