diff --git a/src/main/java/me/itzg/helpers/files/Manifests.java b/src/main/java/me/itzg/helpers/files/Manifests.java index 5bdc10e3..4c00691a 100644 --- a/src/main/java/me/itzg/helpers/files/Manifests.java +++ b/src/main/java/me/itzg/helpers/files/Manifests.java @@ -2,8 +2,12 @@ import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -121,13 +125,29 @@ public static boolean allFilesPresent(Path basePath, BaseManifest manifest) { * @param ignoreMissingFiles relative paths of files to ignore if they're missing */ public static boolean allFilesPresent(Path basePath, BaseManifest manifest, @Nullable List ignoreMissingFiles) { + if (ignoreMissingFiles == null || ignoreMissingFiles.isEmpty()) { + return manifest.getFiles().stream() + .allMatch(p -> Files.exists(basePath.resolve(p))); + } + + if (ignoreMissingFiles.stream().anyMatch(s -> s.equals("*"))) { + return true; + } + + FileSystem fs = FileSystems.getDefault(); + List matchers = ignoreMissingFiles.stream() + .map(pattern -> fs.getPathMatcher("glob:" + pattern)) + .collect(Collectors.toList()); + return manifest.getFiles().stream() - .allMatch(p -> - (ignoreMissingFiles != null && ignoreMissingFiles.contains(p)) - || Files.exists(basePath.resolve(p)) - ); + .allMatch(p -> { + Path file = Paths.get(p); + boolean ignored = matchers.stream().anyMatch(m -> m.matches(file)); + return ignored || Files.exists(basePath.resolve(p)); + }); } + /** * * @param outputDir directory where manifest and other module files are based diff --git a/src/test/java/me/itzg/helpers/files/ManifestsTest.java b/src/test/java/me/itzg/helpers/files/ManifestsTest.java index 793e9732..ccbc25f9 100644 --- a/src/test/java/me/itzg/helpers/files/ManifestsTest.java +++ b/src/test/java/me/itzg/helpers/files/ManifestsTest.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.Collections; import lombok.Getter; import lombok.experimental.SuperBuilder; @@ -13,14 +14,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -class ManifestsTest { +public class ManifestsTest { @TempDir Path tempDir; @Getter @SuperBuilder @Jacksonized static class EmptyManifest extends BaseManifest { - } @Test @@ -33,4 +33,39 @@ void loadFailsGracefullyWhenInvalid() throws IOException { final EmptyManifest manifest = Manifests.load(tempDir, id, EmptyManifest.class); assertThat(manifest).isNull(); } -} \ No newline at end of file + + @Test + void allFilesPresent_withWildcardIgnoreAll() { + EmptyManifest manifest = EmptyManifest.builder() + .files(Arrays.asList("a.jar", "b.jar")) + .build(); + + boolean result = Manifests.allFilesPresent(tempDir, manifest, Collections.singletonList("*")); + assertThat(result).isTrue(); + } + + @Test + void allFilesPresent_withGlobPattern() throws IOException { + Files.createDirectories(tempDir.resolve("mods")); + Files.createFile(tempDir.resolve("mods/present.jar")); + + EmptyManifest manifest = EmptyManifest.builder() + .files(Arrays.asList("mods/present.jar", "mods/missing.jar")) + .build(); + + boolean result = Manifests.allFilesPresent(tempDir, manifest, Collections.singletonList("mods/*.jar")); + assertThat(result).isTrue(); + } + + @Test + void allFilesPresent_withExplicitFileNames() throws IOException { + Files.createFile(tempDir.resolve("keep.jar")); + + EmptyManifest manifest = EmptyManifest.builder() + .files(Arrays.asList("keep.jar", "remove.jar")) + .build(); + + boolean result = Manifests.allFilesPresent(tempDir, manifest, Collections.singletonList("remove.jar")); + assertThat(result).isTrue(); + } +}