@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); }
protected RepositoryValue writeBuildFile(FileValue directoryValue, String contents) throws RepositoryFunctionException { Path buildFilePath = directoryValue.realRootedPath().asPath().getRelative("BUILD"); try { FileSystemUtils.writeContentAsLatin1(buildFilePath, contents); } catch (IOException e) { throw new RepositoryFunctionException(e, Transience.TRANSIENT); } return RepositoryValue.create(directoryValue); }