@@ -21,12 +21,37 @@ def validate_checksum(repo_ctx, url, local_path, expected_sha256):
21
21
))
22
22
23
23
def extract_archive (repo_ctx , local_path , strip_prefix , build_file , build_file_contents ):
24
- # Extract the downloaded archive.
25
- repo_ctx .extract (local_path , stripPrefix = strip_prefix )
24
+ bash_path = repo_ctx .os .environ .get ("BAZEL_SH" , "bash" )
25
+ if local_path .endswith (".tar.zst" ) or local_path .endswith (".tar.zstd" ):
26
+ # Recent TAR supports zstd, if the compressor is installed.
27
+ zst_path = repo_ctx .which ("zstd" )
28
+ if zst_path == None :
29
+ fail ("To decompress .tar.zst, install zstd." )
30
+ tar_path = repo_ctx .which ("tar" )
31
+ if tar_path == None :
32
+ fail ("To decompress .tar.zst, install tar." )
33
+ extra_tar_params = []
34
+ if strip_prefix != None and strip_prefix :
35
+ # Trick: we need to extract a subdir, and remove its components
36
+ # from the path. We do so via `tar xvf file.tar.zst sub/dir
37
+ # --strip-components=N`. Here we figure out the N.
38
+ num_components = 0
39
+ prefix = strip_prefix .strip ("/" )
40
+ for c in prefix .split ("/" ):
41
+ if len (c ) > 0 :
42
+ num_components += 1
43
+ extra_tar_params = [prefix , "--strip-components=" + str (num_components )]
44
+
45
+ # Decompress with tar, piping through zstd internally, and stripping prefix
46
+ # if requested.
47
+ tar_cmd = [tar_path , "-x" , "-f" , local_path ] + extra_tar_params
48
+ repo_ctx .execute (tar_cmd )
49
+ else :
50
+ # Extract the downloaded archive using Bazel's built-in decompressors.
51
+ repo_ctx .extract (local_path , stripPrefix = strip_prefix )
26
52
27
53
# Provide external BUILD file if requested; `build_file_contents` takes
28
54
# priority.
29
- bash_path = repo_ctx .os .environ .get ("BAZEL_SH" , "bash" )
30
55
if build_file_contents :
31
56
repo_ctx .execute ([bash_path , "-c" , "rm -f BUILD BUILD.bazel" ])
32
57
repo_ctx .file ("BUILD.bazel" , build_file_contents , executable = False )
@@ -39,6 +64,8 @@ def cloud_archive_download(
39
64
file_path ,
40
65
expected_sha256 ,
41
66
provider ,
67
+ patches ,
68
+ patch_args ,
42
69
bucket = "" ,
43
70
strip_prefix = "" ,
44
71
build_file = "" ,
@@ -84,14 +111,46 @@ def cloud_archive_download(
84
111
# Verify.
85
112
filename = repo_ctx .path (src_url ).basename
86
113
validate_checksum (repo_ctx , file_path , filename , expected_sha256 )
114
+
115
+ # Extract
87
116
extract_archive (repo_ctx , filename , strip_prefix , build_file , build_file_contents )
88
117
118
+ # If patches are provided, apply them.
119
+ if patches != None and len (patches ) > 0 :
120
+ patches = [str (repo_ctx .path (patch )) for patch in patches ]
121
+
122
+ # Built in Bazel patch only supports -pN or no parameters at all, so we
123
+ # determine if we can use the built in patch.
124
+ only_strip_param = (patch_args != None and
125
+ len (patch_args ) == 1 and
126
+ patch_args [0 ].startswith ("-p" ) and
127
+ patch_args [0 ][2 :].isdigit ())
128
+ strip_n = 0
129
+ if only_strip_param :
130
+ strip_n = int (patch_args [0 ][2 ])
131
+
132
+ if patch_args == None or only_strip_param :
133
+ # OK to use built-in patch.
134
+ for patch in patches :
135
+ repo_ctx .patch (patch , strip = strip_n )
136
+ else :
137
+ # Must use extrenal patch. Note that this hasn't been tested, so it
138
+ # might not work. If it's busted, please send a PR.
139
+ patch_path = repo_ctx .which ("patch" )
140
+ for patch in patches :
141
+ patch_cmd = [patch_path ] + patch_args + ["-i" , patch ]
142
+ result = repo_ctx .execute (patch_cmd )
143
+ if result .return_code != 0 :
144
+ fail ("Patch {} failed to apply." )
145
+
89
146
def _cloud_archive_impl (ctx ):
90
147
cloud_archive_download (
91
148
ctx ,
92
149
ctx .attr .file_path ,
93
150
ctx .attr .sha256 ,
94
151
provider = ctx .attr ._provider ,
152
+ patches = ctx .attr .patches ,
153
+ patch_args = ctx .attr .patch_args ,
95
154
strip_prefix = ctx .attr .strip_prefix ,
96
155
build_file = ctx .attr .build_file ,
97
156
build_file_contents = ctx .attr .build_file_contents ,
@@ -112,6 +171,8 @@ minio_archive = repository_rule(
112
171
doc = "BUILD file for the unpacked archive" ,
113
172
),
114
173
"build_file_contents" : attr .string (doc = "The contents of the build file for the target" ),
174
+ "patches" : attr .label_list (doc = "Patches to apply, if any." , allow_files = True ),
175
+ "patch_args" : attr .string_list (doc = "Arguments to use when applying patches." ),
115
176
"strip_prefix" : attr .string (doc = "Prefix to strip when archive is unpacked" ),
116
177
"_provider" : attr .string (default = "minio" ),
117
178
},
@@ -132,6 +193,8 @@ s3_archive = repository_rule(
132
193
doc = "BUILD file for the unpacked archive" ,
133
194
),
134
195
"build_file_contents" : attr .string (doc = "The contents of the build file for the target" ),
196
+ "patches" : attr .label_list (doc = "Patches to apply, if any." , allow_files = True ),
197
+ "patch_args" : attr .string_list (doc = "Arguments to use when applying patches." ),
135
198
"strip_prefix" : attr .string (doc = "Prefix to strip when archive is unpacked" ),
136
199
"_provider" : attr .string (default = "s3" ),
137
200
},
@@ -151,6 +214,8 @@ gs_archive = repository_rule(
151
214
doc = "BUILD file for the unpacked archive" ,
152
215
),
153
216
"build_file_contents" : attr .string (doc = "The contents of the build file for the target" ),
217
+ "patches" : attr .label_list (doc = "Patches to apply, if any." , allow_files = True ),
218
+ "patch_args" : attr .string_list (doc = "Arguments to use when applying patches." ),
154
219
"strip_prefix" : attr .string (doc = "Prefix to strip when archive is unpacked" ),
155
220
"_provider" : attr .string (default = "google" ),
156
221
},
@@ -170,6 +235,8 @@ b2_archive = repository_rule(
170
235
doc = "BUILD file for the unpacked archive" ,
171
236
),
172
237
"build_file_contents" : attr .string (doc = "The contents of the build file for the target" ),
238
+ "patches" : attr .label_list (doc = "Patches to apply, if any." , allow_files = True ),
239
+ "patch_args" : attr .string_list (doc = "Arguments to use when applying patches." ),
173
240
"strip_prefix" : attr .string (doc = "Prefix to strip when archive is unpacked" ),
174
241
"_provider" : attr .string (default = "backblaze" ),
175
242
},
0 commit comments