diff options
Diffstat (limited to 'src')
4 files changed, 95 insertions, 251 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java b/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java index 42120c4afe..3d28f028fe 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java @@ -36,7 +36,6 @@ import com.google.devtools.build.lib.profiler.ProfilerTask; import com.google.devtools.build.lib.util.Preconditions; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -58,7 +57,6 @@ public final class UnixGlob { private UnixGlob() {} private static List<Path> globInternal(Path base, Collection<String> patterns, - Collection<String> excludePatterns, boolean excludeDirectories, Predicate<Path> dirPred, boolean checkForInterruption, @@ -68,11 +66,10 @@ public final class UnixGlob { GlobVisitor visitor = (threadPool == null) ? new GlobVisitor(checkForInterruption) : new GlobVisitor(threadPool, checkForInterruption); - return visitor.glob(base, patterns, excludePatterns, excludeDirectories, dirPred, syscalls); + return visitor.glob(base, patterns, excludeDirectories, dirPred, syscalls); } private static Future<List<Path>> globAsyncInternal(Path base, Collection<String> patterns, - Collection<String> excludePatterns, boolean excludeDirectories, Predicate<Path> dirPred, FilesystemCalls syscalls, @@ -81,7 +78,7 @@ public final class UnixGlob { Preconditions.checkNotNull(threadPool, "%s %s", base, patterns); try { return new GlobVisitor(threadPool, checkForInterruption) - .globAsync(base, patterns, excludePatterns, excludeDirectories, dirPred, syscalls); + .globAsync(base, patterns, excludeDirectories, dirPred, syscalls); } catch (IOException e) { // We are evaluating asynchronously, so no exceptions should be thrown until the future is // retrieved. @@ -142,54 +139,6 @@ public final class UnixGlob { return null; } - private static boolean excludedOnMatch(Path path, List<String[]> excludePatterns, - int idx, Cache<String, Pattern> cache) { - for (String[] excludePattern : excludePatterns) { - String text = path.getBaseName(); - if (idx == excludePattern.length - && matches(excludePattern[idx - 1], text, cache)) { - return true; - } - } - return false; - } - - /** - * Returns the exclude patterns in {@code excludePatterns} which could - * apply to the children of {@code base} - * - * @param idx index into {@code excludePatterns} for the part of the pattern - * which might match {@code base} - */ - private static List<String[]> getRelevantExcludes( - final Path base, List<String[]> excludePatterns, final int idx, - final Cache<String, Pattern> cache) { - if (excludePatterns.isEmpty()) { - return excludePatterns; - } - List<String[]> list = new ArrayList<>(); - for (String[] patterns : excludePatterns) { - if (excludePatternMatches(patterns, idx, base, cache)) { - list.add(patterns); - } - } - return list; - } - - /** - * @param patterns a list of patterns - * @param idx index into {@code patterns} - */ - private static boolean excludePatternMatches(String[] patterns, int idx, - Path base, - Cache<String, Pattern> cache) { - if (idx == 0) { - return true; - } - String text = base.getBaseName(); - return patterns.length > idx && matches(patterns[idx - 1], text, cache); - } - /** * Calls {@link #matches(String, String, Cache) matches(pattern, str, null)} */ @@ -337,7 +286,6 @@ public final class UnixGlob { public static class Builder { private Path base; private List<String> patterns; - private List<String> excludes; private boolean excludeDirectories; private Predicate<Path> pathFilter; private ThreadPoolExecutor threadPool; @@ -350,7 +298,6 @@ public final class UnixGlob { public Builder(Path base) { this.base = base; this.patterns = Lists.newArrayList(); - this.excludes = Lists.newArrayList(); this.excludeDirectories = false; this.pathFilter = Predicates.alwaysTrue(); } @@ -396,26 +343,6 @@ public final class UnixGlob { } /** - * Adds patterns to exclude from the results to the glob builder. - * - * <p>For a description of the syntax of the patterns, see {@link UnixGlob}. - */ - public Builder addExcludes(String... excludes) { - Collections.addAll(this.excludes, excludes); - return this; - } - - /** - * Adds patterns to exclude from the results to the glob builder. - * - * <p>For a description of the syntax of the patterns, see {@link UnixGlob}. - */ - public Builder addExcludes(Collection<String> excludes) { - this.excludes.addAll(excludes); - return this; - } - - /** * If set to true, directories are not returned in the glob result. */ public Builder setExcludeDirectories(boolean excludeDirectories) { @@ -449,7 +376,7 @@ public final class UnixGlob { */ public List<Path> glob() throws IOException { try { - return globInternal(base, patterns, excludes, excludeDirectories, pathFilter, false, + return globInternal(base, patterns, excludeDirectories, pathFilter, false, syscalls.get(), threadPool); } catch (InterruptedException e) { // cannot happen, since we told globInternal not to throw @@ -463,7 +390,7 @@ public final class UnixGlob { * @throws InterruptedException if the thread is interrupted. */ public List<Path> globInterruptible() throws IOException, InterruptedException { - return globInternal(base, patterns, excludes, excludeDirectories, pathFilter, true, + return globInternal(base, patterns, excludeDirectories, pathFilter, true, syscalls.get(), threadPool); } @@ -474,7 +401,7 @@ public final class UnixGlob { * @param checkForInterrupt if the returned future may throw InterruptedException. */ public Future<List<Path>> globAsync(boolean checkForInterrupt) { - return globAsyncInternal(base, patterns, excludes, excludeDirectories, pathFilter, + return globAsyncInternal(base, patterns, excludeDirectories, pathFilter, syscalls.get(), checkForInterrupt, threadPool); } } @@ -554,9 +481,8 @@ public final class UnixGlob { /** * Performs wildcard globbing: returns the sorted list of filenames that match any of - * {@code patterns} relative to {@code base}, but which do not match {@code excludePatterns}. - * Directories are traversed if and only if they match {@code dirPred}. The predicate is also - * called for the root of the traversal. + * {@code patterns} relative to {@code base}. Directories are traversed if and only if they + * match {@code dirPred}. The predicate is also called for the root of the traversal. * * <p>Patterns may include "*" and "?", but not "[a-z]". * @@ -564,19 +490,16 @@ public final class UnixGlob { * used as a complete path segment it matches the filenames in * subdirectories recursively. * - * @throws IllegalArgumentException if any glob or exclude pattern - * {@linkplain #checkPatternForError(String) contains errors} or if - * any exclude pattern segment contains <code>**</code> or if any - * include pattern segment contains <code>**</code> but not equal to - * it. + * @throws IllegalArgumentException if any glob pattern + * {@linkplain #checkPatternForError(String) contains errors} or if any include pattern + * segment contains <code>**</code> but not equal to it. */ public List<Path> glob(Path base, Collection<String> patterns, - Collection<String> excludePatterns, boolean excludeDirectories, - Predicate<Path> dirPred, FilesystemCalls syscalls) + boolean excludeDirectories, Predicate<Path> dirPred, + FilesystemCalls syscalls) throws IOException, InterruptedException { try { - return globAsync(base, patterns, excludePatterns, excludeDirectories, - dirPred, syscalls).get(); + return globAsync(base, patterns, excludeDirectories, dirPred, syscalls).get(); } catch (ExecutionException e) { Throwable cause = e.getCause(); Throwables.propagateIfPossible(cause, IOException.class); @@ -585,8 +508,8 @@ public final class UnixGlob { } public Future<List<Path>> globAsync(Path base, Collection<String> patterns, - Collection<String> excludePatterns, boolean excludeDirectories, - Predicate<Path> dirPred, FilesystemCalls syscalls) throws IOException { + boolean excludeDirectories, Predicate<Path> dirPred, FilesystemCalls syscalls) + throws IOException { FileStatus baseStat = syscalls.statNullable(base, Symlinks.FOLLOW); if (baseStat == null || patterns.isEmpty()) { @@ -594,7 +517,6 @@ public final class UnixGlob { } List<String[]> splitPatterns = checkAndSplitPatterns(patterns); - List<String[]> splitExcludes = checkAndSplitPatterns(excludePatterns); // We do a dumb loop, even though it will likely duplicate work // (e.g., readdir calls). In order to optimize, we would need @@ -603,8 +525,8 @@ public final class UnixGlob { pendingOps.incrementAndGet(); try { for (String[] splitPattern : splitPatterns) { - queueGlob(base, baseStat.isDirectory(), splitPattern, 0, excludeDirectories, - splitExcludes, 0, results, cache, dirPred, syscalls); + queueGlob(base, baseStat.isDirectory(), splitPattern, 0, excludeDirectories, results, + cache, dirPred, syscalls); } } finally { decrementAndCheckDone(); @@ -616,8 +538,6 @@ public final class UnixGlob { private void queueGlob(final Path base, final boolean baseIsDir, final String[] patternParts, final int idx, final boolean excludeDirectories, - final List<String[]> excludePatterns, - final int excludeIdx, final Collection<Path> results, final Cache<String, Pattern> cache, final Predicate<Path> dirPred, final FilesystemCalls syscalls) throws IOException { enqueue(new Runnable() { @@ -625,8 +545,8 @@ public final class UnixGlob { public void run() { Profiler.instance().startTask(ProfilerTask.VFS_GLOB, this); try { - reallyGlob(base, baseIsDir, patternParts, idx, excludeDirectories, - excludePatterns, excludeIdx, results, cache, dirPred, syscalls); + reallyGlob(base, baseIsDir, patternParts, idx, excludeDirectories, results, cache, + dirPred, syscalls); } catch (IOException e) { failure.set(e); } finally { @@ -637,10 +557,9 @@ public final class UnixGlob { @Override public String toString() { return String.format( - "%s glob(include=[%s], exclude=[%s], exclude_directories=%s)", + "%s glob(include=[%s], exclude_directories=%s)", base.getPathString(), "\"" + Joiner.on("\", \"").join(patternParts) + "\"", - "\"" + Joiner.on("\", \"").join(excludePatterns) + "\"", excludeDirectories); } }); @@ -697,8 +616,6 @@ public final class UnixGlob { */ private void reallyGlob(Path base, boolean baseIsDir, String[] patternParts, int idx, boolean excludeDirectories, - List<String[]> excludePatterns, - int excludeIdx, Collection<Path> results, Cache<String, Pattern> cache, Predicate<Path> dirPred, FilesystemCalls syscalls) throws IOException { @@ -707,8 +624,7 @@ public final class UnixGlob { } if (idx == patternParts.length) { // Base case. - if (!(excludeDirectories && baseIsDir) && - !excludedOnMatch(base, excludePatterns, excludeIdx, cache)) { + if (!(excludeDirectories && baseIsDir)) { results.add(base); } @@ -720,15 +636,13 @@ public final class UnixGlob { return; } - List<String[]> relevantExcludes - = getRelevantExcludes(base, excludePatterns, excludeIdx, cache); final String pattern = patternParts[idx]; // ** is special: it can match nothing at all. // For example, x/** matches x, **/y matches y, and x/**/y matches x/y. if ("**".equals(pattern)) { - queueGlob(base, baseIsDir, patternParts, idx + 1, excludeDirectories, - excludePatterns, excludeIdx, results, cache, dirPred, syscalls); + queueGlob(base, baseIsDir, patternParts, idx + 1, excludeDirectories, results, cache, + dirPred, syscalls); } if (!pattern.contains("*") && !pattern.contains("?")) { @@ -742,8 +656,8 @@ public final class UnixGlob { boolean childIsDir = status.isDirectory(); - queueGlob(child, childIsDir, patternParts, idx + 1, excludeDirectories, - relevantExcludes, excludeIdx + 1, results, cache, dirPred, syscalls); + queueGlob(child, childIsDir, patternParts, idx + 1, excludeDirectories, results, cache, + dirPred, syscalls); return; } @@ -762,19 +676,18 @@ public final class UnixGlob { if ("**".equals(pattern)) { // Recurse without shifting the pattern. if (childIsDir) { - queueGlob(child, childIsDir, patternParts, idx, excludeDirectories, - relevantExcludes, excludeIdx + 1, results, cache, dirPred, syscalls); + queueGlob(child, childIsDir, patternParts, idx, excludeDirectories, results, cache, + dirPred, syscalls); } } if (matches(pattern, text, cache)) { // Recurse and consume one segment of the pattern. if (childIsDir) { - queueGlob(child, childIsDir, patternParts, idx + 1, excludeDirectories, - relevantExcludes, excludeIdx + 1, results, cache, dirPred, syscalls); + queueGlob(child, childIsDir, patternParts, idx + 1, excludeDirectories, results, cache, + dirPred, syscalls); } else { // Instead of using an async call, just repeat the base case above. - if (idx + 1 == patternParts.length && - !excludedOnMatch(child, relevantExcludes, excludeIdx + 1, cache)) { + if (idx + 1 == patternParts.length) { results.add(child); } } diff --git a/src/test/java/com/google/devtools/build/lib/packages/GlobCacheTest.java b/src/test/java/com/google/devtools/build/lib/packages/GlobCacheTest.java index 62f5ca1f0c..11d301f4f8 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/GlobCacheTest.java +++ b/src/test/java/com/google/devtools/build/lib/packages/GlobCacheTest.java @@ -237,6 +237,61 @@ public class GlobCacheTest { "foo/second.js", "bar/second.js"); } + @Test + public void testSingleFileExclude_Star() throws Exception { + assertThat(cache.glob(list("*"), list("first.txt"), false)).containsExactly( + "BUILD", "bar", "first.js", "foo", "second.js", "second.txt").inOrder(); + } + + @Test + public void testSingleFileExclude_StarStar() throws Exception { + assertThat(cache.glob(list("**"), list("first.txt"), false)).containsExactly( + "BUILD", "bar", "bar/first.js", "bar/second.js", "first.js", "foo", "foo/first.js", + "foo/second.js", "second.js", "second.txt").inOrder(); + } + + @Test + public void testExcludeAll_Star() throws Exception { + assertThat(cache.glob(list("*"), list("*"), false)).isEmpty(); + } + + @Test + public void testExcludeAll_Star_NoMatchesAnyway() throws Exception { + assertThat(cache.glob(list("nope"), list("*"), false)).isEmpty(); + } + + @Test + public void testExcludeAll_StarStar() throws Exception { + assertThat(cache.glob(list("**"), list("**"), false)).isEmpty(); + } + + @Test + public void testExcludeAll_Manual() throws Exception { + assertThat(cache.glob(list("**"), list("*", "*/*", "*/*/*"), false)).isEmpty(); + } + + @Test + public void testSingleFileExcludeDoesntMatch() throws Exception { + assertThat(cache.glob(list("first.txt"), list("nope.txt"), false)).containsExactly("first.txt"); + } + + @Test + public void testExcludeDirectory() throws Exception { + assertThat(cache.glob(list("foo/*"), NONE, true)).containsExactly( + "foo/first.js", "foo/second.js"); + assertThat(cache.glob(list("foo/*"), list("foo"), false)).containsExactly( + "foo/first.js", "foo/second.js"); + } + + @Test + public void testChildGlobWithChildExclude() throws Exception { + assertThat(cache.glob(list("foo/*"), list("foo/*"), false)).isEmpty(); + assertThat(cache.glob(list("foo/first.js", "foo/second.js"), list("foo/*"), false)).isEmpty(); + assertThat(cache.glob(list("foo/first.js"), list("foo/first.js"), false)).isEmpty(); + assertThat(cache.glob(list("foo/first.js"), list("*/first.js"), false)).isEmpty(); + assertThat(cache.glob(list("foo/first.js"), list("*/*"), false)).isEmpty(); + } + private void assertEmpty(Collection<?> glob) { assertThat(glob).isEmpty(); } diff --git a/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java b/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java index 1416ca5bec..e8c08f00d5 100644 --- a/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java +++ b/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java @@ -159,81 +159,19 @@ public class GlobTest { assertGlobMatches("foo/bar/wiz/file/*" /* => nothing */); } - @Test - public void testSingleFileExclude() throws Exception { - assertGlobWithExcludeMatches("*", "food", "foo", "fool"); - } - - @Test - public void testExcludeAll() throws Exception { - assertGlobWithExcludeMatches("*", "*"); - } - - @Test - public void testExcludeAllButNoMatches() throws Exception { - assertGlobWithExcludeMatches("not-there", "*"); - } - - @Test - public void testSingleFileExcludeDoesntMatch() throws Exception { - assertGlobWithExcludeMatches("food", "foo", "food"); - } - - @Test - public void testSingleFileExcludeForDirectoryWithChildGlob() - throws Exception { - assertGlobWithExcludeMatches("foo/*", "foo", "foo/bar", "foo/barnacle"); - } - - @Test - public void testChildGlobWithChildExclude() - throws Exception { - assertGlobWithExcludeMatches("foo/*", "foo/*"); - assertGlobWithExcludeMatches("foo/bar", "foo/*"); - assertGlobWithExcludeMatches("foo/bar", "foo/bar"); - assertGlobWithExcludeMatches("foo/bar", "*/bar"); - assertGlobWithExcludeMatches("foo/bar", "*/*"); - assertGlobWithExcludeMatches("foo/bar/wiz", "*/*/*"); - assertGlobWithExcludeMatches("foo/bar/wiz", "foo/*/*"); - assertGlobWithExcludeMatches("foo/bar/wiz", "foo/bar/*"); - assertGlobWithExcludeMatches("foo/bar/wiz", "foo/bar/wiz"); - assertGlobWithExcludeMatches("foo/bar/wiz", "*/bar/wiz"); - assertGlobWithExcludeMatches("foo/bar/wiz", "*/*/wiz"); - assertGlobWithExcludeMatches("foo/bar/wiz", "foo/*/wiz"); - } - private void assertGlobMatches(String pattern, String... expecteds) throws Exception { - assertGlobWithExcludesMatches( - Collections.singleton(pattern), Collections.<String>emptyList(), - expecteds); + assertGlobMatches(Collections.singleton(pattern), expecteds); } private void assertGlobMatches(Collection<String> pattern, String... expecteds) throws Exception { - assertGlobWithExcludesMatches(pattern, Collections.<String>emptyList(), - expecteds); - } - - private void assertGlobWithExcludeMatches(String pattern, String exclude, - String... expecteds) - throws Exception { - assertGlobWithExcludesMatches( - Collections.singleton(pattern), Collections.singleton(exclude), - expecteds); - } - - private void assertGlobWithExcludesMatches(Collection<String> pattern, - Collection<String> excludes, - String... expecteds) - throws Exception { assertThat( - new UnixGlob.Builder(tmpPath) - .addPatterns(pattern) - .addExcludes(excludes) - .globInterruptible()) - .containsExactlyElementsIn(resolvePaths(expecteds)); + new UnixGlob.Builder(tmpPath) + .addPatterns(pattern) + .globInterruptible()) + .containsExactlyElementsIn(resolvePaths(expecteds)); } private Set<Path> resolvePaths(String... relativePaths) { @@ -312,12 +250,6 @@ public class GlobTest { } @Test - public void testMultiplePatternsWithExcludes() throws Exception { - assertGlobWithExcludesMatches(Lists.newArrayList("foo", "foo?"), - Lists.newArrayList("fool"), "foo", "food"); - } - - @Test public void testMatcherMethodRecursiveBelowDir() throws Exception { FileSystemUtils.createEmptyFile(tmpPath.getRelative("foo/file")); String pattern = "foo/**/*"; diff --git a/src/test/java/com/google/devtools/build/lib/vfs/RecursiveGlobTest.java b/src/test/java/com/google/devtools/build/lib/vfs/RecursiveGlobTest.java index acbc2adc1c..694a91d214 100644 --- a/src/test/java/com/google/devtools/build/lib/vfs/RecursiveGlobTest.java +++ b/src/test/java/com/google/devtools/build/lib/vfs/RecursiveGlobTest.java @@ -28,7 +28,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -83,7 +82,6 @@ public class RecursiveGlobTest { for (String pattern : Lists.newArrayList("**fo", "fo**", "**fo**", "fo**fo", "fo**fo**fo")) { assertIllegalWildcard(prefix + pattern); assertIllegalWildcard(pattern + suffix); - assertIllegalWildcard("foo", pattern + suffix); } } } @@ -122,66 +120,13 @@ public class RecursiveGlobTest { assertGlobMatches("foo/bar/wiz/file/**" /* => nothing */); } - @Test - public void testSingleFileExclude() throws Exception { - assertGlobWithExcludeMatches("**", "food", ".", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", - "foo/baz/quip", "foo/baz/quip/wiz", "foo/baz/wiz", - "foo/bar/wiz/file", "food/baz", "food/baz/wiz", "fool", "fool/baz", - "fool/baz/wiz"); - } - - @Test - public void testSingleFileExcludeForDirectoryWithChildGlob() - throws Exception { - assertGlobWithExcludeMatches("foo/**", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", - "foo/baz/quip", "foo/baz/quip/wiz", "foo/baz/wiz", - "foo/bar/wiz/file"); - } - - @Test - public void testGlobExcludeForDirectoryWithChildGlob() - throws Exception { - assertGlobWithExcludeMatches("foo/**", "foo/*", "foo", "foo/bar/wiz", "foo/baz/quip", - "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file"); - } - - @Test - public void testExcludeAll() throws Exception { - assertGlobWithExcludesMatches(Lists.newArrayList("**"), - Lists.newArrayList("*", "*/*", "*/*/*", "*/*/*/*"), "."); - } - - @Test - public void testManualGlobExcludeForDirectoryWithChildGlob() - throws Exception { - assertGlobWithExcludesMatches(Lists.newArrayList("foo/**"), - Lists.newArrayList("foo", "foo/*", "foo/*/*", "foo/*/*/*")); - } - private void assertGlobMatches(String pattern, String... expecteds) throws Exception { - assertGlobWithExcludesMatches( - Collections.singleton(pattern), Collections.<String>emptyList(), - expecteds); - } - - private void assertGlobWithExcludeMatches(String pattern, String exclude, - String... expecteds) - throws Exception { - assertGlobWithExcludesMatches( - Collections.singleton(pattern), Collections.singleton(exclude), - expecteds); - } - - private void assertGlobWithExcludesMatches(Collection<String> pattern, - Collection<String> excludes, - String... expecteds) throws Exception { assertThat( - new UnixGlob.Builder(tmpPath) - .addPatterns(pattern) - .addExcludes(excludes) - .globInterruptible()) - .containsExactlyElementsIn(resolvePaths(expecteds)); + new UnixGlob.Builder(tmpPath) + .addPatterns(pattern) + .globInterruptible()) + .containsExactlyElementsIn(resolvePaths(expecteds)); } private Set<Path> resolvePaths(String... relativePaths) { @@ -209,12 +154,11 @@ public class RecursiveGlobTest { .inOrder(); } - private void assertIllegalWildcard(String pattern, String... excludePatterns) + private void assertIllegalWildcard(String pattern) throws Exception { try { new UnixGlob.Builder(tmpPath) .addPattern(pattern) - .addExcludes(excludePatterns) .globInterruptible(); fail(); } catch (IllegalArgumentException e) { |