diff --git a/site/_includes/documentation-sidebar/1 b/site/_includes/documentation-sidebar/1 deleted file mode 120000 index e440e5c8425869..00000000000000 --- a/site/_includes/documentation-sidebar/1 +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/site/_includes/documentation-sidebar/1/sidebar.html b/site/_includes/documentation-sidebar/1/sidebar.html new file mode 100644 index 00000000000000..0cc4b853565e3a --- /dev/null +++ b/site/_includes/documentation-sidebar/1/sidebar.html @@ -0,0 +1,228 @@ +

Home

+ + +

Installing Bazel

+ + +

Tutorials

+ + +

Using Bazel

+ + +

Reference

+ + +

Extending Bazel

+ diff --git a/site/_includes/documentation-sidebar/2 b/site/_includes/documentation-sidebar/2 deleted file mode 120000 index e440e5c8425869..00000000000000 --- a/site/_includes/documentation-sidebar/2 +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/site/_includes/documentation-sidebar/2/sidebar.html b/site/_includes/documentation-sidebar/2/sidebar.html new file mode 100644 index 00000000000000..0cc4b853565e3a --- /dev/null +++ b/site/_includes/documentation-sidebar/2/sidebar.html @@ -0,0 +1,228 @@ +

Home

+ + +

Installing Bazel

+ + +

Tutorials

+ + +

Using Bazel

+ + +

Reference

+ + +

Extending Bazel

+ diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java index b6180c3e37d3fe..21eb22f4f3b847 100644 --- a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java +++ b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.cmdline; import static com.google.common.util.concurrent.Futures.immediateCancelledFuture; +import static com.google.common.util.concurrent.Futures.immediateVoidFuture; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; @@ -551,14 +552,17 @@ public void eval( "Fully excluded target pattern %s should have already been filtered out (%s)", this, excludedSubdirectories); - ImmutableSet filteredIgnored = + IgnoredPathFragmentsInScopeOrFilteringIgnorer ignoredIntersection = getAllIgnoredSubdirectoriesToExclude(ignoredSubdirectories); + if (warnIfFiltered(ignoredIntersection, resolver)) { + return; + } resolver.findTargetsBeneathDirectory( directory.getRepository(), getOriginalPattern(), directory.getPackageFragment().getPathString(), rulesOnly, - filteredIgnored, + ignoredIntersection.ignoredPathFragments(), excludedSubdirectories, callback, exceptionClass); @@ -577,38 +581,136 @@ public ListenableFuture evalAsync( "Fully excluded target pattern %s should have already been filtered out (%s)", this, excludedSubdirectories); - ImmutableSet filteredIgnored; + IgnoredPathFragmentsInScopeOrFilteringIgnorer ignoredIntersection; try { - filteredIgnored = getAllIgnoredSubdirectoriesToExclude(ignoredSubdirectories); + ignoredIntersection = getAllIgnoredSubdirectoriesToExclude(ignoredSubdirectories); } catch (InterruptedException e) { return immediateCancelledFuture(); } + if (warnIfFiltered(ignoredIntersection, resolver)) { + return immediateVoidFuture(); + } return resolver.findTargetsBeneathDirectoryAsync( directory.getRepository(), getOriginalPattern(), directory.getPackageFragment().getPathString(), rulesOnly, - filteredIgnored, + ignoredIntersection.ignoredPathFragments(), excludedSubdirectories, callback, exceptionClass, executor); } - public ImmutableSet getAllIgnoredSubdirectoriesToExclude( + private boolean warnIfFiltered( + IgnoredPathFragmentsInScopeOrFilteringIgnorer ignoredIntersection, + TargetPatternResolver resolver) { + if (ignoredIntersection.wasFiltered()) { + resolver.warn( + "Pattern '" + + getOriginalPattern() + + "' was filtered out by ignored directory '" + + ignoredIntersection.filteringIgnorer().getPathString() + + "'"); + return true; + } + return false; + } + + public IgnoredPathFragmentsInScopeOrFilteringIgnorer getAllIgnoredSubdirectoriesToExclude( InterruptibleSupplier> ignoredPackagePrefixes) throws InterruptedException { - ImmutableSet ignoredPaths = ignoredPackagePrefixes.get(); ImmutableSet.Builder ignoredPathsBuilder = ImmutableSet.builderWithExpectedSize(0); - for (PathFragment ignoredPackagePrefix : ignoredPaths) { + for (PathFragment ignoredPackagePrefix : ignoredPackagePrefixes.get()) { + if (this.containedIn(ignoredPackagePrefix)) { + return new IgnoredPathFragmentsInScopeOrFilteringIgnorer.FilteringIgnorer( + ignoredPackagePrefix); + } PackageIdentifier pkgIdForIgnoredDirectorPrefix = PackageIdentifier.create(this.getDirectory().getRepository(), ignoredPackagePrefix); if (this.containsAllTransitiveSubdirectories(pkgIdForIgnoredDirectorPrefix)) { ignoredPathsBuilder.add(ignoredPackagePrefix); } } - return ignoredPathsBuilder.build(); + return IgnoredPathFragmentsInScopeOrFilteringIgnorer.IgnoredPathFragments.of( + ignoredPathsBuilder.build()); + } + + /** + * Morally an {@code Either, PathFragment>}, saying whether the given + * set of ignored directories intersected a directory (in which case the directories that were + * in the intersection are returned) or completely contained it (in which case a containing + * directory is returned). + */ + public abstract static class IgnoredPathFragmentsInScopeOrFilteringIgnorer { + public abstract boolean wasFiltered(); + + public abstract ImmutableSet ignoredPathFragments(); + + public abstract PathFragment filteringIgnorer(); + + private static class IgnoredPathFragments + extends IgnoredPathFragmentsInScopeOrFilteringIgnorer { + private static final IgnoredPathFragments EMPTYSET_IGNORED = + new IgnoredPathFragments(ImmutableSet.of()); + + private final ImmutableSet ignoredPathFragments; + + private IgnoredPathFragments(ImmutableSet ignoredPathFragments) { + this.ignoredPathFragments = ignoredPathFragments; + } + + static IgnoredPathFragments of(ImmutableSet ignoredPathFragments) { + if (ignoredPathFragments.isEmpty()) { + return EMPTYSET_IGNORED; + } + return new IgnoredPathFragments(ignoredPathFragments); + } + + @Override + public boolean wasFiltered() { + return false; + } + + @Override + public ImmutableSet ignoredPathFragments() { + return ignoredPathFragments; + } + + @Override + public PathFragment filteringIgnorer() { + throw new UnsupportedOperationException("No filter: " + ignoredPathFragments); + } + } + + private static class FilteringIgnorer extends IgnoredPathFragmentsInScopeOrFilteringIgnorer { + private final PathFragment filteringIgnorer; + + FilteringIgnorer(PathFragment filteringIgnorer) { + this.filteringIgnorer = filteringIgnorer; + } + + @Override + public boolean wasFiltered() { + return true; + } + + @Override + public ImmutableSet ignoredPathFragments() { + throw new UnsupportedOperationException("was filtered: " + filteringIgnorer); + } + + @Override + public PathFragment filteringIgnorer() { + return filteringIgnorer; + } + } + } + + /** Is {@code containingDirectory} an ancestor of or equal to this {@link #directory}? */ + public boolean containedIn(PathFragment containingDirectory) { + return directory.getPackageFragment().startsWith(containingDirectory); } /** diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java index 378905e8f06b2a..4df9df50adff63 100644 --- a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java @@ -46,16 +46,20 @@ public interface RecursivePackageProvider extends PackageProvider { * @param eventHandler any errors emitted during package lookup and loading for {@code directory} * and non-excluded directories beneath it will be reported here * @param directory a {@link RootedPath} specifying the directory to search - * @param blacklistedSubdirectories a set of {@link PathFragment}s specifying transitive - * subdirectories that have been blacklisted + * @param ignoredSubdirectories a set of {@link PathFragment}s specifying transitive + * subdirectories that are ignored. {@code directory} must not be a subdirectory of any of + * these * @param excludedSubdirectories a set of {@link PathFragment}s specifying transitive + * subdirectories that are excluded from this traversal. Different from {@code + * ignoredSubdirectories} only in that these directories should not be embedded in any {@code + * SkyKey}s that are created during the traversal, instead filtered out later */ void streamPackagesUnderDirectory( BatchCallback results, ExtendedEventHandler eventHandler, RepositoryName repository, PathFragment directory, - ImmutableSet blacklistedSubdirectories, + ImmutableSet ignoredSubdirectories, ImmutableSet excludedSubdirectories) throws InterruptedException, QueryException; @@ -121,7 +125,7 @@ public void streamPackagesUnderDirectory( ExtendedEventHandler eventHandler, RepositoryName repository, PathFragment directory, - ImmutableSet blacklistedSubdirectories, + ImmutableSet ignoredSubdirectories, ImmutableSet excludedSubdirectories) { throw new UnsupportedOperationException(); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java index aaf7a40f755d0c..24a43c7260fd0a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java @@ -171,14 +171,9 @@ public void streamPackagesUnderDirectory( roots.add(Root.fromPath(repositoryValue.getPath())); } - if (ignoredSubdirectories.contains(directory)) { - return; - } ImmutableSet filteredIgnoredSubdirectories = ImmutableSet.copyOf( - Iterables.filter( - ignoredSubdirectories, - path -> !path.equals(directory) && path.startsWith(directory))); + Iterables.filter(ignoredSubdirectories, path -> path.startsWith(directory))); for (Root root : roots) { RecursivePkgValue lookup = diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java index 22bd0206068c24..18c59d255dcab7 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java @@ -159,14 +159,7 @@ public boolean isPackage(ExtendedEventHandler eventHandler, PackageIdentifier pa } private ImmutableList checkValidDirectoryAndGetRoots( - RepositoryName repository, - PathFragment directory, - ImmutableSet ignoredSubdirectories, - ImmutableSet excludedSubdirectories) - throws InterruptedException { - if (ignoredSubdirectories.contains(directory) || excludedSubdirectories.contains(directory)) { - return ImmutableList.of(); - } + RepositoryName repository, PathFragment directory) throws InterruptedException { // Check that this package is covered by at least one of our universe patterns. boolean inUniverse = false; @@ -209,9 +202,7 @@ public void streamPackagesUnderDirectory( ImmutableSet ignoredSubdirectories, ImmutableSet excludedSubdirectories) throws InterruptedException, QueryException { - ImmutableList roots = - checkValidDirectoryAndGetRoots( - repository, directory, ignoredSubdirectories, excludedSubdirectories); + ImmutableList roots = checkValidDirectoryAndGetRoots(repository, directory); rootPackageExtractor.streamPackagesFromRoots( results, diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java index 77497fe3f822a2..f623937e4a7c38 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java @@ -260,9 +260,6 @@ public void findTargetsBeneathDirectory( Class exceptionClass) throws TargetParsingException, E, InterruptedException { PathFragment directoryPathFragment = TargetPatternResolverUtil.getPathFragment(directory); - if (repositoryIgnoredSubdirectories.contains(directoryPathFragment)) { - return; - } Preconditions.checkArgument(excludedSubdirectories.isEmpty(), excludedSubdirectories); FilteringPolicy policy = rulesOnly ? FilteringPolicies.RULES_ONLY : FilteringPolicies.NO_FILTER; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java index 580105ecb188b7..bc0e7b5f21a136 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java @@ -45,9 +45,7 @@ public void streamPackagesFromRoots( throws InterruptedException, QueryException { ImmutableSet filteredIgnoredSubdirectories = ImmutableSet.copyOf( - Iterables.filter( - ignoredSubdirectories, - path -> !path.equals(directory) && path.startsWith(directory))); + Iterables.filter(ignoredSubdirectories, path -> path.startsWith(directory))); for (Root root : roots) { RootedPath rootedPath = RootedPath.toRootedPath(root, directory); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java index c3af37c885ac15..fecdf3d08b446b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java @@ -288,8 +288,8 @@ public static class TargetPatternKey implements SkyKey, Serializable { private final PathFragment offset; /** * Must be "compatible" with {@link #parsedPattern}: if {@link #parsedPattern} is a {@link - * TargetsBelowDirectory} object, then no element of {@code excludedSubdirectories} fully - * contains it. + * TargetsBelowDirectory} object, then {@link TargetsBelowDirectory#containedIn} is false for + * every element of {@code excludedSubdirectories}. */ private final ImmutableSet excludedSubdirectories; diff --git a/src/test/shell/bazel/bazelignore_test.sh b/src/test/shell/bazel/bazelignore_test.sh index 6113c30b785c86..c42bb9bb7bfab4 100755 --- a/src/test/shell/bazel/bazelignore_test.sh +++ b/src/test/shell/bazel/bazelignore_test.sh @@ -90,14 +90,57 @@ test_broken_BUILD_files_ignored() { echo This is a broken BUILD file > ignoreme/deep/reallydep/BUILD echo This is a broken BUILD file > ignoreme/deep/reallydep/stillignoreme/BUILD touch BUILD - bazel build ... && fail "Expected failure" || : + bazel build ... >& "$TEST_log" && fail "Expected failure" || : - echo; echo echo ignoreme > .bazelignore - bazel build ... \ + bazel build ... >& "$TEST_log" \ || fail "directory mentioned in .bazelignore not ignored as it should" } +test_broken_BUILD_files_ignored_subdir() { + rm -rf work && mkdir work && cd work + create_workspace_with_default_repos WORKSPACE + mkdir -p ignoreme/deep || fail "Couldn't mkdir" + ln -s deeper ignoreme/deep/deeper || fail "Couldn't create cycle" + touch BUILD + bazel build //ignoreme/deep/... >& "$TEST_log" && fail "Expected failure" \ + || : + expect_log "circular symlinks detected" + expect_log "ignoreme/deep/deeper" + + echo ignoreme > .bazelignore + bazel build //ignoreme/deep/... >& "$TEST_log" || fail "Expected success" + expect_log "WARNING: Pattern '//ignoreme/deep/...' was filtered out by ignored directory 'ignoreme'" + expect_not_log "circular symlinks detected" + expect_not_log "ignoreme/deep/deeper" + + bazel query //ignoreme/deep/... >& "$TEST_log" || fail "Expected success" + expect_log "WARNING: Pattern '//ignoreme/deep/...' was filtered out by ignored directory 'ignoreme'" + expect_not_log "circular symlinks detected" + expect_not_log "ignoreme/deep/deeper" + expect_log "Empty results" + + bazel query //ignoreme/deep/... --universe_scope=//ignoreme/deep/... \ + --order_output=no >& "$TEST_log" || fail "Expected success" + expect_log "WARNING: Pattern '//ignoreme/deep/...' was filtered out by ignored directory 'ignoreme'" + expect_not_log "circular symlinks detected" + expect_not_log "ignoreme/deep/deeper" + expect_log "Empty results" + + # Test patterns with exclude. + bazel build -- //ignoreme/deep/... -//ignoreme/... >& "$TEST_log" \ + || fail "Expected success" + expect_log "WARNING: Pattern '//ignoreme/deep/...' was filtered out by ignored directory 'ignoreme'" + expect_not_log "circular symlinks detected" + expect_not_log "ignoreme/deep/deeper" + + bazel build -- //ignoreme/... -//ignoreme/deep/... >& "$TEST_log" \ + || fail "Expected success" + expect_log "WARNING: Pattern '//ignoreme/...' was filtered out by ignored directory 'ignoreme'" + expect_not_log "circular symlinks detected" + expect_not_log "ignoreme/deep/deeper" +} + test_symlink_cycle_ignored() { rm -rf work && mkdir work && cd work create_workspace_with_default_repos WORKSPACE