Search in sources :

Example 61 with PathFragment

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

the class ASTFileLookupFunction method compute.

@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException {
    Label fileLabel = (Label) skyKey.argument();
    PathFragment filePathFragment = fileLabel.toPathFragment();
    //
    // Determine whether the package designated by fileLabel exists.
    //
    SkyKey pkgSkyKey = PackageLookupValue.key(fileLabel.getPackageIdentifier());
    PackageLookupValue pkgLookupValue = null;
    try {
        pkgLookupValue = (PackageLookupValue) env.getValueOrThrow(pkgSkyKey, BuildFileNotFoundException.class, InconsistentFilesystemException.class);
    } catch (BuildFileNotFoundException e) {
        throw new ASTLookupFunctionException(new ErrorReadingSkylarkExtensionException(e), Transience.PERSISTENT);
    } catch (InconsistentFilesystemException e) {
        throw new ASTLookupFunctionException(e, Transience.PERSISTENT);
    }
    if (pkgLookupValue == null) {
        return null;
    }
    if (!pkgLookupValue.packageExists()) {
        return ASTFileLookupValue.forBadPackage(fileLabel, pkgLookupValue.getErrorMsg());
    }
    //
    // Determine whether the file designated by fileLabel exists.
    //
    Path packageRoot = pkgLookupValue.getRoot();
    RootedPath rootedPath = RootedPath.toRootedPath(packageRoot, filePathFragment);
    SkyKey fileSkyKey = FileValue.key(rootedPath);
    FileValue fileValue = null;
    try {
        fileValue = (FileValue) env.getValueOrThrow(fileSkyKey, IOException.class, FileSymlinkException.class, InconsistentFilesystemException.class);
    } catch (IOException | FileSymlinkException e) {
        throw new ASTLookupFunctionException(new ErrorReadingSkylarkExtensionException(e), Transience.PERSISTENT);
    } catch (InconsistentFilesystemException e) {
        throw new ASTLookupFunctionException(e, Transience.PERSISTENT);
    }
    if (fileValue == null) {
        return null;
    }
    if (!fileValue.isFile()) {
        return ASTFileLookupValue.forBadFile(fileLabel);
    }
    //
    // Both the package and the file exist; load the file and parse it as an AST.
    //
    BuildFileAST ast = null;
    Path path = rootedPath.asPath();
    try {
        long astFileSize = fileValue.getSize();
        try (Mutability mutability = Mutability.create("validate")) {
            ValidationEnvironment validationEnv = new ValidationEnvironment(ruleClassProvider.createSkylarkRuleClassEnvironment(fileLabel, mutability, env.getListener(), /*astFileContentHashCode=*/
            null, /*importMap=*/
            null).setupDynamic(Runtime.PKG_NAME, Runtime.NONE).setupDynamic(Runtime.REPOSITORY_NAME, Runtime.NONE));
            ast = BuildFileAST.parseSkylarkFile(path, astFileSize, env.getListener());
            ast = ast.validate(validationEnv, env.getListener());
        }
    } catch (IOException e) {
        throw new ASTLookupFunctionException(new ErrorReadingSkylarkExtensionException(e), Transience.TRANSIENT);
    }
    return ASTFileLookupValue.withFile(ast);
}
Also used : SkyKey(com.google.devtools.build.skyframe.SkyKey) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) Path(com.google.devtools.build.lib.vfs.Path) BuildFileNotFoundException(com.google.devtools.build.lib.packages.BuildFileNotFoundException) ValidationEnvironment(com.google.devtools.build.lib.syntax.ValidationEnvironment) Label(com.google.devtools.build.lib.cmdline.Label) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Mutability(com.google.devtools.build.lib.syntax.Mutability) IOException(java.io.IOException) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) BuildFileAST(com.google.devtools.build.lib.syntax.BuildFileAST)

Example 62 with PathFragment

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

the class FileFunction method resolveFromAncestors.

/**
   * Returns the path and file state of {@code rootedPath}, accounting for ancestor symlinks, or
   * {@code null} if there was a missing dep.
   */
@Nullable
private static Pair<RootedPath, FileStateValue> resolveFromAncestors(RootedPath rootedPath, Environment env) throws FileFunctionException, InterruptedException {
    PathFragment relativePath = rootedPath.getRelativePath();
    RootedPath realRootedPath = rootedPath;
    FileValue parentFileValue = null;
    if (!relativePath.equals(PathFragment.EMPTY_FRAGMENT)) {
        RootedPath parentRootedPath = RootedPath.toRootedPath(rootedPath.getRoot(), relativePath.getParentDirectory());
        parentFileValue = (FileValue) env.getValue(FileValue.key(parentRootedPath));
        if (parentFileValue == null) {
            return null;
        }
        PathFragment baseName = new PathFragment(relativePath.getBaseName());
        RootedPath parentRealRootedPath = parentFileValue.realRootedPath();
        realRootedPath = RootedPath.toRootedPath(parentRealRootedPath.getRoot(), parentRealRootedPath.getRelativePath().getRelative(baseName));
        if (!parentFileValue.exists()) {
            return Pair.<RootedPath, FileStateValue>of(realRootedPath, FileStateValue.NONEXISTENT_FILE_STATE_NODE);
        }
    }
    FileStateValue realFileStateValue = (FileStateValue) env.getValue(FileStateValue.key(realRootedPath));
    if (realFileStateValue == null) {
        return null;
    }
    if (realFileStateValue.getType() != FileStateValue.Type.NONEXISTENT && parentFileValue != null && !parentFileValue.isDirectory()) {
        String type = realFileStateValue.getType().toString().toLowerCase();
        String message = type + " " + rootedPath.asPath() + " exists but its parent " + "path " + parentFileValue.realRootedPath().asPath() + " isn't an existing directory.";
        throw new FileFunctionException(new InconsistentFilesystemException(message), Transience.TRANSIENT);
    }
    return Pair.of(realRootedPath, realFileStateValue);
}
Also used : PathFragment(com.google.devtools.build.lib.vfs.PathFragment) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) Nullable(javax.annotation.Nullable)

Example 63 with PathFragment

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

the class FilesetEntryFunction method compute.

@Override
public SkyValue compute(SkyKey key, Environment env) throws FilesetEntryFunctionException, InterruptedException {
    FilesetTraversalParams t = (FilesetTraversalParams) key.argument();
    Preconditions.checkState(t.getNestedTraversal().isPresent() != t.getDirectTraversal().isPresent(), "Exactly one of the nested and direct traversals must be specified: %s", t);
    // Create the set of excluded files. Only top-level files can be excluded, i.e. ones that are
    // directly under the root if the root is a directory.
    Set<String> exclusions = createExclusionSet(t.getExcludedFiles());
    // The map of output symlinks. Each key is the path of a output symlink that the Fileset must
    // create, relative to the Fileset.out directory, and each value specifies extra information
    // about the link (its target, associated metadata and again its name).
    Map<PathFragment, FilesetOutputSymlink> outputSymlinks = new LinkedHashMap<>();
    if (t.getNestedTraversal().isPresent()) {
        // The "nested" traversal parameters are present if and only if FilesetEntry.srcdir specifies
        // another Fileset (a "nested" one).
        FilesetEntryValue nested = (FilesetEntryValue) env.getValue(FilesetEntryValue.key(t.getNestedTraversal().get()));
        if (env.valuesMissing()) {
            return null;
        }
        for (FilesetOutputSymlink s : nested.getSymlinks()) {
            if (!exclusions.contains(s.name.getPathString())) {
                maybeStoreSymlink(s, t.getDestPath(), outputSymlinks);
            }
        }
    } else {
        // The "nested" traversal params are absent if and only if the "direct" traversal params are
        // present, which is the case when the FilesetEntry specifies a package's BUILD file, a
        // directory or a list of files.
        // The root of the direct traversal is defined as follows.
        //
        // If FilesetEntry.files is specified, then a TraversalRequest is created for each entry, the
        // root being the respective entry itself. These are all traversed for they may be
        // directories or symlinks to directories, and we need to establish Skyframe dependencies on
        // their contents for incremental correctness. If an entry is indeed a directory (but not when
        // it's a symlink to one) then we have to create symlinks to each of their childen.
        // (NB: there seems to be no good reason for this, it's just how legacy Fileset works. We may
        // want to consider creating a symlink just for the directory and not for its child elements.)
        //
        // If FilesetEntry.files is not specified, then srcdir refers to either a BUILD file or a
        // directory. For the former, the root will be the parent of the BUILD file. For the latter,
        // the root will be srcdir itself.
        DirectTraversal direct = t.getDirectTraversal().get();
        RecursiveFilesystemTraversalValue rftv;
        try {
            // Traverse the filesystem to establish skyframe dependencies.
            rftv = traverse(env, createErrorInfo(t), direct);
        } catch (MissingDepException e) {
            return null;
        }
        // The root can only be absent for the EMPTY rftv instance.
        if (!rftv.getResolvedRoot().isPresent()) {
            return FilesetEntryValue.EMPTY;
        }
        ResolvedFile resolvedRoot = rftv.getResolvedRoot().get();
        // Handle dangling symlinks gracefully be returning empty results.
        if (!resolvedRoot.getType().exists()) {
            return FilesetEntryValue.EMPTY;
        }
        // The prefix to remove is the entire path of the root. This is OK:
        // - when the root is a file, this removes the entire path, but the traversal's destination
        //   path is actually the name of the output symlink, so this works out correctly
        // - when the root is a directory or a symlink to one then we need to strip off the
        //   directory's path from every result (this is how the output symlinks must be created)
        //   before making them relative to the destination path
        PathFragment prefixToRemove = direct.getRoot().getRelativePart();
        Iterable<ResolvedFile> results = null;
        if (direct.isRecursive() || (resolvedRoot.getType().isDirectory() && !resolvedRoot.getType().isSymlink())) {
            // The traversal is recursive (requested for an entire FilesetEntry.srcdir) or it was
            // requested for a FilesetEntry.files entry which turned out to be a directory. We need to
            // create an output symlink for every file in it and all of its subdirectories. Only
            // exception is when the subdirectory is really a symlink to a directory -- no output
            // shall be created for the contents of those.
            // Now we create Dir objects to model the filesystem tree. The object employs a trick to
            // find directory symlinks: directory symlinks have corresponding ResolvedFile entries and
            // are added as files too, while their children, also added as files, contain the path of
            // the parent. Finding and discarding the children is easy if we traverse the tree from
            // root to leaf.
            DirectoryTree root = new DirectoryTree();
            for (ResolvedFile f : rftv.getTransitiveFiles().toCollection()) {
                PathFragment path = f.getNameInSymlinkTree().relativeTo(prefixToRemove);
                if (path.segmentCount() > 0) {
                    path = t.getDestPath().getRelative(path);
                    DirectoryTree dir = root;
                    for (int i = 0; i < path.segmentCount() - 1; ++i) {
                        dir = dir.addOrGetSubdir(path.getSegment(i));
                    }
                    dir.maybeAddFile(f);
                }
            }
            // Here's where the magic happens. The returned iterable will yield all files in the
            // directory that are not under symlinked directories, as well as all directory symlinks.
            results = root.iterateFiles();
        } else {
            // If we're on this branch then the traversal was done for just one entry in
            // FilesetEntry.files (which was not a directory, so it was either a file, a symlink to one
            // or a symlink to a directory), meaning we'll have only one output symlink.
            results = ImmutableList.of(resolvedRoot);
        }
        // Create one output symlink for each entry in the results.
        for (ResolvedFile f : results) {
            // The linkName has to be under the traversal's root, which is also the prefix to remove.
            PathFragment linkName = f.getNameInSymlinkTree().relativeTo(prefixToRemove);
            // It may be dangling, but excluding it is still fine.
            if (exclusions.contains(linkName.getPathString())) {
                continue;
            }
            PathFragment targetName;
            try {
                targetName = f.getTargetInSymlinkTree(direct.isFollowingSymlinks());
            } catch (DanglingSymlinkException e) {
                throw new FilesetEntryFunctionException(e);
            }
            // Metadata field must be present. It can only be absent when stripped by tests.
            String metadata = Integer.toHexString(f.getMetadataHash());
            maybeStoreSymlink(linkName, targetName, metadata, t.getDestPath(), outputSymlinks);
        }
    }
    return FilesetEntryValue.of(ImmutableSet.copyOf(outputSymlinks.values()));
}
Also used : PathFragment(com.google.devtools.build.lib.vfs.PathFragment) DirectTraversal(com.google.devtools.build.lib.actions.FilesetTraversalParams.DirectTraversal) DanglingSymlinkException(com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalFunction.DanglingSymlinkException) LinkedHashMap(java.util.LinkedHashMap) ResolvedFile(com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFile) FilesetTraversalParams(com.google.devtools.build.lib.actions.FilesetTraversalParams) FilesetOutputSymlink(com.google.devtools.build.lib.actions.FilesetOutputSymlink)

Example 64 with PathFragment

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

the class DarwinSandboxedStrategy method finalizeLinks.

private Map<PathFragment, Path> finalizeLinks(Map<PathFragment, Path> unfinalized) throws IOException {
    HashMap<PathFragment, Path> finalizedLinks = new HashMap<>();
    for (Map.Entry<PathFragment, Path> mount : unfinalized.entrySet()) {
        PathFragment target = mount.getKey();
        Path source = mount.getValue();
        // have to deal with finalizing the link.
        if (source == null) {
            finalizedLinks.put(target, source);
            continue;
        }
        FileStatus stat = source.statNullable(Symlinks.NOFOLLOW);
        if (stat != null && stat.isDirectory()) {
            for (Path subSource : FileSystemUtils.traverseTree(source, Predicates.alwaysTrue())) {
                PathFragment subTarget = target.getRelative(subSource.relativeTo(source));
                finalizeLinksPath(finalizedLinks, subTarget, subSource, subSource.statNullable(Symlinks.NOFOLLOW));
            }
        } else {
            finalizeLinksPath(finalizedLinks, target, source, stat);
        }
    }
    return finalizedLinks;
}
Also used : SearchPath(com.google.devtools.build.lib.vfs.SearchPath) Path(com.google.devtools.build.lib.vfs.Path) FileStatus(com.google.devtools.build.lib.vfs.FileStatus) HashMap(java.util.HashMap) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 65 with PathFragment

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

the class DarwinSandboxedStrategy method getRunUnderPath.

/**
   * If a --run_under= option is set and refers to a command via its path (as opposed to via its
   * label), we have to mount this. Note that this is best effort and works fine for shell scripts
   * and small binaries, but we can't track any further dependencies of this command.
   *
   * <p>If --run_under= refers to a label, it is automatically provided in the spawn's input files,
   * so mountInputs() will catch that case.
   */
private Path getRunUnderPath(Spawn spawn) {
    if (spawn.getResourceOwner() instanceof TestRunnerAction) {
        TestRunnerAction testRunnerAction = ((TestRunnerAction) spawn.getResourceOwner());
        RunUnder runUnder = testRunnerAction.getExecutionSettings().getRunUnder();
        if (runUnder != null && runUnder.getCommand() != null) {
            PathFragment sourceFragment = new PathFragment(runUnder.getCommand());
            Path mount;
            if (sourceFragment.isAbsolute()) {
                mount = blazeDirs.getFileSystem().getPath(sourceFragment);
            } else if (blazeDirs.getExecRoot().getRelative(sourceFragment).exists()) {
                mount = blazeDirs.getExecRoot().getRelative(sourceFragment);
            } else {
                List<Path> searchPath = SearchPath.parse(blazeDirs.getFileSystem(), clientEnv.get("PATH"));
                mount = SearchPath.which(searchPath, runUnder.getCommand());
            }
            // only need to hardlink when under workspace
            Path workspace = blazeDirs.getWorkspace();
            if (mount != null && mount.startsWith(workspace)) {
                return mount;
            }
        }
    }
    return null;
}
Also used : SearchPath(com.google.devtools.build.lib.vfs.SearchPath) Path(com.google.devtools.build.lib.vfs.Path) RunUnder(com.google.devtools.build.lib.analysis.config.RunUnder) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) TestRunnerAction(com.google.devtools.build.lib.rules.test.TestRunnerAction) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List)

Aggregations

PathFragment (com.google.devtools.build.lib.vfs.PathFragment)512 Test (org.junit.Test)208 Artifact (com.google.devtools.build.lib.actions.Artifact)184 Path (com.google.devtools.build.lib.vfs.Path)111 RootedPath (com.google.devtools.build.lib.vfs.RootedPath)65 SkyKey (com.google.devtools.build.skyframe.SkyKey)56 IOException (java.io.IOException)38 ArrayList (java.util.ArrayList)35 ImmutableList (com.google.common.collect.ImmutableList)32 Root (com.google.devtools.build.lib.actions.Root)32 HashMap (java.util.HashMap)27 Label (com.google.devtools.build.lib.cmdline.Label)26 LinkedHashMap (java.util.LinkedHashMap)26 TreeFileArtifact (com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact)23 ImmutableMap (com.google.common.collect.ImmutableMap)22 Map (java.util.Map)21 SpecialArtifact (com.google.devtools.build.lib.actions.Artifact.SpecialArtifact)20 FilesetTraversalParams (com.google.devtools.build.lib.actions.FilesetTraversalParams)16 PackageIdentifier (com.google.devtools.build.lib.cmdline.PackageIdentifier)16 NestedSetBuilder (com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder)16