From 70691a0ea0a5d80dfdac083aa626e01115c9b365 Mon Sep 17 00:00:00 2001 From: Damien Martin-Guillerez Date: Wed, 24 Feb 2016 13:01:39 +0000 Subject: Implements repository_ctx.template repository_ctx.template enable writing a file in the remote repository tree using a template and a list of substitution in a similar way as the ctx.template_action for regular skylark rule. Issue #893: Step 4 of http://goo.gl/OZV3o0. See http://goo.gl/fD4ZsY. -- MOS_MIGRATED_REVID=115439344 --- .../skylark/SkylarkRepositoryContext.java | 30 ++++++++++++++++++++++ .../skylark/SkylarkRepositoryIntegrationTest.java | 26 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java index 45138da572..e2500dab2b 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java @@ -33,6 +33,8 @@ import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.Runtime; import com.google.devtools.build.lib.syntax.SkylarkType; import com.google.devtools.build.lib.syntax.Type; +import com.google.devtools.build.lib.util.StringUtilities; +import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.RootedPath; @@ -201,6 +203,34 @@ public class SkylarkRepositoryContext { } } + @SkylarkCallable( + name = "template", + doc = + "Generate a new file using a template. Every occurrence in " + + "template of a key of substitutions will be replaced by " + + "the corresponding value. The result is written in path." + ) + public void createFileFromTemplate( + Object path, Object template, Map substitutions) + throws RepositoryFunctionException, EvalException { + SkylarkPath p = getPath("template()", path); + SkylarkPath t = getPath("template()", template); + try { + checkInOutputDirectory(p); + makeDirectories(p.path); + String tpl = FileSystemUtils.readContent(t.path, StandardCharsets.UTF_8); + for (Map.Entry substitution : substitutions.entrySet()) { + tpl = + StringUtilities.replaceAllLiteral(tpl, substitution.getKey(), substitution.getValue()); + } + try (OutputStream stream = p.path.getOutputStream()) { + stream.write(tpl.getBytes(StandardCharsets.UTF_8)); + } + } catch (IOException e) { + throw new RepositoryFunctionException(e, Transience.TRANSIENT); + } + } + // Create parent directories for the given path private void makeDirectories(Path path) throws IOException { if (!path.isRootDirectory()) { diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryIntegrationTest.java index aaca4d0edb..dcdc6e40f0 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryIntegrationTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryIntegrationTest.java @@ -195,4 +195,30 @@ public class SkylarkRepositoryIntegrationTest extends BuildViewTestCase { Object path = target.getTarget().getAssociatedRule().getAttributeContainer().getAttr("path"); assertThat(path).isEqualTo("foo"); } + + @Test + public void testSkylarkRepositoryTemplate() throws Exception { + scratch.file("/repo2/bar.txt", "filegroup(name='{target}', srcs=['foo.txt'], path='{path}')"); + scratch.file("/repo2/BUILD"); + scratch.file("/repo2/WORKSPACE"); + scratch.file( + "def.bzl", + "def _impl(ctx):", + " ctx.template('BUILD', Label('@repo2//:bar.txt'), {'{target}': 'bar', '{path}': 'foo'})", + " ctx.file('foo.txt', 'foo')", + "", + "repo = repository_rule(", + " implementation=_impl,", + " local=True)"); + scratch.file(rootDirectory.getRelative("BUILD").getPathString()); + scratch.overwriteFile( + rootDirectory.getRelative("WORKSPACE").getPathString(), + "local_repository(name='repo2', path='/repo2')", + "load('//:def.bzl', 'repo')", + "repo(name='foo')"); + invalidatePackages(); + ConfiguredTarget target = getConfiguredTarget("@foo//:bar"); + Object path = target.getTarget().getAssociatedRule().getAttributeContainer().getAttr("path"); + assertThat(path).isEqualTo("foo"); + } } -- cgit v1.2.3