diff options
Diffstat (limited to 'src')
14 files changed, 127 insertions, 27 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 5c517641ce..3c51885c60 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 @@ -81,9 +81,10 @@ public class BazelRepositoryModule extends BlazeModule { private final AtomicBoolean isFetch = new AtomicBoolean(false); private final SkylarkRepositoryFunction skylarkRepositoryFunction = new SkylarkRepositoryFunction(); + private final RepositoryDelegatorFunction delegator; public BazelRepositoryModule() { - repositoryHandlers = + this.repositoryHandlers = ImmutableMap.<String, RepositoryFunction>builder() .put(LocalRepositoryRule.NAME, new LocalRepositoryFunction()) .put(HttpArchiveRule.NAME, new HttpArchiveFunction()) @@ -98,6 +99,8 @@ public class BazelRepositoryModule extends BlazeModule { .put(AndroidNdkRepositoryRule.NAME, new AndroidNdkRepositoryFunction()) .put(MavenServerRule.NAME, new MavenServerRepositoryFunction()) .build(); + this.delegator = new RepositoryDelegatorFunction( + repositoryHandlers, skylarkRepositoryFunction, isFetch); } /** @@ -167,16 +170,14 @@ public class BazelRepositoryModule extends BlazeModule { // Create the repository function everything flows through. builder.put(SkyFunctions.REPOSITORY, new RepositoryLoaderFunction()); - builder.put( - SkyFunctions.REPOSITORY_DIRECTORY, - new RepositoryDelegatorFunction( - repositoryHandlers, skylarkRepositoryFunction, isFetch)); + builder.put(SkyFunctions.REPOSITORY_DIRECTORY, delegator); builder.put(MavenServerFunction.NAME, new MavenServerFunction()); return builder.build(); } @Override public void beforeCommand(Command command, CommandEnvironment env) throws AbruptExitException { + delegator.setClientEnvironment(env.getClientEnv()); skylarkRepositoryFunction.setCommandEnvironment(env); } } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitCloner.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitCloner.java index fc7555708e..af7fa58340 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitCloner.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitCloner.java @@ -40,6 +40,7 @@ import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.NetRCCredentialsProvider; import java.io.IOException; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -91,7 +92,9 @@ public class GitCloner { return false; } - public static SkyValue clone(Rule rule, Path outputDirectory, EventHandler eventHandler) + public static SkyValue clone( + Rule rule, Path outputDirectory, EventHandler eventHandler, + Map<String, String> clientEnvironment) throws RepositoryFunctionException { AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); if ((mapper.has("commit", Type.STRING) == mapper.has("tag", Type.STRING)) @@ -118,7 +121,7 @@ public class GitCloner { // Setup proxy if remote is http or https if (descriptor.remote != null && descriptor.remote.startsWith("http")) { try { - ProxyHelper.createProxyIfNeeded(descriptor.remote); + ProxyHelper.createProxyIfNeeded(descriptor.remote, clientEnvironment); } catch (IOException ie) { throw new RepositoryFunctionException(ie, Transience.TRANSIENT); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java index 5bcdbd4cb7..0ba5c0f5e5 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java @@ -33,6 +33,7 @@ import java.io.IOException; * Clones a Git repository. */ public class GitRepositoryFunction extends RepositoryFunction { + @Override public boolean isLocal(Rule rule) { return false; @@ -43,7 +44,7 @@ public class GitRepositoryFunction extends RepositoryFunction { Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) throws SkyFunctionException { createDirectory(outputDirectory, rule); - GitCloner.clone(rule, outputDirectory, env.getListener()); + GitCloner.clone(rule, outputDirectory, env.getListener(), clientEnvironment); return RepositoryDirectoryValue.create(outputDirectory); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpArchiveFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpArchiveFunction.java index e86c23b586..56522c7312 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpArchiveFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpArchiveFunction.java @@ -35,6 +35,7 @@ import java.io.IOException; * Downloads a file over HTTP. */ public class HttpArchiveFunction extends RepositoryFunction { + @Override public boolean isLocal(Rule rule) { return false; @@ -61,7 +62,8 @@ public class HttpArchiveFunction extends RepositoryFunction { // // This would download png.tar.gz to .external-repository/png/png.tar.gz. createDirectory(outputDirectory); - Path downloadedPath = HttpDownloader.download(rule, outputDirectory, env.getListener()); + Path downloadedPath = HttpDownloader.download( + rule, outputDirectory, env.getListener(), clientEnvironment); DecompressorValue.decompress(getDescriptor(rule, downloadedPath, outputDirectory)); return RepositoryDirectoryValue.create(outputDirectory); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java index 2bf1f18e5d..4a8c56fb5c 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java @@ -38,7 +38,7 @@ public class NewGitRepositoryFunction extends GitRepositoryFunction { } createDirectory(outputDirectory, rule); - GitCloner.clone(rule, outputDirectory, env.getListener()); + GitCloner.clone(rule, outputDirectory, env.getListener(), clientEnvironment); createWorkspaceFile(outputDirectory, rule.getTargetKind(), rule.getName()); buildFileHandler.finishBuildFile(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 index 71e34f6380..29f20e771d 100644 --- 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 @@ -56,7 +56,8 @@ public class NewHttpArchiveFunction extends HttpArchiveFunction { } // Download. - Path downloadedPath = HttpDownloader.download(rule, outputDirectory, env.getListener()); + Path downloadedPath = HttpDownloader.download( + rule, outputDirectory, env.getListener(), clientEnvironment); // Decompress. Path decompressed; diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnection.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnection.java index f41b541e7b..7005fbbd8d 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnection.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnection.java @@ -28,6 +28,7 @@ import java.net.Proxy; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Map; /** * Represents a connection over HTTP. @@ -71,9 +72,10 @@ class HttpConnection implements Closeable { } } - public static HttpConnection createAndConnect(URL url) throws IOException { + public static HttpConnection createAndConnect(URL url, Map<String, String> clientEnv) + throws IOException { int retries = MAX_REDIRECTS; - Proxy proxy = ProxyHelper.createProxyIfNeeded(url.toString()); + Proxy proxy = ProxyHelper.createProxyIfNeeded(url.toString(), clientEnv); do { HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy); try { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpDownloader.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpDownloader.java index 5888b46952..13ade1b6c8 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpDownloader.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpDownloader.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -53,19 +54,23 @@ public class HttpDownloader { private final Path outputDirectory; private final EventHandler eventHandler; private final ScheduledExecutorService scheduler; + private final Map<String, String> clientEnv; - private HttpDownloader(EventHandler eventHandler, String urlString, String sha256, - Path outputDirectory, String type) { + private HttpDownloader( + EventHandler eventHandler, String urlString, String sha256, Path outputDirectory, + String type, Map<String, String> clientEnv) { this.urlString = urlString; this.sha256 = sha256; this.outputDirectory = outputDirectory; this.eventHandler = eventHandler; this.scheduler = Executors.newScheduledThreadPool(1); this.type = type; + this.clientEnv = clientEnv; } @Nullable - public static Path download(Rule rule, Path outputDirectory, EventHandler eventHandler) + public static Path download( + Rule rule, Path outputDirectory, EventHandler eventHandler, Map<String, String> clientEnv) throws RepositoryFunctionException, InterruptedException { AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); String url = mapper.get("url", Type.STRING); @@ -73,7 +78,8 @@ public class HttpDownloader { String type = mapper.has("type", Type.STRING) ? mapper.get("type", Type.STRING) : ""; try { - return new HttpDownloader(eventHandler, url, sha256, outputDirectory, type).download(); + return new HttpDownloader(eventHandler, url, sha256, outputDirectory, type, clientEnv) + .download(); } catch (IOException e) { throw new RepositoryFunctionException(new IOException("Error downloading from " + url + " to " + outputDirectory + ": " + e.getMessage()), @@ -83,10 +89,11 @@ public class HttpDownloader { @Nullable public static Path download( - String url, String sha256, String type, Path output, EventHandler eventHandler) + String url, String sha256, String type, Path output, EventHandler eventHandler, Map<String, + String> clientEnv) throws RepositoryFunctionException, InterruptedException { try { - return new HttpDownloader(eventHandler, url, sha256, output, type).download(); + return new HttpDownloader(eventHandler, url, sha256, output, type, clientEnv).download(); } catch (IOException e) { throw new RepositoryFunctionException( new IOException( @@ -129,7 +136,7 @@ public class HttpDownloader { final ScheduledFuture<?> loggerHandle = getLoggerHandle(totalBytes); try (OutputStream out = destination.getOutputStream(); - HttpConnection connection = HttpConnection.createAndConnect(url)) { + HttpConnection connection = HttpConnection.createAndConnect(url, this.clientEnv)) { InputStream inputStream = connection.getInputStream(); int read; byte[] buf = new byte[BUFFER_SIZE]; diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelper.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelper.java index 1c7f8a6a4a..19e072dfbe 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelper.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelper.java @@ -22,6 +22,7 @@ import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Proxy; import java.net.URLDecoder; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -36,17 +37,26 @@ public class ProxyHelper { * the request if HTTP_PROXY and/or HTTPS_PROXY environment variables are set. * @param requestedUrl The url for the remote resource that may need to be retrieved through a * proxy + * @param env The client environment to check for proxy settings. * @return Proxy * @throws IOException */ - public static Proxy createProxyIfNeeded(String requestedUrl) throws IOException { + public static Proxy createProxyIfNeeded(String requestedUrl, Map<String, String> env) + throws IOException { String lcUrl = requestedUrl.toLowerCase(); + String proxyAddress = null; if (lcUrl.startsWith("https")) { - return createProxy(System.getenv("HTTPS_PROXY")); + proxyAddress = env.get("https_proxy"); + if (Strings.isNullOrEmpty(proxyAddress)) { + proxyAddress = env.get("HTTPS_PROXY"); + } } else if (lcUrl.startsWith("http")) { - return createProxy(System.getenv("HTTP_PROXY")); + proxyAddress = env.get("http_proxy"); + if (Strings.isNullOrEmpty(proxyAddress)) { + proxyAddress = env.get("HTTP_PROXY"); + } } - return Proxy.NO_PROXY; + return createProxy(proxyAddress); } /** 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 0e181ed7de..372d9baac2 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 @@ -363,7 +363,8 @@ public class SkylarkRepositoryContext { try { checkInOutputDirectory(outputPath); makeDirectories(outputPath.path); - HttpDownloader.download(url, sha256, null, outputPath.getPath(), env.getListener()); + HttpDownloader.download( + url, sha256, null, outputPath.getPath(), env.getListener(), osObject.getEnviron()); if (executable) { outputPath.path.setExecutable(true); } @@ -420,8 +421,8 @@ public class SkylarkRepositoryContext { // Download to outputDirectory and delete it after extraction SkylarkPath outputPath = getPath("download_and_extract()", output); checkInOutputDirectory(outputPath); - Path downloadedPath = - HttpDownloader.download(url, sha256, type, outputPath.getPath(), env.getListener()); + Path downloadedPath = HttpDownloader.download( + url, sha256, type, outputPath.getPath(), env.getListener(), osObject.getEnviron()); DecompressorValue.decompress( DecompressorDescriptor.builder() .setTargetKind(rule.getTargetKind()) diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java index 6e39a17a73..d6f143f873 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java @@ -36,6 +36,7 @@ import com.google.devtools.build.skyframe.SkyValue; import java.io.IOException; import java.util.Arrays; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.Nullable; @@ -61,6 +62,8 @@ public final class RepositoryDelegatorFunction implements SkyFunction { // command is a fetch. Remote repository lookups are only allowed during fetches. private final AtomicBoolean isFetch; + private Map<String, String> clientEnvironment; + public RepositoryDelegatorFunction( ImmutableMap<String, RepositoryFunction> handlers, @Nullable RepositoryFunction skylarkHandler, @@ -70,6 +73,10 @@ public final class RepositoryDelegatorFunction implements SkyFunction { this.isFetch = isFetch; } + public void setClientEnvironment(Map<String, String> clientEnvironment) { + this.clientEnvironment = clientEnvironment; + } + private void setupRepositoryRoot(Path repoRoot) throws RepositoryFunctionException { try { FileSystemUtils.deleteTree(repoRoot); @@ -107,6 +114,7 @@ public final class RepositoryDelegatorFunction implements SkyFunction { Path repoRoot = RepositoryFunction.getExternalRepositoryDirectory(directories).getRelative(rule.getName()); + handler.setClientEnvironment(clientEnvironment); if (handler.isLocal(rule)) { // Local repositories are always fetched because the operation is generally fast and they do // not depend on non-local data, so it does not make much sense to try to catch from across diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java index d3f5982fb1..043bd0f0df 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java @@ -50,6 +50,7 @@ import com.google.devtools.build.skyframe.SkyValue; import java.io.IOException; import java.nio.charset.Charset; +import java.util.Map; import javax.annotation.Nullable; @@ -83,6 +84,8 @@ import javax.annotation.Nullable; */ public abstract class RepositoryFunction { + protected Map<String, String> clientEnvironment; + /** * Exception thrown when something goes wrong accessing a remote repository. * @@ -107,6 +110,7 @@ public abstract class RepositoryFunction { public RepositoryFunctionException(EvalException cause, Transience transience) { super(cause, transience); } + } /** @@ -417,6 +421,13 @@ public abstract class RepositoryFunction { } /** + * Sets up a mapping of environment variables to use. + */ + public void setClientEnvironment(Map<String, String> clientEnvironment) { + this.clientEnvironment = clientEnvironment; + } + + /** * Returns the RuleDefinition class for this type of repository. */ public abstract Class<? extends RuleDefinition> getRuleDefinition(); diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/BUILD b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/BUILD new file mode 100644 index 0000000000..308bdec243 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/BUILD @@ -0,0 +1,15 @@ +java_test( + name = "DownloaderTests", + srcs = glob(["*.java"]), + tags = ["rules"], + test_class = "com.google.devtools.build.lib.AllTests", + deps = [ + "//src/main/java/com/google/devtools/build/lib/bazel/repository/downloader", + "//src/test/java/com/google/devtools/build/lib:foundations_testutil", + "//src/test/java/com/google/devtools/build/lib:test_runner", + "//third_party:guava", + "//third_party:junit4", + "//third_party:mockito", + "//third_party:truth", + ], +) diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelperTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelperTest.java index 1d9e36a07e..bec3dd01dd 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelperTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/ProxyHelperTest.java @@ -18,12 +18,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import com.google.common.collect.ImmutableMap; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.io.IOException; import java.net.Proxy; +import java.util.Map; /** * Tests for @{link ProxyHelper}. @@ -32,12 +35,47 @@ import java.net.Proxy; public class ProxyHelperTest { @Test + public void testCreateIfNeededHttpLowerCase() throws Exception { + Map<String, String> env = ImmutableMap.<String, String>builder() + .put("http_proxy", "http://my.example.com").build(); + Proxy proxy = ProxyHelper.createProxyIfNeeded("http://www.something.com", env); + assertThat(proxy.toString()).endsWith("my.example.com:80"); + } + + @Test + public void testCreateIfNeededHttpUpperCase() throws Exception { + Map<String, String> env = ImmutableMap.<String, String>builder() + .put("HTTP_PROXY", "http://my.example.com").build(); + Proxy proxy = ProxyHelper.createProxyIfNeeded("http://www.something.com", env); + assertThat(proxy.toString()).endsWith("my.example.com:80"); + } + + @Test + public void testCreateIfNeededHttpsLowerCase() throws Exception { + Map<String, String> env = ImmutableMap.<String, String>builder() + .put("https_proxy", "https://my.example.com").build(); + Proxy proxy = ProxyHelper.createProxyIfNeeded("https://www.something.com", env); + assertThat(proxy.toString()).endsWith("my.example.com:443"); + } + + @Test + public void testCreateIfNeededHttpsUpperCase() throws Exception { + Map<String, String> env = ImmutableMap.<String, String>builder() + .put("HTTPS_PROXY", "https://my.example.com").build(); + Proxy proxy = ProxyHelper.createProxyIfNeeded("https://www.something.com", env); + assertThat(proxy.toString()).endsWith("my.example.com:443"); + } + + @Test public void testNoProxy() throws Exception { // Empty address. Proxy proxy = ProxyHelper.createProxy(null); assertEquals(Proxy.NO_PROXY, proxy); proxy = ProxyHelper.createProxy(""); assertEquals(Proxy.NO_PROXY, proxy); + Map<String, String> env = ImmutableMap.of(); + proxy = ProxyHelper.createProxyIfNeeded("https://www.something.com", env); + assertEquals(Proxy.NO_PROXY, proxy); } @Test |