Search in sources :

Example 1 with Dirent

use of com.google.devtools.build.lib.vfs.Dirent in project bazel by bazelbuild.

the class UnixFileSystem method readdir.

@Override
protected Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
    String name = path.getPathString();
    long startTime = Profiler.nanoTimeMaybe();
    try {
        Dirents unixDirents = NativePosixFiles.readdir(name, followSymlinks ? ReadTypes.FOLLOW : ReadTypes.NOFOLLOW);
        Preconditions.checkState(unixDirents.hasTypes());
        List<Dirent> dirents = Lists.newArrayListWithCapacity(unixDirents.size());
        for (int i = 0; i < unixDirents.size(); i++) {
            dirents.add(new Dirent(unixDirents.getName(i), convertToDirentType(unixDirents.getType(i))));
        }
        return dirents;
    } finally {
        profiler.logSimpleTask(startTime, ProfilerTask.VFS_DIR, name);
    }
}
Also used : Dirent(com.google.devtools.build.lib.vfs.Dirent) Dirents(com.google.devtools.build.lib.unix.NativePosixFiles.Dirents)

Example 2 with Dirent

use of com.google.devtools.build.lib.vfs.Dirent in project bazel by bazelbuild.

the class AndroidSdkRepositoryFunction method getAndroidDeviceSystemImageDirs.

/**
   * Gets PathFragments for /sdk/system-images/*&#47;*&#47;*, which are the directories in the
   * SDK that contain system images needed for android_device.
   *
   * If the sdk/system-images directory does not exist, an empty set is returned.
   */
private static ImmutableSortedSet<PathFragment> getAndroidDeviceSystemImageDirs(Path androidSdkPath, Environment env) throws RepositoryFunctionException, InterruptedException {
    if (!androidSdkPath.getRelative(SYSTEM_IMAGES_DIR).exists()) {
        return ImmutableSortedSet.of();
    }
    DirectoryListingValue systemImagesDirectoryValue = AndroidRepositoryUtils.getDirectoryListing(androidSdkPath, SYSTEM_IMAGES_DIR, env);
    if (systemImagesDirectoryValue == null) {
        return null;
    }
    ImmutableMap<PathFragment, DirectoryListingValue> apiLevelSystemImageDirs = getSubdirectoryListingValues(androidSdkPath, SYSTEM_IMAGES_DIR, systemImagesDirectoryValue, env);
    if (apiLevelSystemImageDirs == null) {
        return null;
    }
    ImmutableSortedSet.Builder<PathFragment> pathFragments = ImmutableSortedSet.naturalOrder();
    for (PathFragment apiLevelDir : apiLevelSystemImageDirs.keySet()) {
        ImmutableMap<PathFragment, DirectoryListingValue> apiTypeSystemImageDirs = getSubdirectoryListingValues(androidSdkPath, apiLevelDir, apiLevelSystemImageDirs.get(apiLevelDir), env);
        if (apiTypeSystemImageDirs == null) {
            return null;
        }
        for (PathFragment apiTypeDir : apiTypeSystemImageDirs.keySet()) {
            for (Dirent architectureSystemImageDir : apiTypeSystemImageDirs.get(apiTypeDir).getDirents()) {
                pathFragments.add(apiTypeDir.getRelative(architectureSystemImageDir.getName()));
            }
        }
    }
    return pathFragments.build();
}
Also used : DirectoryListingValue(com.google.devtools.build.lib.skyframe.DirectoryListingValue) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Dirent(com.google.devtools.build.lib.vfs.Dirent)

Example 3 with Dirent

use of com.google.devtools.build.lib.vfs.Dirent in project bazel by bazelbuild.

the class GlobFunction method compute.

@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws GlobFunctionException, InterruptedException {
    GlobDescriptor glob = (GlobDescriptor) skyKey.argument();
    // Note that the glob's package is assumed to exist which implies that the package's BUILD file
    // exists which implies that the package's directory exists.
    PathFragment globSubdir = glob.getSubdir();
    if (!globSubdir.equals(PathFragment.EMPTY_FRAGMENT)) {
        PackageLookupValue globSubdirPkgLookupValue = (PackageLookupValue) env.getValue(PackageLookupValue.key(PackageIdentifier.create(glob.getPackageId().getRepository(), glob.getPackageId().getPackageFragment().getRelative(globSubdir))));
        if (globSubdirPkgLookupValue == null) {
            return null;
        }
        if (globSubdirPkgLookupValue.packageExists()) {
            // defines another package, so glob expansion should not descend into that subdir.
            return GlobValue.EMPTY;
        }
    }
    String pattern = glob.getPattern();
    // Split off the first path component of the pattern.
    int slashPos = pattern.indexOf('/');
    String patternHead;
    String patternTail;
    if (slashPos == -1) {
        patternHead = pattern;
        patternTail = null;
    } else {
        // Substrings will share the backing array of the original glob string. That should be fine.
        patternHead = pattern.substring(0, slashPos);
        patternTail = pattern.substring(slashPos + 1);
    }
    NestedSetBuilder<PathFragment> matches = NestedSetBuilder.stableOrder();
    boolean globMatchesBareFile = patternTail == null;
    // "**" also matches an empty segment, so try the case where it is not present.
    if ("**".equals(patternHead)) {
        if (globMatchesBareFile) {
            // Recursive globs aren't supposed to match the package's directory.
            if (!glob.excludeDirs() && !globSubdir.equals(PathFragment.EMPTY_FRAGMENT)) {
                matches.add(globSubdir);
            }
        } else {
            SkyKey globKey = GlobValue.internalKey(glob.getPackageId(), glob.getPackageRoot(), globSubdir, patternTail, glob.excludeDirs());
            GlobValue globValue = (GlobValue) env.getValue(globKey);
            if (globValue == null) {
                return null;
            }
            matches.addTransitive(globValue.getMatches());
        }
    }
    PathFragment dirPathFragment = glob.getPackageId().getPackageFragment().getRelative(globSubdir);
    RootedPath dirRootedPath = RootedPath.toRootedPath(glob.getPackageRoot(), dirPathFragment);
    if (alwaysUseDirListing || containsGlobs(patternHead)) {
        String subdirPattern = "**".equals(patternHead) ? glob.getPattern() : patternTail;
        // Pattern contains globs, so a directory listing is required.
        //
        // Note that we have good reason to believe the directory exists: if this is the
        // top-level directory of the package, the package's existence implies the directory's
        // existence; if this is a lower-level directory in the package, then we got here from
        // previous directory listings. Filesystem operations concurrent with build could mean the
        // directory no longer exists, but DirectoryListingFunction handles that gracefully.
        DirectoryListingValue listingValue = (DirectoryListingValue) env.getValue(DirectoryListingValue.key(dirRootedPath));
        if (listingValue == null) {
            return null;
        }
        // In order to batch Skyframe requests, we do three passes over the directory:
        // (1) Process every dirent, keeping track of values we need to request if the dirent cannot
        //     be processed with current information (symlink targets and subdirectory globs/package
        //     lookups for some subdirectories).
        // (2) Get those values and process the symlinks, keeping track of subdirectory globs/package
        //     lookups we may need to request in case the symlink's target is a directory.
        // (3) Process the necessary subdirectories.
        int direntsSize = listingValue.getDirents().size();
        Map<SkyKey, Dirent> symlinkFileMap = Maps.newHashMapWithExpectedSize(direntsSize);
        Map<SkyKey, Dirent> subdirMap = Maps.newHashMapWithExpectedSize(direntsSize);
        Map<Dirent, Object> sortedResultMap = Maps.newTreeMap();
        // First pass: do normal files and collect SkyKeys to request for subdirectories and symlinks.
        for (Dirent dirent : listingValue.getDirents()) {
            Type direntType = dirent.getType();
            String fileName = dirent.getName();
            if (!UnixGlob.matches(patternHead, fileName, regexPatternCache)) {
                continue;
            }
            if (direntType == Dirent.Type.SYMLINK) {
                // TODO(bazel-team): Consider extracting the symlink resolution logic.
                // For symlinks, look up the corresponding FileValue. This ensures that if the symlink
                // changes and "switches types" (say, from a file to a directory), this value will be
                // invalidated. We also need the target's type to properly process the symlink.
                symlinkFileMap.put(FileValue.key(RootedPath.toRootedPath(glob.getPackageRoot(), dirPathFragment.getRelative(fileName))), dirent);
                continue;
            }
            if (direntType == Dirent.Type.DIRECTORY) {
                SkyKey keyToRequest = getSkyKeyForSubdir(fileName, glob, subdirPattern);
                if (keyToRequest != null) {
                    subdirMap.put(keyToRequest, dirent);
                }
            } else if (globMatchesBareFile) {
                sortedResultMap.put(dirent, glob.getSubdir().getRelative(fileName));
            }
        }
        Map<SkyKey, SkyValue> subdirAndSymlinksResult = env.getValues(Sets.union(subdirMap.keySet(), symlinkFileMap.keySet()));
        if (env.valuesMissing()) {
            return null;
        }
        Map<SkyKey, Dirent> symlinkSubdirMap = Maps.newHashMapWithExpectedSize(symlinkFileMap.size());
        // Also process any known directories.
        for (Map.Entry<SkyKey, SkyValue> lookedUpKeyAndValue : subdirAndSymlinksResult.entrySet()) {
            if (symlinkFileMap.containsKey(lookedUpKeyAndValue.getKey())) {
                FileValue symlinkFileValue = (FileValue) lookedUpKeyAndValue.getValue();
                if (!symlinkFileValue.isSymlink()) {
                    throw new GlobFunctionException(new InconsistentFilesystemException("readdir and stat disagree about whether " + ((RootedPath) lookedUpKeyAndValue.getKey().argument()).asPath() + " is a symlink."), Transience.TRANSIENT);
                }
                if (!symlinkFileValue.exists()) {
                    continue;
                }
                Dirent dirent = symlinkFileMap.get(lookedUpKeyAndValue.getKey());
                String fileName = dirent.getName();
                if (symlinkFileValue.isDirectory()) {
                    SkyKey keyToRequest = getSkyKeyForSubdir(fileName, glob, subdirPattern);
                    if (keyToRequest != null) {
                        symlinkSubdirMap.put(keyToRequest, dirent);
                    }
                } else if (globMatchesBareFile) {
                    sortedResultMap.put(dirent, glob.getSubdir().getRelative(fileName));
                }
            } else {
                processSubdir(lookedUpKeyAndValue, subdirMap, glob, sortedResultMap);
            }
        }
        Map<SkyKey, SkyValue> symlinkSubdirResult = env.getValues(symlinkSubdirMap.keySet());
        if (env.valuesMissing()) {
            return null;
        }
        // pass.
        for (Map.Entry<SkyKey, SkyValue> lookedUpKeyAndValue : symlinkSubdirResult.entrySet()) {
            processSubdir(lookedUpKeyAndValue, symlinkSubdirMap, glob, sortedResultMap);
        }
        for (Map.Entry<Dirent, Object> fileMatches : sortedResultMap.entrySet()) {
            addToMatches(fileMatches.getValue(), matches);
        }
    } else {
        // Pattern does not contain globs, so a direct stat is enough.
        String fileName = patternHead;
        RootedPath fileRootedPath = RootedPath.toRootedPath(glob.getPackageRoot(), dirPathFragment.getRelative(fileName));
        FileValue fileValue = (FileValue) env.getValue(FileValue.key(fileRootedPath));
        if (fileValue == null) {
            return null;
        }
        if (fileValue.exists()) {
            if (fileValue.isDirectory()) {
                SkyKey keyToRequest = getSkyKeyForSubdir(fileName, glob, patternTail);
                if (keyToRequest != null) {
                    SkyValue valueRequested = env.getValue(keyToRequest);
                    if (env.valuesMissing()) {
                        return null;
                    }
                    Object fileMatches = getSubdirMatchesFromSkyValue(fileName, glob, valueRequested);
                    if (fileMatches != null) {
                        addToMatches(fileMatches, matches);
                    }
                }
            } else if (globMatchesBareFile) {
                matches.add(glob.getSubdir().getRelative(fileName));
            }
        }
    }
    Preconditions.checkState(!env.valuesMissing(), skyKey);
    NestedSet<PathFragment> matchesBuilt = matches.build();
    // Use the same value to represent that we did not match anything.
    if (matchesBuilt.isEmpty()) {
        return GlobValue.EMPTY;
    }
    return new GlobValue(matchesBuilt);
}
Also used : PathFragment(com.google.devtools.build.lib.vfs.PathFragment) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) SkyValue(com.google.devtools.build.skyframe.SkyValue) Dirent(com.google.devtools.build.lib.vfs.Dirent) SkyKey(com.google.devtools.build.skyframe.SkyKey) Type(com.google.devtools.build.lib.vfs.Dirent.Type) Map(java.util.Map)

Example 4 with Dirent

use of com.google.devtools.build.lib.vfs.Dirent in project bazel by bazelbuild.

the class GlobFunction method processSubdir.

private static void processSubdir(Map.Entry<SkyKey, SkyValue> keyAndValue, Map<SkyKey, Dirent> subdirMap, GlobDescriptor glob, Map<Dirent, Object> sortedResultMap) {
    Dirent dirent = Preconditions.checkNotNull(subdirMap.get(keyAndValue.getKey()), keyAndValue);
    String fileName = dirent.getName();
    Object dirMatches = getSubdirMatchesFromSkyValue(fileName, glob, keyAndValue.getValue());
    if (dirMatches != null) {
        sortedResultMap.put(dirent, dirMatches);
    }
}
Also used : Dirent(com.google.devtools.build.lib.vfs.Dirent)

Example 5 with Dirent

use of com.google.devtools.build.lib.vfs.Dirent in project bazel by bazelbuild.

the class AndroidSdkRepositoryFunction method getSubdirectoryListingValues.

/** Gets DirectoryListingValues for subdirectories of the directory or returns null. */
private static ImmutableMap<PathFragment, DirectoryListingValue> getSubdirectoryListingValues(final Path root, final PathFragment path, DirectoryListingValue directory, Environment env) throws RepositoryFunctionException, InterruptedException {
    Map<PathFragment, SkyKey> skyKeysForSubdirectoryLookups = Maps.transformEntries(Maps.uniqueIndex(directory.getDirents(), new Function<Dirent, PathFragment>() {

        @Override
        public PathFragment apply(Dirent input) {
            return path.getRelative(input.getName());
        }
    }), new EntryTransformer<PathFragment, Dirent, SkyKey>() {

        @Override
        public SkyKey transformEntry(PathFragment key, Dirent value) {
            return DirectoryListingValue.key(RootedPath.toRootedPath(root, root.getRelative(key)));
        }
    });
    Map<SkyKey, ValueOrException<InconsistentFilesystemException>> values = env.getValuesOrThrow(skyKeysForSubdirectoryLookups.values(), InconsistentFilesystemException.class);
    ImmutableMap.Builder<PathFragment, DirectoryListingValue> directoryListingValues = new ImmutableMap.Builder<>();
    for (PathFragment pathFragment : skyKeysForSubdirectoryLookups.keySet()) {
        try {
            SkyValue skyValue = values.get(skyKeysForSubdirectoryLookups.get(pathFragment)).get();
            if (skyValue == null) {
                return null;
            }
            directoryListingValues.put(pathFragment, (DirectoryListingValue) skyValue);
        } catch (InconsistentFilesystemException e) {
            throw new RepositoryFunctionException(new IOException(e), Transience.PERSISTENT);
        }
    }
    return directoryListingValues.build();
}
Also used : SkyKey(com.google.devtools.build.skyframe.SkyKey) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) IOException(java.io.IOException) InconsistentFilesystemException(com.google.devtools.build.lib.skyframe.InconsistentFilesystemException) ValueOrException(com.google.devtools.build.skyframe.ValueOrException) ImmutableMap(com.google.common.collect.ImmutableMap) SkyValue(com.google.devtools.build.skyframe.SkyValue) RepositoryFunction(com.google.devtools.build.lib.rules.repository.RepositoryFunction) Function(com.google.common.base.Function) DirectoryListingValue(com.google.devtools.build.lib.skyframe.DirectoryListingValue) Dirent(com.google.devtools.build.lib.vfs.Dirent)

Aggregations

Dirent (com.google.devtools.build.lib.vfs.Dirent)14 SkyKey (com.google.devtools.build.skyframe.SkyKey)8 RootedPath (com.google.devtools.build.lib.vfs.RootedPath)7 Path (com.google.devtools.build.lib.vfs.Path)5 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)5 SkyValue (com.google.devtools.build.skyframe.SkyValue)5 ErrorInfo (com.google.devtools.build.skyframe.ErrorInfo)3 IOException (java.io.IOException)3 Test (org.junit.Test)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 DirectoryListingValue (com.google.devtools.build.lib.skyframe.DirectoryListingValue)2 Type (com.google.devtools.build.lib.vfs.Dirent.Type)2 FileSystem (com.google.devtools.build.lib.vfs.FileSystem)2 InMemoryFileSystem (com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem)2 FileNotFoundException (java.io.FileNotFoundException)2 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 Before (org.junit.Before)2 Revision (com.android.repository.Revision)1 Function (com.google.common.base.Function)1