aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
diff options
context:
space:
mode:
authorGravatar Nathan Harmata <nharmata@google.com>2015-11-13 01:43:59 +0000
committerGravatar Lukacs Berki <lberki@google.com>2015-11-13 10:23:23 +0000
commit1e66ccd2f18b03733f22b93ad8051ff2cf37d3dd (patch)
tree01b02da842123097e8fae49960d35758d31c3cde /src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
parentf6866778db261e5d8b95ee1c46622ceb19a609a4 (diff)
RELNOTES: Symlink dirents of directories containing a file named "DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN" will *not* be traversed for transitive target patterns. The motivation here is to allow directories that intentionally contain wonky symlinks (e.g. foo/bar -> foo) to opt out of being consumed by Blaze. For example, given
<workspace>/foo bar bad -> . DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN the 'bad' symlink will *not* be traversed by the pattern '//foo/...'. -- MOS_MIGRATED_REVID=107738930
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java26
1 files changed, 22 insertions, 4 deletions
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 4ee743037f..5c4a4349dd 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
@@ -48,6 +48,8 @@ import java.util.Set;
*/
abstract class RecursiveDirectoryTraversalFunction
<TVisitor extends RecursiveDirectoryTraversalFunction.Visitor, TReturn> {
+ private static final String SENTINEL_FILE_NAME_FOR_NOT_TRAVERSING_SYMLINKS =
+ "DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN";
/**
* Returned from {@link #visitDirectory} if its {@code recursivePkgKey} is a symlink or not a
@@ -232,16 +234,18 @@ abstract class RecursiveDirectoryTraversalFunction
}
List<SkyKey> childDeps = Lists.newArrayList();
+ boolean followSymlinks = shouldFollowSymlinksWhenTraversing(dirListingValue.getDirents());
for (Dirent dirent : dirListingValue.getDirents()) {
- if (dirent.getType() != Type.DIRECTORY && dirent.getType() != Type.SYMLINK) {
+ Type type = dirent.getType();
+ if (type != Type.DIRECTORY
+ && (type != Type.SYMLINK || (type == Type.SYMLINK && !followSymlinks))) {
// Non-directories can never host packages. Symlinks to non-directories are weeded out at
// the next level of recursion when we check if its FileValue is a directory. This is slower
// if there are a lot of symlinks in the tree, but faster if there are only a few, which is
// the case most of the time.
//
- // We are not afraid of weird symlink structure here: cyclical ones are diagnosed by
- // FileValue and ones that give rise to infinite directory trees work just like they do with
- // globbing: they work until a certain level of nesting, after which they fail.
+ // We are not afraid of weird symlink structure here: both cyclical ones and ones that give
+ // rise to infinite directory trees are diagnosed by FileValue.
continue;
}
String basename = dirent.getName();
@@ -282,6 +286,20 @@ abstract class RecursiveDirectoryTraversalFunction
return aggregateWithSubdirectorySkyValues(visitor, subdirectorySkyValues);
}
+ private static boolean shouldFollowSymlinksWhenTraversing(Dirents dirents) {
+ for (Dirent dirent : dirents) {
+ // This is a specical sentinel file whose existence tells Blaze not to follow symlinks when
+ // recursively traversing through this directory.
+ //
+ // This admittedly ugly feature is used to support workspaces with directories with weird
+ // symlink structures that aren't intended to be consumed by Blaze.
+ if (dirent.getName().equals(SENTINEL_FILE_NAME_FOR_NOT_TRAVERSING_SYMLINKS)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
// Ignore all errors in traversal and return an empty value.
private TReturn reportErrorAndReturn(String errorPrefix, Exception e,
PathFragment rootRelativePath, EventHandler handler) {