From 1e66ccd2f18b03733f22b93ad8051ff2cf37d3dd Mon Sep 17 00:00:00 2001 From: Nathan Harmata Date: Fri, 13 Nov 2015 01:43:59 +0000 Subject: 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 /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 --- .../RecursiveDirectoryTraversalFunction.java | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java') 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 { + 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 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) { -- cgit v1.2.3