blob: c184c728ba5a801420cd9708c8d7247ac9816084 [file] [log] [blame]
David Chen451599a2016-11-18 23:58:35 +00001# Copyright 2016 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Rules for downloading files and archives over HTTP.
15
16### Setup
17
18To use these rules, load them in your `WORKSPACE` file as follows:
19
20```python
21load(
22 "@bazel_tools//tools/build_defs/repo:http.bzl",
23 "http_archive",
24 "http_file",
Klaus Aehlig17735dd2018-05-23 07:13:49 -070025 "http_jar",
David Chen451599a2016-11-18 23:58:35 +000026)
27```
28
Klaus Aehligc3d73f72019-09-20 07:17:33 -070029These rules are improved versions of the native http rules and will eventually
30replace the native rules.
David Chen451599a2016-11-18 23:58:35 +000031"""
32
Klaus Aehlige1e074c2019-07-04 04:20:09 -070033load(
34 ":utils.bzl",
35 "patch",
Klaus Aehligc3d73f72019-09-20 07:17:33 -070036 "read_netrc",
Zhongpeng Linf4214742022-01-21 04:31:27 -080037 "read_user_netrc",
Klaus Aehlige1e074c2019-07-04 04:20:09 -070038 "update_attrs",
Klaus Aehligc3d73f72019-09-20 07:17:33 -070039 "use_netrc",
Klaus Aehlige1e074c2019-07-04 04:20:09 -070040 "workspace_and_buildfile",
41)
42
Jingwen Chenc5ec3c02020-03-25 16:53:15 -070043# Shared between http_jar, http_file and http_archive.
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -070044
45_URL_DOC = """A URL to a file that will be made available to Bazel.
46
47This must be a file, http or https URL. Redirections are followed.
48Authentication is not supported.
49
50More flexibility can be achieved by the urls parameter that allows
51to specify alternative URLs to fetch from."""
52
53_URLS_DOC = """A list of URLs to a file that will be made available to Bazel.
54
55Each entry must be a file, http or https URL. Redirections are followed.
56Authentication is not supported.
57
58URLs are tried in order until one succeeds, so you should list local mirrors first.
59If all downloads fail, the rule will fail."""
60
61def _get_all_urls(ctx):
62 """Returns all urls provided via the url or urls attributes.
63
64 Also checks that at least one url is provided."""
65 if not ctx.attr.url and not ctx.attr.urls:
66 fail("At least one of url and urls must be provided")
67
68 all_urls = []
69 if ctx.attr.urls:
70 all_urls = ctx.attr.urls
71 if ctx.attr.url:
72 all_urls = [ctx.attr.url] + all_urls
73
74 return all_urls
75
Jingwen Chenc5ec3c02020-03-25 16:53:15 -070076_AUTH_PATTERN_DOC = """An optional dict mapping host names to custom authorization patterns.
77
78If a URL's host name is present in this dict the value will be used as a pattern when
79generating the authorization header for the http request. This enables the use of custom
80authorization schemes used in a lot of common cloud storage providers.
81
82The pattern currently supports 2 tokens: <code>&lt;login&gt;</code> and
83<code>&lt;password&gt;</code>, which are replaced with their equivalent value
84in the netrc file for the same host name. After formatting, the result is set
85as the value for the <code>Authorization</code> field of the HTTP request.
86
87Example attribute and netrc for a http download to an oauth2 enabled API using a bearer token:
88
89<pre>
90auth_patterns = {
91 "storage.cloudprovider.com": "Bearer &lt;password&gt;"
92}
93</pre>
94
95netrc:
96
97<pre>
98machine storage.cloudprovider.com
99 password RANDOM-TOKEN
100</pre>
101
102The final HTTP request would have the following header:
103
104<pre>
105Authorization: Bearer RANDOM-TOKEN
106</pre>
107"""
108
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700109def _get_auth(ctx, urls):
110 """Given the list of URLs obtain the correct auth dict."""
111 if ctx.attr.netrc:
112 netrc = read_netrc(ctx, ctx.attr.netrc)
Zhongpeng Linf4214742022-01-21 04:31:27 -0800113 else:
114 netrc = read_user_netrc(ctx)
115 return use_netrc(netrc, urls, ctx.attr.auth_patterns)
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700116
David Chen451599a2016-11-18 23:58:35 +0000117def _http_archive_impl(ctx):
vladmos20a042f2018-06-01 04:51:21 -0700118 """Implementation of the http_archive rule."""
vladmos20a042f2018-06-01 04:51:21 -0700119 if ctx.attr.build_file and ctx.attr.build_file_content:
Nicolas Lopez2c9c05b2018-08-07 06:43:52 -0700120 fail("Only one of build_file and build_file_content can be provided.")
David Chen451599a2016-11-18 23:58:35 +0000121
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700122 all_urls = _get_all_urls(ctx)
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700123 auth = _get_auth(ctx, all_urls)
124
dannark94e1dcc2018-12-20 16:35:32 -0800125 download_info = ctx.download_and_extract(
vladmos20a042f2018-06-01 04:51:21 -0700126 all_urls,
127 "",
128 ctx.attr.sha256,
129 ctx.attr.type,
130 ctx.attr.strip_prefix,
Klaus Aehligc917ab22019-05-20 07:08:30 -0700131 canonical_id = ctx.attr.canonical_id,
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700132 auth = auth,
pcloudye9a4e932021-07-07 04:55:00 -0700133 integrity = ctx.attr.integrity,
vladmos20a042f2018-06-01 04:51:21 -0700134 )
vladmos20a042f2018-06-01 04:51:21 -0700135 workspace_and_buildfile(ctx)
pcloudye9a4e932021-07-07 04:55:00 -0700136 patch(ctx, auth = auth)
David Chen451599a2016-11-18 23:58:35 +0000137
pcloudye9a4e932021-07-07 04:55:00 -0700138 # We don't need to override the sha256 attribute if integrity is already specified.
139 sha256_override = {} if ctx.attr.integrity else {"sha256": download_info.sha256}
140 return update_attrs(ctx.attr, _http_archive_attrs.keys(), sha256_override)
dannark94e1dcc2018-12-20 16:35:32 -0800141
Jay Bazuzid6089e62022-03-15 10:38:47 -0700142_HTTP_FILE_BUILD = """\
David Chen451599a2016-11-18 23:58:35 +0000143package(default_visibility = ["//visibility:public"])
144
145filegroup(
146 name = "file",
Nicolas Lopez2c9c05b2018-08-07 06:43:52 -0700147 srcs = ["{}"],
David Chen451599a2016-11-18 23:58:35 +0000148)
149"""
150
151def _http_file_impl(ctx):
vladmos20a042f2018-06-01 04:51:21 -0700152 """Implementation of the http_file rule."""
Nicolas Lopez2c9c05b2018-08-07 06:43:52 -0700153 repo_root = ctx.path(".")
154 forbidden_files = [
155 repo_root,
156 ctx.path("WORKSPACE"),
157 ctx.path("BUILD"),
158 ctx.path("BUILD.bazel"),
159 ctx.path("file/BUILD"),
160 ctx.path("file/BUILD.bazel"),
161 ]
162 downloaded_file_path = ctx.attr.downloaded_file_path
163 download_path = ctx.path("file/" + downloaded_file_path)
164 if download_path in forbidden_files or not str(download_path).startswith(str(repo_root)):
165 fail("'%s' cannot be used as downloaded_file_path in http_file" % ctx.attr.downloaded_file_path)
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700166 all_urls = _get_all_urls(ctx)
167 auth = _get_auth(ctx, all_urls)
dannark94e1dcc2018-12-20 16:35:32 -0800168 download_info = ctx.download(
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700169 all_urls,
Nicolas Lopez2c9c05b2018-08-07 06:43:52 -0700170 "file/" + downloaded_file_path,
vladmos20a042f2018-06-01 04:51:21 -0700171 ctx.attr.sha256,
172 ctx.attr.executable,
David Ostrovsky3e5ece32020-01-20 02:29:56 -0800173 canonical_id = ctx.attr.canonical_id,
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700174 auth = auth,
vladmos20a042f2018-06-01 04:51:21 -0700175 )
176 ctx.file("WORKSPACE", "workspace(name = \"{name}\")".format(name = ctx.name))
Nicolas Lopez2c9c05b2018-08-07 06:43:52 -0700177 ctx.file("file/BUILD", _HTTP_FILE_BUILD.format(downloaded_file_path))
David Chen451599a2016-11-18 23:58:35 +0000178
dannark94e1dcc2018-12-20 16:35:32 -0800179 return update_attrs(ctx.attr, _http_file_attrs.keys(), {"sha256": download_info.sha256})
180
Jay Bazuzid6089e62022-03-15 10:38:47 -0700181_HTTP_JAR_BUILD = """\
George Gensurecfda0412020-01-10 11:09:42 -0800182load("@rules_java//java:defs.bzl", "java_import")
183
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700184package(default_visibility = ["//visibility:public"])
185
186java_import(
187 name = 'jar',
Rabi Shanker Guha15b18402021-09-21 10:42:39 -0700188 jars = ["{file_name}"],
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700189 visibility = ['//visibility:public'],
190)
191
192filegroup(
193 name = 'file',
Rabi Shanker Guha15b18402021-09-21 10:42:39 -0700194 srcs = ["{file_name}"],
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700195 visibility = ['//visibility:public'],
196)
197
198"""
199
200def _http_jar_impl(ctx):
vladmos20a042f2018-06-01 04:51:21 -0700201 """Implementation of the http_jar rule."""
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700202 all_urls = _get_all_urls(ctx)
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700203 auth = _get_auth(ctx, all_urls)
Rabi Shanker Guha15b18402021-09-21 10:42:39 -0700204 downloaded_file_name = ctx.attr.downloaded_file_name
Klaus Aehlige1e074c2019-07-04 04:20:09 -0700205 download_info = ctx.download(
206 all_urls,
Rabi Shanker Guha15b18402021-09-21 10:42:39 -0700207 "jar/" + downloaded_file_name,
Klaus Aehlige1e074c2019-07-04 04:20:09 -0700208 ctx.attr.sha256,
David Ostrovsky3e5ece32020-01-20 02:29:56 -0800209 canonical_id = ctx.attr.canonical_id,
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700210 auth = auth,
Klaus Aehlige1e074c2019-07-04 04:20:09 -0700211 )
vladmos20a042f2018-06-01 04:51:21 -0700212 ctx.file("WORKSPACE", "workspace(name = \"{name}\")".format(name = ctx.name))
Rabi Shanker Guha15b18402021-09-21 10:42:39 -0700213 ctx.file("jar/BUILD", _HTTP_JAR_BUILD.format(file_name = downloaded_file_name))
dannark94e1dcc2018-12-20 16:35:32 -0800214 return update_attrs(ctx.attr, _http_jar_attrs.keys(), {"sha256": download_info.sha256})
David Chen451599a2016-11-18 23:58:35 +0000215
216_http_archive_attrs = {
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700217 "url": attr.string(doc = _URL_DOC),
218 "urls": attr.string_list(doc = _URLS_DOC),
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700219 "sha256": attr.string(
220 doc = """The expected SHA-256 of the file downloaded.
221
222This must match the SHA-256 of the file downloaded. _It is a security risk
223to omit the SHA-256 as remote files can change._ At best omitting this
224field will make your build non-hermetic. It is optional to make development
pcloudye9a4e932021-07-07 04:55:00 -0700225easier but either this attribute or `integrity` should be set before shipping.""",
226 ),
227 "integrity": attr.string(
228 doc = """Expected checksum in Subresource Integrity format of the file downloaded.
229
230This must match the checksum of the file downloaded. _It is a security risk
231to omit the checksum as remote files can change._ At best omitting this
232field will make your build non-hermetic. It is optional to make development
233easier but either this attribute or `sha256` should be set before shipping.""",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700234 ),
pcloudy7aa52372022-01-11 05:03:54 -0800235 "netrc": attr.string(
236 doc = "Location of the .netrc file to use for authentication",
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700237 ),
Cristian Hanciladb645502020-03-09 11:12:52 -0700238 "auth_patterns": attr.string_dict(
Jingwen Chenc5ec3c02020-03-25 16:53:15 -0700239 doc = _AUTH_PATTERN_DOC,
Cristian Hanciladb645502020-03-09 11:12:52 -0700240 ),
Klaus Aehligc917ab22019-05-20 07:08:30 -0700241 "canonical_id": attr.string(
Googlere9bef0c2019-11-21 08:32:07 -0800242 doc = """A canonical id of the archive downloaded.
Klaus Aehligc917ab22019-05-20 07:08:30 -0700243
David Ostrovsky3e5ece32020-01-20 02:29:56 -0800244If specified and non-empty, bazel will not take the archive from cache,
245unless it was added to the cache by a request with the same canonical id.
Klaus Aehligc917ab22019-05-20 07:08:30 -0700246""",
247 ),
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700248 "strip_prefix": attr.string(
249 doc = """A directory prefix to strip from the extracted files.
250
251Many archives contain a top-level directory that contains all of the useful
252files in archive. Instead of needing to specify this prefix over and over
253in the `build_file`, this field can be used to strip it from all of the
254extracted files.
255
256For example, suppose you are using `foo-lib-latest.zip`, which contains the
257directory `foo-lib-1.2.3/` under which there is a `WORKSPACE` file and are
258`src/`, `lib/`, and `test/` directories that contain the actual code you
259wish to build. Specify `strip_prefix = "foo-lib-1.2.3"` to use the
260`foo-lib-1.2.3` directory as your top-level directory.
261
262Note that if there are files outside of this directory, they will be
263discarded and inaccessible (e.g., a top-level license file). This includes
264files/directories that start with the prefix but are not in the directory
265(e.g., `foo-lib-1.2.3.release-notes`). If the specified prefix does not
266match a directory in the archive, Bazel will return an error.""",
267 ),
268 "type": attr.string(
269 doc = """The archive type of the downloaded file.
270
271By default, the archive type is determined from the file extension of the
272URL. If the file has no extension, you can explicitly specify one of the
Christopher Peterson Sauer9055c672021-07-28 10:43:20 -0700273following: `"zip"`, `"jar"`, `"war"`, `"aar"`, `"tar"`, `"tar.gz"`, `"tgz"`,
Kevin Lubick9c981202022-04-05 06:56:26 -0700274`"tar.xz"`, `"txz"`, `"tar.zst"`, `"tzst"`, `tar.bz2`, `"ar"`, or `"deb"`.""",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700275 ),
276 "patches": attr.label_list(
277 default = [],
278 doc =
Yun Peng80a63d72019-07-11 06:52:25 -0700279 "A list of files that are to be applied as patches after " +
280 "extracting the archive. By default, it uses the Bazel-native patch implementation " +
281 "which doesn't support fuzz match and binary patch, but Bazel will fall back to use " +
282 "patch command line tool if `patch_tool` attribute is specified or there are " +
283 "arguments other than `-p` in `patch_args` attribute.",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700284 ),
pcloudye9a4e932021-07-07 04:55:00 -0700285 "remote_patches": attr.string_dict(
286 default = {},
287 doc =
288 "A map of patch file URL to its integrity value, they are applied after extracting " +
289 "the archive and before applying patch files from the `patches` attribute. " +
290 "It uses the Bazel-native patch implementation, you can specify the patch strip " +
291 "number with `remote_patch_strip`",
292 ),
293 "remote_patch_strip": attr.int(
294 default = 0,
295 doc =
296 "The number of leading slashes to be stripped from the file name in the remote patches.",
297 ),
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700298 "patch_tool": attr.string(
Yun Peng80a63d72019-07-11 06:52:25 -0700299 default = "",
300 doc = "The patch(1) utility to use. If this is specified, Bazel will use the specifed " +
301 "patch tool instead of the Bazel-native patch implementation.",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700302 ),
303 "patch_args": attr.string_list(
304 default = ["-p0"],
Yun Peng80a63d72019-07-11 06:52:25 -0700305 doc =
306 "The arguments given to the patch tool. Defaults to -p0, " +
307 "however -p1 will usually be needed for patches generated by " +
308 "git. If multiple -p arguments are specified, the last one will take effect." +
309 "If arguments other than -p are specified, Bazel will fall back to use patch " +
310 "command line tool instead of the Bazel-native patch implementation. When falling " +
311 "back to patch command line tool and patch_tool attribute is not specified, " +
pcloudye9a4e932021-07-07 04:55:00 -0700312 "`patch` will be used. This only affects patch files in the `patches` attribute.",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700313 ),
314 "patch_cmds": attr.string_list(
315 default = [],
Yun Peng80a63d72019-07-11 06:52:25 -0700316 doc = "Sequence of Bash commands to be applied on Linux/Macos after patches are applied.",
317 ),
318 "patch_cmds_win": attr.string_list(
319 default = [],
320 doc = "Sequence of Powershell commands to be applied on Windows after patches are " +
321 "applied. If this attribute is not set, patch_cmds will be executed on Windows, " +
322 "which requires Bash binary to exist.",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700323 ),
324 "build_file": attr.label(
325 allow_single_file = True,
326 doc =
327 "The file to use as the BUILD file for this repository." +
328 "This attribute is an absolute label (use '@//' for the main " +
329 "repo). The file does not need to be named BUILD, but can " +
330 "be (something like BUILD.new-repo-name may work well for " +
331 "distinguishing it from the repository's actual BUILD files. " +
332 "Either build_file or build_file_content can be specified, but " +
333 "not both.",
334 ),
335 "build_file_content": attr.string(
336 doc =
337 "The content for the BUILD file for this repository. " +
338 "Either build_file or build_file_content can be specified, but " +
339 "not both.",
340 ),
341 "workspace_file": attr.label(
342 doc =
343 "The file to use as the `WORKSPACE` file for this repository. " +
344 "Either `workspace_file` or `workspace_file_content` can be " +
345 "specified, or neither, but not both.",
346 ),
347 "workspace_file_content": attr.string(
348 doc =
349 "The content for the WORKSPACE file for this repository. " +
350 "Either `workspace_file` or `workspace_file_content` can be " +
351 "specified, or neither, but not both.",
352 ),
David Chen451599a2016-11-18 23:58:35 +0000353}
354
David Chen451599a2016-11-18 23:58:35 +0000355http_archive = repository_rule(
356 implementation = _http_archive_impl,
357 attrs = _http_archive_attrs,
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700358 doc =
359 """Downloads a Bazel repository as a compressed archive file, decompresses it,
David Chen451599a2016-11-18 23:58:35 +0000360and makes its targets available for binding.
361
Kevin Lubick9c981202022-04-05 06:56:26 -0700362It supports the following file extensions: `"zip"`, `"jar"`, `"war"`, `"aar"`, `"tar"`,
363`"tar.gz"`, `"tgz"`, `"tar.xz"`, `"txz"`, `"tar.zst"`, `"tzst"`, `tar.bz2`, `"ar"`,
364or `"deb"`.
David Chen451599a2016-11-18 23:58:35 +0000365
366Examples:
367 Suppose the current repository contains the source code for a chat program,
368 rooted at the directory `~/chat-app`. It needs to depend on an SSL library
369 which is available from http://example.com/openssl.zip. This `.zip` file
370 contains the following directory structure:
371
372 ```
373 WORKSPACE
374 src/
375 openssl.cc
376 openssl.h
377 ```
378
379 In the local repository, the user creates a `openssl.BUILD` file which
380 contains the following target definition:
381
382 ```python
383 cc_library(
384 name = "openssl-lib",
385 srcs = ["src/openssl.cc"],
386 hdrs = ["src/openssl.h"],
387 )
388 ```
389
390 Targets in the `~/chat-app` repository can depend on this target if the
391 following lines are added to `~/chat-app/WORKSPACE`:
392
393 ```python
Klaus Aehlig8808f952019-03-22 02:59:01 -0700394 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
395
David Chen451599a2016-11-18 23:58:35 +0000396 http_archive(
397 name = "my_ssl",
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700398 url = "http://example.com/openssl.zip",
Klaus Aehligcbe6aed2019-04-26 06:30:46 -0700399 sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700400 build_file = "@//:openssl.BUILD",
David Chen451599a2016-11-18 23:58:35 +0000401 )
402 ```
403
404 Then targets would specify `@my_ssl//:openssl-lib` as a dependency.
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700405""",
406)
David Chen451599a2016-11-18 23:58:35 +0000407
dannark94e1dcc2018-12-20 16:35:32 -0800408_http_file_attrs = {
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700409 "executable": attr.bool(
410 doc = "If the downloaded file should be made executable.",
411 ),
412 "downloaded_file_path": attr.string(
413 default = "downloaded",
414 doc = "Path assigned to the file downloaded",
415 ),
416 "sha256": attr.string(
417 doc = """The expected SHA-256 of the file downloaded.
418
419This must match the SHA-256 of the file downloaded. _It is a security risk
420to omit the SHA-256 as remote files can change._ At best omitting this
421field will make your build non-hermetic. It is optional to make development
422easier but should be set before shipping.""",
423 ),
David Ostrovsky3e5ece32020-01-20 02:29:56 -0800424 "canonical_id": attr.string(
425 doc = """A canonical id of the archive downloaded.
426
427If specified and non-empty, bazel will not take the archive from cache,
428unless it was added to the cache by a request with the same canonical id.
429""",
430 ),
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700431 "url": attr.string(doc = _URL_DOC),
432 "urls": attr.string_list(doc = _URLS_DOC),
pcloudy7aa52372022-01-11 05:03:54 -0800433 "netrc": attr.string(
434 doc = "Location of the .netrc file to use for authentication",
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700435 ),
Cristian Hanciladb645502020-03-09 11:12:52 -0700436 "auth_patterns": attr.string_dict(
Jingwen Chenc5ec3c02020-03-25 16:53:15 -0700437 doc = _AUTH_PATTERN_DOC,
Cristian Hanciladb645502020-03-09 11:12:52 -0700438 ),
dannark94e1dcc2018-12-20 16:35:32 -0800439}
440
David Chen451599a2016-11-18 23:58:35 +0000441http_file = repository_rule(
442 implementation = _http_file_impl,
dannark94e1dcc2018-12-20 16:35:32 -0800443 attrs = _http_file_attrs,
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700444 doc =
445 """Downloads a file from a URL and makes it available to be used as a file
David Chen451599a2016-11-18 23:58:35 +0000446group.
447
448Examples:
449 Suppose you need to have a debian package for your custom rules. This package
450 is available from http://example.com/package.deb. Then you can add to your
451 WORKSPACE file:
452
453 ```python
Klaus Aehlig8808f952019-03-22 02:59:01 -0700454 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
455
David Chen451599a2016-11-18 23:58:35 +0000456 http_file(
457 name = "my_deb",
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700458 url = "http://example.com/package.deb",
Klaus Aehligcbe6aed2019-04-26 06:30:46 -0700459 sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
David Chen451599a2016-11-18 23:58:35 +0000460 )
461 ```
462
463 Targets would specify `@my_deb//file` as a dependency to depend on this file.
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700464""",
465)
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700466
dannark94e1dcc2018-12-20 16:35:32 -0800467_http_jar_attrs = {
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700468 "sha256": attr.string(
469 doc = "The expected SHA-256 of the file downloaded.",
470 ),
David Ostrovsky3e5ece32020-01-20 02:29:56 -0800471 "canonical_id": attr.string(
472 doc = """A canonical id of the archive downloaded.
473
474If specified and non-empty, bazel will not take the archive from cache,
475unless it was added to the cache by a request with the same canonical id.
476""",
477 ),
Christopher Peterson Sauerd273cb62022-05-17 08:20:57 -0700478 "url": attr.string(doc = _URL_DOC + "\n\nThe URL must end in `.jar`."),
479 "urls": attr.string_list(doc = _URLS_DOC + "\n\nAll URLs must end in `.jar`."),
pcloudy7aa52372022-01-11 05:03:54 -0800480 "netrc": attr.string(
481 doc = "Location of the .netrc file to use for authentication",
Klaus Aehligc3d73f72019-09-20 07:17:33 -0700482 ),
Cristian Hanciladb645502020-03-09 11:12:52 -0700483 "auth_patterns": attr.string_dict(
Jingwen Chenc5ec3c02020-03-25 16:53:15 -0700484 doc = _AUTH_PATTERN_DOC,
Cristian Hanciladb645502020-03-09 11:12:52 -0700485 ),
Rabi Shanker Guha15b18402021-09-21 10:42:39 -0700486 "downloaded_file_name": attr.string(
487 default = "downloaded.jar",
488 doc = "Filename assigned to the jar downloaded",
489 ),
dannark94e1dcc2018-12-20 16:35:32 -0800490}
491
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700492http_jar = repository_rule(
493 implementation = _http_jar_impl,
dannark94e1dcc2018-12-20 16:35:32 -0800494 attrs = _http_jar_attrs,
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700495 doc =
496 """Downloads a jar from a URL and makes it available as java_import
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700497
498Downloaded files must have a .jar extension.
499
500Examples:
501 Suppose the current repository contains the source code for a chat program, rooted at the
502 directory `~/chat-app`. It needs to depend on an SSL library which is available from
503 `http://example.com/openssl-0.2.jar`.
504
505 Targets in the `~/chat-app` repository can depend on this target if the following lines are
506 added to `~/chat-app/WORKSPACE`:
507
508 ```python
Klaus Aehlig8808f952019-03-22 02:59:01 -0700509 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")
510
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700511 http_jar(
512 name = "my_ssl",
513 url = "http://example.com/openssl-0.2.jar",
Klaus Aehligcbe6aed2019-04-26 06:30:46 -0700514 sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
Klaus Aehlig17735dd2018-05-23 07:13:49 -0700515 )
516 ```
517
518 Targets would specify <code>@my_ssl//jar</code> as a dependency to depend on this jar.
519
Laszlo Csomore926cfc2018-06-21 06:02:16 -0700520 You may also reference files on the current system (localhost) by using "file:///path/to/file"
521 if you are on Unix-based systems. If you're on Windows, use "file:///c:/path/to/file". In both
522 examples, note the three slashes (`/`) -- the first two slashes belong to `file://` and the third
523 one belongs to the absolute path to the file.
Klaus Aehlig852c11f2019-03-19 06:42:17 -0700524""",
525)