@Nullable @Override public SkyValue compute(SkyKey skyKey, SkyFunction.Environment env) throws RepositoryFunctionException { RepositoryName repositoryName = (RepositoryName) skyKey.argument(); Rule rule = getRule(repositoryName, NewHttpArchiveRule.NAME, env); if (rule == null) { return null; } Path outputDirectory = getExternalRepositoryDirectory().getRelative(rule.getName()); try { FileSystemUtils.createDirectoryAndParents(outputDirectory); } catch (IOException e) { throw new RepositoryFunctionException( new IOException( "Could not create directory for " + rule.getName() + ": " + e.getMessage()), Transience.TRANSIENT); } FileValue repositoryDirectory = getRepositoryDirectory(outputDirectory, env); if (repositoryDirectory == null) { return null; } // Download. HttpDownloadValue downloadedFileValue; try { downloadedFileValue = (HttpDownloadValue) env.getValueOrThrow( HttpDownloadFunction.key(rule, outputDirectory), IOException.class); } catch (IOException e) { throw new RepositoryFunctionException(e, Transience.PERSISTENT); } if (downloadedFileValue == null) { return null; } // Decompress. DecompressorValue decompressed; try { decompressed = (DecompressorValue) env.getValueOrThrow( DecompressorValue.key( rule.getTargetKind(), rule.getName(), downloadedFileValue.getPath(), outputDirectory), IOException.class); if (decompressed == null) { return null; } } catch (IOException e) { throw new RepositoryFunctionException(new IOException(e.getMessage()), Transience.TRANSIENT); } // Add WORKSPACE and BUILD files. createWorkspaceFile(decompressed.getDirectory(), rule); return symlinkBuildFile(rule, getWorkspace(), repositoryDirectory, env); }
@Override public SkyValue fetch(Rule rule, Path outputDirectory, Environment env) throws SkyFunctionException { prepareLocalRepositorySymlinkTree(rule, outputDirectory); PathFragment pathFragment = getTargetPath(rule, getWorkspace()); if (!symlinkLocalRepositoryContents( outputDirectory, getOutputBase().getFileSystem().getPath(pathFragment))) { return null; } AttributeMap attributes = NonconfigurableAttributeMapper.of(rule); String buildToolsVersion = attributes.get("build_tools_version", Type.STRING); Integer apiLevel = attributes.get("api_level", Type.INTEGER); String template = getStringResource("android_sdk_repository_template.txt"); String buildFile = template .replaceAll("%repository_name%", rule.getName()) .replaceAll("%build_tools_version%", buildToolsVersion) .replaceAll("%api_level%", apiLevel.toString()); writeBuildFile(outputDirectory, buildFile); return RepositoryDirectoryValue.create(outputDirectory); }
/** Adds the given rule to the stack trace of the exception (if there is one). */ private static void addRuleToStackTrace(EvalException ex, Rule rule, BaseFunction ruleImpl) { if (ex instanceof EvalExceptionWithStackTrace) { ((EvalExceptionWithStackTrace) ex) .registerPhantomFuncall( String.format("%s(name = '%s')", rule.getRuleClass(), rule.getName()), rule.getLocation(), ruleImpl); } }
protected void createDirectory(Path path, Rule rule) throws RepositoryFunctionException { try { FileSystemUtils.createDirectoryAndParents(path); } catch (IOException e) { throw new RepositoryFunctionException( new IOException( "Could not create directory for " + rule.getName() + ": " + e.getMessage()), Transience.TRANSIENT); } }
@Nullable @Override public Map<String, Label> apply(Rule rule) { ImmutableMap.Builder<String, Label> result = ImmutableMap.builder(); for (String tool : TOOLS) { result.put( "android/" + tool, Label.parseAbsoluteUnchecked("@" + rule.getName() + "//tools/android:" + tool)); } return result.build(); }
protected SkyValue compute(Environment env, Rule rule) throws RepositoryFunctionException { // The output directory is always under .external-repository (to stay out of the way of // artifacts from this repository) and uses the rule's name to avoid conflicts with other // remote repository rules. For example, suppose you had the following WORKSPACE file: // // http_archive(name = "png", url = "http://example.com/downloads/png.tar.gz", sha256 = "...") // // This would download png.tar.gz to .external-repository/png/png.tar.gz. Path outputDirectory = getExternalRepositoryDirectory().getRelative(rule.getName()); FileValue directoryValue = createDirectory(outputDirectory, env); if (directoryValue == null) { return null; } AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); URL url = null; try { url = new URL(mapper.get("url", Type.STRING)); } catch (MalformedURLException e) { throw new RepositoryFunctionException( new EvalException(rule.getLocation(), "Error parsing URL: " + e.getMessage()), Transience.PERSISTENT); } String sha256 = mapper.get("sha256", Type.STRING); HttpDownloader downloader = new HttpDownloader(url, sha256, outputDirectory); try { Path archiveFile = downloader.download(); outputDirectory = DecompressorFactory.create( rule.getTargetKind(), rule.getName(), archiveFile, outputDirectory) .decompress(); } catch (IOException e) { // Assumes all IO errors transient. throw new RepositoryFunctionException(e, Transience.TRANSIENT); } catch (DecompressorException e) { throw new RepositoryFunctionException(new IOException(e.getMessage()), Transience.TRANSIENT); } return new RepositoryValue(outputDirectory, directoryValue); }
protected FileValue prepareLocalRepositorySymlinkTree(Rule rule, Environment env) throws RepositoryFunctionException { Path repositoryDirectory = getExternalRepositoryDirectory().getRelative(rule.getName()); try { FileSystemUtils.deleteTree(repositoryDirectory); FileSystemUtils.createDirectoryAndParents(repositoryDirectory); } catch (IOException e) { throw new RepositoryFunctionException(e, Transience.TRANSIENT); } FileValue directoryValue = getRepositoryDirectory(repositoryDirectory, env); if (directoryValue == null) { return null; } // Add x/WORKSPACE. createWorkspaceFile(repositoryDirectory, rule); return directoryValue; }
public void testRuleProperties() throws Exception { assertEquals(rule.getName(), mapper.getName()); assertEquals(rule.getLabel(), mapper.getLabel()); }