diff options
author | 2015-11-13 01:43:59 +0000 | |
---|---|---|
committer | 2015-11-13 10:23:23 +0000 | |
commit | 1e66ccd2f18b03733f22b93ad8051ff2cf37d3dd (patch) | |
tree | 01b02da842123097e8fae49960d35758d31c3cde /src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java | |
parent | f6866778db261e5d8b95ee1c46622ceb19a609a4 (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.java | 26 |
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) { |