aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--site/docs/bazel-user-manual.html8
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/target-syntax.txt9
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java4
6 files changed, 52 insertions, 13 deletions
diff --git a/site/docs/bazel-user-manual.html b/site/docs/bazel-user-manual.html
index 7c2320bf40..e712d562df 100644
--- a/site/docs/bazel-user-manual.html
+++ b/site/docs/bazel-user-manual.html
@@ -396,9 +396,11 @@ Specifying all rules recursively beneath a package:
//foo/...:all Matches all rules in all packages beneath directory 'foo'.
//foo/... (ditto)
- By default, directory symlinks are followed when performing this recursive traversal. But we
- understand that your workspace may intentionally contain directories with weird symlink structures
- that you don't want consumed. As such, if a directory has a file named
+ By default, directory symlinks are followed when performing this recursive traversal, except
+ those that point to under the output base (for example, the convenience symlinks that are created
+ in the root directory of the workspace) But we understand that your workspace may intentionally
+ contain directories with unusual symlink structures that you don't want consumed. As such, if a
+ directory has a file named
'DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN' then symlinks
in that directory won't be followed when evaluating recursive target patterns.
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/target-syntax.txt b/src/main/java/com/google/devtools/build/lib/runtime/commands/target-syntax.txt
index 3eec42e21b..df0089bf8b 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/target-syntax.txt
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/target-syntax.txt
@@ -25,10 +25,11 @@ Specifying all rules recursively beneath a package:
//foo/...:all Matches all rules in all packages beneath directory 'foo'.
//foo/... (ditto)
- By default, directory symlinks are followed when performing this recursive
- traversal. But we understand that your workspace may intentionally contain
- directories with weird symlink structures that you don't want consumed. As
- such, if a directory has a file named
+ By default, directory symlinks are followed when performing this recursive traversal, except
+ those that point to under the output base (for example, the convenience symlinks that are created
+ in the root directory of the workspace) But we understand that your workspace may intentionally
+ contain directories with weird symlink structures that you don't want consumed. As such, if a
+ directory has a file named
'DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN'
then symlinks in that directory won't be followed when evaluating recursive
target patterns.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java
index e7d487fb4f..e1f3105280 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java
@@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
@@ -48,6 +49,11 @@ import javax.annotation.Nullable;
* subdirectories.
*/
public class PrepareDepsOfTargetsUnderDirectoryFunction implements SkyFunction {
+ private final BlazeDirectories directories;
+
+ public PrepareDepsOfTargetsUnderDirectoryFunction(BlazeDirectories directories) {
+ this.directories = directories;
+ }
@Override
public SkyValue compute(SkyKey skyKey, Environment env) {
@@ -58,13 +64,14 @@ public class PrepareDepsOfTargetsUnderDirectoryFunction implements SkyFunction {
return new MyTraversalFunction(filteringPolicy).visitDirectory(recursivePkgKey, env);
}
- private static class MyTraversalFunction
+ private class MyTraversalFunction
extends RecursiveDirectoryTraversalFunction<MyVisitor,
PrepareDepsOfTargetsUnderDirectoryValue> {
private final FilteringPolicy filteringPolicy;
private MyTraversalFunction(FilteringPolicy filteringPolicy) {
+ super(directories);
this.filteringPolicy = filteringPolicy;
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
index 5c4a4349dd..203e54a7f4 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
@@ -16,8 +16,8 @@ package com.google.devtools.build.lib.skyframe;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
import com.google.devtools.build.lib.events.Event;
@@ -37,6 +37,7 @@ import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.ValueOrException4;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -51,6 +52,12 @@ abstract class RecursiveDirectoryTraversalFunction
private static final String SENTINEL_FILE_NAME_FOR_NOT_TRAVERSING_SYMLINKS =
"DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN";
+ private final BlazeDirectories directories;
+
+ protected RecursiveDirectoryTraversalFunction(BlazeDirectories directories) {
+ this.directories = directories;
+ }
+
/**
* Returned from {@link #visitDirectory} if its {@code recursivePkgKey} is a symlink or not a
* directory, or if a dependency value lookup returns an error.
@@ -144,6 +151,18 @@ abstract class RecursiveDirectoryTraversalFunction
PackageIdentifier packageId = PackageIdentifier.create(
recursivePkgKey.getRepository(), rootRelativePath);
+
+ if (packageId.getRepository().isDefault()
+ && fileValue.isSymlink()
+ && fileValue.getUnresolvedLinkTarget().startsWith(directories.getOutputBase().asFragment())) {
+ // Symlinks back to the output base are not traversed so that we avoid convenience symlinks.
+ // Note that it's not enough to just check for the convenience symlinks themselves, because
+ // if the value of --symlink_prefix changes, the old symlinks are left in place. This
+ // algorithm also covers more creative use cases where people create convenience symlinks
+ // somewhere in the directory tree manually.
+ return getEmptyReturn();
+ }
+
SkyKey pkgLookupKey = PackageLookupValue.key(packageId);
SkyKey dirListingKey = DirectoryListingValue.key(rootedPath);
Map<SkyKey,
@@ -233,8 +252,8 @@ abstract class RecursiveDirectoryTraversalFunction
throw new IllegalStateException(e);
}
- List<SkyKey> childDeps = Lists.newArrayList();
boolean followSymlinks = shouldFollowSymlinksWhenTraversing(dirListingValue.getDirents());
+ List<SkyKey> childDeps = new ArrayList<>();
for (Dirent dirent : dirListingValue.getDirents()) {
Type type = dirent.getType();
if (type != Type.DIRECTORY
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java
index b42d9b45c8..dbbbe8cd6d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.skyframe;
import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -38,15 +39,24 @@ import javax.annotation.Nullable;
* "foo/subpkg".
*/
public class RecursivePkgFunction implements SkyFunction {
+ private final BlazeDirectories directories;
+
+ public RecursivePkgFunction(BlazeDirectories directories) {
+ this.directories = directories;
+ }
@Override
public SkyValue compute(SkyKey skyKey, Environment env) {
return new MyTraversalFunction().visitDirectory((RecursivePkgKey) skyKey.argument(), env);
}
- private static class MyTraversalFunction
+ private class MyTraversalFunction
extends RecursiveDirectoryTraversalFunction<MyVisitor, RecursivePkgValue> {
+ private MyTraversalFunction() {
+ super(directories);
+ }
+
@Override
protected RecursivePkgValue getEmptyReturn() {
return RecursivePkgValue.EMPTY;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index f3e5d16c76..9a316f4aa1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -344,12 +344,12 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory {
map.put(SkyFunctions.PREPARE_DEPS_OF_PATTERNS, new PrepareDepsOfPatternsFunction());
map.put(SkyFunctions.PREPARE_DEPS_OF_PATTERN, new PrepareDepsOfPatternFunction(pkgLocator));
map.put(SkyFunctions.PREPARE_DEPS_OF_TARGETS_UNDER_DIRECTORY,
- new PrepareDepsOfTargetsUnderDirectoryFunction());
+ new PrepareDepsOfTargetsUnderDirectoryFunction(directories));
map.put(SkyFunctions.BLACKLISTED_PACKAGE_PREFIXES, new BlacklistedPackagePrefixesFunction());
map.put(SkyFunctions.TESTS_IN_SUITE, new TestsInSuiteFunction());
map.put(SkyFunctions.TEST_SUITE_EXPANSION, new TestSuiteExpansionFunction());
map.put(SkyFunctions.TARGET_PATTERN_PHASE, new TargetPatternPhaseFunction());
- map.put(SkyFunctions.RECURSIVE_PKG, new RecursivePkgFunction());
+ map.put(SkyFunctions.RECURSIVE_PKG, new RecursivePkgFunction(directories));
map.put(
SkyFunctions.PACKAGE,
newPackageFunction(