__init__.py 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144
  1. """
  2. BitBake 'Fetch' implementations
  3. Classes for obtaining upstream sources for the
  4. BitBake build tools.
  5. """
  6. # Copyright (C) 2003, 2004 Chris Larson
  7. # Copyright (C) 2012 Intel Corporation
  8. #
  9. # SPDX-License-Identifier: GPL-2.0-only
  10. #
  11. # Based on functions from the base bb module, Copyright 2003 Holger Schurig
  12. import os, re
  13. import signal
  14. import logging
  15. import urllib.request, urllib.parse, urllib.error
  16. if 'git' not in urllib.parse.uses_netloc:
  17. urllib.parse.uses_netloc.append('git')
  18. import operator
  19. import collections
  20. import subprocess
  21. import pickle
  22. import errno
  23. import bb.utils
  24. import bb.checksum
  25. import bb.process
  26. import bb.event
  27. __version__ = "2"
  28. _checksum_cache = bb.checksum.FileChecksumCache()
  29. _revisions_cache = bb.checksum.RevisionsCache()
  30. logger = logging.getLogger("BitBake.Fetcher")
  31. CHECKSUM_LIST = [ "goh1", "md5", "sha256", "sha1", "sha384", "sha512" ]
  32. SHOWN_CHECKSUM_LIST = ["sha256"]
  33. class BBFetchException(Exception):
  34. """Class all fetch exceptions inherit from"""
  35. def __init__(self, message):
  36. self.msg = message
  37. Exception.__init__(self, message)
  38. def __str__(self):
  39. return self.msg
  40. class UntrustedUrl(BBFetchException):
  41. """Exception raised when encountering a host not listed in BB_ALLOWED_NETWORKS"""
  42. def __init__(self, url, message=''):
  43. if message:
  44. msg = message
  45. else:
  46. msg = "The URL: '%s' is not trusted and cannot be used" % url
  47. self.url = url
  48. BBFetchException.__init__(self, msg)
  49. self.args = (url,)
  50. class MalformedUrl(BBFetchException):
  51. """Exception raised when encountering an invalid url"""
  52. def __init__(self, url, message=''):
  53. if message:
  54. msg = message
  55. else:
  56. msg = "The URL: '%s' is invalid and cannot be interpreted" % url
  57. self.url = url
  58. BBFetchException.__init__(self, msg)
  59. self.args = (url,)
  60. class FetchError(BBFetchException):
  61. """General fetcher exception when something happens incorrectly"""
  62. def __init__(self, message, url = None):
  63. if url:
  64. msg = "Fetcher failure for URL: '%s'. %s" % (url, message)
  65. else:
  66. msg = "Fetcher failure: %s" % message
  67. self.url = url
  68. BBFetchException.__init__(self, msg)
  69. self.args = (message, url)
  70. class ChecksumError(FetchError):
  71. """Exception when mismatched checksum encountered"""
  72. def __init__(self, message, url = None, checksum = None):
  73. self.checksum = checksum
  74. FetchError.__init__(self, message, url)
  75. class NoChecksumError(FetchError):
  76. """Exception when no checksum is specified, but BB_STRICT_CHECKSUM is set"""
  77. class UnpackError(BBFetchException):
  78. """General fetcher exception when something happens incorrectly when unpacking"""
  79. def __init__(self, message, url):
  80. msg = "Unpack failure for URL: '%s'. %s" % (url, message)
  81. self.url = url
  82. BBFetchException.__init__(self, msg)
  83. self.args = (message, url)
  84. class NoMethodError(BBFetchException):
  85. """Exception raised when there is no method to obtain a supplied url or set of urls"""
  86. def __init__(self, url):
  87. msg = "Could not find a fetcher which supports the URL: '%s'" % url
  88. self.url = url
  89. BBFetchException.__init__(self, msg)
  90. self.args = (url,)
  91. class MissingParameterError(BBFetchException):
  92. """Exception raised when a fetch method is missing a critical parameter in the url"""
  93. def __init__(self, missing, url):
  94. msg = "URL: '%s' is missing the required parameter '%s'" % (url, missing)
  95. self.url = url
  96. self.missing = missing
  97. BBFetchException.__init__(self, msg)
  98. self.args = (missing, url)
  99. class ParameterError(BBFetchException):
  100. """Exception raised when a url cannot be processed due to invalid parameters."""
  101. def __init__(self, message, url):
  102. msg = "URL: '%s' has invalid parameters. %s" % (url, message)
  103. self.url = url
  104. BBFetchException.__init__(self, msg)
  105. self.args = (message, url)
  106. class NetworkAccess(BBFetchException):
  107. """Exception raised when network access is disabled but it is required."""
  108. def __init__(self, url, cmd):
  109. 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)
  110. self.url = url
  111. self.cmd = cmd
  112. BBFetchException.__init__(self, msg)
  113. self.args = (url, cmd)
  114. class NonLocalMethod(Exception):
  115. def __init__(self):
  116. Exception.__init__(self)
  117. class MissingChecksumEvent(bb.event.Event):
  118. def __init__(self, url, **checksums):
  119. self.url = url
  120. self.checksums = checksums
  121. bb.event.Event.__init__(self)
  122. class URI(object):
  123. """
  124. A class representing a generic URI, with methods for
  125. accessing the URI components, and stringifies to the
  126. URI.
  127. It is constructed by calling it with a URI, or setting
  128. the attributes manually:
  129. uri = URI("http://example.com/")
  130. uri = URI()
  131. uri.scheme = 'http'
  132. uri.hostname = 'example.com'
  133. uri.path = '/'
  134. It has the following attributes:
  135. * scheme (read/write)
  136. * userinfo (authentication information) (read/write)
  137. * username (read/write)
  138. * password (read/write)
  139. Note, password is deprecated as of RFC 3986.
  140. * hostname (read/write)
  141. * port (read/write)
  142. * hostport (read only)
  143. "hostname:port", if both are set, otherwise just "hostname"
  144. * path (read/write)
  145. * path_quoted (read/write)
  146. A URI quoted version of path
  147. * params (dict) (read/write)
  148. * query (dict) (read/write)
  149. * relative (bool) (read only)
  150. True if this is a "relative URI", (e.g. file:foo.diff)
  151. It stringifies to the URI itself.
  152. Some notes about relative URIs: while it's specified that
  153. a URI beginning with <scheme>:// should either be directly
  154. followed by a hostname or a /, the old URI handling of the
  155. fetch2 library did not conform to this. Therefore, this URI
  156. class has some kludges to make sure that URIs are parsed in
  157. a way comforming to bitbake's current usage. This URI class
  158. supports the following:
  159. file:relative/path.diff (IETF compliant)
  160. git:relative/path.git (IETF compliant)
  161. git:///absolute/path.git (IETF compliant)
  162. file:///absolute/path.diff (IETF compliant)
  163. file://relative/path.diff (not IETF compliant)
  164. But it does not support the following:
  165. file://hostname/absolute/path.diff (would be IETF compliant)
  166. Note that the last case only applies to a list of
  167. explicitly allowed schemes (currently only file://), that requires
  168. its URIs to not have a network location.
  169. """
  170. _relative_schemes = ['file', 'git']
  171. _netloc_forbidden = ['file']
  172. def __init__(self, uri=None):
  173. self.scheme = ''
  174. self.userinfo = ''
  175. self.hostname = ''
  176. self.port = None
  177. self._path = ''
  178. self.params = {}
  179. self.query = {}
  180. self.relative = False
  181. if not uri:
  182. return
  183. # We hijack the URL parameters, since the way bitbake uses
  184. # them are not quite RFC compliant.
  185. uri, param_str = (uri.split(";", 1) + [None])[:2]
  186. urlp = urllib.parse.urlparse(uri)
  187. self.scheme = urlp.scheme
  188. reparse = 0
  189. # Coerce urlparse to make URI scheme use netloc
  190. if not self.scheme in urllib.parse.uses_netloc:
  191. urllib.parse.uses_params.append(self.scheme)
  192. reparse = 1
  193. # Make urlparse happy(/ier) by converting local resources
  194. # to RFC compliant URL format. E.g.:
  195. # file://foo.diff -> file:foo.diff
  196. if urlp.scheme in self._netloc_forbidden:
  197. uri = re.sub(r"(?<=:)//(?!/)", "", uri, count=1)
  198. reparse = 1
  199. if reparse:
  200. urlp = urllib.parse.urlparse(uri)
  201. # Identify if the URI is relative or not
  202. if urlp.scheme in self._relative_schemes and \
  203. re.compile(r"^\w+:(?!//)").match(uri):
  204. self.relative = True
  205. if not self.relative:
  206. self.hostname = urlp.hostname or ''
  207. self.port = urlp.port
  208. self.userinfo += urlp.username or ''
  209. if urlp.password:
  210. self.userinfo += ':%s' % urlp.password
  211. self.path = urllib.parse.unquote(urlp.path)
  212. if param_str:
  213. self.params = self._param_str_split(param_str, ";")
  214. if urlp.query:
  215. self.query = self._param_str_split(urlp.query, "&")
  216. def __str__(self):
  217. userinfo = self.userinfo
  218. if userinfo:
  219. userinfo += '@'
  220. return "%s:%s%s%s%s%s%s" % (
  221. self.scheme,
  222. '' if self.relative else '//',
  223. userinfo,
  224. self.hostport,
  225. self.path_quoted,
  226. self._query_str(),
  227. self._param_str())
  228. def _param_str(self):
  229. return (
  230. ''.join([';', self._param_str_join(self.params, ";")])
  231. if self.params else '')
  232. def _query_str(self):
  233. return (
  234. ''.join(['?', self._param_str_join(self.query, "&")])
  235. if self.query else '')
  236. def _param_str_split(self, string, elmdelim, kvdelim="="):
  237. ret = collections.OrderedDict()
  238. for k, v in [x.split(kvdelim, 1) if kvdelim in x else (x, None) for x in string.split(elmdelim) if x]:
  239. ret[k] = v
  240. return ret
  241. def _param_str_join(self, dict_, elmdelim, kvdelim="="):
  242. return elmdelim.join([kvdelim.join([k, v]) if v else k for k, v in dict_.items()])
  243. @property
  244. def hostport(self):
  245. if not self.port:
  246. return self.hostname
  247. return "%s:%d" % (self.hostname, self.port)
  248. @property
  249. def path_quoted(self):
  250. return urllib.parse.quote(self.path)
  251. @path_quoted.setter
  252. def path_quoted(self, path):
  253. self.path = urllib.parse.unquote(path)
  254. @property
  255. def path(self):
  256. return self._path
  257. @path.setter
  258. def path(self, path):
  259. self._path = path
  260. if not path or re.compile("^/").match(path):
  261. self.relative = False
  262. else:
  263. self.relative = True
  264. @property
  265. def username(self):
  266. if self.userinfo:
  267. return (self.userinfo.split(":", 1))[0]
  268. return ''
  269. @username.setter
  270. def username(self, username):
  271. password = self.password
  272. self.userinfo = username
  273. if password:
  274. self.userinfo += ":%s" % password
  275. @property
  276. def password(self):
  277. if self.userinfo and ":" in self.userinfo:
  278. return (self.userinfo.split(":", 1))[1]
  279. return ''
  280. @password.setter
  281. def password(self, password):
  282. self.userinfo = "%s:%s" % (self.username, password)
  283. def decodeurl(url):
  284. """Decodes an URL into the tokens (scheme, network location, path,
  285. user, password, parameters).
  286. """
  287. uri = URI(url)
  288. path = uri.path if uri.path else "/"
  289. return uri.scheme, uri.hostport, path, uri.username, uri.password, uri.params
  290. def decodemirrorurl(url):
  291. """Decodes a mirror URL into the tokens (scheme, network location, path,
  292. user, password, parameters).
  293. """
  294. m = re.compile('(?P<type>[^:]*)://((?P<user>[^/;]+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
  295. if not m:
  296. raise MalformedUrl(url)
  297. type = m.group('type')
  298. location = m.group('location')
  299. if not location:
  300. raise MalformedUrl(url)
  301. user = m.group('user')
  302. parm = m.group('parm')
  303. locidx = location.find('/')
  304. if locidx != -1 and type.lower() != 'file':
  305. host = location[:locidx]
  306. path = location[locidx:]
  307. elif type.lower() == 'file':
  308. host = ""
  309. path = location
  310. if user:
  311. path = user + '@' + path
  312. user = ""
  313. else:
  314. host = location
  315. path = "/"
  316. if user:
  317. m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
  318. if m:
  319. user = m.group('user')
  320. pswd = m.group('pswd')
  321. else:
  322. user = ''
  323. pswd = ''
  324. p = collections.OrderedDict()
  325. if parm:
  326. for s in parm.split(';'):
  327. if s:
  328. if not '=' in s:
  329. raise MalformedUrl(url, "The URL: '%s' is invalid: parameter %s does not specify a value (missing '=')" % (url, s))
  330. s1, s2 = s.split('=', 1)
  331. p[s1] = s2
  332. return type, host, urllib.parse.unquote(path), user, pswd, p
  333. def encodeurl(decoded):
  334. """Encodes a URL from tokens (scheme, network location, path,
  335. user, password, parameters).
  336. """
  337. type, host, path, user, pswd, p = decoded
  338. if not type:
  339. raise MissingParameterError('type', "encoded from the data %s" % str(decoded))
  340. uri = URI()
  341. uri.scheme = type
  342. if user and type != "file":
  343. uri.username = user
  344. if pswd:
  345. uri.password = pswd
  346. if host and type != "file":
  347. uri.hostname = host
  348. if path:
  349. # Standardise path to ensure comparisons work
  350. while '//' in path:
  351. path = path.replace("//", "/")
  352. uri.path = path
  353. if type == "file":
  354. # Use old not IETF compliant style
  355. uri.relative = False
  356. if p:
  357. uri.params = p
  358. return str(uri)
  359. def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
  360. if not ud.url or not uri_find or not uri_replace:
  361. logger.error("uri_replace: passed an undefined value, not replacing")
  362. return None
  363. uri_decoded = list(decodemirrorurl(ud.url))
  364. uri_find_decoded = list(decodemirrorurl(uri_find))
  365. uri_replace_decoded = list(decodemirrorurl(uri_replace))
  366. logger.debug2("For url %s comparing %s to %s" % (uri_decoded, uri_find_decoded, uri_replace_decoded))
  367. result_decoded = ['', '', '', '', '', {}]
  368. # 0 - type, 1 - host, 2 - path, 3 - user, 4- pswd, 5 - params
  369. for loc, i in enumerate(uri_find_decoded):
  370. result_decoded[loc] = uri_decoded[loc]
  371. regexp = i
  372. if loc == 0 and regexp and not regexp.endswith("$"):
  373. # Leaving the type unanchored can mean "https" matching "file" can become "files"
  374. # which is clearly undesirable.
  375. regexp += "$"
  376. if loc == 5:
  377. # Handle URL parameters
  378. if i:
  379. # Any specified URL parameters must match
  380. for k in uri_find_decoded[loc]:
  381. if uri_decoded[loc][k] != uri_find_decoded[loc][k]:
  382. return None
  383. # Overwrite any specified replacement parameters
  384. for k in uri_replace_decoded[loc]:
  385. for l in replacements:
  386. uri_replace_decoded[loc][k] = uri_replace_decoded[loc][k].replace(l, replacements[l])
  387. result_decoded[loc][k] = uri_replace_decoded[loc][k]
  388. elif (loc == 3 or loc == 4) and uri_replace_decoded[loc]:
  389. # User/password in the replacement is just a straight replacement
  390. result_decoded[loc] = uri_replace_decoded[loc]
  391. elif (re.match(regexp, uri_decoded[loc])):
  392. if not uri_replace_decoded[loc]:
  393. result_decoded[loc] = ""
  394. else:
  395. for k in replacements:
  396. uri_replace_decoded[loc] = uri_replace_decoded[loc].replace(k, replacements[k])
  397. #bb.note("%s %s %s" % (regexp, uri_replace_decoded[loc], uri_decoded[loc]))
  398. result_decoded[loc] = re.sub(regexp, uri_replace_decoded[loc], uri_decoded[loc], count=1)
  399. if loc == 2:
  400. # Handle path manipulations
  401. basename = None
  402. if uri_decoded[0] != uri_replace_decoded[0] and mirrortarball:
  403. # If the source and destination url types differ, must be a mirrortarball mapping
  404. basename = os.path.basename(mirrortarball)
  405. # Kill parameters, they make no sense for mirror tarballs
  406. uri_decoded[5] = {}
  407. uri_find_decoded[5] = {}
  408. elif ud.localpath and ud.method.supports_checksum(ud):
  409. basename = os.path.basename(ud.localpath)
  410. if basename:
  411. uri_basename = os.path.basename(uri_decoded[loc])
  412. # Prefix with a slash as a sentinel in case
  413. # result_decoded[loc] does not contain one.
  414. path = "/" + result_decoded[loc]
  415. if uri_basename and basename != uri_basename and path.endswith("/" + uri_basename):
  416. result_decoded[loc] = path[1:-len(uri_basename)] + basename
  417. elif not path.endswith("/" + basename):
  418. result_decoded[loc] = os.path.join(path[1:], basename)
  419. else:
  420. return None
  421. result = encodeurl(result_decoded)
  422. if result == ud.url:
  423. return None
  424. logger.debug2("For url %s returning %s" % (ud.url, result))
  425. return result
  426. methods = []
  427. urldata_cache = {}
  428. saved_headrevs = {}
  429. def fetcher_init(d, servercontext=True):
  430. """
  431. Called to initialize the fetchers once the configuration data is known.
  432. Calls before this must not hit the cache.
  433. """
  434. _checksum_cache.init_cache(d.getVar("BB_CACHEDIR"))
  435. _revisions_cache.init_cache(d.getVar("BB_CACHEDIR"))
  436. if not servercontext:
  437. return
  438. try:
  439. # fetcher_init is called multiple times, so make sure we only save the
  440. # revs the first time it is called.
  441. if not bb.fetch2.saved_headrevs:
  442. bb.fetch2.saved_headrevs = _revisions_cache.get_revs()
  443. except:
  444. pass
  445. # When to drop SCM head revisions controlled by user policy
  446. srcrev_policy = d.getVar('BB_SRCREV_POLICY') or "clear"
  447. if srcrev_policy == "cache":
  448. logger.debug("Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
  449. elif srcrev_policy == "clear":
  450. logger.debug("Clearing SRCREV cache due to cache policy of: %s", srcrev_policy)
  451. _revisions_cache.clear_cache()
  452. else:
  453. raise FetchError("Invalid SRCREV cache policy of: %s" % srcrev_policy)
  454. for m in methods:
  455. if hasattr(m, "init"):
  456. m.init(d)
  457. def fetcher_parse_save():
  458. _checksum_cache.save_extras()
  459. _revisions_cache.save_extras()
  460. def fetcher_parse_done():
  461. _checksum_cache.save_merge()
  462. _revisions_cache.save_merge()
  463. def fetcher_compare_revisions(d):
  464. """
  465. Compare the revisions in the persistent cache with the saved values from
  466. when bitbake was started and return true if they have changed.
  467. """
  468. headrevs = _revisions_cache.get_revs()
  469. return headrevs != bb.fetch2.saved_headrevs
  470. def mirror_from_string(data):
  471. mirrors = (data or "").replace('\\n',' ').split()
  472. # Split into pairs
  473. if len(mirrors) % 2 != 0:
  474. bb.warn('Invalid mirror data %s, should have paired members.' % data)
  475. return list(zip(*[iter(mirrors)]*2))
  476. def verify_checksum(ud, d, precomputed={}, localpath=None, fatal_nochecksum=True):
  477. """
  478. verify the MD5 and SHA256 checksum for downloaded src
  479. Raises a FetchError if one or both of the SRC_URI checksums do not match
  480. the downloaded file, or if BB_STRICT_CHECKSUM is set and there are no
  481. checksums specified.
  482. Returns a dict of checksums that can be stored in a done stamp file and
  483. passed in as precomputed parameter in a later call to avoid re-computing
  484. the checksums from the file. This allows verifying the checksums of the
  485. file against those in the recipe each time, rather than only after
  486. downloading. See https://bugzilla.yoctoproject.org/show_bug.cgi?id=5571.
  487. """
  488. if ud.ignore_checksums or not ud.method.supports_checksum(ud):
  489. return {}
  490. if localpath is None:
  491. localpath = ud.localpath
  492. def compute_checksum_info(checksum_id):
  493. checksum_name = getattr(ud, "%s_name" % checksum_id)
  494. if checksum_id in precomputed:
  495. checksum_data = precomputed[checksum_id]
  496. else:
  497. checksum_data = getattr(bb.utils, "%s_file" % checksum_id)(localpath)
  498. checksum_expected = getattr(ud, "%s_expected" % checksum_id)
  499. if checksum_expected == '':
  500. checksum_expected = None
  501. return {
  502. "id": checksum_id,
  503. "name": checksum_name,
  504. "data": checksum_data,
  505. "expected": checksum_expected
  506. }
  507. checksum_infos = []
  508. for checksum_id in CHECKSUM_LIST:
  509. checksum_infos.append(compute_checksum_info(checksum_id))
  510. checksum_dict = {ci["id"] : ci["data"] for ci in checksum_infos}
  511. checksum_event = {"%ssum" % ci["id"] : ci["data"] for ci in checksum_infos}
  512. for ci in checksum_infos:
  513. if ci["id"] in SHOWN_CHECKSUM_LIST:
  514. checksum_lines = ["SRC_URI[%s] = \"%s\"" % (ci["name"], ci["data"])]
  515. # If no checksum has been provided
  516. if fatal_nochecksum and ud.method.recommends_checksum(ud) and all(ci["expected"] is None for ci in checksum_infos):
  517. messages = []
  518. strict = d.getVar("BB_STRICT_CHECKSUM") or "0"
  519. # If strict checking enabled and neither sum defined, raise error
  520. if strict == "1":
  521. raise NoChecksumError("\n".join(checksum_lines))
  522. bb.event.fire(MissingChecksumEvent(ud.url, **checksum_event), d)
  523. if strict == "ignore":
  524. return checksum_dict
  525. # Log missing sums so user can more easily add them
  526. messages.append("Missing checksum for '%s', consider adding at " \
  527. "least one to the recipe:" % ud.localpath)
  528. messages.extend(checksum_lines)
  529. logger.warning("\n".join(messages))
  530. # We want to alert the user if a checksum is defined in the recipe but
  531. # it does not match.
  532. messages = []
  533. messages.append("Checksum mismatch!")
  534. bad_checksum = None
  535. for ci in checksum_infos:
  536. if ci["expected"] and ci["expected"] != ci["data"]:
  537. messages.append("File: '%s' has %s checksum '%s' when '%s' was " \
  538. "expected" % (localpath, ci["id"], ci["data"], ci["expected"]))
  539. bad_checksum = ci["data"]
  540. if bad_checksum:
  541. messages.append("If this change is expected (e.g. you have upgraded " \
  542. "to a new version without updating the checksums) " \
  543. "then you can use these lines within the recipe:")
  544. messages.extend(checksum_lines)
  545. messages.append("Otherwise you should retry the download and/or " \
  546. "check with upstream to determine if the file has " \
  547. "become corrupted or otherwise unexpectedly modified.")
  548. raise ChecksumError("\n".join(messages), ud.url, bad_checksum)
  549. return checksum_dict
  550. def verify_donestamp(ud, d, origud=None):
  551. """
  552. Check whether the done stamp file has the right checksums (if the fetch
  553. method supports them). If it doesn't, delete the done stamp and force
  554. a re-download.
  555. Returns True, if the donestamp exists and is valid, False otherwise. When
  556. returning False, any existing done stamps are removed.
  557. """
  558. if not ud.needdonestamp or (origud and not origud.needdonestamp):
  559. return True
  560. if not os.path.exists(ud.localpath):
  561. # local path does not exist
  562. if os.path.exists(ud.donestamp):
  563. # done stamp exists, but the downloaded file does not; the done stamp
  564. # must be incorrect, re-trigger the download
  565. bb.utils.remove(ud.donestamp)
  566. return False
  567. if (not ud.method.supports_checksum(ud) or
  568. (origud and not origud.method.supports_checksum(origud))):
  569. # if done stamp exists and checksums not supported; assume the local
  570. # file is current
  571. return os.path.exists(ud.donestamp)
  572. precomputed_checksums = {}
  573. # Only re-use the precomputed checksums if the donestamp is newer than the
  574. # file. Do not rely on the mtime of directories, though. If ud.localpath is
  575. # a directory, there will probably not be any checksums anyway.
  576. if os.path.exists(ud.donestamp) and (os.path.isdir(ud.localpath) or
  577. os.path.getmtime(ud.localpath) < os.path.getmtime(ud.donestamp)):
  578. try:
  579. with open(ud.donestamp, "rb") as cachefile:
  580. pickled = pickle.Unpickler(cachefile)
  581. precomputed_checksums.update(pickled.load())
  582. except Exception as e:
  583. # Avoid the warnings on the upgrade path from emtpy done stamp
  584. # files to those containing the checksums.
  585. if not isinstance(e, EOFError):
  586. # Ignore errors, they aren't fatal
  587. logger.warning("Couldn't load checksums from donestamp %s: %s "
  588. "(msg: %s)" % (ud.donestamp, type(e).__name__,
  589. str(e)))
  590. try:
  591. checksums = verify_checksum(ud, d, precomputed_checksums)
  592. # If the cache file did not have the checksums, compute and store them
  593. # as an upgrade path from the previous done stamp file format.
  594. if checksums != precomputed_checksums:
  595. with open(ud.donestamp, "wb") as cachefile:
  596. p = pickle.Pickler(cachefile, 2)
  597. p.dump(checksums)
  598. return True
  599. except ChecksumError as e:
  600. # Checksums failed to verify, trigger re-download and remove the
  601. # incorrect stamp file.
  602. logger.warning("Checksum mismatch for local file %s\n"
  603. "Cleaning and trying again." % ud.localpath)
  604. if os.path.exists(ud.localpath):
  605. rename_bad_checksum(ud, e.checksum)
  606. bb.utils.remove(ud.donestamp)
  607. return False
  608. def update_stamp(ud, d):
  609. """
  610. donestamp is file stamp indicating the whole fetching is done
  611. this function update the stamp after verifying the checksum
  612. """
  613. if not ud.needdonestamp:
  614. return
  615. if os.path.exists(ud.donestamp):
  616. # Touch the done stamp file to show active use of the download
  617. try:
  618. os.utime(ud.donestamp, None)
  619. except:
  620. # Errors aren't fatal here
  621. pass
  622. else:
  623. try:
  624. checksums = verify_checksum(ud, d)
  625. # Store the checksums for later re-verification against the recipe
  626. with open(ud.donestamp, "wb") as cachefile:
  627. p = pickle.Pickler(cachefile, 2)
  628. p.dump(checksums)
  629. except ChecksumError as e:
  630. # Checksums failed to verify, trigger re-download and remove the
  631. # incorrect stamp file.
  632. logger.warning("Checksum mismatch for local file %s\n"
  633. "Cleaning and trying again." % ud.localpath)
  634. if os.path.exists(ud.localpath):
  635. rename_bad_checksum(ud, e.checksum)
  636. bb.utils.remove(ud.donestamp)
  637. raise
  638. def subprocess_setup():
  639. # Python installs a SIGPIPE handler by default. This is usually not what
  640. # non-Python subprocesses expect.
  641. # SIGPIPE errors are known issues with gzip/bash
  642. signal.signal(signal.SIGPIPE, signal.SIG_DFL)
  643. def mark_recipe_nocache(d):
  644. if d.getVar('BB_SRCREV_POLICY') != "cache":
  645. d.setVar('BB_DONT_CACHE', '1')
  646. def get_autorev(d):
  647. mark_recipe_nocache(d)
  648. d.setVar("__BBAUTOREV_SEEN", True)
  649. return "AUTOINC"
  650. def _get_srcrev(d, method_name='sortable_revision'):
  651. """
  652. Return the revision string, usually for use in the version string (PV) of the current package
  653. Most packages usually only have one SCM so we just pass on the call.
  654. In the multi SCM case, we build a value based on SRCREV_FORMAT which must
  655. have been set.
  656. The idea here is that we put the string "AUTOINC+" into return value if the revisions are not
  657. incremental, other code is then responsible for turning that into an increasing value (if needed)
  658. A method_name can be supplied to retrieve an alternatively formatted revision from a fetcher, if
  659. that fetcher provides a method with the given name and the same signature as sortable_revision.
  660. """
  661. d.setVar("__BBSRCREV_SEEN", "1")
  662. recursion = d.getVar("__BBINSRCREV")
  663. if recursion:
  664. raise FetchError("There are recursive references in fetcher variables, likely through SRC_URI")
  665. d.setVar("__BBINSRCREV", True)
  666. scms = []
  667. revs = []
  668. fetcher = Fetch(d.getVar('SRC_URI').split(), d)
  669. urldata = fetcher.ud
  670. for u in urldata:
  671. if urldata[u].method.supports_srcrev():
  672. scms.append(u)
  673. if not scms:
  674. d.delVar("__BBINSRCREV")
  675. return "", revs
  676. if len(scms) == 1:
  677. autoinc, rev = getattr(urldata[scms[0]].method, method_name)(urldata[scms[0]], d, urldata[scms[0]].name)
  678. revs.append(rev)
  679. if len(rev) > 10:
  680. rev = rev[:10]
  681. d.delVar("__BBINSRCREV")
  682. if autoinc:
  683. return "AUTOINC+" + rev, revs
  684. return rev, revs
  685. #
  686. # Mutiple SCMs are in SRC_URI so we resort to SRCREV_FORMAT
  687. #
  688. format = d.getVar('SRCREV_FORMAT')
  689. if not format:
  690. raise FetchError("The SRCREV_FORMAT variable must be set when multiple SCMs are used.\n"\
  691. "The SCMs are:\n%s" % '\n'.join(scms))
  692. name_to_rev = {}
  693. seenautoinc = False
  694. for scm in scms:
  695. ud = urldata[scm]
  696. autoinc, rev = getattr(ud.method, method_name)(ud, d, ud.name)
  697. revs.append(rev)
  698. seenautoinc = seenautoinc or autoinc
  699. if len(rev) > 10:
  700. rev = rev[:10]
  701. name_to_rev[ud.name] = rev
  702. # Replace names by revisions in the SRCREV_FORMAT string. The approach used
  703. # here can handle names being prefixes of other names and names appearing
  704. # as substrings in revisions (in which case the name should not be
  705. # expanded). The '|' regular expression operator tries matches from left to
  706. # right, so we need to sort the names with the longest ones first.
  707. names_descending_len = sorted(name_to_rev, key=len, reverse=True)
  708. name_to_rev_re = "|".join(re.escape(name) for name in names_descending_len)
  709. format = re.sub(name_to_rev_re, lambda match: name_to_rev[match.group(0)], format)
  710. if seenautoinc:
  711. format = "AUTOINC+" + format
  712. d.delVar("__BBINSRCREV")
  713. return format, revs
  714. def get_hashvalue(d, method_name='sortable_revision'):
  715. pkgv, revs = _get_srcrev(d, method_name=method_name)
  716. return " ".join(revs)
  717. def get_pkgv_string(d, method_name='sortable_revision'):
  718. pkgv, revs = _get_srcrev(d, method_name=method_name)
  719. return pkgv
  720. def get_srcrev(d, method_name='sortable_revision'):
  721. pkgv, revs = _get_srcrev(d, method_name=method_name)
  722. if not pkgv:
  723. raise FetchError("SRCREV was used yet no valid SCM was found in SRC_URI")
  724. return pkgv
  725. def localpath(url, d):
  726. fetcher = bb.fetch2.Fetch([url], d)
  727. return fetcher.localpath(url)
  728. # Need to export PATH as binary could be in metadata paths
  729. # rather than host provided
  730. # Also include some other variables.
  731. FETCH_EXPORT_VARS = ['HOME', 'PATH',
  732. 'HTTP_PROXY', 'http_proxy',
  733. 'HTTPS_PROXY', 'https_proxy',
  734. 'FTP_PROXY', 'ftp_proxy',
  735. 'FTPS_PROXY', 'ftps_proxy',
  736. 'NO_PROXY', 'no_proxy',
  737. 'ALL_PROXY', 'all_proxy',
  738. 'GIT_PROXY_COMMAND',
  739. 'GIT_SSH',
  740. 'GIT_SSH_COMMAND',
  741. 'GIT_SSL_CAINFO',
  742. 'GIT_SMART_HTTP',
  743. 'SSH_AUTH_SOCK', 'SSH_AGENT_PID',
  744. 'SOCKS5_USER', 'SOCKS5_PASSWD',
  745. 'DBUS_SESSION_BUS_ADDRESS',
  746. 'P4CONFIG',
  747. 'SSL_CERT_FILE',
  748. 'NODE_EXTRA_CA_CERTS',
  749. 'AWS_PROFILE',
  750. 'AWS_ACCESS_KEY_ID',
  751. 'AWS_SECRET_ACCESS_KEY',
  752. 'AWS_ROLE_ARN',
  753. 'AWS_WEB_IDENTITY_TOKEN_FILE',
  754. 'AWS_DEFAULT_REGION',
  755. 'AWS_SESSION_TOKEN',
  756. 'GIT_CACHE_PATH',
  757. 'REMOTE_CONTAINERS_IPC',
  758. 'GITHUB_TOKEN',
  759. 'SSL_CERT_DIR']
  760. def get_fetcher_environment(d):
  761. newenv = {}
  762. origenv = d.getVar("BB_ORIGENV")
  763. for name in bb.fetch2.FETCH_EXPORT_VARS:
  764. value = d.getVar(name)
  765. if not value and origenv:
  766. value = origenv.getVar(name)
  767. if value:
  768. newenv[name] = value
  769. return newenv
  770. def runfetchcmd(cmd, d, quiet=False, cleanup=None, log=None, workdir=None):
  771. """
  772. Run cmd returning the command output
  773. Raise an error if interrupted or cmd fails
  774. Optionally echo command output to stdout
  775. Optionally remove the files/directories listed in cleanup upon failure
  776. """
  777. exportvars = FETCH_EXPORT_VARS
  778. if not cleanup:
  779. cleanup = []
  780. # If PATH contains WORKDIR which contains PV-PR which contains SRCPV we
  781. # can end up in circular recursion here so give the option of breaking it
  782. # in a data store copy.
  783. try:
  784. d.getVar("PV")
  785. d.getVar("PR")
  786. except bb.data_smart.ExpansionError:
  787. d = bb.data.createCopy(d)
  788. d.setVar("PV", "fetcheravoidrecurse")
  789. d.setVar("PR", "fetcheravoidrecurse")
  790. origenv = d.getVar("BB_ORIGENV", False)
  791. for var in exportvars:
  792. val = d.getVar(var) or (origenv and origenv.getVar(var))
  793. if val:
  794. cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
  795. # Disable pseudo as it may affect ssh, potentially causing it to hang.
  796. cmd = 'export PSEUDO_DISABLED=1; ' + cmd
  797. if workdir:
  798. logger.debug("Running '%s' in %s" % (cmd, workdir))
  799. else:
  800. logger.debug("Running %s", cmd)
  801. success = False
  802. error_message = ""
  803. try:
  804. (output, errors) = bb.process.run(cmd, log=log, shell=True, stderr=subprocess.PIPE, cwd=workdir)
  805. success = True
  806. except bb.process.NotFoundError as e:
  807. error_message = "Fetch command %s not found" % (e.command)
  808. except bb.process.ExecutionError as e:
  809. if e.stdout:
  810. output = "output:\n%s\n%s" % (e.stdout, e.stderr)
  811. elif e.stderr:
  812. output = "output:\n%s" % e.stderr
  813. else:
  814. if log:
  815. output = "see logfile for output"
  816. else:
  817. output = "no output"
  818. error_message = "Fetch command %s failed with exit code %s, %s" % (e.command, e.exitcode, output)
  819. except bb.process.CmdError as e:
  820. error_message = "Fetch command %s could not be run:\n%s" % (e.command, e.msg)
  821. if not success:
  822. for f in cleanup:
  823. try:
  824. bb.utils.remove(f, True)
  825. except OSError:
  826. pass
  827. raise FetchError(error_message)
  828. return output
  829. def check_network_access(d, info, url):
  830. """
  831. log remote network access, and error if BB_NO_NETWORK is set or the given
  832. URI is untrusted
  833. """
  834. if bb.utils.to_boolean(d.getVar("BB_NO_NETWORK")):
  835. raise NetworkAccess(url, info)
  836. elif not trusted_network(d, url):
  837. raise UntrustedUrl(url, info)
  838. else:
  839. logger.debug("Fetcher accessed the network with the command %s" % info)
  840. def build_mirroruris(origud, mirrors, ld):
  841. uris = []
  842. uds = []
  843. replacements = {}
  844. replacements["TYPE"] = origud.type
  845. replacements["HOST"] = origud.host
  846. replacements["PATH"] = origud.path
  847. replacements["BASENAME"] = origud.path.split("/")[-1]
  848. replacements["MIRRORNAME"] = origud.host.replace(':','.') + origud.path.replace('/', '.').replace('*', '.')
  849. def adduri(ud, uris, uds, mirrors, tarballs):
  850. for line in mirrors:
  851. try:
  852. (find, replace) = line
  853. except ValueError:
  854. continue
  855. for tarball in tarballs:
  856. newuri = uri_replace(ud, find, replace, replacements, ld, tarball)
  857. if not newuri or newuri in uris or newuri == origud.url:
  858. continue
  859. if not trusted_network(ld, newuri):
  860. logger.debug("Mirror %s not in the list of trusted networks, skipping" % (newuri))
  861. continue
  862. # Create a local copy of the mirrors minus the current line
  863. # this will prevent us from recursively processing the same line
  864. # as well as indirect recursion A -> B -> C -> A
  865. localmirrors = list(mirrors)
  866. localmirrors.remove(line)
  867. try:
  868. newud = FetchData(newuri, ld)
  869. newud.ignore_checksums = True
  870. newud.setup_localpath(ld)
  871. except bb.fetch2.BBFetchException as e:
  872. logger.debug("Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
  873. logger.debug(str(e))
  874. try:
  875. # setup_localpath of file:// urls may fail, we should still see
  876. # if mirrors of the url exist
  877. adduri(newud, uris, uds, localmirrors, tarballs)
  878. except UnboundLocalError:
  879. pass
  880. continue
  881. uris.append(newuri)
  882. uds.append(newud)
  883. adduri(newud, uris, uds, localmirrors, tarballs)
  884. adduri(origud, uris, uds, mirrors, origud.mirrortarballs or [None])
  885. return uris, uds
  886. def rename_bad_checksum(ud, suffix):
  887. """
  888. Renames files to have suffix from parameter
  889. """
  890. if ud.localpath is None:
  891. return
  892. new_localpath = "%s_bad-checksum_%s" % (ud.localpath, suffix)
  893. bb.warn("Renaming %s to %s" % (ud.localpath, new_localpath))
  894. if not bb.utils.movefile(ud.localpath, new_localpath):
  895. bb.warn("Renaming %s to %s failed, grep movefile in log.do_fetch to see why" % (ud.localpath, new_localpath))
  896. def try_mirror_url(fetch, origud, ud, ld, check = False):
  897. # Return of None or a value means we're finished
  898. # False means try another url
  899. if ud.lockfile and ud.lockfile != origud.lockfile:
  900. lf = bb.utils.lockfile(ud.lockfile)
  901. try:
  902. if check:
  903. found = ud.method.checkstatus(fetch, ud, ld)
  904. if found:
  905. return found
  906. return False
  907. if not verify_donestamp(ud, ld, origud) or ud.method.need_update(ud, ld):
  908. ud.method.download(ud, ld)
  909. if hasattr(ud.method,"build_mirror_data"):
  910. ud.method.build_mirror_data(ud, ld)
  911. if not ud.localpath or not os.path.exists(ud.localpath):
  912. return False
  913. if ud.localpath == origud.localpath:
  914. return ud.localpath
  915. # We may be obtaining a mirror tarball which needs further processing by the real fetcher
  916. # If that tarball is a local file:// we need to provide a symlink to it
  917. dldir = ld.getVar("DL_DIR")
  918. if bb.utils.to_boolean(ld.getVar("BB_FETCH_PREMIRRORONLY")):
  919. ld = ld.createCopy()
  920. ld.setVar("BB_NO_NETWORK", "1")
  921. if origud.mirrortarballs and os.path.basename(ud.localpath) in origud.mirrortarballs and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
  922. # Create donestamp in old format to avoid triggering a re-download
  923. if ud.donestamp:
  924. bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
  925. open(ud.donestamp, 'w').close()
  926. dest = os.path.join(dldir, os.path.basename(ud.localpath))
  927. if not os.path.exists(dest):
  928. # In case this is executing without any file locks held (as is
  929. # the case for file:// URLs), two tasks may end up here at the
  930. # same time, in which case we do not want the second task to
  931. # fail when the link has already been created by the first task.
  932. try:
  933. os.symlink(ud.localpath, dest)
  934. except FileExistsError:
  935. pass
  936. if not verify_donestamp(origud, ld) or origud.method.need_update(origud, ld):
  937. origud.method.download(origud, ld)
  938. if hasattr(origud.method, "build_mirror_data"):
  939. origud.method.build_mirror_data(origud, ld)
  940. return origud.localpath
  941. # Otherwise the result is a local file:// and we symlink to it
  942. # This may also be a link to a shallow archive
  943. # When using shallow mode, add a symlink to the original fullshallow
  944. # path to ensure a valid symlink even in the `PREMIRRORS` case
  945. origud.method.update_mirror_links(ud, origud)
  946. update_stamp(origud, ld)
  947. return ud.localpath
  948. except bb.fetch2.NetworkAccess:
  949. raise
  950. except IOError as e:
  951. if e.errno in [errno.ESTALE]:
  952. logger.warning("Stale Error Observed %s." % ud.url)
  953. return False
  954. raise
  955. except bb.fetch2.BBFetchException as e:
  956. if isinstance(e, ChecksumError):
  957. logger.warning("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (ud.url, origud.url))
  958. logger.warning(str(e))
  959. if os.path.exists(ud.localpath):
  960. rename_bad_checksum(ud, e.checksum)
  961. elif isinstance(e, NoChecksumError):
  962. raise
  963. else:
  964. logger.debug("Mirror fetch failure for url %s (original url: %s)" % (ud.url, origud.url))
  965. logger.debug(str(e))
  966. try:
  967. if ud.method.cleanup_upon_failure():
  968. ud.method.clean(ud, ld)
  969. except UnboundLocalError:
  970. pass
  971. return False
  972. finally:
  973. if ud.lockfile and ud.lockfile != origud.lockfile:
  974. bb.utils.unlockfile(lf)
  975. def try_mirrors(fetch, d, origud, mirrors, check = False):
  976. """
  977. Try to use a mirrored version of the sources.
  978. This method will be automatically called before the fetchers go.
  979. d Is a bb.data instance
  980. uri is the original uri we're trying to download
  981. mirrors is the list of mirrors we're going to try
  982. """
  983. ld = d.createCopy()
  984. uris, uds = build_mirroruris(origud, mirrors, ld)
  985. for index, uri in enumerate(uris):
  986. ret = try_mirror_url(fetch, origud, uds[index], ld, check)
  987. if ret:
  988. return ret
  989. return None
  990. def trusted_network(d, url):
  991. """
  992. Use a trusted url during download if networking is enabled and
  993. BB_ALLOWED_NETWORKS is set globally or for a specific recipe.
  994. Note: modifies SRC_URI & mirrors.
  995. """
  996. if bb.utils.to_boolean(d.getVar("BB_NO_NETWORK")):
  997. return True
  998. pkgname = d.getVar('PN')
  999. trusted_hosts = None
  1000. if pkgname:
  1001. trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname, False)
  1002. if not trusted_hosts:
  1003. trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS')
  1004. # Not enabled.
  1005. if not trusted_hosts:
  1006. return True
  1007. scheme, network, path, user, passwd, param = decodeurl(url)
  1008. if not network:
  1009. return True
  1010. network = network.split(':')[0]
  1011. network = network.lower()
  1012. for host in trusted_hosts.split(" "):
  1013. host = host.lower()
  1014. if host.startswith("*.") and ("." + network).endswith(host[1:]):
  1015. return True
  1016. if host == network:
  1017. return True
  1018. return False
  1019. def srcrev_internal_helper(ud, d, name):
  1020. """
  1021. Return:
  1022. a) a source revision if specified
  1023. b) latest revision if SRCREV="AUTOINC"
  1024. c) None if not specified
  1025. """
  1026. srcrev = None
  1027. pn = d.getVar("PN")
  1028. attempts = []
  1029. if name != '' and pn:
  1030. attempts.append("SRCREV_%s:pn-%s" % (name, pn))
  1031. if name != '':
  1032. attempts.append("SRCREV_%s" % name)
  1033. if pn:
  1034. attempts.append("SRCREV:pn-%s" % pn)
  1035. attempts.append("SRCREV")
  1036. for a in attempts:
  1037. srcrev = d.getVar(a)
  1038. if srcrev and srcrev != "INVALID":
  1039. break
  1040. if 'rev' in ud.parm:
  1041. parmrev = ud.parm['rev']
  1042. if srcrev == "INVALID" or not srcrev:
  1043. return parmrev
  1044. if srcrev != parmrev:
  1045. raise FetchError("Conflicting revisions (%s from SRCREV and %s from the url) found, please specify one valid value" % (srcrev, parmrev))
  1046. return parmrev
  1047. if 'tag' in ud.parm and (srcrev == "INVALID" or not srcrev):
  1048. return ud.parm['tag']
  1049. if srcrev == "INVALID" or not srcrev:
  1050. 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)
  1051. if srcrev == "AUTOINC":
  1052. d.setVar("__BBAUTOREV_ACTED_UPON", True)
  1053. srcrev = ud.method.latest_revision(ud, d, name)
  1054. return srcrev
  1055. def get_checksum_file_list(d):
  1056. """ Get a list of files checksum in SRC_URI
  1057. Returns the resolved local paths of all local file entries in
  1058. SRC_URI as a space-separated string
  1059. """
  1060. fetch = Fetch([], d, cache = False, localonly = True)
  1061. filelist = []
  1062. for u in fetch.urls:
  1063. ud = fetch.ud[u]
  1064. if ud and isinstance(ud.method, local.Local):
  1065. found = False
  1066. paths = ud.method.localfile_searchpaths(ud, d)
  1067. for f in paths:
  1068. pth = ud.path
  1069. if os.path.exists(f):
  1070. found = True
  1071. filelist.append(f + ":" + str(os.path.exists(f)))
  1072. if not found:
  1073. bb.fatal(("Unable to get checksum for %s SRC_URI entry %s: file could not be found"
  1074. "\nThe following paths were searched:"
  1075. "\n%s") % (d.getVar('PN'), os.path.basename(f), '\n'.join(paths)))
  1076. return " ".join(filelist)
  1077. def get_file_checksums(filelist, pn, localdirsexclude):
  1078. """Get a list of the checksums for a list of local files
  1079. Returns the checksums for a list of local files, caching the results as
  1080. it proceeds
  1081. """
  1082. return _checksum_cache.get_checksums(filelist, pn, localdirsexclude)
  1083. class FetchData(object):
  1084. """
  1085. A class which represents the fetcher state for a given URI.
  1086. """
  1087. def __init__(self, url, d, localonly = False):
  1088. # localpath is the location of a downloaded result. If not set, the file is local.
  1089. self.donestamp = None
  1090. self.needdonestamp = True
  1091. self.localfile = ""
  1092. self.localpath = None
  1093. self.lockfile = None
  1094. self.mirrortarballs = []
  1095. self.basename = None
  1096. self.basepath = None
  1097. (self.type, self.host, self.path, self.user, self.pswd, self.parm) = decodeurl(d.expand(url))
  1098. self.date = self.getSRCDate(d)
  1099. self.url = url
  1100. if not self.user and "user" in self.parm:
  1101. self.user = self.parm["user"]
  1102. if not self.pswd and "pswd" in self.parm:
  1103. self.pswd = self.parm["pswd"]
  1104. self.setup = False
  1105. def configure_checksum(checksum_id):
  1106. checksum_plain_name = "%ssum" % checksum_id
  1107. if "name" in self.parm:
  1108. checksum_name = "%s.%ssum" % (self.parm["name"], checksum_id)
  1109. else:
  1110. checksum_name = checksum_plain_name
  1111. if checksum_name in self.parm:
  1112. checksum_expected = self.parm[checksum_name]
  1113. elif checksum_plain_name in self.parm:
  1114. checksum_expected = self.parm[checksum_plain_name]
  1115. checksum_name = checksum_plain_name
  1116. elif self.type not in ["http", "https", "ftp", "ftps", "sftp", "s3", "az", "crate", "gs", "gomod", "npm"]:
  1117. checksum_expected = None
  1118. else:
  1119. checksum_expected = d.getVarFlag("SRC_URI", checksum_name)
  1120. setattr(self, "%s_name" % checksum_id, checksum_name)
  1121. setattr(self, "%s_expected" % checksum_id, checksum_expected)
  1122. self.name = self.parm.get("name",'default')
  1123. if "," in self.name:
  1124. raise ParameterError("The fetcher no longer supports multiple name parameters in a single url", self.url)
  1125. self.method = None
  1126. for m in methods:
  1127. if m.supports(self, d):
  1128. self.method = m
  1129. break
  1130. if not self.method:
  1131. raise NoMethodError(url)
  1132. if localonly and not isinstance(self.method, local.Local):
  1133. raise NonLocalMethod()
  1134. if self.parm.get("proto", None) and "protocol" not in self.parm:
  1135. logger.warning('Consider updating %s recipe to use "protocol" not "proto" in SRC_URI.', d.getVar('PN'))
  1136. self.parm["protocol"] = self.parm.get("proto", None)
  1137. if hasattr(self.method, "urldata_init"):
  1138. self.method.urldata_init(self, d)
  1139. for checksum_id in CHECKSUM_LIST:
  1140. configure_checksum(checksum_id)
  1141. self.ignore_checksums = False
  1142. if "localpath" in self.parm:
  1143. # if user sets localpath for file, use it instead.
  1144. self.localpath = self.parm["localpath"]
  1145. self.basename = os.path.basename(self.localpath)
  1146. elif self.localfile:
  1147. self.localpath = self.method.localpath(self, d)
  1148. dldir = d.getVar("DL_DIR")
  1149. if not self.needdonestamp:
  1150. return
  1151. # Note: .done and .lock files should always be in DL_DIR whereas localpath may not be.
  1152. if self.localpath and self.localpath.startswith(dldir):
  1153. basepath = self.localpath
  1154. elif self.localpath:
  1155. basepath = dldir + os.sep + os.path.basename(self.localpath)
  1156. elif self.basepath or self.basename:
  1157. basepath = dldir + os.sep + (self.basepath or self.basename)
  1158. else:
  1159. bb.fatal("Can't determine lock path for url %s" % url)
  1160. self.donestamp = basepath + '.done'
  1161. self.lockfile = basepath + '.lock'
  1162. def setup_revisions(self, d):
  1163. self.revision = srcrev_internal_helper(self, d, self.name)
  1164. def setup_localpath(self, d):
  1165. if not self.localpath:
  1166. self.localpath = self.method.localpath(self, d)
  1167. def getSRCDate(self, d):
  1168. """
  1169. Return the SRC Date for the component
  1170. d the bb.data module
  1171. """
  1172. if "srcdate" in self.parm:
  1173. return self.parm['srcdate']
  1174. pn = d.getVar("PN")
  1175. if pn:
  1176. return d.getVar("SRCDATE_%s" % pn) or d.getVar("SRCDATE") or d.getVar("DATE")
  1177. return d.getVar("SRCDATE") or d.getVar("DATE")
  1178. class FetchMethod(object):
  1179. """Base class for 'fetch'ing data"""
  1180. def __init__(self, urls=None):
  1181. self.urls = []
  1182. def supports(self, urldata, d):
  1183. """
  1184. Check to see if this fetch class supports a given url.
  1185. """
  1186. return 0
  1187. def localpath(self, urldata, d):
  1188. """
  1189. Return the local filename of a given url assuming a successful fetch.
  1190. Can also setup variables in urldata for use in go (saving code duplication
  1191. and duplicate code execution)
  1192. """
  1193. return os.path.join(d.getVar("DL_DIR"), urldata.localfile)
  1194. def supports_checksum(self, urldata):
  1195. """
  1196. Is localpath something that can be represented by a checksum?
  1197. """
  1198. # We cannot compute checksums for None
  1199. if urldata.localpath is None:
  1200. return False
  1201. # We cannot compute checksums for directories
  1202. if os.path.isdir(urldata.localpath):
  1203. return False
  1204. return True
  1205. def recommends_checksum(self, urldata):
  1206. """
  1207. Is the backend on where checksumming is recommended (should warnings
  1208. be displayed if there is no checksum)?
  1209. """
  1210. return False
  1211. def cleanup_upon_failure(self):
  1212. """
  1213. When a fetch fails, should clean() be called?
  1214. """
  1215. return True
  1216. def verify_donestamp(self, ud, d):
  1217. """
  1218. Verify the donestamp file
  1219. """
  1220. return verify_donestamp(ud, d)
  1221. def update_donestamp(self, ud, d):
  1222. """
  1223. Update the donestamp file
  1224. """
  1225. update_stamp(ud, d)
  1226. def _strip_leading_slashes(self, relpath):
  1227. """
  1228. Remove leading slash as os.path.join can't cope
  1229. """
  1230. while os.path.isabs(relpath):
  1231. relpath = relpath[1:]
  1232. return relpath
  1233. def setUrls(self, urls):
  1234. self.__urls = urls
  1235. def getUrls(self):
  1236. return self.__urls
  1237. urls = property(getUrls, setUrls, None, "Urls property")
  1238. def need_update(self, ud, d):
  1239. """
  1240. Force a fetch, even if localpath exists?
  1241. """
  1242. if os.path.exists(ud.localpath):
  1243. return False
  1244. return True
  1245. def supports_srcrev(self):
  1246. """
  1247. The fetcher supports auto source revisions (SRCREV)
  1248. """
  1249. return False
  1250. def download(self, urldata, d):
  1251. """
  1252. Fetch urls
  1253. Assumes localpath was called first
  1254. """
  1255. raise NoMethodError(urldata.url)
  1256. def unpack(self, urldata, rootdir, data):
  1257. iterate = False
  1258. file = urldata.localpath
  1259. try:
  1260. unpack = bb.utils.to_boolean(urldata.parm.get('unpack'), True)
  1261. except ValueError as exc:
  1262. bb.fatal("Invalid value for 'unpack' parameter for %s: %s" %
  1263. (file, urldata.parm.get('unpack')))
  1264. base, ext = os.path.splitext(file)
  1265. if ext in ['.gz', '.bz2', '.Z', '.xz', '.lz', '.zst']:
  1266. efile = os.path.join(rootdir, os.path.basename(base))
  1267. else:
  1268. efile = file
  1269. cmd = None
  1270. if unpack:
  1271. tar_cmd = 'tar --extract --no-same-owner'
  1272. if 'striplevel' in urldata.parm:
  1273. tar_cmd += ' --strip-components=%s' % urldata.parm['striplevel']
  1274. if file.endswith('.tar'):
  1275. cmd = '%s -f %s' % (tar_cmd, file)
  1276. elif file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'):
  1277. cmd = '%s -z -f %s' % (tar_cmd, file)
  1278. elif file.endswith('.tbz') or file.endswith('.tbz2') or file.endswith('.tar.bz2'):
  1279. cmd = 'bzip2 -dc %s | %s -f -' % (file, tar_cmd)
  1280. elif file.endswith('.gz') or file.endswith('.Z') or file.endswith('.z'):
  1281. cmd = 'gzip -dc %s > %s' % (file, efile)
  1282. elif file.endswith('.bz2'):
  1283. cmd = 'bzip2 -dc %s > %s' % (file, efile)
  1284. elif file.endswith('.txz') or file.endswith('.tar.xz'):
  1285. cmd = 'xz -dc %s | %s -f -' % (file, tar_cmd)
  1286. elif file.endswith('.xz'):
  1287. cmd = 'xz -dc %s > %s' % (file, efile)
  1288. elif file.endswith('.tar.lz'):
  1289. cmd = 'lzip -dc %s | %s -f -' % (file, tar_cmd)
  1290. elif file.endswith('.lz'):
  1291. cmd = 'lzip -dc %s > %s' % (file, efile)
  1292. elif file.endswith('.tar.7z'):
  1293. cmd = '7z x -so %s | %s -f -' % (file, tar_cmd)
  1294. elif file.endswith('.7z'):
  1295. cmd = '7za x -y %s 1>/dev/null' % file
  1296. elif file.endswith('.tzst') or file.endswith('.tar.zst'):
  1297. cmd = 'zstd --decompress --stdout %s | %s -f -' % (file, tar_cmd)
  1298. elif file.endswith('.zst'):
  1299. cmd = 'zstd --decompress --stdout %s > %s' % (file, efile)
  1300. elif file.endswith('.zip') or file.endswith('.jar'):
  1301. try:
  1302. dos = bb.utils.to_boolean(urldata.parm.get('dos'), False)
  1303. except ValueError as exc:
  1304. bb.fatal("Invalid value for 'dos' parameter for %s: %s" %
  1305. (file, urldata.parm.get('dos')))
  1306. cmd = 'unzip -q -o'
  1307. if dos:
  1308. cmd = '%s -a' % cmd
  1309. cmd = "%s '%s'" % (cmd, file)
  1310. elif file.endswith('.rpm') or file.endswith('.srpm'):
  1311. if 'extract' in urldata.parm:
  1312. unpack_file = urldata.parm.get('extract')
  1313. cmd = 'rpm2cpio.sh %s | cpio -id %s' % (file, unpack_file)
  1314. iterate = True
  1315. iterate_file = unpack_file
  1316. else:
  1317. cmd = 'rpm2cpio.sh %s | cpio -id' % (file)
  1318. elif file.endswith('.deb') or file.endswith('.ipk'):
  1319. output = subprocess.check_output(['ar', '-t', file], preexec_fn=subprocess_setup)
  1320. datafile = None
  1321. if output:
  1322. for line in output.decode().splitlines():
  1323. if line.startswith('data.tar.') or line == 'data.tar':
  1324. datafile = line
  1325. break
  1326. else:
  1327. raise UnpackError("Unable to unpack deb/ipk package - does not contain data.tar* file", urldata.url)
  1328. else:
  1329. raise UnpackError("Unable to unpack deb/ipk package - could not list contents", urldata.url)
  1330. cmd = 'ar x %s %s && %s -p -f %s && rm %s' % (file, datafile, tar_cmd, datafile, datafile)
  1331. # If 'subdir' param exists, create a dir and use it as destination for unpack cmd
  1332. if 'subdir' in urldata.parm:
  1333. subdir = urldata.parm.get('subdir')
  1334. if os.path.isabs(subdir):
  1335. if not os.path.realpath(subdir).startswith(os.path.realpath(rootdir)):
  1336. raise UnpackError("subdir argument isn't a subdirectory of unpack root %s" % rootdir, urldata.url)
  1337. unpackdir = subdir
  1338. else:
  1339. unpackdir = os.path.join(rootdir, subdir)
  1340. bb.utils.mkdirhier(unpackdir)
  1341. else:
  1342. unpackdir = rootdir
  1343. if not unpack or not cmd:
  1344. urldata.unpack_tracer.unpack("file-copy", unpackdir)
  1345. # If file == dest, then avoid any copies, as we already put the file into dest!
  1346. dest = os.path.join(unpackdir, os.path.basename(file))
  1347. if file != dest and not (os.path.exists(dest) and os.path.samefile(file, dest)):
  1348. destdir = '.'
  1349. # For file:// entries all intermediate dirs in path must be created at destination
  1350. if urldata.type == "file":
  1351. # Trailing '/' does a copying to wrong place
  1352. urlpath = urldata.path.rstrip('/')
  1353. # Want files places relative to cwd so no leading '/'
  1354. urlpath = urlpath.lstrip('/')
  1355. if urlpath.find("/") != -1:
  1356. destdir = urlpath.rsplit("/", 1)[0] + '/'
  1357. bb.utils.mkdirhier("%s/%s" % (unpackdir, destdir))
  1358. cmd = 'cp --force --preserve=timestamps --no-dereference --recursive -H "%s" "%s"' % (file, destdir)
  1359. else:
  1360. urldata.unpack_tracer.unpack("archive-extract", unpackdir)
  1361. if not cmd:
  1362. return
  1363. path = data.getVar('PATH')
  1364. if path:
  1365. cmd = "PATH=\"%s\" %s" % (path, cmd)
  1366. bb.note("Unpacking %s to %s/" % (file, unpackdir))
  1367. ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True, cwd=unpackdir)
  1368. if ret != 0:
  1369. raise UnpackError("Unpack command %s failed with return value %s" % (cmd, ret), urldata.url)
  1370. if iterate is True:
  1371. iterate_urldata = urldata
  1372. iterate_urldata.localpath = "%s/%s" % (rootdir, iterate_file)
  1373. self.unpack(urldata, rootdir, data)
  1374. return
  1375. def clean(self, urldata, d):
  1376. """
  1377. Clean any existing full or partial download
  1378. """
  1379. bb.utils.remove(urldata.localpath)
  1380. def ensure_symlink(self, target, link_name):
  1381. if not os.path.exists(link_name):
  1382. dirname = os.path.dirname(link_name)
  1383. bb.utils.mkdirhier(dirname)
  1384. if os.path.islink(link_name):
  1385. # Broken symbolic link
  1386. os.unlink(link_name)
  1387. # In case this is executing without any file locks held (as is
  1388. # the case for file:// URLs), two tasks may end up here at the
  1389. # same time, in which case we do not want the second task to
  1390. # fail when the link has already been created by the first task.
  1391. try:
  1392. os.symlink(target, link_name)
  1393. except FileExistsError:
  1394. pass
  1395. def update_mirror_links(self, ud, origud):
  1396. # For local file:// results, create a symlink to them
  1397. # This may also be a link to a shallow archive
  1398. self.ensure_symlink(ud.localpath, origud.localpath)
  1399. def try_premirror(self, urldata, d):
  1400. """
  1401. Should premirrors be used?
  1402. """
  1403. return True
  1404. def try_mirrors(self, fetch, urldata, d, mirrors, check=False):
  1405. """
  1406. Try to use a mirror
  1407. """
  1408. return bool(try_mirrors(fetch, d, urldata, mirrors, check))
  1409. def checkstatus(self, fetch, urldata, d):
  1410. """
  1411. Check the status of a URL
  1412. Assumes localpath was called first
  1413. """
  1414. logger.info("URL %s could not be checked for status since no method exists.", urldata.url)
  1415. return True
  1416. def latest_revision(self, ud, d, name):
  1417. """
  1418. Look in the cache for the latest revision, if not present ask the SCM.
  1419. """
  1420. if not hasattr(self, "_latest_revision"):
  1421. raise ParameterError("The fetcher for this URL does not support _latest_revision", ud.url)
  1422. key = self.generate_revision_key(ud, d, name)
  1423. rev = _revisions_cache.get_rev(key)
  1424. if rev is None:
  1425. rev = self._latest_revision(ud, d, name)
  1426. _revisions_cache.set_rev(key, rev)
  1427. return rev
  1428. def sortable_revision(self, ud, d, name):
  1429. latest_rev = self._build_revision(ud, d, name)
  1430. return True, str(latest_rev)
  1431. def generate_revision_key(self, ud, d, name):
  1432. return self._revision_key(ud, d, name)
  1433. def latest_versionstring(self, ud, d):
  1434. """
  1435. Compute the latest release name like "x.y.x" in "x.y.x+gitHASH"
  1436. by searching through the tags output of ls-remote, comparing
  1437. versions and returning the highest match as a (version, revision) pair.
  1438. """
  1439. return ('', '')
  1440. def done(self, ud, d):
  1441. """
  1442. Is the download done ?
  1443. """
  1444. if os.path.exists(ud.localpath):
  1445. return True
  1446. return False
  1447. def implicit_urldata(self, ud, d):
  1448. """
  1449. Get a list of FetchData objects for any implicit URLs that will also
  1450. be downloaded when we fetch the given URL.
  1451. """
  1452. return []
  1453. class DummyUnpackTracer(object):
  1454. """
  1455. Abstract API definition for a class that traces unpacked source files back
  1456. to their respective upstream SRC_URI entries, for software composition
  1457. analysis, license compliance and detailed SBOM generation purposes.
  1458. User may load their own unpack tracer class (instead of the dummy
  1459. one) by setting the BB_UNPACK_TRACER_CLASS config parameter.
  1460. """
  1461. def start(self, unpackdir, urldata_dict, d):
  1462. """
  1463. Start tracing the core Fetch.unpack process, using an index to map
  1464. unpacked files to each SRC_URI entry.
  1465. This method is called by Fetch.unpack and it may receive nested calls by
  1466. gitsm and npmsw fetchers, that expand SRC_URI entries by adding implicit
  1467. URLs and by recursively calling Fetch.unpack from new (nested) Fetch
  1468. instances.
  1469. """
  1470. return
  1471. def start_url(self, url):
  1472. """Start tracing url unpack process.
  1473. This method is called by Fetch.unpack before the fetcher-specific unpack
  1474. method starts, and it may receive nested calls by gitsm and npmsw
  1475. fetchers.
  1476. """
  1477. return
  1478. def unpack(self, unpack_type, destdir):
  1479. """
  1480. Set unpack_type and destdir for current url.
  1481. This method is called by the fetcher-specific unpack method after url
  1482. tracing started.
  1483. """
  1484. return
  1485. def finish_url(self, url):
  1486. """Finish tracing url unpack process and update the file index.
  1487. This method is called by Fetch.unpack after the fetcher-specific unpack
  1488. method finished its job, and it may receive nested calls by gitsm
  1489. and npmsw fetchers.
  1490. """
  1491. return
  1492. def complete(self):
  1493. """
  1494. Finish tracing the Fetch.unpack process, and check if all nested
  1495. Fecth.unpack calls (if any) have been completed; if so, save collected
  1496. metadata.
  1497. """
  1498. return
  1499. class Fetch(object):
  1500. def __init__(self, urls, d, cache = True, localonly = False, connection_cache = None):
  1501. if localonly and cache:
  1502. raise Exception("bb.fetch2.Fetch.__init__: cannot set cache and localonly at same time")
  1503. if not urls:
  1504. urls = d.getVar("SRC_URI").split()
  1505. self.urls = urls
  1506. self.d = d
  1507. self.ud = {}
  1508. self.connection_cache = connection_cache
  1509. fn = d.getVar('FILE')
  1510. mc = d.getVar('__BBMULTICONFIG') or ""
  1511. key = None
  1512. if cache and fn:
  1513. key = mc + fn + str(id(d))
  1514. if key in urldata_cache:
  1515. self.ud = urldata_cache[key]
  1516. # the unpack_tracer object needs to be made available to possible nested
  1517. # Fetch instances (when those are created by gitsm and npmsw fetchers)
  1518. # so we set it as a global variable
  1519. global unpack_tracer
  1520. try:
  1521. unpack_tracer
  1522. except NameError:
  1523. class_path = d.getVar("BB_UNPACK_TRACER_CLASS")
  1524. if class_path:
  1525. # use user-defined unpack tracer class
  1526. import importlib
  1527. module_name, _, class_name = class_path.rpartition(".")
  1528. module = importlib.import_module(module_name)
  1529. class_ = getattr(module, class_name)
  1530. unpack_tracer = class_()
  1531. else:
  1532. # fall back to the dummy/abstract class
  1533. unpack_tracer = DummyUnpackTracer()
  1534. for url in urls:
  1535. if url not in self.ud:
  1536. try:
  1537. self.ud[url] = FetchData(url, d, localonly)
  1538. self.ud[url].unpack_tracer = unpack_tracer
  1539. except NonLocalMethod:
  1540. if localonly:
  1541. self.ud[url] = None
  1542. pass
  1543. if key:
  1544. urldata_cache[key] = self.ud
  1545. def localpath(self, url):
  1546. if url not in self.urls:
  1547. self.ud[url] = FetchData(url, self.d)
  1548. self.ud[url].setup_localpath(self.d)
  1549. return self.ud[url].localpath
  1550. def localpaths(self):
  1551. """
  1552. Return a list of the local filenames, assuming successful fetch
  1553. """
  1554. local = []
  1555. for u in self.urls:
  1556. ud = self.ud[u]
  1557. ud.setup_localpath(self.d)
  1558. local.append(ud.localpath)
  1559. return local
  1560. def download(self, urls=None):
  1561. """
  1562. Fetch all urls
  1563. """
  1564. if not urls:
  1565. urls = self.urls
  1566. network = self.d.getVar("BB_NO_NETWORK")
  1567. premirroronly = bb.utils.to_boolean(self.d.getVar("BB_FETCH_PREMIRRORONLY"))
  1568. checksum_missing_messages = []
  1569. for u in urls:
  1570. ud = self.ud[u]
  1571. ud.setup_localpath(self.d)
  1572. m = ud.method
  1573. done = False
  1574. if ud.lockfile:
  1575. lf = bb.utils.lockfile(ud.lockfile)
  1576. try:
  1577. self.d.setVar("BB_NO_NETWORK", network)
  1578. if m.verify_donestamp(ud, self.d) and not m.need_update(ud, self.d):
  1579. done = True
  1580. elif m.try_premirror(ud, self.d):
  1581. logger.debug("Trying PREMIRRORS")
  1582. mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
  1583. done = m.try_mirrors(self, ud, self.d, mirrors)
  1584. if done:
  1585. try:
  1586. # early checksum verification so that if the checksum of the premirror
  1587. # contents mismatch the fetcher can still try upstream and mirrors
  1588. m.update_donestamp(ud, self.d)
  1589. except ChecksumError as e:
  1590. logger.warning("Checksum failure encountered with premirror download of %s - will attempt other sources." % u)
  1591. logger.debug(str(e))
  1592. done = False
  1593. d = self.d
  1594. if premirroronly:
  1595. # Only disable the network in a copy
  1596. d = bb.data.createCopy(self.d)
  1597. d.setVar("BB_NO_NETWORK", "1")
  1598. firsterr = None
  1599. verified_stamp = False
  1600. if done:
  1601. verified_stamp = m.verify_donestamp(ud, d)
  1602. if not done and (not verified_stamp or m.need_update(ud, d)):
  1603. try:
  1604. if not trusted_network(d, ud.url):
  1605. raise UntrustedUrl(ud.url)
  1606. logger.debug("Trying Upstream")
  1607. m.download(ud, d)
  1608. if hasattr(m, "build_mirror_data"):
  1609. m.build_mirror_data(ud, d)
  1610. done = True
  1611. # early checksum verify, so that if checksum mismatched,
  1612. # fetcher still have chance to fetch from mirror
  1613. m.update_donestamp(ud, d)
  1614. except bb.fetch2.NetworkAccess:
  1615. raise
  1616. except BBFetchException as e:
  1617. if isinstance(e, ChecksumError):
  1618. logger.warning("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
  1619. logger.debug(str(e))
  1620. if os.path.exists(ud.localpath):
  1621. rename_bad_checksum(ud, e.checksum)
  1622. elif isinstance(e, NoChecksumError):
  1623. raise
  1624. else:
  1625. logger.warning('Failed to fetch URL %s, attempting MIRRORS if available' % u)
  1626. logger.debug(str(e))
  1627. firsterr = e
  1628. # Remove any incomplete fetch
  1629. if not verified_stamp and m.cleanup_upon_failure():
  1630. m.clean(ud, d)
  1631. logger.debug("Trying MIRRORS")
  1632. mirrors = mirror_from_string(d.getVar('MIRRORS'))
  1633. done = m.try_mirrors(self, ud, d, mirrors)
  1634. if not done or not m.done(ud, d):
  1635. if firsterr:
  1636. logger.error(str(firsterr))
  1637. raise FetchError("Unable to fetch URL from any source.", u)
  1638. m.update_donestamp(ud, d)
  1639. except IOError as e:
  1640. if e.errno in [errno.ESTALE]:
  1641. logger.error("Stale Error Observed %s." % u)
  1642. raise ChecksumError("Stale Error Detected")
  1643. except BBFetchException as e:
  1644. if isinstance(e, NoChecksumError):
  1645. (message, _) = e.args
  1646. checksum_missing_messages.append(message)
  1647. continue
  1648. elif isinstance(e, ChecksumError):
  1649. logger.error("Checksum failure fetching %s" % u)
  1650. raise
  1651. finally:
  1652. if ud.lockfile:
  1653. bb.utils.unlockfile(lf)
  1654. if checksum_missing_messages:
  1655. logger.error("Missing SRC_URI checksum, please add those to the recipe: \n%s", "\n".join(checksum_missing_messages))
  1656. raise BBFetchException("There was some missing checksums in the recipe")
  1657. def checkstatus(self, urls=None):
  1658. """
  1659. Check all URLs exist upstream.
  1660. Returns None if the URLs exist, raises FetchError if the check wasn't
  1661. successful but there wasn't an error (such as file not found), and
  1662. raises other exceptions in error cases.
  1663. """
  1664. if not urls:
  1665. urls = self.urls
  1666. for u in urls:
  1667. ud = self.ud[u]
  1668. ud.setup_localpath(self.d)
  1669. m = ud.method
  1670. logger.debug("Testing URL %s", u)
  1671. # First try checking uri, u, from PREMIRRORS
  1672. mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
  1673. ret = m.try_mirrors(self, ud, self.d, mirrors, True)
  1674. if not ret:
  1675. # Next try checking from the original uri, u
  1676. ret = m.checkstatus(self, ud, self.d)
  1677. if not ret:
  1678. # Finally, try checking uri, u, from MIRRORS
  1679. mirrors = mirror_from_string(self.d.getVar('MIRRORS'))
  1680. ret = m.try_mirrors(self, ud, self.d, mirrors, True)
  1681. if not ret:
  1682. raise FetchError("URL doesn't work", u)
  1683. def unpack(self, root, urls=None):
  1684. """
  1685. Unpack urls to root
  1686. """
  1687. if not urls:
  1688. urls = self.urls
  1689. unpack_tracer.start(root, self.ud, self.d)
  1690. for u in urls:
  1691. ud = self.ud[u]
  1692. ud.setup_localpath(self.d)
  1693. if ud.lockfile:
  1694. lf = bb.utils.lockfile(ud.lockfile)
  1695. unpack_tracer.start_url(u)
  1696. ud.method.unpack(ud, root, self.d)
  1697. unpack_tracer.finish_url(u)
  1698. if ud.lockfile:
  1699. bb.utils.unlockfile(lf)
  1700. unpack_tracer.complete()
  1701. def clean(self, urls=None):
  1702. """
  1703. Clean files that the fetcher gets or places
  1704. """
  1705. if not urls:
  1706. urls = self.urls
  1707. for url in urls:
  1708. if url not in self.ud:
  1709. self.ud[url] = FetchData(url, self.d)
  1710. ud = self.ud[url]
  1711. ud.setup_localpath(self.d)
  1712. if not ud.localfile and ud.localpath is None:
  1713. continue
  1714. if ud.lockfile:
  1715. lf = bb.utils.lockfile(ud.lockfile)
  1716. ud.method.clean(ud, self.d)
  1717. if ud.donestamp:
  1718. bb.utils.remove(ud.donestamp)
  1719. if ud.lockfile:
  1720. bb.utils.unlockfile(lf)
  1721. def expanded_urldata(self, urls=None):
  1722. """
  1723. Get an expanded list of FetchData objects covering both the given
  1724. URLS and any additional implicit URLs that are added automatically by
  1725. the appropriate FetchMethod.
  1726. """
  1727. if not urls:
  1728. urls = self.urls
  1729. urldata = []
  1730. for url in urls:
  1731. ud = self.ud[url]
  1732. urldata.append(ud)
  1733. urldata += ud.method.implicit_urldata(ud, self.d)
  1734. return urldata
  1735. class FetchConnectionCache(object):
  1736. """
  1737. A class which represents an container for socket connections.
  1738. """
  1739. def __init__(self):
  1740. self.cache = {}
  1741. def get_connection_name(self, host, port):
  1742. return host + ':' + str(port)
  1743. def add_connection(self, host, port, connection):
  1744. cn = self.get_connection_name(host, port)
  1745. if cn not in self.cache:
  1746. self.cache[cn] = connection
  1747. def get_connection(self, host, port):
  1748. connection = None
  1749. cn = self.get_connection_name(host, port)
  1750. if cn in self.cache:
  1751. connection = self.cache[cn]
  1752. return connection
  1753. def remove_connection(self, host, port):
  1754. cn = self.get_connection_name(host, port)
  1755. if cn in self.cache:
  1756. self.cache[cn].close()
  1757. del self.cache[cn]
  1758. def close_connections(self):
  1759. for cn in list(self.cache.keys()):
  1760. self.cache[cn].close()
  1761. del self.cache[cn]
  1762. from . import cvs
  1763. from . import git
  1764. from . import gitsm
  1765. from . import gitannex
  1766. from . import local
  1767. from . import svn
  1768. from . import wget
  1769. from . import ssh
  1770. from . import sftp
  1771. from . import s3
  1772. from . import perforce
  1773. from . import bzr
  1774. from . import hg
  1775. from . import osc
  1776. from . import repo
  1777. from . import clearcase
  1778. from . import npm
  1779. from . import npmsw
  1780. from . import az
  1781. from . import crate
  1782. from . import gcp
  1783. from . import gomod
  1784. methods.append(local.Local())
  1785. methods.append(wget.Wget())
  1786. methods.append(svn.Svn())
  1787. methods.append(git.Git())
  1788. methods.append(gitsm.GitSM())
  1789. methods.append(gitannex.GitANNEX())
  1790. methods.append(cvs.Cvs())
  1791. methods.append(ssh.SSH())
  1792. methods.append(sftp.SFTP())
  1793. methods.append(s3.S3())
  1794. methods.append(perforce.Perforce())
  1795. methods.append(bzr.Bzr())
  1796. methods.append(hg.Hg())
  1797. methods.append(osc.Osc())
  1798. methods.append(repo.Repo())
  1799. methods.append(clearcase.ClearCase())
  1800. methods.append(npm.Npm())
  1801. methods.append(npmsw.NpmShrinkWrap())
  1802. methods.append(az.Az())
  1803. methods.append(crate.Crate())
  1804. methods.append(gcp.GCP())
  1805. methods.append(gomod.GoMod())
  1806. methods.append(gomod.GoModGit())