private static FileValue createSymbolicLink(Path from, Path to, Environment env) throws RepositoryFunctionException { try { if (!from.exists()) { from.createSymbolicLink(to); } } catch (IOException e) { throw new RepositoryFunctionException( new IOException( String.format( "Error creating symbolic link from %s to %s: %s", from, to, e.getMessage())), Transience.TRANSIENT); } SkyKey outputDirectoryKey = FileValue.key(RootedPath.toRootedPath(from, PathFragment.EMPTY_FRAGMENT)); try { return (FileValue) env.getValueOrThrow( outputDirectoryKey, IOException.class, FileSymlinkException.class, InconsistentFilesystemException.class); } catch (IOException | FileSymlinkException | InconsistentFilesystemException e) { throw new RepositoryFunctionException( new IOException(String.format("Could not access %s: %s", from, e.getMessage())), Transience.PERSISTENT); } }
@Override public SkyValue fetch(Rule rule, Path outputDirectory, Environment env) throws SkyFunctionException { AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); PathFragment pathFragment = new PathFragment(mapper.get("path", Type.STRING)); try { FileSystem fs = outputDirectory.getFileSystem(); if (fs.supportsSymbolicLinksNatively()) { outputDirectory.createSymbolicLink(pathFragment); } else { FileSystemUtils.createDirectoryAndParents(outputDirectory); FileSystemUtils.copyTreesBelow( fs.getPath(getTargetPath(rule, getWorkspace())), outputDirectory); } } catch (IOException e) { throw new RepositoryFunctionException( new IOException( "Could not create symlink to repository " + pathFragment + ": " + e.getMessage()), Transience.TRANSIENT); } FileValue repositoryValue = getRepositoryDirectory(outputDirectory, env); if (repositoryValue == null) { // TODO(bazel-team): If this returns null, we unnecessarily recreate the symlink above on the // second execution. return null; } if (!repositoryValue.isDirectory()) { throw new RepositoryFunctionException( new IOException(rule + " must specify an existing directory"), Transience.TRANSIENT); } return RepositoryValue.create(outputDirectory); }
@Override public void setUp() throws Exception { super.setUp(); input = scratch.file("input.txt", "Hello, world."); inputArtifact = getSourceArtifact("input.txt"); Path linkedInput = directories.getExecRoot().getRelative("input.txt"); FileSystemUtils.createDirectoryAndParents(linkedInput.getParentDirectory()); linkedInput.createSymbolicLink(input); outputArtifact = getBinArtifactWithNoOwner("destination.txt"); output = outputArtifact.getPath(); FileSystemUtils.createDirectoryAndParents(output.getParentDirectory()); action = new SymlinkAction(NULL_ACTION_OWNER, inputArtifact, outputArtifact, "Symlinking test"); }