blob: ac557176d78c5d91db02d88867aab552341f1a74 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
2BitBake 'Fetch' implementations
3
4Classes for obtaining upstream sources for the
5BitBake build tools.
6"""
7
8# Copyright (C) 2003, 2004 Chris Larson
9# Copyright (C) 2012 Intel Corporation
10#
Brad Bishopc342db32019-05-15 21:57:59 -040011# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050012#
13# Based on functions from the base bb module, Copyright 2003 Holger Schurig
14
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015import os, re
16import signal
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017import logging
Patrick Williamsc0f7c042017-02-23 20:41:17 -060018import urllib.request, urllib.parse, urllib.error
19if 'git' not in urllib.parse.uses_netloc:
20 urllib.parse.uses_netloc.append('git')
21import operator
22import collections
23import subprocess
24import pickle
Brad Bishop6e60e8b2018-02-01 10:27:11 -050025import errno
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026import bb.persist_data, bb.utils
27import bb.checksum
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028import bb.process
Brad Bishopd7bf8c12018-02-25 22:55:05 -050029import bb.event
Patrick Williamsc124f4f2015-09-15 14:41:29 -050030
31__version__ = "2"
32_checksum_cache = bb.checksum.FileChecksumCache()
33
34logger = logging.getLogger("BitBake.Fetcher")
35
Andrew Geissler82c905d2020-04-13 13:39:40 -050036CHECKSUM_LIST = [ "md5", "sha256", "sha1", "sha384", "sha512" ]
37SHOWN_CHECKSUM_LIST = ["sha256"]
38
Patrick Williamsc124f4f2015-09-15 14:41:29 -050039class BBFetchException(Exception):
40 """Class all fetch exceptions inherit from"""
41 def __init__(self, message):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050042 self.msg = message
43 Exception.__init__(self, message)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044
45 def __str__(self):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050046 return self.msg
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047
48class UntrustedUrl(BBFetchException):
49 """Exception raised when encountering a host not listed in BB_ALLOWED_NETWORKS"""
50 def __init__(self, url, message=''):
51 if message:
52 msg = message
53 else:
54 msg = "The URL: '%s' is not trusted and cannot be used" % url
55 self.url = url
56 BBFetchException.__init__(self, msg)
57 self.args = (url,)
58
59class MalformedUrl(BBFetchException):
60 """Exception raised when encountering an invalid url"""
61 def __init__(self, url, message=''):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050062 if message:
63 msg = message
64 else:
65 msg = "The URL: '%s' is invalid and cannot be interpreted" % url
66 self.url = url
67 BBFetchException.__init__(self, msg)
68 self.args = (url,)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069
70class FetchError(BBFetchException):
71 """General fetcher exception when something happens incorrectly"""
72 def __init__(self, message, url = None):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050073 if url:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050074 msg = "Fetcher failure for URL: '%s'. %s" % (url, message)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050075 else:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050076 msg = "Fetcher failure: %s" % message
Brad Bishopd7bf8c12018-02-25 22:55:05 -050077 self.url = url
78 BBFetchException.__init__(self, msg)
79 self.args = (message, url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080
81class ChecksumError(FetchError):
82 """Exception when mismatched checksum encountered"""
83 def __init__(self, message, url = None, checksum = None):
84 self.checksum = checksum
85 FetchError.__init__(self, message, url)
86
87class NoChecksumError(FetchError):
88 """Exception when no checksum is specified, but BB_STRICT_CHECKSUM is set"""
89
90class UnpackError(BBFetchException):
91 """General fetcher exception when something happens incorrectly when unpacking"""
92 def __init__(self, message, url):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050093 msg = "Unpack failure for URL: '%s'. %s" % (url, message)
94 self.url = url
95 BBFetchException.__init__(self, msg)
96 self.args = (message, url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097
98class NoMethodError(BBFetchException):
99 """Exception raised when there is no method to obtain a supplied url or set of urls"""
100 def __init__(self, url):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500101 msg = "Could not find a fetcher which supports the URL: '%s'" % url
102 self.url = url
103 BBFetchException.__init__(self, msg)
104 self.args = (url,)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500105
106class MissingParameterError(BBFetchException):
107 """Exception raised when a fetch method is missing a critical parameter in the url"""
108 def __init__(self, missing, url):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500109 msg = "URL: '%s' is missing the required parameter '%s'" % (url, missing)
110 self.url = url
111 self.missing = missing
112 BBFetchException.__init__(self, msg)
113 self.args = (missing, url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500114
115class ParameterError(BBFetchException):
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000116 """Exception raised when a url cannot be processed due to invalid parameters."""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500117 def __init__(self, message, url):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500118 msg = "URL: '%s' has invalid parameters. %s" % (url, message)
119 self.url = url
120 BBFetchException.__init__(self, msg)
121 self.args = (message, url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500122
123class NetworkAccess(BBFetchException):
124 """Exception raised when network access is disabled but it is required."""
125 def __init__(self, url, cmd):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500126 msg = "Network access disabled through BB_NO_NETWORK (or set indirectly due to use of BB_FETCH_PREMIRRORONLY) but access requested with command %s (for url %s)" % (cmd, url)
127 self.url = url
128 self.cmd = cmd
129 BBFetchException.__init__(self, msg)
130 self.args = (url, cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500131
132class NonLocalMethod(Exception):
133 def __init__(self):
134 Exception.__init__(self)
135
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500136class MissingChecksumEvent(bb.event.Event):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500137 def __init__(self, url, **checksums):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500138 self.url = url
Andrew Geissler82c905d2020-04-13 13:39:40 -0500139 self.checksums = checksums
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500140 bb.event.Event.__init__(self)
141
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142
143class URI(object):
144 """
145 A class representing a generic URI, with methods for
146 accessing the URI components, and stringifies to the
147 URI.
148
149 It is constructed by calling it with a URI, or setting
150 the attributes manually:
151
152 uri = URI("http://example.com/")
153
154 uri = URI()
155 uri.scheme = 'http'
156 uri.hostname = 'example.com'
157 uri.path = '/'
158
159 It has the following attributes:
160
161 * scheme (read/write)
162 * userinfo (authentication information) (read/write)
163 * username (read/write)
164 * password (read/write)
165
166 Note, password is deprecated as of RFC 3986.
167
168 * hostname (read/write)
169 * port (read/write)
170 * hostport (read only)
171 "hostname:port", if both are set, otherwise just "hostname"
172 * path (read/write)
173 * path_quoted (read/write)
174 A URI quoted version of path
175 * params (dict) (read/write)
176 * query (dict) (read/write)
177 * relative (bool) (read only)
178 True if this is a "relative URI", (e.g. file:foo.diff)
179
180 It stringifies to the URI itself.
181
182 Some notes about relative URIs: while it's specified that
183 a URI beginning with <scheme>:// should either be directly
184 followed by a hostname or a /, the old URI handling of the
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000185 fetch2 library did not conform to this. Therefore, this URI
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186 class has some kludges to make sure that URIs are parsed in
187 a way comforming to bitbake's current usage. This URI class
188 supports the following:
189
190 file:relative/path.diff (IETF compliant)
191 git:relative/path.git (IETF compliant)
192 git:///absolute/path.git (IETF compliant)
193 file:///absolute/path.diff (IETF compliant)
194
195 file://relative/path.diff (not IETF compliant)
196
197 But it does not support the following:
198
199 file://hostname/absolute/path.diff (would be IETF compliant)
200
201 Note that the last case only applies to a list of
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000202 explicitly allowed schemes (currently only file://), that requires
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500203 its URIs to not have a network location.
204 """
205
206 _relative_schemes = ['file', 'git']
207 _netloc_forbidden = ['file']
208
209 def __init__(self, uri=None):
210 self.scheme = ''
211 self.userinfo = ''
212 self.hostname = ''
213 self.port = None
214 self._path = ''
215 self.params = {}
216 self.query = {}
217 self.relative = False
218
219 if not uri:
220 return
221
222 # We hijack the URL parameters, since the way bitbake uses
223 # them are not quite RFC compliant.
224 uri, param_str = (uri.split(";", 1) + [None])[:2]
225
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600226 urlp = urllib.parse.urlparse(uri)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500227 self.scheme = urlp.scheme
228
229 reparse = 0
230
231 # Coerce urlparse to make URI scheme use netloc
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600232 if not self.scheme in urllib.parse.uses_netloc:
233 urllib.parse.uses_params.append(self.scheme)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500234 reparse = 1
235
236 # Make urlparse happy(/ier) by converting local resources
237 # to RFC compliant URL format. E.g.:
238 # file://foo.diff -> file:foo.diff
239 if urlp.scheme in self._netloc_forbidden:
240 uri = re.sub("(?<=:)//(?!/)", "", uri, 1)
241 reparse = 1
242
243 if reparse:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600244 urlp = urllib.parse.urlparse(uri)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500245
246 # Identify if the URI is relative or not
247 if urlp.scheme in self._relative_schemes and \
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800248 re.compile(r"^\w+:(?!//)").match(uri):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500249 self.relative = True
250
251 if not self.relative:
252 self.hostname = urlp.hostname or ''
253 self.port = urlp.port
254
255 self.userinfo += urlp.username or ''
256
257 if urlp.password:
258 self.userinfo += ':%s' % urlp.password
259
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600260 self.path = urllib.parse.unquote(urlp.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500261
262 if param_str:
263 self.params = self._param_str_split(param_str, ";")
264 if urlp.query:
265 self.query = self._param_str_split(urlp.query, "&")
266
267 def __str__(self):
268 userinfo = self.userinfo
269 if userinfo:
270 userinfo += '@'
271
272 return "%s:%s%s%s%s%s%s" % (
273 self.scheme,
274 '' if self.relative else '//',
275 userinfo,
276 self.hostport,
277 self.path_quoted,
278 self._query_str(),
279 self._param_str())
280
281 def _param_str(self):
282 return (
283 ''.join([';', self._param_str_join(self.params, ";")])
284 if self.params else '')
285
286 def _query_str(self):
287 return (
288 ''.join(['?', self._param_str_join(self.query, "&")])
289 if self.query else '')
290
291 def _param_str_split(self, string, elmdelim, kvdelim="="):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600292 ret = collections.OrderedDict()
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600293 for k, v in [x.split(kvdelim, 1) for x in string.split(elmdelim) if x]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500294 ret[k] = v
295 return ret
296
297 def _param_str_join(self, dict_, elmdelim, kvdelim="="):
298 return elmdelim.join([kvdelim.join([k, v]) for k, v in dict_.items()])
299
300 @property
301 def hostport(self):
302 if not self.port:
303 return self.hostname
304 return "%s:%d" % (self.hostname, self.port)
305
306 @property
307 def path_quoted(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600308 return urllib.parse.quote(self.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500309
310 @path_quoted.setter
311 def path_quoted(self, path):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600312 self.path = urllib.parse.unquote(path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500313
314 @property
315 def path(self):
316 return self._path
317
318 @path.setter
319 def path(self, path):
320 self._path = path
321
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500322 if not path or re.compile("^/").match(path):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500323 self.relative = False
324 else:
325 self.relative = True
326
327 @property
328 def username(self):
329 if self.userinfo:
330 return (self.userinfo.split(":", 1))[0]
331 return ''
332
333 @username.setter
334 def username(self, username):
335 password = self.password
336 self.userinfo = username
337 if password:
338 self.userinfo += ":%s" % password
339
340 @property
341 def password(self):
342 if self.userinfo and ":" in self.userinfo:
343 return (self.userinfo.split(":", 1))[1]
344 return ''
345
346 @password.setter
347 def password(self, password):
348 self.userinfo = "%s:%s" % (self.username, password)
349
350def decodeurl(url):
351 """Decodes an URL into the tokens (scheme, network location, path,
352 user, password, parameters).
353 """
354
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500355 m = re.compile('(?P<type>[^:]*)://((?P<user>[^/;]+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356 if not m:
357 raise MalformedUrl(url)
358
359 type = m.group('type')
360 location = m.group('location')
361 if not location:
362 raise MalformedUrl(url)
363 user = m.group('user')
364 parm = m.group('parm')
365
366 locidx = location.find('/')
367 if locidx != -1 and type.lower() != 'file':
368 host = location[:locidx]
369 path = location[locidx:]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500370 elif type.lower() == 'file':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 host = ""
372 path = location
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500373 else:
374 host = location
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800375 path = "/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376 if user:
377 m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
378 if m:
379 user = m.group('user')
380 pswd = m.group('pswd')
381 else:
382 user = ''
383 pswd = ''
384
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600385 p = collections.OrderedDict()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500386 if parm:
387 for s in parm.split(';'):
388 if s:
389 if not '=' in s:
390 raise MalformedUrl(url, "The URL: '%s' is invalid: parameter %s does not specify a value (missing '=')" % (url, s))
391 s1, s2 = s.split('=')
392 p[s1] = s2
393
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600394 return type, host, urllib.parse.unquote(path), user, pswd, p
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395
396def encodeurl(decoded):
397 """Encodes a URL from tokens (scheme, network location, path,
398 user, password, parameters).
399 """
400
401 type, host, path, user, pswd, p = decoded
402
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500403 if not type:
404 raise MissingParameterError('type', "encoded from the data %s" % str(decoded))
Andrew Geissler595f6302022-01-24 19:11:47 +0000405 url = ['%s://' % type]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406 if user and type != "file":
Andrew Geissler595f6302022-01-24 19:11:47 +0000407 url.append("%s" % user)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500408 if pswd:
Andrew Geissler595f6302022-01-24 19:11:47 +0000409 url.append(":%s" % pswd)
410 url.append("@")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500411 if host and type != "file":
Andrew Geissler595f6302022-01-24 19:11:47 +0000412 url.append("%s" % host)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500413 if path:
414 # Standardise path to ensure comparisons work
415 while '//' in path:
416 path = path.replace("//", "/")
Andrew Geissler595f6302022-01-24 19:11:47 +0000417 url.append("%s" % urllib.parse.quote(path))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500418 if p:
419 for parm in p:
Andrew Geissler595f6302022-01-24 19:11:47 +0000420 url.append(";%s=%s" % (parm, p[parm]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500421
Andrew Geissler595f6302022-01-24 19:11:47 +0000422 return "".join(url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500423
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500424def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500425 if not ud.url or not uri_find or not uri_replace:
426 logger.error("uri_replace: passed an undefined value, not replacing")
427 return None
428 uri_decoded = list(decodeurl(ud.url))
429 uri_find_decoded = list(decodeurl(uri_find))
430 uri_replace_decoded = list(decodeurl(uri_replace))
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600431 logger.debug2("For url %s comparing %s to %s" % (uri_decoded, uri_find_decoded, uri_replace_decoded))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500432 result_decoded = ['', '', '', '', '', {}]
Andrew Geissler595f6302022-01-24 19:11:47 +0000433 # 0 - type, 1 - host, 2 - path, 3 - user, 4- pswd, 5 - params
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500434 for loc, i in enumerate(uri_find_decoded):
435 result_decoded[loc] = uri_decoded[loc]
436 regexp = i
437 if loc == 0 and regexp and not regexp.endswith("$"):
438 # Leaving the type unanchored can mean "https" matching "file" can become "files"
439 # which is clearly undesirable.
440 regexp += "$"
441 if loc == 5:
442 # Handle URL parameters
443 if i:
444 # Any specified URL parameters must match
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800445 for k in uri_find_decoded[loc]:
446 if uri_decoded[loc][k] != uri_find_decoded[loc][k]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500447 return None
448 # Overwrite any specified replacement parameters
449 for k in uri_replace_decoded[loc]:
450 for l in replacements:
451 uri_replace_decoded[loc][k] = uri_replace_decoded[loc][k].replace(l, replacements[l])
452 result_decoded[loc][k] = uri_replace_decoded[loc][k]
Andrew Geissler595f6302022-01-24 19:11:47 +0000453 elif (loc == 3 or loc == 4) and uri_replace_decoded[loc]:
454 # User/password in the replacement is just a straight replacement
455 result_decoded[loc] = uri_replace_decoded[loc]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500456 elif (re.match(regexp, uri_decoded[loc])):
457 if not uri_replace_decoded[loc]:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500458 result_decoded[loc] = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500459 else:
460 for k in replacements:
461 uri_replace_decoded[loc] = uri_replace_decoded[loc].replace(k, replacements[k])
462 #bb.note("%s %s %s" % (regexp, uri_replace_decoded[loc], uri_decoded[loc]))
Patrick Williamsd7e96312015-09-22 08:09:05 -0500463 result_decoded[loc] = re.sub(regexp, uri_replace_decoded[loc], uri_decoded[loc], 1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500464 if loc == 2:
465 # Handle path manipulations
466 basename = None
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500467 if uri_decoded[0] != uri_replace_decoded[0] and mirrortarball:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500468 # If the source and destination url types differ, must be a mirrortarball mapping
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500469 basename = os.path.basename(mirrortarball)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500470 # Kill parameters, they make no sense for mirror tarballs
471 uri_decoded[5] = {}
472 elif ud.localpath and ud.method.supports_checksum(ud):
Andrew Geissler595f6302022-01-24 19:11:47 +0000473 basename = os.path.basename(ud.localpath)
474 if basename:
475 uri_basename = os.path.basename(uri_decoded[loc])
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000476 # Prefix with a slash as a sentinel in case
477 # result_decoded[loc] does not contain one.
478 path = "/" + result_decoded[loc]
479 if uri_basename and basename != uri_basename and path.endswith("/" + uri_basename):
480 result_decoded[loc] = path[1:-len(uri_basename)] + basename
481 elif not path.endswith("/" + basename):
482 result_decoded[loc] = os.path.join(path[1:], basename)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500483 else:
484 return None
485 result = encodeurl(result_decoded)
486 if result == ud.url:
487 return None
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600488 logger.debug2("For url %s returning %s" % (ud.url, result))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500489 return result
490
491methods = []
492urldata_cache = {}
493saved_headrevs = {}
494
495def fetcher_init(d):
496 """
497 Called to initialize the fetchers once the configuration data is known.
498 Calls before this must not hit the cache.
499 """
Andrew Geissler82c905d2020-04-13 13:39:40 -0500500
501 revs = bb.persist_data.persist('BB_URI_HEADREVS', d)
502 try:
503 # fetcher_init is called multiple times, so make sure we only save the
504 # revs the first time it is called.
505 if not bb.fetch2.saved_headrevs:
506 bb.fetch2.saved_headrevs = dict(revs)
507 except:
508 pass
509
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500510 # When to drop SCM head revisions controlled by user policy
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500511 srcrev_policy = d.getVar('BB_SRCREV_POLICY') or "clear"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500512 if srcrev_policy == "cache":
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600513 logger.debug("Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500514 elif srcrev_policy == "clear":
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600515 logger.debug("Clearing SRCREV cache due to cache policy of: %s", srcrev_policy)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500516 revs.clear()
517 else:
518 raise FetchError("Invalid SRCREV cache policy of: %s" % srcrev_policy)
519
520 _checksum_cache.init_cache(d)
521
522 for m in methods:
523 if hasattr(m, "init"):
524 m.init(d)
525
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500526def fetcher_parse_save():
527 _checksum_cache.save_extras()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500528
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500529def fetcher_parse_done():
530 _checksum_cache.save_merge()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500531
Brad Bishop19323692019-04-05 15:28:33 -0400532def fetcher_compare_revisions(d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500533 """
Andrew Geissler82c905d2020-04-13 13:39:40 -0500534 Compare the revisions in the persistent cache with the saved values from
535 when bitbake was started and return true if they have changed.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500536 """
537
Andrew Geissler82c905d2020-04-13 13:39:40 -0500538 headrevs = dict(bb.persist_data.persist('BB_URI_HEADREVS', d))
539 return headrevs != bb.fetch2.saved_headrevs
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500540
541def mirror_from_string(data):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500542 mirrors = (data or "").replace('\\n',' ').split()
543 # Split into pairs
544 if len(mirrors) % 2 != 0:
545 bb.warn('Invalid mirror data %s, should have paired members.' % data)
546 return list(zip(*[iter(mirrors)]*2))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500547
548def verify_checksum(ud, d, precomputed={}):
549 """
550 verify the MD5 and SHA256 checksum for downloaded src
551
552 Raises a FetchError if one or both of the SRC_URI checksums do not match
553 the downloaded file, or if BB_STRICT_CHECKSUM is set and there are no
554 checksums specified.
555
556 Returns a dict of checksums that can be stored in a done stamp file and
557 passed in as precomputed parameter in a later call to avoid re-computing
558 the checksums from the file. This allows verifying the checksums of the
559 file against those in the recipe each time, rather than only after
560 downloading. See https://bugzilla.yoctoproject.org/show_bug.cgi?id=5571.
561 """
562
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500563 if ud.ignore_checksums or not ud.method.supports_checksum(ud):
564 return {}
565
Andrew Geissler82c905d2020-04-13 13:39:40 -0500566 def compute_checksum_info(checksum_id):
567 checksum_name = getattr(ud, "%s_name" % checksum_id)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500568
Andrew Geissler82c905d2020-04-13 13:39:40 -0500569 if checksum_id in precomputed:
570 checksum_data = precomputed[checksum_id]
571 else:
572 checksum_data = getattr(bb.utils, "%s_file" % checksum_id)(ud.localpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500573
Andrew Geissler82c905d2020-04-13 13:39:40 -0500574 checksum_expected = getattr(ud, "%s_expected" % checksum_id)
575
Andrew Geissler09036742021-06-25 14:25:14 -0500576 if checksum_expected == '':
577 checksum_expected = None
578
Andrew Geissler82c905d2020-04-13 13:39:40 -0500579 return {
580 "id": checksum_id,
581 "name": checksum_name,
582 "data": checksum_data,
583 "expected": checksum_expected
584 }
585
586 checksum_infos = []
587 for checksum_id in CHECKSUM_LIST:
588 checksum_infos.append(compute_checksum_info(checksum_id))
589
590 checksum_dict = {ci["id"] : ci["data"] for ci in checksum_infos}
591 checksum_event = {"%ssum" % ci["id"] : ci["data"] for ci in checksum_infos}
592
593 for ci in checksum_infos:
594 if ci["id"] in SHOWN_CHECKSUM_LIST:
595 checksum_lines = ["SRC_URI[%s] = \"%s\"" % (ci["name"], ci["data"])]
596
597 # If no checksum has been provided
598 if ud.method.recommends_checksum(ud) and all(ci["expected"] is None for ci in checksum_infos):
599 messages = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500600 strict = d.getVar("BB_STRICT_CHECKSUM") or "0"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500601
Andrew Geissler82c905d2020-04-13 13:39:40 -0500602 # If strict checking enabled and neither sum defined, raise error
603 if strict == "1":
604 messages.append("No checksum specified for '%s', please add at " \
605 "least one to the recipe:" % ud.localpath)
606 messages.extend(checksum_lines)
607 logger.error("\n".join(messages))
608 raise NoChecksumError("Missing SRC_URI checksum", ud.url)
609
610 bb.event.fire(MissingChecksumEvent(ud.url, **checksum_event), d)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500611
612 if strict == "ignore":
Andrew Geissler82c905d2020-04-13 13:39:40 -0500613 return checksum_dict
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500614
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500615 # Log missing sums so user can more easily add them
Andrew Geissler82c905d2020-04-13 13:39:40 -0500616 messages.append("Missing checksum for '%s', consider adding at " \
617 "least one to the recipe:" % ud.localpath)
618 messages.extend(checksum_lines)
619 logger.warning("\n".join(messages))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500620
621 # We want to alert the user if a checksum is defined in the recipe but
622 # it does not match.
Andrew Geissler82c905d2020-04-13 13:39:40 -0500623 messages = []
624 messages.append("Checksum mismatch!")
625 bad_checksum = None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500626
Andrew Geissler82c905d2020-04-13 13:39:40 -0500627 for ci in checksum_infos:
628 if ci["expected"] and ci["expected"] != ci["data"]:
Andrew Geissler09036742021-06-25 14:25:14 -0500629 messages.append("File: '%s' has %s checksum '%s' when '%s' was " \
Andrew Geissler82c905d2020-04-13 13:39:40 -0500630 "expected" % (ud.localpath, ci["id"], ci["data"], ci["expected"]))
631 bad_checksum = ci["data"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500632
Andrew Geissler82c905d2020-04-13 13:39:40 -0500633 if bad_checksum:
634 messages.append("If this change is expected (e.g. you have upgraded " \
635 "to a new version without updating the checksums) " \
636 "then you can use these lines within the recipe:")
637 messages.extend(checksum_lines)
638 messages.append("Otherwise you should retry the download and/or " \
639 "check with upstream to determine if the file has " \
640 "become corrupted or otherwise unexpectedly modified.")
641 raise ChecksumError("\n".join(messages), ud.url, bad_checksum)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500642
Andrew Geissler82c905d2020-04-13 13:39:40 -0500643 return checksum_dict
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500644
645def verify_donestamp(ud, d, origud=None):
646 """
647 Check whether the done stamp file has the right checksums (if the fetch
648 method supports them). If it doesn't, delete the done stamp and force
649 a re-download.
650
651 Returns True, if the donestamp exists and is valid, False otherwise. When
652 returning False, any existing done stamps are removed.
653 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500654 if not ud.needdonestamp or (origud and not origud.needdonestamp):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500655 return True
656
Brad Bishop316dfdd2018-06-25 12:45:53 -0400657 if not os.path.exists(ud.localpath):
658 # local path does not exist
659 if os.path.exists(ud.donestamp):
660 # done stamp exists, but the downloaded file does not; the done stamp
661 # must be incorrect, re-trigger the download
662 bb.utils.remove(ud.donestamp)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500663 return False
664
665 if (not ud.method.supports_checksum(ud) or
666 (origud and not origud.method.supports_checksum(origud))):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400667 # if done stamp exists and checksums not supported; assume the local
668 # file is current
669 return os.path.exists(ud.donestamp)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500670
671 precomputed_checksums = {}
672 # Only re-use the precomputed checksums if the donestamp is newer than the
673 # file. Do not rely on the mtime of directories, though. If ud.localpath is
674 # a directory, there will probably not be any checksums anyway.
Brad Bishop316dfdd2018-06-25 12:45:53 -0400675 if os.path.exists(ud.donestamp) and (os.path.isdir(ud.localpath) or
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500676 os.path.getmtime(ud.localpath) < os.path.getmtime(ud.donestamp)):
677 try:
678 with open(ud.donestamp, "rb") as cachefile:
679 pickled = pickle.Unpickler(cachefile)
680 precomputed_checksums.update(pickled.load())
681 except Exception as e:
682 # Avoid the warnings on the upgrade path from emtpy done stamp
683 # files to those containing the checksums.
684 if not isinstance(e, EOFError):
685 # Ignore errors, they aren't fatal
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600686 logger.warning("Couldn't load checksums from donestamp %s: %s "
687 "(msg: %s)" % (ud.donestamp, type(e).__name__,
688 str(e)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500689
690 try:
691 checksums = verify_checksum(ud, d, precomputed_checksums)
692 # If the cache file did not have the checksums, compute and store them
693 # as an upgrade path from the previous done stamp file format.
694 if checksums != precomputed_checksums:
695 with open(ud.donestamp, "wb") as cachefile:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600696 p = pickle.Pickler(cachefile, 2)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500697 p.dump(checksums)
698 return True
699 except ChecksumError as e:
700 # Checksums failed to verify, trigger re-download and remove the
701 # incorrect stamp file.
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600702 logger.warning("Checksum mismatch for local file %s\n"
703 "Cleaning and trying again." % ud.localpath)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500704 if os.path.exists(ud.localpath):
705 rename_bad_checksum(ud, e.checksum)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500706 bb.utils.remove(ud.donestamp)
707 return False
708
709
710def update_stamp(ud, d):
711 """
712 donestamp is file stamp indicating the whole fetching is done
713 this function update the stamp after verifying the checksum
714 """
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500715 if not ud.needdonestamp:
716 return
717
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500718 if os.path.exists(ud.donestamp):
719 # Touch the done stamp file to show active use of the download
720 try:
721 os.utime(ud.donestamp, None)
722 except:
723 # Errors aren't fatal here
724 pass
725 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500726 try:
727 checksums = verify_checksum(ud, d)
728 # Store the checksums for later re-verification against the recipe
729 with open(ud.donestamp, "wb") as cachefile:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600730 p = pickle.Pickler(cachefile, 2)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500731 p.dump(checksums)
732 except ChecksumError as e:
733 # Checksums failed to verify, trigger re-download and remove the
734 # incorrect stamp file.
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600735 logger.warning("Checksum mismatch for local file %s\n"
736 "Cleaning and trying again." % ud.localpath)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500737 if os.path.exists(ud.localpath):
738 rename_bad_checksum(ud, e.checksum)
739 bb.utils.remove(ud.donestamp)
740 raise
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500741
742def subprocess_setup():
743 # Python installs a SIGPIPE handler by default. This is usually not what
744 # non-Python subprocesses expect.
745 # SIGPIPE errors are known issues with gzip/bash
746 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
747
748def get_autorev(d):
749 # only not cache src rev in autorev case
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500750 if d.getVar('BB_SRCREV_POLICY') != "cache":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500751 d.setVar('BB_DONT_CACHE', '1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500752 return "AUTOINC"
753
754def get_srcrev(d, method_name='sortable_revision'):
755 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500756 Return the revision string, usually for use in the version string (PV) of the current package
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500757 Most packages usually only have one SCM so we just pass on the call.
758 In the multi SCM case, we build a value based on SRCREV_FORMAT which must
759 have been set.
760
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500761 The idea here is that we put the string "AUTOINC+" into return value if the revisions are not
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500762 incremental, other code is then responsible for turning that into an increasing value (if needed)
763
764 A method_name can be supplied to retrieve an alternatively formatted revision from a fetcher, if
765 that fetcher provides a method with the given name and the same signature as sortable_revision.
766 """
767
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000768 d.setVar("__BBSEENSRCREV", "1")
Andrew Geissler5199d832021-09-24 16:47:35 -0500769 recursion = d.getVar("__BBINSRCREV")
770 if recursion:
771 raise FetchError("There are recursive references in fetcher variables, likely through SRC_URI")
772 d.setVar("__BBINSRCREV", True)
773
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500774 scms = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500775 fetcher = Fetch(d.getVar('SRC_URI').split(), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500776 urldata = fetcher.ud
777 for u in urldata:
778 if urldata[u].method.supports_srcrev():
779 scms.append(u)
780
Andrew Geissler595f6302022-01-24 19:11:47 +0000781 if not scms:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500782 raise FetchError("SRCREV was used yet no valid SCM was found in SRC_URI")
783
784 if len(scms) == 1 and len(urldata[scms[0]].names) == 1:
785 autoinc, rev = getattr(urldata[scms[0]].method, method_name)(urldata[scms[0]], d, urldata[scms[0]].names[0])
786 if len(rev) > 10:
787 rev = rev[:10]
Andrew Geissler5199d832021-09-24 16:47:35 -0500788 d.delVar("__BBINSRCREV")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500789 if autoinc:
790 return "AUTOINC+" + rev
791 return rev
792
793 #
794 # Mutiple SCMs are in SRC_URI so we resort to SRCREV_FORMAT
795 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500796 format = d.getVar('SRCREV_FORMAT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500797 if not format:
Brad Bishop19323692019-04-05 15:28:33 -0400798 raise FetchError("The SRCREV_FORMAT variable must be set when multiple SCMs are used.\n"\
799 "The SCMs are:\n%s" % '\n'.join(scms))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500800
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600801 name_to_rev = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500802 seenautoinc = False
803 for scm in scms:
804 ud = urldata[scm]
805 for name in ud.names:
806 autoinc, rev = getattr(ud.method, method_name)(ud, d, name)
807 seenautoinc = seenautoinc or autoinc
808 if len(rev) > 10:
809 rev = rev[:10]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600810 name_to_rev[name] = rev
811 # Replace names by revisions in the SRCREV_FORMAT string. The approach used
812 # here can handle names being prefixes of other names and names appearing
813 # as substrings in revisions (in which case the name should not be
814 # expanded). The '|' regular expression operator tries matches from left to
815 # right, so we need to sort the names with the longest ones first.
816 names_descending_len = sorted(name_to_rev, key=len, reverse=True)
817 name_to_rev_re = "|".join(re.escape(name) for name in names_descending_len)
818 format = re.sub(name_to_rev_re, lambda match: name_to_rev[match.group(0)], format)
819
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500820 if seenautoinc:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500821 format = "AUTOINC+" + format
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500822
Andrew Geissler5199d832021-09-24 16:47:35 -0500823 d.delVar("__BBINSRCREV")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500824 return format
825
826def localpath(url, d):
827 fetcher = bb.fetch2.Fetch([url], d)
828 return fetcher.localpath(url)
829
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500830# Need to export PATH as binary could be in metadata paths
831# rather than host provided
832# Also include some other variables.
833FETCH_EXPORT_VARS = ['HOME', 'PATH',
834 'HTTP_PROXY', 'http_proxy',
835 'HTTPS_PROXY', 'https_proxy',
836 'FTP_PROXY', 'ftp_proxy',
837 'FTPS_PROXY', 'ftps_proxy',
838 'NO_PROXY', 'no_proxy',
839 'ALL_PROXY', 'all_proxy',
840 'GIT_PROXY_COMMAND',
841 'GIT_SSH',
Patrick Williams03907ee2022-05-01 06:28:52 -0500842 'GIT_SSH_COMMAND',
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500843 'GIT_SSL_CAINFO',
844 'GIT_SMART_HTTP',
845 'SSH_AUTH_SOCK', 'SSH_AGENT_PID',
846 'SOCKS5_USER', 'SOCKS5_PASSWD',
847 'DBUS_SESSION_BUS_ADDRESS',
848 'P4CONFIG',
849 'SSL_CERT_FILE',
Andrew Geissler5199d832021-09-24 16:47:35 -0500850 'AWS_PROFILE',
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500851 'AWS_ACCESS_KEY_ID',
852 'AWS_SECRET_ACCESS_KEY',
853 'AWS_DEFAULT_REGION']
854
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000855def get_fetcher_environment(d):
856 newenv = {}
857 origenv = d.getVar("BB_ORIGENV")
858 for name in bb.fetch2.FETCH_EXPORT_VARS:
859 value = d.getVar(name)
860 if not value and origenv:
861 value = origenv.getVar(name)
862 if value:
863 newenv[name] = value
864 return newenv
865
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600866def runfetchcmd(cmd, d, quiet=False, cleanup=None, log=None, workdir=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500867 """
868 Run cmd returning the command output
869 Raise an error if interrupted or cmd fails
870 Optionally echo command output to stdout
871 Optionally remove the files/directories listed in cleanup upon failure
872 """
873
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500874 exportvars = FETCH_EXPORT_VARS
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500875
876 if not cleanup:
877 cleanup = []
878
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800879 # If PATH contains WORKDIR which contains PV-PR which contains SRCPV we
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500880 # can end up in circular recursion here so give the option of breaking it
881 # in a data store copy.
882 try:
883 d.getVar("PV")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800884 d.getVar("PR")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500885 except bb.data_smart.ExpansionError:
886 d = bb.data.createCopy(d)
887 d.setVar("PV", "fetcheravoidrecurse")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800888 d.setVar("PR", "fetcheravoidrecurse")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500889
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600890 origenv = d.getVar("BB_ORIGENV", False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500891 for var in exportvars:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500892 val = d.getVar(var) or (origenv and origenv.getVar(var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500893 if val:
894 cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
895
Brad Bishop316dfdd2018-06-25 12:45:53 -0400896 # Disable pseudo as it may affect ssh, potentially causing it to hang.
897 cmd = 'export PSEUDO_DISABLED=1; ' + cmd
898
Brad Bishop19323692019-04-05 15:28:33 -0400899 if workdir:
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600900 logger.debug("Running '%s' in %s" % (cmd, workdir))
Brad Bishop19323692019-04-05 15:28:33 -0400901 else:
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600902 logger.debug("Running %s", cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500903
904 success = False
905 error_message = ""
906
907 try:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600908 (output, errors) = bb.process.run(cmd, log=log, shell=True, stderr=subprocess.PIPE, cwd=workdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500909 success = True
910 except bb.process.NotFoundError as e:
Andrew Geisslereff27472021-10-29 15:35:00 -0500911 error_message = "Fetch command %s not found" % (e.command)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500912 except bb.process.ExecutionError as e:
913 if e.stdout:
914 output = "output:\n%s\n%s" % (e.stdout, e.stderr)
915 elif e.stderr:
916 output = "output:\n%s" % e.stderr
917 else:
918 output = "no output"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600919 error_message = "Fetch command %s failed with exit code %s, %s" % (e.command, e.exitcode, output)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500920 except bb.process.CmdError as e:
921 error_message = "Fetch command %s could not be run:\n%s" % (e.command, e.msg)
922 if not success:
923 for f in cleanup:
924 try:
925 bb.utils.remove(f, True)
926 except OSError:
927 pass
928
929 raise FetchError(error_message)
930
931 return output
932
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500933def check_network_access(d, info, url):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500934 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500935 log remote network access, and error if BB_NO_NETWORK is set or the given
936 URI is untrusted
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500937 """
Brad Bishop19323692019-04-05 15:28:33 -0400938 if bb.utils.to_boolean(d.getVar("BB_NO_NETWORK")):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500939 raise NetworkAccess(url, info)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500940 elif not trusted_network(d, url):
941 raise UntrustedUrl(url, info)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500942 else:
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600943 logger.debug("Fetcher accessed the network with the command %s" % info)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500944
945def build_mirroruris(origud, mirrors, ld):
946 uris = []
947 uds = []
948
949 replacements = {}
950 replacements["TYPE"] = origud.type
951 replacements["HOST"] = origud.host
952 replacements["PATH"] = origud.path
953 replacements["BASENAME"] = origud.path.split("/")[-1]
954 replacements["MIRRORNAME"] = origud.host.replace(':','.') + origud.path.replace('/', '.').replace('*', '.')
955
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500956 def adduri(ud, uris, uds, mirrors, tarballs):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500957 for line in mirrors:
958 try:
959 (find, replace) = line
960 except ValueError:
961 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500962
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500963 for tarball in tarballs:
964 newuri = uri_replace(ud, find, replace, replacements, ld, tarball)
965 if not newuri or newuri in uris or newuri == origud.url:
966 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500967
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500968 if not trusted_network(ld, newuri):
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600969 logger.debug("Mirror %s not in the list of trusted networks, skipping" % (newuri))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500970 continue
Patrick Williamsd7e96312015-09-22 08:09:05 -0500971
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500972 # Create a local copy of the mirrors minus the current line
973 # this will prevent us from recursively processing the same line
974 # as well as indirect recursion A -> B -> C -> A
975 localmirrors = list(mirrors)
976 localmirrors.remove(line)
977
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500978 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500979 newud = FetchData(newuri, ld)
980 newud.setup_localpath(ld)
981 except bb.fetch2.BBFetchException as e:
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600982 logger.debug("Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
983 logger.debug(str(e))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500984 try:
985 # setup_localpath of file:// urls may fail, we should still see
986 # if mirrors of the url exist
987 adduri(newud, uris, uds, localmirrors, tarballs)
988 except UnboundLocalError:
989 pass
990 continue
991 uris.append(newuri)
992 uds.append(newud)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500993
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500994 adduri(newud, uris, uds, localmirrors, tarballs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500995
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500996 adduri(origud, uris, uds, mirrors, origud.mirrortarballs or [None])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500997
998 return uris, uds
999
1000def rename_bad_checksum(ud, suffix):
1001 """
1002 Renames files to have suffix from parameter
1003 """
1004
1005 if ud.localpath is None:
1006 return
1007
1008 new_localpath = "%s_bad-checksum_%s" % (ud.localpath, suffix)
1009 bb.warn("Renaming %s to %s" % (ud.localpath, new_localpath))
Brad Bishop79641f22019-09-10 07:20:22 -04001010 if not bb.utils.movefile(ud.localpath, new_localpath):
1011 bb.warn("Renaming %s to %s failed, grep movefile in log.do_fetch to see why" % (ud.localpath, new_localpath))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001012
1013
1014def try_mirror_url(fetch, origud, ud, ld, check = False):
1015 # Return of None or a value means we're finished
1016 # False means try another url
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001017
1018 if ud.lockfile and ud.lockfile != origud.lockfile:
1019 lf = bb.utils.lockfile(ud.lockfile)
1020
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001021 try:
1022 if check:
1023 found = ud.method.checkstatus(fetch, ud, ld)
1024 if found:
1025 return found
1026 return False
1027
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001028 if not verify_donestamp(ud, ld, origud) or ud.method.need_update(ud, ld):
1029 ud.method.download(ud, ld)
1030 if hasattr(ud.method,"build_mirror_data"):
1031 ud.method.build_mirror_data(ud, ld)
1032
1033 if not ud.localpath or not os.path.exists(ud.localpath):
1034 return False
1035
1036 if ud.localpath == origud.localpath:
1037 return ud.localpath
1038
1039 # We may be obtaining a mirror tarball which needs further processing by the real fetcher
1040 # If that tarball is a local file:// we need to provide a symlink to it
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001041 dldir = ld.getVar("DL_DIR")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001042
1043 if origud.mirrortarballs and os.path.basename(ud.localpath) in origud.mirrortarballs and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001044 # Create donestamp in old format to avoid triggering a re-download
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001045 if ud.donestamp:
1046 bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
1047 open(ud.donestamp, 'w').close()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001048 dest = os.path.join(dldir, os.path.basename(ud.localpath))
1049 if not os.path.exists(dest):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001050 # In case this is executing without any file locks held (as is
1051 # the case for file:// URLs), two tasks may end up here at the
1052 # same time, in which case we do not want the second task to
1053 # fail when the link has already been created by the first task.
1054 try:
1055 os.symlink(ud.localpath, dest)
1056 except FileExistsError:
1057 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001058 if not verify_donestamp(origud, ld) or origud.method.need_update(origud, ld):
1059 origud.method.download(origud, ld)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001060 if hasattr(origud.method, "build_mirror_data"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001061 origud.method.build_mirror_data(origud, ld)
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001062 return origud.localpath
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001063 # Otherwise the result is a local file:// and we symlink to it
Andrew Geissler09209ee2020-12-13 08:44:15 -06001064 ensure_symlink(ud.localpath, origud.localpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001065 update_stamp(origud, ld)
1066 return ud.localpath
1067
1068 except bb.fetch2.NetworkAccess:
1069 raise
1070
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001071 except IOError as e:
Brad Bishop19323692019-04-05 15:28:33 -04001072 if e.errno in [errno.ESTALE]:
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001073 logger.warning("Stale Error Observed %s." % ud.url)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001074 return False
1075 raise
1076
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001077 except bb.fetch2.BBFetchException as e:
1078 if isinstance(e, ChecksumError):
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001079 logger.warning("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (ud.url, origud.url))
1080 logger.warning(str(e))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001081 if os.path.exists(ud.localpath):
1082 rename_bad_checksum(ud, e.checksum)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001083 elif isinstance(e, NoChecksumError):
1084 raise
1085 else:
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001086 logger.debug("Mirror fetch failure for url %s (original url: %s)" % (ud.url, origud.url))
1087 logger.debug(str(e))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001088 try:
1089 ud.method.clean(ud, ld)
1090 except UnboundLocalError:
1091 pass
1092 return False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001093 finally:
1094 if ud.lockfile and ud.lockfile != origud.lockfile:
1095 bb.utils.unlockfile(lf)
1096
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001097
Andrew Geissler09209ee2020-12-13 08:44:15 -06001098def ensure_symlink(target, link_name):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001099 if not os.path.exists(link_name):
1100 if os.path.islink(link_name):
1101 # Broken symbolic link
1102 os.unlink(link_name)
1103
1104 # In case this is executing without any file locks held (as is
1105 # the case for file:// URLs), two tasks may end up here at the
1106 # same time, in which case we do not want the second task to
1107 # fail when the link has already been created by the first task.
1108 try:
1109 os.symlink(target, link_name)
1110 except FileExistsError:
1111 pass
1112
1113
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001114def try_mirrors(fetch, d, origud, mirrors, check = False):
1115 """
1116 Try to use a mirrored version of the sources.
1117 This method will be automatically called before the fetchers go.
1118
1119 d Is a bb.data instance
1120 uri is the original uri we're trying to download
1121 mirrors is the list of mirrors we're going to try
1122 """
1123 ld = d.createCopy()
1124
1125 uris, uds = build_mirroruris(origud, mirrors, ld)
1126
1127 for index, uri in enumerate(uris):
1128 ret = try_mirror_url(fetch, origud, uds[index], ld, check)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001129 if ret:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001130 return ret
1131 return None
1132
1133def trusted_network(d, url):
1134 """
1135 Use a trusted url during download if networking is enabled and
1136 BB_ALLOWED_NETWORKS is set globally or for a specific recipe.
1137 Note: modifies SRC_URI & mirrors.
1138 """
Brad Bishop19323692019-04-05 15:28:33 -04001139 if bb.utils.to_boolean(d.getVar("BB_NO_NETWORK")):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001140 return True
1141
1142 pkgname = d.expand(d.getVar('PN', False))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001143 trusted_hosts = None
1144 if pkgname:
1145 trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname, False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001146
1147 if not trusted_hosts:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001148 trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001149
1150 # Not enabled.
1151 if not trusted_hosts:
1152 return True
1153
1154 scheme, network, path, user, passwd, param = decodeurl(url)
1155
1156 if not network:
1157 return True
1158
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001159 network = network.split(':')[0]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001160 network = network.lower()
1161
1162 for host in trusted_hosts.split(" "):
1163 host = host.lower()
1164 if host.startswith("*.") and ("." + network).endswith(host[1:]):
1165 return True
1166 if host == network:
1167 return True
1168
1169 return False
1170
1171def srcrev_internal_helper(ud, d, name):
1172 """
1173 Return:
1174 a) a source revision if specified
1175 b) latest revision if SRCREV="AUTOINC"
1176 c) None if not specified
1177 """
1178
1179 srcrev = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001180 pn = d.getVar("PN")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001181 attempts = []
1182 if name != '' and pn:
Patrick Williams213cb262021-08-07 19:21:33 -05001183 attempts.append("SRCREV_%s:pn-%s" % (name, pn))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001184 if name != '':
1185 attempts.append("SRCREV_%s" % name)
1186 if pn:
Patrick Williams213cb262021-08-07 19:21:33 -05001187 attempts.append("SRCREV:pn-%s" % pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001188 attempts.append("SRCREV")
1189
1190 for a in attempts:
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001191 srcrev = d.getVar(a)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001192 if srcrev and srcrev != "INVALID":
1193 break
1194
1195 if 'rev' in ud.parm and 'tag' in ud.parm:
1196 raise FetchError("Please specify a ;rev= parameter or a ;tag= parameter in the url %s but not both." % (ud.url))
1197
1198 if 'rev' in ud.parm or 'tag' in ud.parm:
1199 if 'rev' in ud.parm:
1200 parmrev = ud.parm['rev']
1201 else:
1202 parmrev = ud.parm['tag']
1203 if srcrev == "INVALID" or not srcrev:
1204 return parmrev
1205 if srcrev != parmrev:
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001206 raise FetchError("Conflicting revisions (%s from SRCREV and %s from the url) found, please specify one valid value" % (srcrev, parmrev))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001207 return parmrev
1208
1209 if srcrev == "INVALID" or not srcrev:
1210 raise FetchError("Please set a valid SRCREV for url %s (possible key names are %s, or use a ;rev=X URL parameter)" % (str(attempts), ud.url), ud.url)
1211 if srcrev == "AUTOINC":
1212 srcrev = ud.method.latest_revision(ud, d, name)
1213
1214 return srcrev
1215
1216def get_checksum_file_list(d):
1217 """ Get a list of files checksum in SRC_URI
1218
1219 Returns the resolved local paths of all local file entries in
1220 SRC_URI as a space-separated string
1221 """
1222 fetch = Fetch([], d, cache = False, localonly = True)
1223
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001224 dl_dir = d.getVar('DL_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001225 filelist = []
1226 for u in fetch.urls:
1227 ud = fetch.ud[u]
1228
1229 if ud and isinstance(ud.method, local.Local):
1230 paths = ud.method.localpaths(ud, d)
1231 for f in paths:
1232 pth = ud.decodedurl
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001233 if f.startswith(dl_dir):
1234 # The local fetcher's behaviour is to return a path under DL_DIR if it couldn't find the file anywhere else
1235 if os.path.exists(f):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001236 bb.warn("Getting checksum for %s SRC_URI entry %s: file not found except in DL_DIR" % (d.getVar('PN'), os.path.basename(f)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001237 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001238 bb.warn("Unable to get checksum for %s SRC_URI entry %s: file could not be found" % (d.getVar('PN'), os.path.basename(f)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001239 filelist.append(f + ":" + str(os.path.exists(f)))
1240
1241 return " ".join(filelist)
1242
Andrew Geissler82c905d2020-04-13 13:39:40 -05001243def get_file_checksums(filelist, pn, localdirsexclude):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001244 """Get a list of the checksums for a list of local files
1245
1246 Returns the checksums for a list of local files, caching the results as
1247 it proceeds
1248
1249 """
Andrew Geissler82c905d2020-04-13 13:39:40 -05001250 return _checksum_cache.get_checksums(filelist, pn, localdirsexclude)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001251
1252
1253class FetchData(object):
1254 """
1255 A class which represents the fetcher state for a given URI.
1256 """
1257 def __init__(self, url, d, localonly = False):
1258 # localpath is the location of a downloaded result. If not set, the file is local.
1259 self.donestamp = None
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001260 self.needdonestamp = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001261 self.localfile = ""
1262 self.localpath = None
1263 self.lockfile = None
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001264 self.mirrortarballs = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001265 self.basename = None
1266 self.basepath = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001267 (self.type, self.host, self.path, self.user, self.pswd, self.parm) = decodeurl(d.expand(url))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001268 self.date = self.getSRCDate(d)
1269 self.url = url
1270 if not self.user and "user" in self.parm:
1271 self.user = self.parm["user"]
1272 if not self.pswd and "pswd" in self.parm:
1273 self.pswd = self.parm["pswd"]
1274 self.setup = False
1275
Andrew Geissler82c905d2020-04-13 13:39:40 -05001276 def configure_checksum(checksum_id):
1277 if "name" in self.parm:
1278 checksum_name = "%s.%ssum" % (self.parm["name"], checksum_id)
1279 else:
1280 checksum_name = "%ssum" % checksum_id
1281
1282 setattr(self, "%s_name" % checksum_id, checksum_name)
1283
1284 if checksum_name in self.parm:
1285 checksum_expected = self.parm[checksum_name]
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001286 elif self.type not in ["http", "https", "ftp", "ftps", "sftp", "s3", "az"]:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001287 checksum_expected = None
1288 else:
1289 checksum_expected = d.getVarFlag("SRC_URI", checksum_name)
1290
1291 setattr(self, "%s_expected" % checksum_id, checksum_expected)
1292
1293 for checksum_id in CHECKSUM_LIST:
1294 configure_checksum(checksum_id)
1295
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001296 self.ignore_checksums = False
1297
1298 self.names = self.parm.get("name",'default').split(',')
1299
1300 self.method = None
1301 for m in methods:
1302 if m.supports(self, d):
1303 self.method = m
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001304 break
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001305
1306 if not self.method:
1307 raise NoMethodError(url)
1308
1309 if localonly and not isinstance(self.method, local.Local):
1310 raise NonLocalMethod()
1311
1312 if self.parm.get("proto", None) and "protocol" not in self.parm:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001313 logger.warning('Consider updating %s recipe to use "protocol" not "proto" in SRC_URI.', d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001314 self.parm["protocol"] = self.parm.get("proto", None)
1315
1316 if hasattr(self.method, "urldata_init"):
1317 self.method.urldata_init(self, d)
1318
1319 if "localpath" in self.parm:
1320 # if user sets localpath for file, use it instead.
1321 self.localpath = self.parm["localpath"]
1322 self.basename = os.path.basename(self.localpath)
1323 elif self.localfile:
1324 self.localpath = self.method.localpath(self, d)
1325
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001326 dldir = d.getVar("DL_DIR")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001327
1328 if not self.needdonestamp:
1329 return
1330
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001331 # Note: .done and .lock files should always be in DL_DIR whereas localpath may not be.
1332 if self.localpath and self.localpath.startswith(dldir):
1333 basepath = self.localpath
1334 elif self.localpath:
1335 basepath = dldir + os.sep + os.path.basename(self.localpath)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001336 elif self.basepath or self.basename:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001337 basepath = dldir + os.sep + (self.basepath or self.basename)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001338 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001339 bb.fatal("Can't determine lock path for url %s" % url)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001340
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001341 self.donestamp = basepath + '.done'
1342 self.lockfile = basepath + '.lock'
1343
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001344 def setup_revisions(self, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001345 self.revisions = {}
1346 for name in self.names:
1347 self.revisions[name] = srcrev_internal_helper(self, d, name)
1348
1349 # add compatibility code for non name specified case
1350 if len(self.names) == 1:
1351 self.revision = self.revisions[self.names[0]]
1352
1353 def setup_localpath(self, d):
1354 if not self.localpath:
1355 self.localpath = self.method.localpath(self, d)
1356
1357 def getSRCDate(self, d):
1358 """
1359 Return the SRC Date for the component
1360
1361 d the bb.data module
1362 """
1363 if "srcdate" in self.parm:
1364 return self.parm['srcdate']
1365
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001366 pn = d.getVar("PN")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001367
1368 if pn:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001369 return d.getVar("SRCDATE_%s" % pn) or d.getVar("SRCDATE") or d.getVar("DATE")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001370
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001371 return d.getVar("SRCDATE") or d.getVar("DATE")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001372
1373class FetchMethod(object):
1374 """Base class for 'fetch'ing data"""
1375
1376 def __init__(self, urls=None):
1377 self.urls = []
1378
1379 def supports(self, urldata, d):
1380 """
1381 Check to see if this fetch class supports a given url.
1382 """
1383 return 0
1384
1385 def localpath(self, urldata, d):
1386 """
1387 Return the local filename of a given url assuming a successful fetch.
1388 Can also setup variables in urldata for use in go (saving code duplication
1389 and duplicate code execution)
1390 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001391 return os.path.join(d.getVar("DL_DIR"), urldata.localfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001392
1393 def supports_checksum(self, urldata):
1394 """
1395 Is localpath something that can be represented by a checksum?
1396 """
1397
1398 # We cannot compute checksums for directories
Andrew Geissler82c905d2020-04-13 13:39:40 -05001399 if os.path.isdir(urldata.localpath):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001400 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001401 return True
1402
1403 def recommends_checksum(self, urldata):
1404 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001405 Is the backend on where checksumming is recommended (should warnings
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001406 be displayed if there is no checksum)?
1407 """
1408 return False
1409
Andrew Geissler82c905d2020-04-13 13:39:40 -05001410 def verify_donestamp(self, ud, d):
1411 """
1412 Verify the donestamp file
1413 """
1414 return verify_donestamp(ud, d)
1415
1416 def update_donestamp(self, ud, d):
1417 """
1418 Update the donestamp file
1419 """
1420 update_stamp(ud, d)
1421
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001422 def _strip_leading_slashes(self, relpath):
1423 """
1424 Remove leading slash as os.path.join can't cope
1425 """
1426 while os.path.isabs(relpath):
1427 relpath = relpath[1:]
1428 return relpath
1429
1430 def setUrls(self, urls):
1431 self.__urls = urls
1432
1433 def getUrls(self):
1434 return self.__urls
1435
1436 urls = property(getUrls, setUrls, None, "Urls property")
1437
1438 def need_update(self, ud, d):
1439 """
1440 Force a fetch, even if localpath exists?
1441 """
1442 if os.path.exists(ud.localpath):
1443 return False
1444 return True
1445
1446 def supports_srcrev(self):
1447 """
1448 The fetcher supports auto source revisions (SRCREV)
1449 """
1450 return False
1451
1452 def download(self, urldata, d):
1453 """
1454 Fetch urls
1455 Assumes localpath was called first
1456 """
Brad Bishop19323692019-04-05 15:28:33 -04001457 raise NoMethodError(urldata.url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001458
1459 def unpack(self, urldata, rootdir, data):
1460 iterate = False
1461 file = urldata.localpath
1462
1463 try:
1464 unpack = bb.utils.to_boolean(urldata.parm.get('unpack'), True)
1465 except ValueError as exc:
1466 bb.fatal("Invalid value for 'unpack' parameter for %s: %s" %
1467 (file, urldata.parm.get('unpack')))
1468
1469 base, ext = os.path.splitext(file)
1470 if ext in ['.gz', '.bz2', '.Z', '.xz', '.lz']:
1471 efile = os.path.join(rootdir, os.path.basename(base))
1472 else:
1473 efile = file
1474 cmd = None
1475
1476 if unpack:
Andrew Geissler595f6302022-01-24 19:11:47 +00001477 tar_cmd = 'tar --extract --no-same-owner'
1478 if 'striplevel' in urldata.parm:
1479 tar_cmd += ' --strip-components=%s' % urldata.parm['striplevel']
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001480 if file.endswith('.tar'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001481 cmd = '%s -f %s' % (tar_cmd, file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001482 elif file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001483 cmd = '%s -z -f %s' % (tar_cmd, file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001484 elif file.endswith('.tbz') or file.endswith('.tbz2') or file.endswith('.tar.bz2'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001485 cmd = 'bzip2 -dc %s | %s -f -' % (file, tar_cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001486 elif file.endswith('.gz') or file.endswith('.Z') or file.endswith('.z'):
1487 cmd = 'gzip -dc %s > %s' % (file, efile)
1488 elif file.endswith('.bz2'):
1489 cmd = 'bzip2 -dc %s > %s' % (file, efile)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001490 elif file.endswith('.txz') or file.endswith('.tar.xz'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001491 cmd = 'xz -dc %s | %s -f -' % (file, tar_cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001492 elif file.endswith('.xz'):
1493 cmd = 'xz -dc %s > %s' % (file, efile)
1494 elif file.endswith('.tar.lz'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001495 cmd = 'lzip -dc %s | %s -f -' % (file, tar_cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001496 elif file.endswith('.lz'):
1497 cmd = 'lzip -dc %s > %s' % (file, efile)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001498 elif file.endswith('.tar.7z'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001499 cmd = '7z x -so %s | %s -f -' % (file, tar_cmd)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001500 elif file.endswith('.7z'):
1501 cmd = '7za x -y %s 1>/dev/null' % file
Andrew Geissler6ce62a22020-11-30 19:58:47 -06001502 elif file.endswith('.tzst') or file.endswith('.tar.zst'):
Andrew Geissler595f6302022-01-24 19:11:47 +00001503 cmd = 'zstd --decompress --stdout %s | %s -f -' % (file, tar_cmd)
Andrew Geissler6ce62a22020-11-30 19:58:47 -06001504 elif file.endswith('.zst'):
1505 cmd = 'zstd --decompress --stdout %s > %s' % (file, efile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001506 elif file.endswith('.zip') or file.endswith('.jar'):
1507 try:
1508 dos = bb.utils.to_boolean(urldata.parm.get('dos'), False)
1509 except ValueError as exc:
1510 bb.fatal("Invalid value for 'dos' parameter for %s: %s" %
1511 (file, urldata.parm.get('dos')))
1512 cmd = 'unzip -q -o'
1513 if dos:
1514 cmd = '%s -a' % cmd
1515 cmd = "%s '%s'" % (cmd, file)
1516 elif file.endswith('.rpm') or file.endswith('.srpm'):
1517 if 'extract' in urldata.parm:
1518 unpack_file = urldata.parm.get('extract')
1519 cmd = 'rpm2cpio.sh %s | cpio -id %s' % (file, unpack_file)
1520 iterate = True
1521 iterate_file = unpack_file
1522 else:
1523 cmd = 'rpm2cpio.sh %s | cpio -id' % (file)
1524 elif file.endswith('.deb') or file.endswith('.ipk'):
Brad Bishopa5c52ff2018-11-23 10:55:50 +13001525 output = subprocess.check_output(['ar', '-t', file], preexec_fn=subprocess_setup)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001526 datafile = None
1527 if output:
1528 for line in output.decode().splitlines():
1529 if line.startswith('data.tar.'):
1530 datafile = line
1531 break
1532 else:
1533 raise UnpackError("Unable to unpack deb/ipk package - does not contain data.tar.* file", urldata.url)
1534 else:
1535 raise UnpackError("Unable to unpack deb/ipk package - could not list contents", urldata.url)
Andrew Geissler595f6302022-01-24 19:11:47 +00001536 cmd = 'ar x %s %s && %s -p -f %s && rm %s' % (file, datafile, tar_cmd, datafile, datafile)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001537
1538 # If 'subdir' param exists, create a dir and use it as destination for unpack cmd
1539 if 'subdir' in urldata.parm:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001540 subdir = urldata.parm.get('subdir')
1541 if os.path.isabs(subdir):
1542 if not os.path.realpath(subdir).startswith(os.path.realpath(rootdir)):
1543 raise UnpackError("subdir argument isn't a subdirectory of unpack root %s" % rootdir, urldata.url)
1544 unpackdir = subdir
1545 else:
1546 unpackdir = os.path.join(rootdir, subdir)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001547 bb.utils.mkdirhier(unpackdir)
1548 else:
1549 unpackdir = rootdir
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001550
1551 if not unpack or not cmd:
1552 # If file == dest, then avoid any copies, as we already put the file into dest!
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001553 dest = os.path.join(unpackdir, os.path.basename(file))
1554 if file != dest and not (os.path.exists(dest) and os.path.samefile(file, dest)):
1555 destdir = '.'
1556 # For file:// entries all intermediate dirs in path must be created at destination
1557 if urldata.type == "file":
1558 # Trailing '/' does a copying to wrong place
1559 urlpath = urldata.path.rstrip('/')
1560 # Want files places relative to cwd so no leading '/'
1561 urlpath = urlpath.lstrip('/')
1562 if urlpath.find("/") != -1:
1563 destdir = urlpath.rsplit("/", 1)[0] + '/'
1564 bb.utils.mkdirhier("%s/%s" % (unpackdir, destdir))
Andrew Geisslerc3d88e42020-10-02 09:45:00 -05001565 cmd = 'cp -fpPRH "%s" "%s"' % (file, destdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001566
1567 if not cmd:
1568 return
1569
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001570 path = data.getVar('PATH')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001571 if path:
1572 cmd = "PATH=\"%s\" %s" % (path, cmd)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001573 bb.note("Unpacking %s to %s/" % (file, unpackdir))
1574 ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True, cwd=unpackdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001575
1576 if ret != 0:
1577 raise UnpackError("Unpack command %s failed with return value %s" % (cmd, ret), urldata.url)
1578
1579 if iterate is True:
1580 iterate_urldata = urldata
1581 iterate_urldata.localpath = "%s/%s" % (rootdir, iterate_file)
1582 self.unpack(urldata, rootdir, data)
1583
1584 return
1585
1586 def clean(self, urldata, d):
1587 """
1588 Clean any existing full or partial download
1589 """
1590 bb.utils.remove(urldata.localpath)
1591
1592 def try_premirror(self, urldata, d):
1593 """
1594 Should premirrors be used?
1595 """
1596 return True
1597
Andrew Geissler82c905d2020-04-13 13:39:40 -05001598 def try_mirrors(self, fetch, urldata, d, mirrors, check=False):
1599 """
1600 Try to use a mirror
1601 """
1602 return bool(try_mirrors(fetch, d, urldata, mirrors, check))
1603
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001604 def checkstatus(self, fetch, urldata, d):
1605 """
1606 Check the status of a URL
1607 Assumes localpath was called first
1608 """
Brad Bishop19323692019-04-05 15:28:33 -04001609 logger.info("URL %s could not be checked for status since no method exists.", urldata.url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001610 return True
1611
1612 def latest_revision(self, ud, d, name):
1613 """
1614 Look in the cache for the latest revision, if not present ask the SCM.
1615 """
1616 if not hasattr(self, "_latest_revision"):
Brad Bishop19323692019-04-05 15:28:33 -04001617 raise ParameterError("The fetcher for this URL does not support _latest_revision", ud.url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001618
1619 revs = bb.persist_data.persist('BB_URI_HEADREVS', d)
1620 key = self.generate_revision_key(ud, d, name)
1621 try:
1622 return revs[key]
1623 except KeyError:
1624 revs[key] = rev = self._latest_revision(ud, d, name)
1625 return rev
1626
1627 def sortable_revision(self, ud, d, name):
1628 latest_rev = self._build_revision(ud, d, name)
1629 return True, str(latest_rev)
1630
1631 def generate_revision_key(self, ud, d, name):
Andrew Geissler82c905d2020-04-13 13:39:40 -05001632 return self._revision_key(ud, d, name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001633
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001634 def latest_versionstring(self, ud, d):
1635 """
1636 Compute the latest release name like "x.y.x" in "x.y.x+gitHASH"
1637 by searching through the tags output of ls-remote, comparing
1638 versions and returning the highest match as a (version, revision) pair.
1639 """
1640 return ('', '')
1641
Andrew Geissler82c905d2020-04-13 13:39:40 -05001642 def done(self, ud, d):
1643 """
1644 Is the download done ?
1645 """
1646 if os.path.exists(ud.localpath):
1647 return True
Andrew Geissler82c905d2020-04-13 13:39:40 -05001648 return False
1649
Andrew Geissler4ed12e12020-06-05 18:00:41 -05001650 def implicit_urldata(self, ud, d):
1651 """
1652 Get a list of FetchData objects for any implicit URLs that will also
1653 be downloaded when we fetch the given URL.
1654 """
1655 return []
1656
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001657class Fetch(object):
1658 def __init__(self, urls, d, cache = True, localonly = False, connection_cache = None):
1659 if localonly and cache:
1660 raise Exception("bb.fetch2.Fetch.__init__: cannot set cache and localonly at same time")
1661
Andrew Geissler595f6302022-01-24 19:11:47 +00001662 if not urls:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001663 urls = d.getVar("SRC_URI").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001664 self.urls = urls
1665 self.d = d
1666 self.ud = {}
1667 self.connection_cache = connection_cache
1668
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001669 fn = d.getVar('FILE')
1670 mc = d.getVar('__BBMULTICONFIG') or ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001671 key = None
1672 if cache and fn:
1673 key = mc + fn + str(id(d))
1674 if key in urldata_cache:
1675 self.ud = urldata_cache[key]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001676
1677 for url in urls:
1678 if url not in self.ud:
1679 try:
1680 self.ud[url] = FetchData(url, d, localonly)
1681 except NonLocalMethod:
1682 if localonly:
1683 self.ud[url] = None
1684 pass
1685
Andrew Geissler82c905d2020-04-13 13:39:40 -05001686 if key:
1687 urldata_cache[key] = self.ud
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001688
1689 def localpath(self, url):
1690 if url not in self.urls:
1691 self.ud[url] = FetchData(url, self.d)
1692
1693 self.ud[url].setup_localpath(self.d)
1694 return self.d.expand(self.ud[url].localpath)
1695
1696 def localpaths(self):
1697 """
1698 Return a list of the local filenames, assuming successful fetch
1699 """
1700 local = []
1701
1702 for u in self.urls:
1703 ud = self.ud[u]
1704 ud.setup_localpath(self.d)
1705 local.append(ud.localpath)
1706
1707 return local
1708
1709 def download(self, urls=None):
1710 """
1711 Fetch all urls
1712 """
1713 if not urls:
1714 urls = self.urls
1715
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001716 network = self.d.getVar("BB_NO_NETWORK")
Brad Bishop19323692019-04-05 15:28:33 -04001717 premirroronly = bb.utils.to_boolean(self.d.getVar("BB_FETCH_PREMIRRORONLY"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001718
1719 for u in urls:
1720 ud = self.ud[u]
1721 ud.setup_localpath(self.d)
1722 m = ud.method
Andrew Geissler82c905d2020-04-13 13:39:40 -05001723 done = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001724
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001725 if ud.lockfile:
1726 lf = bb.utils.lockfile(ud.lockfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001727
1728 try:
1729 self.d.setVar("BB_NO_NETWORK", network)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001730
Andrew Geissler82c905d2020-04-13 13:39:40 -05001731 if m.verify_donestamp(ud, self.d) and not m.need_update(ud, self.d):
1732 done = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001733 elif m.try_premirror(ud, self.d):
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001734 logger.debug("Trying PREMIRRORS")
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001735 mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001736 done = m.try_mirrors(self, ud, self.d, mirrors)
1737 if done:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001738 try:
1739 # early checksum verification so that if the checksum of the premirror
1740 # contents mismatch the fetcher can still try upstream and mirrors
Andrew Geissler82c905d2020-04-13 13:39:40 -05001741 m.update_donestamp(ud, self.d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001742 except ChecksumError as e:
1743 logger.warning("Checksum failure encountered with premirror download of %s - will attempt other sources." % u)
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001744 logger.debug(str(e))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001745 done = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001746
1747 if premirroronly:
1748 self.d.setVar("BB_NO_NETWORK", "1")
1749
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001750 firsterr = None
Andrew Geisslereff27472021-10-29 15:35:00 -05001751 verified_stamp = False
1752 if done:
1753 verified_stamp = m.verify_donestamp(ud, self.d)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001754 if not done and (not verified_stamp or m.need_update(ud, self.d)):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001755 try:
1756 if not trusted_network(self.d, ud.url):
1757 raise UntrustedUrl(ud.url)
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001758 logger.debug("Trying Upstream")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001759 m.download(ud, self.d)
1760 if hasattr(m, "build_mirror_data"):
1761 m.build_mirror_data(ud, self.d)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001762 done = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001763 # early checksum verify, so that if checksum mismatched,
1764 # fetcher still have chance to fetch from mirror
Andrew Geissler82c905d2020-04-13 13:39:40 -05001765 m.update_donestamp(ud, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001766
1767 except bb.fetch2.NetworkAccess:
1768 raise
1769
1770 except BBFetchException as e:
1771 if isinstance(e, ChecksumError):
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001772 logger.warning("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001773 logger.debug(str(e))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001774 if os.path.exists(ud.localpath):
1775 rename_bad_checksum(ud, e.checksum)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001776 elif isinstance(e, NoChecksumError):
1777 raise
1778 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001779 logger.warning('Failed to fetch URL %s, attempting MIRRORS if available' % u)
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001780 logger.debug(str(e))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001781 firsterr = e
1782 # Remove any incomplete fetch
1783 if not verified_stamp:
1784 m.clean(ud, self.d)
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001785 logger.debug("Trying MIRRORS")
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001786 mirrors = mirror_from_string(self.d.getVar('MIRRORS'))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001787 done = m.try_mirrors(self, ud, self.d, mirrors)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001788
Andrew Geissler82c905d2020-04-13 13:39:40 -05001789 if not done or not m.done(ud, self.d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001790 if firsterr:
1791 logger.error(str(firsterr))
1792 raise FetchError("Unable to fetch URL from any source.", u)
1793
Andrew Geissler82c905d2020-04-13 13:39:40 -05001794 m.update_donestamp(ud, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001795
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001796 except IOError as e:
Brad Bishop19323692019-04-05 15:28:33 -04001797 if e.errno in [errno.ESTALE]:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001798 logger.error("Stale Error Observed %s." % u)
1799 raise ChecksumError("Stale Error Detected")
1800
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001801 except BBFetchException as e:
1802 if isinstance(e, ChecksumError):
1803 logger.error("Checksum failure fetching %s" % u)
1804 raise
1805
1806 finally:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001807 if ud.lockfile:
1808 bb.utils.unlockfile(lf)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001809
1810 def checkstatus(self, urls=None):
1811 """
Andrew Geisslereff27472021-10-29 15:35:00 -05001812 Check all URLs exist upstream.
1813
1814 Returns None if the URLs exist, raises FetchError if the check wasn't
1815 successful but there wasn't an error (such as file not found), and
1816 raises other exceptions in error cases.
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001817 """
1818
1819 if not urls:
1820 urls = self.urls
1821
1822 for u in urls:
1823 ud = self.ud[u]
1824 ud.setup_localpath(self.d)
1825 m = ud.method
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001826 logger.debug("Testing URL %s", u)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001827 # First try checking uri, u, from PREMIRRORS
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001828 mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001829 ret = m.try_mirrors(self, ud, self.d, mirrors, True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001830 if not ret:
1831 # Next try checking from the original uri, u
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001832 ret = m.checkstatus(self, ud, self.d)
1833 if not ret:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001834 # Finally, try checking uri, u, from MIRRORS
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001835 mirrors = mirror_from_string(self.d.getVar('MIRRORS'))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001836 ret = m.try_mirrors(self, ud, self.d, mirrors, True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001837
1838 if not ret:
1839 raise FetchError("URL %s doesn't work" % u, u)
1840
1841 def unpack(self, root, urls=None):
1842 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001843 Unpack urls to root
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001844 """
1845
1846 if not urls:
1847 urls = self.urls
1848
1849 for u in urls:
1850 ud = self.ud[u]
1851 ud.setup_localpath(self.d)
1852
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001853 if ud.lockfile:
1854 lf = bb.utils.lockfile(ud.lockfile)
1855
1856 ud.method.unpack(ud, root, self.d)
1857
1858 if ud.lockfile:
1859 bb.utils.unlockfile(lf)
1860
1861 def clean(self, urls=None):
1862 """
1863 Clean files that the fetcher gets or places
1864 """
1865
1866 if not urls:
1867 urls = self.urls
1868
1869 for url in urls:
1870 if url not in self.ud:
Brad Bishop19323692019-04-05 15:28:33 -04001871 self.ud[url] = FetchData(url, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001872 ud = self.ud[url]
1873 ud.setup_localpath(self.d)
1874
1875 if not ud.localfile and ud.localpath is None:
1876 continue
1877
1878 if ud.lockfile:
1879 lf = bb.utils.lockfile(ud.lockfile)
1880
1881 ud.method.clean(ud, self.d)
1882 if ud.donestamp:
1883 bb.utils.remove(ud.donestamp)
1884
1885 if ud.lockfile:
1886 bb.utils.unlockfile(lf)
1887
Andrew Geissler4ed12e12020-06-05 18:00:41 -05001888 def expanded_urldata(self, urls=None):
1889 """
1890 Get an expanded list of FetchData objects covering both the given
1891 URLS and any additional implicit URLs that are added automatically by
1892 the appropriate FetchMethod.
1893 """
1894
1895 if not urls:
1896 urls = self.urls
1897
1898 urldata = []
1899 for url in urls:
1900 ud = self.ud[url]
1901 urldata.append(ud)
1902 urldata += ud.method.implicit_urldata(ud, self.d)
1903
1904 return urldata
1905
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001906class FetchConnectionCache(object):
1907 """
1908 A class which represents an container for socket connections.
1909 """
1910 def __init__(self):
1911 self.cache = {}
1912
1913 def get_connection_name(self, host, port):
1914 return host + ':' + str(port)
1915
1916 def add_connection(self, host, port, connection):
1917 cn = self.get_connection_name(host, port)
1918
1919 if cn not in self.cache:
1920 self.cache[cn] = connection
1921
1922 def get_connection(self, host, port):
1923 connection = None
1924
1925 cn = self.get_connection_name(host, port)
1926 if cn in self.cache:
1927 connection = self.cache[cn]
1928
1929 return connection
1930
1931 def remove_connection(self, host, port):
1932 cn = self.get_connection_name(host, port)
1933 if cn in self.cache:
1934 self.cache[cn].close()
1935 del self.cache[cn]
1936
1937 def close_connections(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001938 for cn in list(self.cache.keys()):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001939 self.cache[cn].close()
1940 del self.cache[cn]
1941
1942from . import cvs
1943from . import git
1944from . import gitsm
1945from . import gitannex
1946from . import local
1947from . import svn
1948from . import wget
1949from . import ssh
1950from . import sftp
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001951from . import s3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001952from . import perforce
1953from . import bzr
1954from . import hg
1955from . import osc
1956from . import repo
1957from . import clearcase
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001958from . import npm
Andrew Geissler82c905d2020-04-13 13:39:40 -05001959from . import npmsw
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001960from . import az
Andrew Geissler595f6302022-01-24 19:11:47 +00001961from . import crate
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001962
1963methods.append(local.Local())
1964methods.append(wget.Wget())
1965methods.append(svn.Svn())
1966methods.append(git.Git())
1967methods.append(gitsm.GitSM())
1968methods.append(gitannex.GitANNEX())
1969methods.append(cvs.Cvs())
1970methods.append(ssh.SSH())
1971methods.append(sftp.SFTP())
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001972methods.append(s3.S3())
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001973methods.append(perforce.Perforce())
1974methods.append(bzr.Bzr())
1975methods.append(hg.Hg())
1976methods.append(osc.Osc())
1977methods.append(repo.Repo())
1978methods.append(clearcase.ClearCase())
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001979methods.append(npm.Npm())
Andrew Geissler82c905d2020-04-13 13:39:40 -05001980methods.append(npmsw.NpmShrinkWrap())
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001981methods.append(az.Az())
Andrew Geissler595f6302022-01-24 19:11:47 +00001982methods.append(crate.Crate())