aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
authorGravatar Kristina Chodorow <kchodorow@google.com>2015-03-18 17:00:21 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-03-20 14:26:56 +0000
commit830af4ca3ad02de3901dbbd790713753668b2b0e (patch)
tree66aa1122cc4ec7967599bcaf4afff200970e7adc /src/main/java/com
parentd584f6520da8f480bdfdfdac7e7f8160102379ae (diff)
Add on-the-fly remote repos
Adds a new rule: new_http_archive( name = "whatever", url = "http://www.github.com/google/bazel-tools/my-tools.zip", sha256 = "...", build_file = "my/tools/objc.BUILD", ) This will download & unzip my-tools.zip, put a WORKSPACE file in its root, and link the provided BUILD file into its root. -- MOS_MIGRATED_REVID=88941267
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorFactory.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloadFunction.java131
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java88
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/NewLocalRepositoryFunction.java52
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/HttpArchiveRule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewHttpArchiveRule.java121
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewLocalRepositoryRule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RepositoryValue.java4
10 files changed, 402 insertions, 24 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java
index 483103f8c3..988afec114 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java
@@ -20,9 +20,11 @@ import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.bazel.repository.HttpArchiveFunction;
+import com.google.devtools.build.lib.bazel.repository.HttpDownloadFunction;
import com.google.devtools.build.lib.bazel.repository.HttpJarFunction;
import com.google.devtools.build.lib.bazel.repository.LocalRepositoryFunction;
import com.google.devtools.build.lib.bazel.repository.MavenJarFunction;
+import com.google.devtools.build.lib.bazel.repository.NewHttpArchiveFunction;
import com.google.devtools.build.lib.bazel.repository.NewLocalRepositoryFunction;
import com.google.devtools.build.lib.bazel.repository.RepositoryDelegatorFunction;
import com.google.devtools.build.lib.bazel.repository.RepositoryFunction;
@@ -30,6 +32,7 @@ import com.google.devtools.build.lib.bazel.rules.workspace.HttpArchiveRule;
import com.google.devtools.build.lib.bazel.rules.workspace.HttpJarRule;
import com.google.devtools.build.lib.bazel.rules.workspace.LocalRepositoryRule;
import com.google.devtools.build.lib.bazel.rules.workspace.MavenJarRule;
+import com.google.devtools.build.lib.bazel.rules.workspace.NewHttpArchiveRule;
import com.google.devtools.build.lib.bazel.rules.workspace.NewLocalRepositoryRule;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
@@ -53,12 +56,14 @@ public class BazelRepositoryModule extends BlazeModule {
private final ImmutableMap<String, RepositoryFunction> repositoryHandlers;
public BazelRepositoryModule() {
- repositoryHandlers = ImmutableMap.of(
- LocalRepositoryRule.NAME, new LocalRepositoryFunction(),
- HttpArchiveRule.NAME, new HttpArchiveFunction(),
- HttpJarRule.NAME, new HttpJarFunction(),
- MavenJarRule.NAME, new MavenJarFunction(),
- NewLocalRepositoryRule.NAME, new NewLocalRepositoryFunction());
+ repositoryHandlers = ImmutableMap.<String, RepositoryFunction>builder()
+ .put(LocalRepositoryRule.NAME, new LocalRepositoryFunction())
+ .put(HttpArchiveRule.NAME, new HttpArchiveFunction())
+ .put(HttpJarRule.NAME, new HttpJarFunction())
+ .put(MavenJarRule.NAME, new MavenJarFunction())
+ .put(NewHttpArchiveRule.NAME, new NewHttpArchiveFunction())
+ .put(NewLocalRepositoryRule.NAME, new NewLocalRepositoryFunction())
+ .build();
}
@Override
@@ -95,6 +100,9 @@ public class BazelRepositoryModule extends BlazeModule {
// Create the delegator everything flows through.
builder.put(SkyFunctions.REPOSITORY,
new RepositoryDelegatorFunction(repositoryHandlers));
+
+ // Helper SkyFunctions.
+ builder.put(SkyFunctionName.computed(HttpDownloadFunction.NAME), new HttpDownloadFunction());
return builder.build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorFactory.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorFactory.java
index 3660317148..d3001a40ee 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorFactory.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.bazel.repository;
import com.google.devtools.build.lib.bazel.rules.workspace.HttpArchiveRule;
import com.google.devtools.build.lib.bazel.rules.workspace.HttpJarRule;
+import com.google.devtools.build.lib.bazel.rules.workspace.NewHttpArchiveRule;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -55,7 +56,8 @@ public abstract class DecompressorFactory {
}
}
- if (targetKind.startsWith(HttpArchiveRule.NAME + " ")) {
+ if (targetKind.startsWith(HttpArchiveRule.NAME + " ")
+ || targetKind.startsWith(NewHttpArchiveRule.NAME + " ")) {
if (baseName.endsWith(".zip") || baseName.endsWith(".jar")) {
return new ZipDecompressor(archivePath);
} else {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloadFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloadFunction.java
new file mode 100644
index 0000000000..c16f5093ea
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloadFunction.java
@@ -0,0 +1,131 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.repository;
+
+import com.google.devtools.build.lib.bazel.repository.RepositoryFunction.RepositoryFunctionException;
+import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.skyframe.FileValue;
+import com.google.devtools.build.lib.skyframe.RepositoryValue;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunctionException;
+import com.google.devtools.build.skyframe.SkyFunctionName;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Objects;
+
+import javax.annotation.Nullable;
+
+/**
+ * Downloads an archive file over HTTP.
+ */
+public class HttpDownloadFunction implements SkyFunction {
+ public static final String NAME = "HTTP_DOWNLOAD";
+
+ @Nullable
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env) throws RepositoryFunctionException {
+ HttpDescriptor descriptor = (HttpDescriptor) skyKey.argument();
+ try {
+ FileSystemUtils.createDirectoryAndParents(descriptor.outputDirectory);
+ } catch (IOException e) {
+ throw new RepositoryFunctionException(e, SkyFunctionException.Transience.TRANSIENT);
+ }
+ FileValue repositoryValue = RepositoryFunction.getRepositoryDirectory(
+ descriptor.outputDirectory, env);
+ if (repositoryValue == null) {
+ System.out.println("Returning null");
+ return null;
+ }
+
+ Path archive;
+ try {
+ archive = new HttpDownloader(descriptor.url, descriptor.sha256, descriptor.outputDirectory)
+ .download();
+ } catch (IOException e) {
+ throw new RepositoryFunctionException(new IOException("Error downloading from "
+ + descriptor.url + " to " + descriptor.outputDirectory + ": " + e.getMessage()),
+ SkyFunctionException.Transience.TRANSIENT);
+ }
+ return new RepositoryValue(archive, repositoryValue);
+ }
+
+ @Nullable
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+
+ public static SkyKey key(Rule rule, Path outputDirectory)
+ throws RepositoryFunction.RepositoryFunctionException {
+ AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
+ URL url = null;
+ try {
+ url = new URL(mapper.get("url", Type.STRING));
+ } catch (MalformedURLException e) {
+ throw new RepositoryFunction.RepositoryFunctionException(
+ new EvalException(rule.getLocation(), "Error parsing URL: " + e.getMessage()),
+ SkyFunctionException.Transience.PERSISTENT);
+ }
+ String sha256 = mapper.get("sha256", Type.STRING);
+ return new SkyKey(
+ SkyFunctionName.computed(NAME),
+ new HttpDownloadFunction.HttpDescriptor(url, sha256, outputDirectory));
+ }
+
+ static final class HttpDescriptor {
+ private URL url;
+ private String sha256;
+ private Path outputDirectory;
+
+ public HttpDescriptor(URL url, String sha256, Path outputDirectory) {
+ this.url = url;
+ this.sha256 = sha256;
+ this.outputDirectory = outputDirectory;
+ }
+
+ @Override
+ public String toString() {
+ return url + " -> " + outputDirectory + " (" + sha256 + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof HttpDescriptor)) {
+ return false;
+ }
+ HttpDescriptor other = (HttpDescriptor) obj;
+ return Objects.equals(url, other.url)
+ && Objects.equals(sha256, other.sha256)
+ && Objects.equals(outputDirectory, other.outputDirectory);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(url, sha256, outputDirectory);
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java
new file mode 100644
index 0000000000..af9ad22996
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewHttpArchiveFunction.java
@@ -0,0 +1,88 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.repository;
+
+import com.google.devtools.build.lib.bazel.rules.workspace.NewHttpArchiveRule;
+import com.google.devtools.build.lib.packages.ExternalPackage;
+import com.google.devtools.build.lib.packages.PackageIdentifier.RepositoryName;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.skyframe.RepositoryValue;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunctionException;
+import com.google.devtools.build.skyframe.SkyFunctionName;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+
+import java.io.IOException;
+
+import javax.annotation.Nullable;
+
+/**
+ * Downloads an archive from a URL, decompresses it, creates a WORKSPACE file, and adds a BUILD
+ * file for it.
+ */
+public class NewHttpArchiveFunction extends HttpArchiveFunction {
+
+ @Override
+ public SkyFunctionName getSkyFunctionName() {
+ return SkyFunctionName.computed(NewHttpArchiveRule.NAME);
+ }
+
+ @Nullable
+ @Override
+ public SkyValue compute(SkyKey skyKey, SkyFunction.Environment env)
+ throws RepositoryFunctionException {
+ RepositoryName repositoryName = (RepositoryName) skyKey.argument();
+ Rule rule = RepositoryFunction.getRule(repositoryName, NewHttpArchiveRule.NAME, env);
+ if (rule == null) {
+ return null;
+ }
+
+ // Download.
+ Path outputDirectory = getOutputBase().getRelative(ExternalPackage.NAME)
+ .getRelative(rule.getName());
+ RepositoryValue downloadedFileValue;
+ try {
+ downloadedFileValue = (RepositoryValue) env.getValueOrThrow(
+ HttpDownloadFunction.key(rule, outputDirectory), IOException.class);
+ } catch (IOException e) {
+ throw new RepositoryFunctionException(e, SkyFunctionException.Transience.PERSISTENT);
+ }
+ if (downloadedFileValue == null) {
+ return null;
+ }
+
+ // Decompress.
+ Path decompressedDirectory;
+ try {
+ decompressedDirectory = DecompressorFactory.create(
+ rule.getTargetKind(), rule.getName(), downloadedFileValue.getPath()).decompress();
+ } catch (DecompressorFactory.DecompressorException e) {
+ throw new RepositoryFunctionException(
+ new IOException(e.getMessage()), SkyFunctionException.Transience.TRANSIENT);
+ }
+
+ // Add WORKSPACE and BUILD files.
+ NewLocalRepositoryFunction.createWorkspaceFile(decompressedDirectory, rule);
+ if (NewLocalRepositoryFunction.createBuildFile(
+ rule, getWorkspace(), decompressedDirectory, env) == null) {
+ return null;
+ }
+
+ return new RepositoryValue(
+ decompressedDirectory, downloadedFileValue.getRepositoryDirectory());
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewLocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewLocalRepositoryFunction.java
index 8f03ac4781..510d36cd60 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewLocalRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewLocalRepositoryFunction.java
@@ -78,13 +78,7 @@ public class NewLocalRepositoryFunction extends RepositoryFunction {
}
// Add x/WORKSPACE.
- try {
- Path workspaceFile = repositoryDirectory.getRelative("WORKSPACE");
- FileSystemUtils.writeContent(workspaceFile, Charset.forName("UTF-8"),
- "# DO NOT EDIT: automatically generated WORKSPACE file for " + rule + "\n");
- } catch (IOException e) {
- throw new RepositoryFunctionException(e, Transience.TRANSIENT);
- }
+ createWorkspaceFile(repositoryDirectory, rule);
AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
String path = mapper.get("path", Type.STRING);
@@ -112,24 +106,52 @@ public class NewLocalRepositoryFunction extends RepositoryFunction {
}
// Link x/BUILD to <build_root>/x.BUILD.
+ if (createBuildFile(rule, getWorkspace(), repositoryDirectory, env) == null) {
+ return null;
+ }
+
+ return new RepositoryValue(repositoryDirectory, directoryValue);
+ }
+
+ public static void createWorkspaceFile(Path repositoryDirectory, Rule rule)
+ throws RepositoryFunctionException {
+ try {
+ Path workspaceFile = repositoryDirectory.getRelative("WORKSPACE");
+ FileSystemUtils.writeContent(workspaceFile, Charset.forName("UTF-8"),
+ "# DO NOT EDIT: automatically generated WORKSPACE file for " + rule + "\n");
+ } catch (IOException e) {
+ throw new RepositoryFunctionException(e, Transience.TRANSIENT);
+ }
+ }
+
+ /**
+ * Symlinks a BUILD file from the local filesystem into the external repository's root.
+ * @param rule the rule that declares the build_file path.
+ * @param workspaceDirectory the workspace root for the build.
+ * @param repositoryDirectory the external repository's root directory.
+ * @param env the Skyframe environment.
+ * @return the file value of the symlink created.
+ * @throws RepositoryFunctionException if the BUILD file specified does not exist or cannot be
+ * linked.
+ */
+ public static FileValue createBuildFile(Rule rule, Path workspaceDirectory,
+ Path repositoryDirectory, Environment env)
+ throws RepositoryFunctionException {
+ AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
PathFragment buildFile = new PathFragment(mapper.get("build_file", Type.STRING));
- Path buildFileTarget = getWorkspace().getRelative(buildFile);
+ Path buildFileTarget = workspaceDirectory.getRelative(buildFile);
if (!buildFileTarget.exists()) {
throw new RepositoryFunctionException(
new EvalException(rule.getLocation(), "In " + rule
+ " the 'build_file' attribute does not specify an existing file ("
- + buildFile + " does not exist)"),
+ + buildFileTarget + " does not exist)"),
Transience.PERSISTENT);
}
Path buildFilePath = repositoryDirectory.getRelative("BUILD");
- if (createSymbolicLink(buildFilePath, buildFileTarget, env) == null) {
- return null;
- }
-
- return new RepositoryValue(repositoryDirectory, directoryValue);
+ return createSymbolicLink(buildFilePath, buildFileTarget, env);
}
- private FileValue createSymbolicLink(Path from, Path to, Environment env)
+ private static FileValue createSymbolicLink(Path from, Path to, Environment env)
throws RepositoryFunctionException {
try {
if (!from.exists()) {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index 1eaf6a210d..0a43d80d6e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -52,6 +52,7 @@ import com.google.devtools.build.lib.bazel.rules.workspace.HttpArchiveRule;
import com.google.devtools.build.lib.bazel.rules.workspace.HttpJarRule;
import com.google.devtools.build.lib.bazel.rules.workspace.LocalRepositoryRule;
import com.google.devtools.build.lib.bazel.rules.workspace.MavenJarRule;
+import com.google.devtools.build.lib.bazel.rules.workspace.NewHttpArchiveRule;
import com.google.devtools.build.lib.bazel.rules.workspace.NewLocalRepositoryRule;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.PackageGroup;
@@ -274,6 +275,7 @@ public class BazelRuleClassProvider {
builder.addRuleDefinition(HttpJarRule.class);
builder.addRuleDefinition(LocalRepositoryRule.class);
builder.addRuleDefinition(MavenJarRule.class);
+ builder.addRuleDefinition(NewHttpArchiveRule.class);
builder.addRuleDefinition(NewLocalRepositoryRule.class);
builder.addConfigurationFragment(new BazelConfiguration.Loader());
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/HttpArchiveRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/HttpArchiveRule.java
index a2d5a35473..5da1ae9966 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/HttpArchiveRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/HttpArchiveRule.java
@@ -42,7 +42,7 @@ public class HttpArchiveRule implements RuleDefinition {
A URL to an archive file containing a Bazel repository.
${SYNOPSIS}
- <p>This must be an http URL that ends with .zip. There is no support for authentication or
+ <p>This must be an HTTP URL that ends with .zip. There is no support for authentication or
redirection.</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("url", STRING).mandatory())
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewHttpArchiveRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewHttpArchiveRule.java
new file mode 100644
index 0000000000..131bbac910
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewHttpArchiveRule.java
@@ -0,0 +1,121 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.workspace;
+
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.Type.STRING;
+
+import com.google.devtools.build.lib.analysis.BlazeRule;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.RuleClass;
+
+/**
+ * Rule definition for the new_http_archive rule.
+ */
+@BlazeRule(name = NewHttpArchiveRule.NAME,
+ type = RuleClass.Builder.RuleClassType.WORKSPACE,
+ ancestors = { WorkspaceBaseRule.class },
+ factoryClass = WorkspaceConfiguredTargetFactory.class)
+public class NewHttpArchiveRule implements RuleDefinition {
+ public static final String NAME = "new_http_archive";
+
+ @Override
+ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
+ return builder
+ /* <!-- #BLAZE_RULE(new_http_archive).ATTRIBUTE(url) -->
+ A URL to an archive file containing a Bazel repository.
+ ${SYNOPSIS}
+
+ <p>This must be an HTTP URL that ends with .zip. There is no support for authentication or
+ redirection.</p>
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr("url", STRING).mandatory())
+ /* <!-- #BLAZE_RULE(new_http_archive).ATTRIBUTE(sha256) -->
+ The expected SHA-256 hash of the file downloaded.
+ ${SYNOPSIS}
+
+ <p>This must match the SHA-256 hash of the file downloaded.</p>
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr("sha256", STRING).mandatory())
+ /* <!-- #BLAZE_RULE(new_http_archive).ATTRIBUTE(build_file) -->
+ A file to use as a BUILD file for this directory.
+ ${SYNOPSIS}
+
+ <p>This path is relative to the build's workspace. The file does not need to be named
+ BUILD, but can be (something like BUILD.new-repo-name may work well for distinguishing it
+ from the repository's actual BUILD files.</p>
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr("build_file", STRING).mandatory())
+ .setWorkspaceOnly()
+ .build();
+ }
+}
+
+/*<!-- #BLAZE_RULE (NAME = new_http_archive, TYPE = OTHER, FAMILY = General)[GENERIC_RULE] -->
+
+${ATTRIBUTE_SIGNATURE}
+
+<p>Downloads a compressed archive file, decompresses it, and creates a Bazel repository by
+combining the archive with the provided BUILD file.</p>
+
+<p>Only Zip-formatted archives with the .zip extension are supported.</p>
+
+${ATTRIBUTE_DEFINITION}
+
+<h4 id="new_http_archive_examples">Examples</h4>
+
+<p>Suppose the current repository contains the source code for a chat program, rooted at the
+ directory <i>~/chat-app</i>. It needs to depend on an SSL library which is available from
+ <i>http://example.com/openssl.zip</i>. This .zip file contains the following directory
+ structure:</p>
+
+<pre class="code">
+src/
+ openssl.cc
+ openssl.h
+</pre>
+
+<p>In the local repository, the user creates a <i>ssl.BUILD</i> file which contains the following
+target definition:</p>
+
+<pre class="code">
+cc_library(
+ name = "openssl-lib",
+ srcs = ["src/openssl.cc"],
+ hdrs = ["src/openssl.h"],
+)
+</pre>
+
+<p>Targets in the <i>~/chat-app</i> repository can depend on this target if the following lines are
+ added to <i>~/chat-app/WORKSPACE</i>:</p>
+
+<pre class="code">
+new_http_archive(
+ name = "my-ssl",
+ url = "http://example.com/openssl.zip",
+ sha256 = "03a58ac630e59778f328af4bcc4acb4f80208ed4",
+ build_file = "ssl.BUILD",
+)
+
+bind(
+ name = "openssl",
+ actual = "@my-ssl//:openssl-lib",
+)
+</pre>
+
+<p>See <a href="#bind_examples">Bind</a> for how to use bound targets.</p>
+
+<!-- #END_BLAZE_RULE -->*/
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewLocalRepositoryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewLocalRepositoryRule.java
index 96438fed8d..f8f8b85baf 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewLocalRepositoryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/workspace/NewLocalRepositoryRule.java
@@ -48,7 +48,7 @@ public class NewLocalRepositoryRule implements RuleDefinition {
A file to use as a BUILD file for this directory.
${SYNOPSIS}
- <p>This path must be relative to the build's workspace. The file does not need to be named
+ <p>This path is relative to the build's workspace. The file does not need to be named
BUILD, but can be (something like BUILD.new-repo-name may work well for distinguishing it
from the repository's actual BUILD files.</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryValue.java
index 3183953e77..8272e6726a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryValue.java
@@ -47,6 +47,10 @@ public class RepositoryValue implements SkyValue {
return path;
}
+ public FileValue getRepositoryDirectory() {
+ return details;
+ }
+
@Override
public boolean equals(Object other) {
if (this == other) {