private void reallyGlob()

in base/src/com/google/idea/blaze/base/lang/buildfile/globbing/UnixGlob.java [515:606]


    private void reallyGlob(
        File base,
        boolean baseIsDirectory,
        String[] patternParts,
        int idx,
        boolean excludeDirectories,
        Collection<File> results,
        Cache<String, Pattern> cache,
        Predicate<File> dirPred)
        throws IOException {
      ProgressManager.checkCanceled();
      if (baseIsDirectory && !dirPred.test(base)) {
        return;
      }

      if (idx == patternParts.length) { // Base case.
        if (!(excludeDirectories && baseIsDirectory)) {
          results.add(base);
        }
        return;
      }

      if (!baseIsDirectory) {
        // Nothing to find here.
        return;
      }

      final String pattern = patternParts[idx];

      // ** is special: it can match nothing at all.
      // For example, x/** matches x, **/y matches y, and x/**/y matches x/y.
      if ("**".equals(pattern)) {
        queueGlob(
            base,
            baseIsDirectory,
            patternParts,
            idx + 1,
            excludeDirectories,
            results,
            cache,
            dirPred);
      }

      if (!pattern.contains("*") && !pattern.contains("?")) {
        // We do not need to do a readdir in this case, just a stat.
        File child = new File(base, pattern);
        boolean childIsDir = fileOperationProvider.isDirectory(child);
        if (!childIsDir && !fileOperationProvider.isFile(child)) {
          // The file is a dangling symlink, fifo, does not exist, etc.
          return;
        }

        queueGlob(
            child, childIsDir, patternParts, idx + 1, excludeDirectories, results, cache, dirPred);
        return;
      }

      File[] children = getChildren(base);
      if (children == null) {
        return;
      }
      for (File child : children) {
        boolean childIsDir = fileOperationProvider.isDirectory(child);

        if ("**".equals(pattern)) {
          // Recurse without shifting the pattern.
          if (childIsDir) {
            queueGlob(
                child, childIsDir, patternParts, idx, excludeDirectories, results, cache, dirPred);
          }
        }
        if (matches(pattern, child.getName(), cache)) {
          // Recurse and consume one segment of the pattern.
          if (childIsDir) {
            queueGlob(
                child,
                childIsDir,
                patternParts,
                idx + 1,
                excludeDirectories,
                results,
                cache,
                dirPred);
          } else {
            // Instead of using an async call, just repeat the base case above.
            if (idx + 1 == patternParts.length) {
              results.add(child);
            }
          }
        }
      }
    }