Make Bazel not raise an error when a symlink points to its own ancestor.

This is only an error when the symlink is to be traversed recursively. E.g. `a/a/a/b` is perfectly acceptable if `a/a` is a symlink to `.`, except if we want to recursively traverse into it during a glob or recursive target pattern expansion.

RELNOTES: Blaze now allows symbolic links that point to their own ancestor unless they are traversed recursively by e.g. a //... recursive target pattern or a recursive glob.
PiperOrigin-RevId: 334982640
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java
index b832485..8aee295 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java
@@ -235,6 +235,28 @@
           if (!symlinkFileValue.exists()) {
             continue;
           }
+
+          // This check is more strict than necessary: we raise an error if globbing traverses into
+          // a directory for any reason, even though it's only necessary if that reason was the
+          // resolution of a recursive glob ("**"). Fixing this would require plumbing the ancestor
+          // symlink information through DirectoryListingValue.
+          if (symlinkFileValue.isDirectory()
+              && symlinkFileValue.unboundedAncestorSymlinkExpansionChain() != null) {
+            SkyKey uniquenessKey =
+                FileSymlinkInfiniteExpansionUniquenessFunction.key(
+                    symlinkFileValue.unboundedAncestorSymlinkExpansionChain());
+            env.getValue(uniquenessKey);
+            if (env.valuesMissing()) {
+              return null;
+            }
+
+            FileSymlinkInfiniteExpansionException symlinkException =
+                new FileSymlinkInfiniteExpansionException(
+                    symlinkFileValue.pathToUnboundedAncestorSymlinkExpansionChain(),
+                    symlinkFileValue.unboundedAncestorSymlinkExpansionChain());
+            throw new GlobFunctionException(symlinkException, Transience.PERSISTENT);
+          }
+
           Dirent dirent = symlinkFileMap.get(lookedUpKeyAndValue.getKey());
           String fileName = dirent.getName();
           if (symlinkFileValue.isDirectory()) {
@@ -414,5 +436,9 @@
     public GlobFunctionException(InconsistentFilesystemException e, Transience transience) {
       super(e, transience);
     }
+
+    public GlobFunctionException(FileSymlinkInfiniteExpansionException e, Transience transience) {
+      super(e, transience);
+    }
   }
 }