__init__.py 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780
  1. # ex:ts=4:sw=4:sts=4:et
  2. # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
  3. """
  4. BitBake 'Fetch' implementations
  5. Classes for obtaining upstream sources for the
  6. BitBake build tools.
  7. """
  8. # Copyright (C) 2003, 2004 Chris Larson
  9. # Copyright (C) 2012 Intel Corporation
  10. #
  11. # This program is free software; you can redistribute it and/or modify
  12. # it under the terms of the GNU General Public License version 2 as
  13. # published by the Free Software Foundation.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License along
  21. # with this program; if not, write to the Free Software Foundation, Inc.,
  22. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  23. #
  24. # Based on functions from the base bb module, Copyright 2003 Holger Schurig
  25. from __future__ import absolute_import
  26. from __future__ import print_function
  27. import os, re
  28. import signal
  29. import glob
  30. import logging
  31. import urllib
  32. import urlparse
  33. import operator
  34. import bb.persist_data, bb.utils
  35. import bb.checksum
  36. from bb import data
  37. import bb.process
  38. import subprocess
  39. __version__ = "2"
  40. _checksum_cache = bb.checksum.FileChecksumCache()
  41. logger = logging.getLogger("BitBake.Fetcher")
  42. try:
  43. import cPickle as pickle
  44. except ImportError:
  45. import pickle
  46. logger.info("Importing cPickle failed. "
  47. "Falling back to a very slow implementation.")
  48. class BBFetchException(Exception):
  49. """Class all fetch exceptions inherit from"""
  50. def __init__(self, message):
  51. self.msg = message
  52. Exception.__init__(self, message)
  53. def __str__(self):
  54. return self.msg
  55. class UntrustedUrl(BBFetchException):
  56. """Exception raised when encountering a host not listed in BB_ALLOWED_NETWORKS"""
  57. def __init__(self, url, message=''):
  58. if message:
  59. msg = message
  60. else:
  61. msg = "The URL: '%s' is not trusted and cannot be used" % url
  62. self.url = url
  63. BBFetchException.__init__(self, msg)
  64. self.args = (url,)
  65. class MalformedUrl(BBFetchException):
  66. """Exception raised when encountering an invalid url"""
  67. def __init__(self, url, message=''):
  68. if message:
  69. msg = message
  70. else:
  71. msg = "The URL: '%s' is invalid and cannot be interpreted" % url
  72. self.url = url
  73. BBFetchException.__init__(self, msg)
  74. self.args = (url,)
  75. class FetchError(BBFetchException):
  76. """General fetcher exception when something happens incorrectly"""
  77. def __init__(self, message, url = None):
  78. if url:
  79. msg = "Fetcher failure for URL: '%s'. %s" % (url, message)
  80. else:
  81. msg = "Fetcher failure: %s" % message
  82. self.url = url
  83. BBFetchException.__init__(self, msg)
  84. self.args = (message, url)
  85. class ChecksumError(FetchError):
  86. """Exception when mismatched checksum encountered"""
  87. def __init__(self, message, url = None, checksum = None):
  88. self.checksum = checksum
  89. FetchError.__init__(self, message, url)
  90. class NoChecksumError(FetchError):
  91. """Exception when no checksum is specified, but BB_STRICT_CHECKSUM is set"""
  92. class UnpackError(BBFetchException):
  93. """General fetcher exception when something happens incorrectly when unpacking"""
  94. def __init__(self, message, url):
  95. msg = "Unpack failure for URL: '%s'. %s" % (url, message)
  96. self.url = url
  97. BBFetchException.__init__(self, msg)
  98. self.args = (message, url)
  99. class NoMethodError(BBFetchException):
  100. """Exception raised when there is no method to obtain a supplied url or set of urls"""
  101. def __init__(self, url):
  102. msg = "Could not find a fetcher which supports the URL: '%s'" % url
  103. self.url = url
  104. BBFetchException.__init__(self, msg)
  105. self.args = (url,)
  106. class MissingParameterError(BBFetchException):
  107. """Exception raised when a fetch method is missing a critical parameter in the url"""
  108. def __init__(self, missing, url):
  109. 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)
  114. class ParameterError(BBFetchException):
  115. """Exception raised when a url cannot be proccessed due to invalid parameters."""
  116. def __init__(self, message, url):
  117. msg = "URL: '%s' has invalid parameters. %s" % (url, message)
  118. self.url = url
  119. BBFetchException.__init__(self, msg)
  120. self.args = (message, url)
  121. class NetworkAccess(BBFetchException):
  122. """Exception raised when network access is disabled but it is required."""
  123. def __init__(self, url, cmd):
  124. 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)
  125. self.url = url
  126. self.cmd = cmd
  127. BBFetchException.__init__(self, msg)
  128. self.args = (url, cmd)
  129. class NonLocalMethod(Exception):
  130. def __init__(self):
  131. Exception.__init__(self)
  132. class URI(object):
  133. """
  134. A class representing a generic URI, with methods for
  135. accessing the URI components, and stringifies to the
  136. URI.
  137. It is constructed by calling it with a URI, or setting
  138. the attributes manually:
  139. uri = URI("http://example.com/")
  140. uri = URI()
  141. uri.scheme = 'http'
  142. uri.hostname = 'example.com'
  143. uri.path = '/'
  144. It has the following attributes:
  145. * scheme (read/write)
  146. * userinfo (authentication information) (read/write)
  147. * username (read/write)
  148. * password (read/write)
  149. Note, password is deprecated as of RFC 3986.
  150. * hostname (read/write)
  151. * port (read/write)
  152. * hostport (read only)
  153. "hostname:port", if both are set, otherwise just "hostname"
  154. * path (read/write)
  155. * path_quoted (read/write)
  156. A URI quoted version of path
  157. * params (dict) (read/write)
  158. * query (dict) (read/write)
  159. * relative (bool) (read only)
  160. True if this is a "relative URI", (e.g. file:foo.diff)
  161. It stringifies to the URI itself.
  162. Some notes about relative URIs: while it's specified that
  163. a URI beginning with <scheme>:// should either be directly
  164. followed by a hostname or a /, the old URI handling of the
  165. fetch2 library did not comform to this. Therefore, this URI
  166. class has some kludges to make sure that URIs are parsed in
  167. a way comforming to bitbake's current usage. This URI class
  168. supports the following:
  169. file:relative/path.diff (IETF compliant)
  170. git:relative/path.git (IETF compliant)
  171. git:///absolute/path.git (IETF compliant)
  172. file:///absolute/path.diff (IETF compliant)
  173. file://relative/path.diff (not IETF compliant)
  174. But it does not support the following:
  175. file://hostname/absolute/path.diff (would be IETF compliant)
  176. Note that the last case only applies to a list of
  177. "whitelisted" schemes (currently only file://), that requires
  178. its URIs to not have a network location.
  179. """
  180. _relative_schemes = ['file', 'git']
  181. _netloc_forbidden = ['file']
  182. def __init__(self, uri=None):
  183. self.scheme = ''
  184. self.userinfo = ''
  185. self.hostname = ''
  186. self.port = None
  187. self._path = ''
  188. self.params = {}
  189. self.query = {}
  190. self.relative = False
  191. if not uri:
  192. return
  193. # We hijack the URL parameters, since the way bitbake uses
  194. # them are not quite RFC compliant.
  195. uri, param_str = (uri.split(";", 1) + [None])[:2]
  196. urlp = urlparse.urlparse(uri)
  197. self.scheme = urlp.scheme
  198. reparse = 0
  199. # Coerce urlparse to make URI scheme use netloc
  200. if not self.scheme in urlparse.uses_netloc:
  201. urlparse.uses_params.append(self.scheme)
  202. reparse = 1
  203. # Make urlparse happy(/ier) by converting local resources
  204. # to RFC compliant URL format. E.g.:
  205. # file://foo.diff -> file:foo.diff
  206. if urlp.scheme in self._netloc_forbidden:
  207. uri = re.sub("(?<=:)//(?!/)", "", uri, 1)
  208. reparse = 1
  209. if reparse:
  210. urlp = urlparse.urlparse(uri)
  211. # Identify if the URI is relative or not
  212. if urlp.scheme in self._relative_schemes and \
  213. re.compile("^\w+:(?!//)").match(uri):
  214. self.relative = True
  215. if not self.relative:
  216. self.hostname = urlp.hostname or ''
  217. self.port = urlp.port
  218. self.userinfo += urlp.username or ''
  219. if urlp.password:
  220. self.userinfo += ':%s' % urlp.password
  221. self.path = urllib.unquote(urlp.path)
  222. if param_str:
  223. self.params = self._param_str_split(param_str, ";")
  224. if urlp.query:
  225. self.query = self._param_str_split(urlp.query, "&")
  226. def __str__(self):
  227. userinfo = self.userinfo
  228. if userinfo:
  229. userinfo += '@'
  230. return "%s:%s%s%s%s%s%s" % (
  231. self.scheme,
  232. '' if self.relative else '//',
  233. userinfo,
  234. self.hostport,
  235. self.path_quoted,
  236. self._query_str(),
  237. self._param_str())
  238. def _param_str(self):
  239. return (
  240. ''.join([';', self._param_str_join(self.params, ";")])
  241. if self.params else '')
  242. def _query_str(self):
  243. return (
  244. ''.join(['?', self._param_str_join(self.query, "&")])
  245. if self.query else '')
  246. def _param_str_split(self, string, elmdelim, kvdelim="="):
  247. ret = {}
  248. for k, v in [x.split(kvdelim, 1) for x in string.split(elmdelim)]:
  249. ret[k] = v
  250. return ret
  251. def _param_str_join(self, dict_, elmdelim, kvdelim="="):
  252. return elmdelim.join([kvdelim.join([k, v]) for k, v in dict_.items()])
  253. @property
  254. def hostport(self):
  255. if not self.port:
  256. return self.hostname
  257. return "%s:%d" % (self.hostname, self.port)
  258. @property
  259. def path_quoted(self):
  260. return urllib.quote(self.path)
  261. @path_quoted.setter
  262. def path_quoted(self, path):
  263. self.path = urllib.unquote(path)
  264. @property
  265. def path(self):
  266. return self._path
  267. @path.setter
  268. def path(self, path):
  269. self._path = path
  270. if re.compile("^/").match(path):
  271. self.relative = False
  272. else:
  273. self.relative = True
  274. @property
  275. def username(self):
  276. if self.userinfo:
  277. return (self.userinfo.split(":", 1))[0]
  278. return ''
  279. @username.setter
  280. def username(self, username):
  281. password = self.password
  282. self.userinfo = username
  283. if password:
  284. self.userinfo += ":%s" % password
  285. @property
  286. def password(self):
  287. if self.userinfo and ":" in self.userinfo:
  288. return (self.userinfo.split(":", 1))[1]
  289. return ''
  290. @password.setter
  291. def password(self, password):
  292. self.userinfo = "%s:%s" % (self.username, password)
  293. def decodeurl(url):
  294. """Decodes an URL into the tokens (scheme, network location, path,
  295. user, password, parameters).
  296. """
  297. m = re.compile('(?P<type>[^:]*)://((?P<user>[^/]+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
  298. if not m:
  299. raise MalformedUrl(url)
  300. type = m.group('type')
  301. location = m.group('location')
  302. if not location:
  303. raise MalformedUrl(url)
  304. user = m.group('user')
  305. parm = m.group('parm')
  306. locidx = location.find('/')
  307. if locidx != -1 and type.lower() != 'file':
  308. host = location[:locidx]
  309. path = location[locidx:]
  310. else:
  311. host = ""
  312. path = location
  313. if user:
  314. m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
  315. if m:
  316. user = m.group('user')
  317. pswd = m.group('pswd')
  318. else:
  319. user = ''
  320. pswd = ''
  321. p = {}
  322. if parm:
  323. for s in parm.split(';'):
  324. if s:
  325. if not '=' in s:
  326. raise MalformedUrl(url, "The URL: '%s' is invalid: parameter %s does not specify a value (missing '=')" % (url, s))
  327. s1, s2 = s.split('=')
  328. p[s1] = s2
  329. return type, host, urllib.unquote(path), user, pswd, p
  330. def encodeurl(decoded):
  331. """Encodes a URL from tokens (scheme, network location, path,
  332. user, password, parameters).
  333. """
  334. type, host, path, user, pswd, p = decoded
  335. if not path:
  336. raise MissingParameterError('path', "encoded from the data %s" % str(decoded))
  337. if not type:
  338. raise MissingParameterError('type', "encoded from the data %s" % str(decoded))
  339. url = '%s://' % type
  340. if user and type != "file":
  341. url += "%s" % user
  342. if pswd:
  343. url += ":%s" % pswd
  344. url += "@"
  345. if host and type != "file":
  346. url += "%s" % host
  347. # Standardise path to ensure comparisons work
  348. while '//' in path:
  349. path = path.replace("//", "/")
  350. url += "%s" % urllib.quote(path)
  351. if p:
  352. for parm in p:
  353. url += ";%s=%s" % (parm, p[parm])
  354. return url
  355. def uri_replace(ud, uri_find, uri_replace, replacements, d):
  356. if not ud.url or not uri_find or not uri_replace:
  357. logger.error("uri_replace: passed an undefined value, not replacing")
  358. return None
  359. uri_decoded = list(decodeurl(ud.url))
  360. uri_find_decoded = list(decodeurl(uri_find))
  361. uri_replace_decoded = list(decodeurl(uri_replace))
  362. logger.debug(2, "For url %s comparing %s to %s" % (uri_decoded, uri_find_decoded, uri_replace_decoded))
  363. result_decoded = ['', '', '', '', '', {}]
  364. for loc, i in enumerate(uri_find_decoded):
  365. result_decoded[loc] = uri_decoded[loc]
  366. regexp = i
  367. if loc == 0 and regexp and not regexp.endswith("$"):
  368. # Leaving the type unanchored can mean "https" matching "file" can become "files"
  369. # which is clearly undesirable.
  370. regexp += "$"
  371. if loc == 5:
  372. # Handle URL parameters
  373. if i:
  374. # Any specified URL parameters must match
  375. for k in uri_replace_decoded[loc]:
  376. if uri_decoded[loc][k] != uri_replace_decoded[loc][k]:
  377. return None
  378. # Overwrite any specified replacement parameters
  379. for k in uri_replace_decoded[loc]:
  380. for l in replacements:
  381. uri_replace_decoded[loc][k] = uri_replace_decoded[loc][k].replace(l, replacements[l])
  382. result_decoded[loc][k] = uri_replace_decoded[loc][k]
  383. elif (re.match(regexp, uri_decoded[loc])):
  384. if not uri_replace_decoded[loc]:
  385. result_decoded[loc] = ""
  386. else:
  387. for k in replacements:
  388. uri_replace_decoded[loc] = uri_replace_decoded[loc].replace(k, replacements[k])
  389. #bb.note("%s %s %s" % (regexp, uri_replace_decoded[loc], uri_decoded[loc]))
  390. result_decoded[loc] = re.sub(regexp, uri_replace_decoded[loc], uri_decoded[loc])
  391. if loc == 2:
  392. # Handle path manipulations
  393. basename = None
  394. if uri_decoded[0] != uri_replace_decoded[0] and ud.mirrortarball:
  395. # If the source and destination url types differ, must be a mirrortarball mapping
  396. basename = os.path.basename(ud.mirrortarball)
  397. # Kill parameters, they make no sense for mirror tarballs
  398. uri_decoded[5] = {}
  399. elif ud.localpath and ud.method.supports_checksum(ud):
  400. basename = os.path.basename(ud.localpath)
  401. if basename and not result_decoded[loc].endswith(basename):
  402. result_decoded[loc] = os.path.join(result_decoded[loc], basename)
  403. else:
  404. return None
  405. result = encodeurl(result_decoded)
  406. if result == ud.url:
  407. return None
  408. logger.debug(2, "For url %s returning %s" % (ud.url, result))
  409. return result
  410. methods = []
  411. urldata_cache = {}
  412. saved_headrevs = {}
  413. def fetcher_init(d):
  414. """
  415. Called to initialize the fetchers once the configuration data is known.
  416. Calls before this must not hit the cache.
  417. """
  418. # When to drop SCM head revisions controlled by user policy
  419. srcrev_policy = d.getVar('BB_SRCREV_POLICY', True) or "clear"
  420. if srcrev_policy == "cache":
  421. logger.debug(1, "Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
  422. elif srcrev_policy == "clear":
  423. logger.debug(1, "Clearing SRCREV cache due to cache policy of: %s", srcrev_policy)
  424. revs = bb.persist_data.persist('BB_URI_HEADREVS', d)
  425. try:
  426. bb.fetch2.saved_headrevs = revs.items()
  427. except:
  428. pass
  429. revs.clear()
  430. else:
  431. raise FetchError("Invalid SRCREV cache policy of: %s" % srcrev_policy)
  432. _checksum_cache.init_cache(d)
  433. for m in methods:
  434. if hasattr(m, "init"):
  435. m.init(d)
  436. def fetcher_parse_save(d):
  437. _checksum_cache.save_extras(d)
  438. def fetcher_parse_done(d):
  439. _checksum_cache.save_merge(d)
  440. def fetcher_compare_revisions(d):
  441. """
  442. Compare the revisions in the persistant cache with current values and
  443. return true/false on whether they've changed.
  444. """
  445. data = bb.persist_data.persist('BB_URI_HEADREVS', d).items()
  446. data2 = bb.fetch2.saved_headrevs
  447. changed = False
  448. for key in data:
  449. if key not in data2 or data2[key] != data[key]:
  450. logger.debug(1, "%s changed", key)
  451. changed = True
  452. return True
  453. else:
  454. logger.debug(2, "%s did not change", key)
  455. return False
  456. def mirror_from_string(data):
  457. return [ i.split() for i in (data or "").replace('\\n','\n').split('\n') if i ]
  458. def verify_checksum(ud, d, precomputed={}):
  459. """
  460. verify the MD5 and SHA256 checksum for downloaded src
  461. Raises a FetchError if one or both of the SRC_URI checksums do not match
  462. the downloaded file, or if BB_STRICT_CHECKSUM is set and there are no
  463. checksums specified.
  464. Returns a dict of checksums that can be stored in a done stamp file and
  465. passed in as precomputed parameter in a later call to avoid re-computing
  466. the checksums from the file. This allows verifying the checksums of the
  467. file against those in the recipe each time, rather than only after
  468. downloading. See https://bugzilla.yoctoproject.org/show_bug.cgi?id=5571.
  469. """
  470. _MD5_KEY = "md5"
  471. _SHA256_KEY = "sha256"
  472. if ud.ignore_checksums or not ud.method.supports_checksum(ud):
  473. return {}
  474. if _MD5_KEY in precomputed:
  475. md5data = precomputed[_MD5_KEY]
  476. else:
  477. md5data = bb.utils.md5_file(ud.localpath)
  478. if _SHA256_KEY in precomputed:
  479. sha256data = precomputed[_SHA256_KEY]
  480. else:
  481. sha256data = bb.utils.sha256_file(ud.localpath)
  482. if ud.method.recommends_checksum(ud):
  483. # If strict checking enabled and neither sum defined, raise error
  484. strict = d.getVar("BB_STRICT_CHECKSUM", True) or "0"
  485. if (strict == "1") and not (ud.md5_expected or ud.sha256_expected):
  486. logger.error('No checksum specified for %s, please add at least one to the recipe:\n'
  487. 'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' %
  488. (ud.localpath, ud.md5_name, md5data,
  489. ud.sha256_name, sha256data))
  490. raise NoChecksumError('Missing SRC_URI checksum', ud.url)
  491. # Log missing sums so user can more easily add them
  492. if not ud.md5_expected:
  493. logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
  494. 'SRC_URI[%s] = "%s"',
  495. ud.localpath, ud.md5_name, md5data)
  496. if not ud.sha256_expected:
  497. logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
  498. 'SRC_URI[%s] = "%s"',
  499. ud.localpath, ud.sha256_name, sha256data)
  500. md5mismatch = False
  501. sha256mismatch = False
  502. if ud.md5_expected != md5data:
  503. md5mismatch = True
  504. if ud.sha256_expected != sha256data:
  505. sha256mismatch = True
  506. # We want to alert the user if a checksum is defined in the recipe but
  507. # it does not match.
  508. msg = ""
  509. mismatch = False
  510. if md5mismatch and ud.md5_expected:
  511. msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'md5', md5data, ud.md5_expected)
  512. mismatch = True;
  513. if sha256mismatch and ud.sha256_expected:
  514. msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'sha256', sha256data, ud.sha256_expected)
  515. mismatch = True;
  516. if mismatch:
  517. msg = msg + '\nIf this change is expected (e.g. you have upgraded to a new version without updating the checksums) then you can use these lines within the recipe:\nSRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"\nOtherwise you should retry the download and/or check with upstream to determine if the file has become corrupted or otherwise unexpectedly modified.\n' % (ud.md5_name, md5data, ud.sha256_name, sha256data)
  518. if len(msg):
  519. raise ChecksumError('Checksum mismatch!%s' % msg, ud.url, md5data)
  520. return {
  521. _MD5_KEY: md5data,
  522. _SHA256_KEY: sha256data
  523. }
  524. def verify_donestamp(ud, d):
  525. """
  526. Check whether the done stamp file has the right checksums (if the fetch
  527. method supports them). If it doesn't, delete the done stamp and force
  528. a re-download.
  529. Returns True, if the donestamp exists and is valid, False otherwise. When
  530. returning False, any existing done stamps are removed.
  531. """
  532. if not os.path.exists(ud.donestamp):
  533. return False
  534. if not ud.method.supports_checksum(ud):
  535. # done stamp exists, checksums not supported; assume the local file is
  536. # current
  537. return True
  538. if not os.path.exists(ud.localpath):
  539. # done stamp exists, but the downloaded file does not; the done stamp
  540. # must be incorrect, re-trigger the download
  541. bb.utils.remove(ud.donestamp)
  542. return False
  543. precomputed_checksums = {}
  544. # Only re-use the precomputed checksums if the donestamp is newer than the
  545. # file. Do not rely on the mtime of directories, though. If ud.localpath is
  546. # a directory, there will probably not be any checksums anyway.
  547. if (os.path.isdir(ud.localpath) or
  548. os.path.getmtime(ud.localpath) < os.path.getmtime(ud.donestamp)):
  549. try:
  550. with open(ud.donestamp, "rb") as cachefile:
  551. pickled = pickle.Unpickler(cachefile)
  552. precomputed_checksums.update(pickled.load())
  553. except Exception as e:
  554. # Avoid the warnings on the upgrade path from emtpy done stamp
  555. # files to those containing the checksums.
  556. if not isinstance(e, EOFError):
  557. # Ignore errors, they aren't fatal
  558. logger.warn("Couldn't load checksums from donestamp %s: %s "
  559. "(msg: %s)" % (ud.donestamp, type(e).__name__,
  560. str(e)))
  561. try:
  562. checksums = verify_checksum(ud, d, precomputed_checksums)
  563. # If the cache file did not have the checksums, compute and store them
  564. # as an upgrade path from the previous done stamp file format.
  565. if checksums != precomputed_checksums:
  566. with open(ud.donestamp, "wb") as cachefile:
  567. p = pickle.Pickler(cachefile, pickle.HIGHEST_PROTOCOL)
  568. p.dump(checksums)
  569. return True
  570. except ChecksumError as e:
  571. # Checksums failed to verify, trigger re-download and remove the
  572. # incorrect stamp file.
  573. logger.warn("Checksum mismatch for local file %s\n"
  574. "Cleaning and trying again." % ud.localpath)
  575. rename_bad_checksum(ud, e.checksum)
  576. bb.utils.remove(ud.donestamp)
  577. return False
  578. def update_stamp(ud, d):
  579. """
  580. donestamp is file stamp indicating the whole fetching is done
  581. this function update the stamp after verifying the checksum
  582. """
  583. if os.path.exists(ud.donestamp):
  584. # Touch the done stamp file to show active use of the download
  585. try:
  586. os.utime(ud.donestamp, None)
  587. except:
  588. # Errors aren't fatal here
  589. pass
  590. else:
  591. checksums = verify_checksum(ud, d)
  592. # Store the checksums for later re-verification against the recipe
  593. with open(ud.donestamp, "wb") as cachefile:
  594. p = pickle.Pickler(cachefile, pickle.HIGHEST_PROTOCOL)
  595. p.dump(checksums)
  596. def subprocess_setup():
  597. # Python installs a SIGPIPE handler by default. This is usually not what
  598. # non-Python subprocesses expect.
  599. # SIGPIPE errors are known issues with gzip/bash
  600. signal.signal(signal.SIGPIPE, signal.SIG_DFL)
  601. def get_autorev(d):
  602. # only not cache src rev in autorev case
  603. if d.getVar('BB_SRCREV_POLICY', True) != "cache":
  604. d.setVar('__BB_DONT_CACHE', '1')
  605. return "AUTOINC"
  606. def get_srcrev(d, method_name='sortable_revision'):
  607. """
  608. Return the revsion string, usually for use in the version string (PV) of the current package
  609. Most packages usually only have one SCM so we just pass on the call.
  610. In the multi SCM case, we build a value based on SRCREV_FORMAT which must
  611. have been set.
  612. The idea here is that we put the string "AUTOINC+" into return value if the revisions are not
  613. incremental, other code is then responsible for turning that into an increasing value (if needed)
  614. A method_name can be supplied to retrieve an alternatively formatted revision from a fetcher, if
  615. that fetcher provides a method with the given name and the same signature as sortable_revision.
  616. """
  617. scms = []
  618. fetcher = Fetch(d.getVar('SRC_URI', True).split(), d)
  619. urldata = fetcher.ud
  620. for u in urldata:
  621. if urldata[u].method.supports_srcrev():
  622. scms.append(u)
  623. if len(scms) == 0:
  624. raise FetchError("SRCREV was used yet no valid SCM was found in SRC_URI")
  625. if len(scms) == 1 and len(urldata[scms[0]].names) == 1:
  626. autoinc, rev = getattr(urldata[scms[0]].method, method_name)(urldata[scms[0]], d, urldata[scms[0]].names[0])
  627. if len(rev) > 10:
  628. rev = rev[:10]
  629. if autoinc:
  630. return "AUTOINC+" + rev
  631. return rev
  632. #
  633. # Mutiple SCMs are in SRC_URI so we resort to SRCREV_FORMAT
  634. #
  635. format = d.getVar('SRCREV_FORMAT', True)
  636. if not format:
  637. raise FetchError("The SRCREV_FORMAT variable must be set when multiple SCMs are used.")
  638. seenautoinc = False
  639. for scm in scms:
  640. ud = urldata[scm]
  641. for name in ud.names:
  642. autoinc, rev = getattr(ud.method, method_name)(ud, d, name)
  643. seenautoinc = seenautoinc or autoinc
  644. if len(rev) > 10:
  645. rev = rev[:10]
  646. format = format.replace(name, rev)
  647. if seenautoinc:
  648. format = "AUTOINC+" + format
  649. return format
  650. def localpath(url, d):
  651. fetcher = bb.fetch2.Fetch([url], d)
  652. return fetcher.localpath(url)
  653. def runfetchcmd(cmd, d, quiet = False, cleanup = []):
  654. """
  655. Run cmd returning the command output
  656. Raise an error if interrupted or cmd fails
  657. Optionally echo command output to stdout
  658. Optionally remove the files/directories listed in cleanup upon failure
  659. """
  660. # Need to export PATH as binary could be in metadata paths
  661. # rather than host provided
  662. # Also include some other variables.
  663. # FIXME: Should really include all export varaiables?
  664. exportvars = ['HOME', 'PATH',
  665. 'HTTP_PROXY', 'http_proxy',
  666. 'HTTPS_PROXY', 'https_proxy',
  667. 'FTP_PROXY', 'ftp_proxy',
  668. 'FTPS_PROXY', 'ftps_proxy',
  669. 'NO_PROXY', 'no_proxy',
  670. 'ALL_PROXY', 'all_proxy',
  671. 'GIT_PROXY_COMMAND',
  672. 'GIT_SSL_CAINFO',
  673. 'GIT_SMART_HTTP',
  674. 'SSH_AUTH_SOCK', 'SSH_AGENT_PID',
  675. 'SOCKS5_USER', 'SOCKS5_PASSWD']
  676. for var in exportvars:
  677. val = d.getVar(var, True)
  678. if val:
  679. cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
  680. logger.debug(1, "Running %s", cmd)
  681. success = False
  682. error_message = ""
  683. try:
  684. (output, errors) = bb.process.run(cmd, shell=True, stderr=subprocess.PIPE)
  685. success = True
  686. except bb.process.NotFoundError as e:
  687. error_message = "Fetch command %s" % (e.command)
  688. except bb.process.ExecutionError as e:
  689. if e.stdout:
  690. output = "output:\n%s\n%s" % (e.stdout, e.stderr)
  691. elif e.stderr:
  692. output = "output:\n%s" % e.stderr
  693. else:
  694. output = "no output"
  695. error_message = "Fetch command failed with exit code %s, %s" % (e.exitcode, output)
  696. except bb.process.CmdError as e:
  697. error_message = "Fetch command %s could not be run:\n%s" % (e.command, e.msg)
  698. if not success:
  699. for f in cleanup:
  700. try:
  701. bb.utils.remove(f, True)
  702. except OSError:
  703. pass
  704. raise FetchError(error_message)
  705. return output
  706. def check_network_access(d, info = "", url = None):
  707. """
  708. log remote network access, and error if BB_NO_NETWORK is set
  709. """
  710. if d.getVar("BB_NO_NETWORK", True) == "1":
  711. raise NetworkAccess(url, info)
  712. else:
  713. logger.debug(1, "Fetcher accessed the network with the command %s" % info)
  714. def build_mirroruris(origud, mirrors, ld):
  715. uris = []
  716. uds = []
  717. replacements = {}
  718. replacements["TYPE"] = origud.type
  719. replacements["HOST"] = origud.host
  720. replacements["PATH"] = origud.path
  721. replacements["BASENAME"] = origud.path.split("/")[-1]
  722. replacements["MIRRORNAME"] = origud.host.replace(':','.') + origud.path.replace('/', '.').replace('*', '.')
  723. def adduri(ud, uris, uds):
  724. for line in mirrors:
  725. try:
  726. (find, replace) = line
  727. except ValueError:
  728. continue
  729. newuri = uri_replace(ud, find, replace, replacements, ld)
  730. if not newuri or newuri in uris or newuri == origud.url:
  731. continue
  732. if not trusted_network(ld, newuri):
  733. logger.debug(1, "Mirror %s not in the list of trusted networks, skipping" % (newuri))
  734. continue
  735. try:
  736. newud = FetchData(newuri, ld)
  737. newud.setup_localpath(ld)
  738. except bb.fetch2.BBFetchException as e:
  739. logger.debug(1, "Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
  740. logger.debug(1, str(e))
  741. try:
  742. # setup_localpath of file:// urls may fail, we should still see
  743. # if mirrors of the url exist
  744. adduri(newud, uris, uds)
  745. except UnboundLocalError:
  746. pass
  747. continue
  748. uris.append(newuri)
  749. uds.append(newud)
  750. adduri(newud, uris, uds)
  751. adduri(origud, uris, uds)
  752. return uris, uds
  753. def rename_bad_checksum(ud, suffix):
  754. """
  755. Renames files to have suffix from parameter
  756. """
  757. if ud.localpath is None:
  758. return
  759. new_localpath = "%s_bad-checksum_%s" % (ud.localpath, suffix)
  760. bb.warn("Renaming %s to %s" % (ud.localpath, new_localpath))
  761. bb.utils.movefile(ud.localpath, new_localpath)
  762. def try_mirror_url(fetch, origud, ud, ld, check = False):
  763. # Return of None or a value means we're finished
  764. # False means try another url
  765. try:
  766. if check:
  767. found = ud.method.checkstatus(fetch, ud, ld)
  768. if found:
  769. return found
  770. return False
  771. os.chdir(ld.getVar("DL_DIR", True))
  772. if not verify_donestamp(ud, ld) or ud.method.need_update(ud, ld):
  773. ud.method.download(ud, ld)
  774. if hasattr(ud.method,"build_mirror_data"):
  775. ud.method.build_mirror_data(ud, ld)
  776. if not ud.localpath or not os.path.exists(ud.localpath):
  777. return False
  778. if ud.localpath == origud.localpath:
  779. return ud.localpath
  780. # We may be obtaining a mirror tarball which needs further processing by the real fetcher
  781. # If that tarball is a local file:// we need to provide a symlink to it
  782. dldir = ld.getVar("DL_DIR", True)
  783. if origud.mirrortarball and os.path.basename(ud.localpath) == os.path.basename(origud.mirrortarball) \
  784. and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
  785. # Create donestamp in old format to avoid triggering a re-download
  786. bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
  787. open(ud.donestamp, 'w').close()
  788. dest = os.path.join(dldir, os.path.basename(ud.localpath))
  789. if not os.path.exists(dest):
  790. os.symlink(ud.localpath, dest)
  791. if not verify_donestamp(origud, ld) or origud.method.need_update(origud, ld):
  792. origud.method.download(origud, ld)
  793. if hasattr(origud.method,"build_mirror_data"):
  794. origud.method.build_mirror_data(origud, ld)
  795. return ud.localpath
  796. # Otherwise the result is a local file:// and we symlink to it
  797. if not os.path.exists(origud.localpath):
  798. if os.path.islink(origud.localpath):
  799. # Broken symbolic link
  800. os.unlink(origud.localpath)
  801. os.symlink(ud.localpath, origud.localpath)
  802. update_stamp(origud, ld)
  803. return ud.localpath
  804. except bb.fetch2.NetworkAccess:
  805. raise
  806. except bb.fetch2.BBFetchException as e:
  807. if isinstance(e, ChecksumError):
  808. logger.warn("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (ud.url, origud.url))
  809. logger.warn(str(e))
  810. rename_bad_checksum(ud, e.checksum)
  811. elif isinstance(e, NoChecksumError):
  812. raise
  813. else:
  814. logger.debug(1, "Mirror fetch failure for url %s (original url: %s)" % (ud.url, origud.url))
  815. logger.debug(1, str(e))
  816. try:
  817. ud.method.clean(ud, ld)
  818. except UnboundLocalError:
  819. pass
  820. return False
  821. def try_mirrors(fetch, d, origud, mirrors, check = False):
  822. """
  823. Try to use a mirrored version of the sources.
  824. This method will be automatically called before the fetchers go.
  825. d Is a bb.data instance
  826. uri is the original uri we're trying to download
  827. mirrors is the list of mirrors we're going to try
  828. """
  829. ld = d.createCopy()
  830. uris, uds = build_mirroruris(origud, mirrors, ld)
  831. for index, uri in enumerate(uris):
  832. ret = try_mirror_url(fetch, origud, uds[index], ld, check)
  833. if ret != False:
  834. return ret
  835. return None
  836. def trusted_network(d, url):
  837. """
  838. Use a trusted url during download if networking is enabled and
  839. BB_ALLOWED_NETWORKS is set globally or for a specific recipe.
  840. Note: modifies SRC_URI & mirrors.
  841. """
  842. if d.getVar('BB_NO_NETWORK', True) == "1":
  843. return True
  844. pkgname = d.expand(d.getVar('PN', False))
  845. trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname)
  846. if not trusted_hosts:
  847. trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS', True)
  848. # Not enabled.
  849. if not trusted_hosts:
  850. return True
  851. scheme, network, path, user, passwd, param = decodeurl(url)
  852. if not network:
  853. return True
  854. network = network.lower()
  855. for host in trusted_hosts.split(" "):
  856. host = host.lower()
  857. if host.startswith("*.") and ("." + network).endswith(host[1:]):
  858. return True
  859. if host == network:
  860. return True
  861. return False
  862. def srcrev_internal_helper(ud, d, name):
  863. """
  864. Return:
  865. a) a source revision if specified
  866. b) latest revision if SRCREV="AUTOINC"
  867. c) None if not specified
  868. """
  869. srcrev = None
  870. pn = d.getVar("PN", True)
  871. attempts = []
  872. if name != '' and pn:
  873. attempts.append("SRCREV_%s_pn-%s" % (name, pn))
  874. if name != '':
  875. attempts.append("SRCREV_%s" % name)
  876. if pn:
  877. attempts.append("SRCREV_pn-%s" % pn)
  878. attempts.append("SRCREV")
  879. for a in attempts:
  880. srcrev = d.getVar(a, True)
  881. if srcrev and srcrev != "INVALID":
  882. break
  883. if 'rev' in ud.parm and 'tag' in ud.parm:
  884. raise FetchError("Please specify a ;rev= parameter or a ;tag= parameter in the url %s but not both." % (ud.url))
  885. if 'rev' in ud.parm or 'tag' in ud.parm:
  886. if 'rev' in ud.parm:
  887. parmrev = ud.parm['rev']
  888. else:
  889. parmrev = ud.parm['tag']
  890. if srcrev == "INVALID" or not srcrev:
  891. return parmrev
  892. if srcrev != parmrev:
  893. raise FetchError("Conflicting revisions (%s from SRCREV and %s from the url) found, please spcify one valid value" % (srcrev, parmrev))
  894. return parmrev
  895. if srcrev == "INVALID" or not srcrev:
  896. 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)
  897. if srcrev == "AUTOINC":
  898. srcrev = ud.method.latest_revision(ud, d, name)
  899. return srcrev
  900. def get_checksum_file_list(d):
  901. """ Get a list of files checksum in SRC_URI
  902. Returns the resolved local paths of all local file entries in
  903. SRC_URI as a space-separated string
  904. """
  905. fetch = Fetch([], d, cache = False, localonly = True)
  906. dl_dir = d.getVar('DL_DIR', True)
  907. filelist = []
  908. for u in fetch.urls:
  909. ud = fetch.ud[u]
  910. if ud and isinstance(ud.method, local.Local):
  911. paths = ud.method.localpaths(ud, d)
  912. for f in paths:
  913. pth = ud.decodedurl
  914. if '*' in pth:
  915. f = os.path.join(os.path.abspath(f), pth)
  916. if f.startswith(dl_dir):
  917. # The local fetcher's behaviour is to return a path under DL_DIR if it couldn't find the file anywhere else
  918. if os.path.exists(f):
  919. bb.warn("Getting checksum for %s SRC_URI entry %s: file not found except in DL_DIR" % (d.getVar('PN', True), os.path.basename(f)))
  920. else:
  921. bb.warn("Unable to get checksum for %s SRC_URI entry %s: file could not be found" % (d.getVar('PN', True), os.path.basename(f)))
  922. filelist.append(f + ":" + str(os.path.exists(f)))
  923. return " ".join(filelist)
  924. def get_file_checksums(filelist, pn):
  925. """Get a list of the checksums for a list of local files
  926. Returns the checksums for a list of local files, caching the results as
  927. it proceeds
  928. """
  929. def checksum_file(f):
  930. try:
  931. checksum = _checksum_cache.get_checksum(f)
  932. except OSError as e:
  933. bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
  934. return None
  935. return checksum
  936. def checksum_dir(pth):
  937. # Handle directories recursively
  938. dirchecksums = []
  939. for root, dirs, files in os.walk(pth):
  940. for name in files:
  941. fullpth = os.path.join(root, name)
  942. checksum = checksum_file(fullpth)
  943. if checksum:
  944. dirchecksums.append((fullpth, checksum))
  945. return dirchecksums
  946. checksums = []
  947. for pth in filelist.split():
  948. exist = pth.split(":")[1]
  949. if exist == "False":
  950. continue
  951. pth = pth.split(":")[0]
  952. if '*' in pth:
  953. # Handle globs
  954. for f in glob.glob(pth):
  955. if os.path.isdir(f):
  956. checksums.extend(checksum_dir(f))
  957. else:
  958. checksum = checksum_file(f)
  959. checksums.append((f, checksum))
  960. elif os.path.isdir(pth):
  961. checksums.extend(checksum_dir(pth))
  962. else:
  963. checksum = checksum_file(pth)
  964. checksums.append((pth, checksum))
  965. checksums.sort(key=operator.itemgetter(1))
  966. return checksums
  967. class FetchData(object):
  968. """
  969. A class which represents the fetcher state for a given URI.
  970. """
  971. def __init__(self, url, d, localonly = False):
  972. # localpath is the location of a downloaded result. If not set, the file is local.
  973. self.donestamp = None
  974. self.localfile = ""
  975. self.localpath = None
  976. self.lockfile = None
  977. self.mirrortarball = None
  978. self.basename = None
  979. self.basepath = None
  980. (self.type, self.host, self.path, self.user, self.pswd, self.parm) = decodeurl(data.expand(url, d))
  981. self.date = self.getSRCDate(d)
  982. self.url = url
  983. if not self.user and "user" in self.parm:
  984. self.user = self.parm["user"]
  985. if not self.pswd and "pswd" in self.parm:
  986. self.pswd = self.parm["pswd"]
  987. self.setup = False
  988. if "name" in self.parm:
  989. self.md5_name = "%s.md5sum" % self.parm["name"]
  990. self.sha256_name = "%s.sha256sum" % self.parm["name"]
  991. else:
  992. self.md5_name = "md5sum"
  993. self.sha256_name = "sha256sum"
  994. if self.md5_name in self.parm:
  995. self.md5_expected = self.parm[self.md5_name]
  996. elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
  997. self.md5_expected = None
  998. else:
  999. self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name)
  1000. if self.sha256_name in self.parm:
  1001. self.sha256_expected = self.parm[self.sha256_name]
  1002. elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
  1003. self.sha256_expected = None
  1004. else:
  1005. self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name)
  1006. self.ignore_checksums = False
  1007. self.names = self.parm.get("name",'default').split(',')
  1008. self.method = None
  1009. for m in methods:
  1010. if m.supports(self, d):
  1011. self.method = m
  1012. break
  1013. if not self.method:
  1014. raise NoMethodError(url)
  1015. if localonly and not isinstance(self.method, local.Local):
  1016. raise NonLocalMethod()
  1017. if self.parm.get("proto", None) and "protocol" not in self.parm:
  1018. logger.warn('Consider updating %s recipe to use "protocol" not "proto" in SRC_URI.', d.getVar('PN', True))
  1019. self.parm["protocol"] = self.parm.get("proto", None)
  1020. if hasattr(self.method, "urldata_init"):
  1021. self.method.urldata_init(self, d)
  1022. if "localpath" in self.parm:
  1023. # if user sets localpath for file, use it instead.
  1024. self.localpath = self.parm["localpath"]
  1025. self.basename = os.path.basename(self.localpath)
  1026. elif self.localfile:
  1027. self.localpath = self.method.localpath(self, d)
  1028. dldir = d.getVar("DL_DIR", True)
  1029. # Note: .done and .lock files should always be in DL_DIR whereas localpath may not be.
  1030. if self.localpath and self.localpath.startswith(dldir):
  1031. basepath = self.localpath
  1032. elif self.localpath:
  1033. basepath = dldir + os.sep + os.path.basename(self.localpath)
  1034. else:
  1035. basepath = dldir + os.sep + (self.basepath or self.basename)
  1036. self.donestamp = basepath + '.done'
  1037. self.lockfile = basepath + '.lock'
  1038. def setup_revisons(self, d):
  1039. self.revisions = {}
  1040. for name in self.names:
  1041. self.revisions[name] = srcrev_internal_helper(self, d, name)
  1042. # add compatibility code for non name specified case
  1043. if len(self.names) == 1:
  1044. self.revision = self.revisions[self.names[0]]
  1045. def setup_localpath(self, d):
  1046. if not self.localpath:
  1047. self.localpath = self.method.localpath(self, d)
  1048. def getSRCDate(self, d):
  1049. """
  1050. Return the SRC Date for the component
  1051. d the bb.data module
  1052. """
  1053. if "srcdate" in self.parm:
  1054. return self.parm['srcdate']
  1055. pn = d.getVar("PN", True)
  1056. if pn:
  1057. return d.getVar("SRCDATE_%s" % pn, True) or d.getVar("SRCDATE", True) or d.getVar("DATE", True)
  1058. return d.getVar("SRCDATE", True) or d.getVar("DATE", True)
  1059. class FetchMethod(object):
  1060. """Base class for 'fetch'ing data"""
  1061. def __init__(self, urls = []):
  1062. self.urls = []
  1063. def supports(self, urldata, d):
  1064. """
  1065. Check to see if this fetch class supports a given url.
  1066. """
  1067. return 0
  1068. def localpath(self, urldata, d):
  1069. """
  1070. Return the local filename of a given url assuming a successful fetch.
  1071. Can also setup variables in urldata for use in go (saving code duplication
  1072. and duplicate code execution)
  1073. """
  1074. return os.path.join(data.getVar("DL_DIR", d, True), urldata.localfile)
  1075. def supports_checksum(self, urldata):
  1076. """
  1077. Is localpath something that can be represented by a checksum?
  1078. """
  1079. # We cannot compute checksums for directories
  1080. if os.path.isdir(urldata.localpath) == True:
  1081. return False
  1082. if urldata.localpath.find("*") != -1:
  1083. return False
  1084. return True
  1085. def recommends_checksum(self, urldata):
  1086. """
  1087. Is the backend on where checksumming is recommended (should warnings
  1088. be displayed if there is no checksum)?
  1089. """
  1090. return False
  1091. def _strip_leading_slashes(self, relpath):
  1092. """
  1093. Remove leading slash as os.path.join can't cope
  1094. """
  1095. while os.path.isabs(relpath):
  1096. relpath = relpath[1:]
  1097. return relpath
  1098. def setUrls(self, urls):
  1099. self.__urls = urls
  1100. def getUrls(self):
  1101. return self.__urls
  1102. urls = property(getUrls, setUrls, None, "Urls property")
  1103. def need_update(self, ud, d):
  1104. """
  1105. Force a fetch, even if localpath exists?
  1106. """
  1107. if os.path.exists(ud.localpath):
  1108. return False
  1109. return True
  1110. def supports_srcrev(self):
  1111. """
  1112. The fetcher supports auto source revisions (SRCREV)
  1113. """
  1114. return False
  1115. def download(self, urldata, d):
  1116. """
  1117. Fetch urls
  1118. Assumes localpath was called first
  1119. """
  1120. raise NoMethodError(url)
  1121. def unpack(self, urldata, rootdir, data):
  1122. iterate = False
  1123. file = urldata.localpath
  1124. try:
  1125. unpack = bb.utils.to_boolean(urldata.parm.get('unpack'), True)
  1126. except ValueError as exc:
  1127. bb.fatal("Invalid value for 'unpack' parameter for %s: %s" %
  1128. (file, urldata.parm.get('unpack')))
  1129. base, ext = os.path.splitext(file)
  1130. if ext in ['.gz', '.bz2', '.Z', '.xz', '.lz']:
  1131. efile = os.path.join(rootdir, os.path.basename(base))
  1132. else:
  1133. efile = file
  1134. cmd = None
  1135. if unpack:
  1136. if file.endswith('.tar'):
  1137. cmd = 'tar x --no-same-owner -f %s' % file
  1138. elif file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'):
  1139. cmd = 'tar xz --no-same-owner -f %s' % file
  1140. elif file.endswith('.tbz') or file.endswith('.tbz2') or file.endswith('.tar.bz2'):
  1141. cmd = 'bzip2 -dc %s | tar x --no-same-owner -f -' % file
  1142. elif file.endswith('.gz') or file.endswith('.Z') or file.endswith('.z'):
  1143. cmd = 'gzip -dc %s > %s' % (file, efile)
  1144. elif file.endswith('.bz2'):
  1145. cmd = 'bzip2 -dc %s > %s' % (file, efile)
  1146. elif file.endswith('.tar.xz'):
  1147. cmd = 'xz -dc %s | tar x --no-same-owner -f -' % file
  1148. elif file.endswith('.xz'):
  1149. cmd = 'xz -dc %s > %s' % (file, efile)
  1150. elif file.endswith('.tar.lz'):
  1151. cmd = 'lzip -dc %s | tar x --no-same-owner -f -' % file
  1152. elif file.endswith('.lz'):
  1153. cmd = 'lzip -dc %s > %s' % (file, efile)
  1154. elif file.endswith('.zip') or file.endswith('.jar'):
  1155. try:
  1156. dos = bb.utils.to_boolean(urldata.parm.get('dos'), False)
  1157. except ValueError as exc:
  1158. bb.fatal("Invalid value for 'dos' parameter for %s: %s" %
  1159. (file, urldata.parm.get('dos')))
  1160. cmd = 'unzip -q -o'
  1161. if dos:
  1162. cmd = '%s -a' % cmd
  1163. cmd = "%s '%s'" % (cmd, file)
  1164. elif file.endswith('.rpm') or file.endswith('.srpm'):
  1165. if 'extract' in urldata.parm:
  1166. unpack_file = urldata.parm.get('extract')
  1167. cmd = 'rpm2cpio.sh %s | cpio -id %s' % (file, unpack_file)
  1168. iterate = True
  1169. iterate_file = unpack_file
  1170. else:
  1171. cmd = 'rpm2cpio.sh %s | cpio -id' % (file)
  1172. elif file.endswith('.deb') or file.endswith('.ipk'):
  1173. cmd = 'ar -p %s data.tar.gz | zcat | tar --no-same-owner -xpf -' % file
  1174. if not unpack or not cmd:
  1175. # If file == dest, then avoid any copies, as we already put the file into dest!
  1176. dest = os.path.join(rootdir, os.path.basename(file))
  1177. if (file != dest) and not (os.path.exists(dest) and os.path.samefile(file, dest)):
  1178. if os.path.isdir(file):
  1179. # If for example we're asked to copy file://foo/bar, we need to unpack the result into foo/bar
  1180. basepath = getattr(urldata, "basepath", None)
  1181. destdir = "."
  1182. if basepath and basepath.endswith("/"):
  1183. basepath = basepath.rstrip("/")
  1184. elif basepath:
  1185. basepath = os.path.dirname(basepath)
  1186. if basepath and basepath.find("/") != -1:
  1187. destdir = basepath[:basepath.rfind('/')]
  1188. destdir = destdir.strip('/')
  1189. if destdir != "." and not os.access("%s/%s" % (rootdir, destdir), os.F_OK):
  1190. os.makedirs("%s/%s" % (rootdir, destdir))
  1191. cmd = 'cp -fpPR %s %s/%s/' % (file, rootdir, destdir)
  1192. #cmd = 'tar -cf - -C "%d" -ps . | tar -xf - -C "%s/%s/"' % (file, rootdir, destdir)
  1193. else:
  1194. # The "destdir" handling was specifically done for FILESPATH
  1195. # items. So, only do so for file:// entries.
  1196. if urldata.type == "file" and urldata.path.find("/") != -1:
  1197. destdir = urldata.path.rsplit("/", 1)[0]
  1198. if urldata.parm.get('subdir') != None:
  1199. destdir = urldata.parm.get('subdir') + "/" + destdir
  1200. else:
  1201. if urldata.parm.get('subdir') != None:
  1202. destdir = urldata.parm.get('subdir')
  1203. else:
  1204. destdir = "."
  1205. bb.utils.mkdirhier("%s/%s" % (rootdir, destdir))
  1206. cmd = 'cp -f %s %s/%s/' % (file, rootdir, destdir)
  1207. if not cmd:
  1208. return
  1209. # Change to subdir before executing command
  1210. save_cwd = os.getcwd();
  1211. os.chdir(rootdir)
  1212. if 'subdir' in urldata.parm:
  1213. newdir = ("%s/%s" % (rootdir, urldata.parm.get('subdir')))
  1214. bb.utils.mkdirhier(newdir)
  1215. os.chdir(newdir)
  1216. path = data.getVar('PATH', True)
  1217. if path:
  1218. cmd = "PATH=\"%s\" %s" % (path, cmd)
  1219. bb.note("Unpacking %s to %s/" % (file, os.getcwd()))
  1220. ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True)
  1221. os.chdir(save_cwd)
  1222. if ret != 0:
  1223. raise UnpackError("Unpack command %s failed with return value %s" % (cmd, ret), urldata.url)
  1224. if iterate is True:
  1225. iterate_urldata = urldata
  1226. iterate_urldata.localpath = "%s/%s" % (rootdir, iterate_file)
  1227. self.unpack(urldata, rootdir, data)
  1228. return
  1229. def clean(self, urldata, d):
  1230. """
  1231. Clean any existing full or partial download
  1232. """
  1233. bb.utils.remove(urldata.localpath)
  1234. def try_premirror(self, urldata, d):
  1235. """
  1236. Should premirrors be used?
  1237. """
  1238. return True
  1239. def checkstatus(self, fetch, urldata, d):
  1240. """
  1241. Check the status of a URL
  1242. Assumes localpath was called first
  1243. """
  1244. logger.info("URL %s could not be checked for status since no method exists.", url)
  1245. return True
  1246. def latest_revision(self, ud, d, name):
  1247. """
  1248. Look in the cache for the latest revision, if not present ask the SCM.
  1249. """
  1250. if not hasattr(self, "_latest_revision"):
  1251. raise ParameterError("The fetcher for this URL does not support _latest_revision", url)
  1252. revs = bb.persist_data.persist('BB_URI_HEADREVS', d)
  1253. key = self.generate_revision_key(ud, d, name)
  1254. try:
  1255. return revs[key]
  1256. except KeyError:
  1257. revs[key] = rev = self._latest_revision(ud, d, name)
  1258. return rev
  1259. def sortable_revision(self, ud, d, name):
  1260. latest_rev = self._build_revision(ud, d, name)
  1261. return True, str(latest_rev)
  1262. def generate_revision_key(self, ud, d, name):
  1263. key = self._revision_key(ud, d, name)
  1264. return "%s-%s" % (key, d.getVar("PN", True) or "")
  1265. class Fetch(object):
  1266. def __init__(self, urls, d, cache = True, localonly = False):
  1267. if localonly and cache:
  1268. raise Exception("bb.fetch2.Fetch.__init__: cannot set cache and localonly at same time")
  1269. if len(urls) == 0:
  1270. urls = d.getVar("SRC_URI", True).split()
  1271. self.urls = urls
  1272. self.d = d
  1273. self.ud = {}
  1274. fn = d.getVar('FILE', True)
  1275. if cache and fn and fn in urldata_cache:
  1276. self.ud = urldata_cache[fn]
  1277. for url in urls:
  1278. if url not in self.ud:
  1279. try:
  1280. self.ud[url] = FetchData(url, d, localonly)
  1281. except NonLocalMethod:
  1282. if localonly:
  1283. self.ud[url] = None
  1284. pass
  1285. if fn and cache:
  1286. urldata_cache[fn] = self.ud
  1287. def localpath(self, url):
  1288. if url not in self.urls:
  1289. self.ud[url] = FetchData(url, self.d)
  1290. self.ud[url].setup_localpath(self.d)
  1291. return self.d.expand(self.ud[url].localpath)
  1292. def localpaths(self):
  1293. """
  1294. Return a list of the local filenames, assuming successful fetch
  1295. """
  1296. local = []
  1297. for u in self.urls:
  1298. ud = self.ud[u]
  1299. ud.setup_localpath(self.d)
  1300. local.append(ud.localpath)
  1301. return local
  1302. def download(self, urls = []):
  1303. """
  1304. Fetch all urls
  1305. """
  1306. if len(urls) == 0:
  1307. urls = self.urls
  1308. network = self.d.getVar("BB_NO_NETWORK", True)
  1309. premirroronly = (self.d.getVar("BB_FETCH_PREMIRRORONLY", True) == "1")
  1310. for u in urls:
  1311. ud = self.ud[u]
  1312. ud.setup_localpath(self.d)
  1313. m = ud.method
  1314. localpath = ""
  1315. lf = bb.utils.lockfile(ud.lockfile)
  1316. try:
  1317. self.d.setVar("BB_NO_NETWORK", network)
  1318. if verify_donestamp(ud, self.d) and not m.need_update(ud, self.d):
  1319. localpath = ud.localpath
  1320. elif m.try_premirror(ud, self.d):
  1321. logger.debug(1, "Trying PREMIRRORS")
  1322. mirrors = mirror_from_string(self.d.getVar('PREMIRRORS', True))
  1323. localpath = try_mirrors(self, self.d, ud, mirrors, False)
  1324. if premirroronly:
  1325. self.d.setVar("BB_NO_NETWORK", "1")
  1326. os.chdir(self.d.getVar("DL_DIR", True))
  1327. firsterr = None
  1328. if not localpath and ((not verify_donestamp(ud, self.d)) or m.need_update(ud, self.d)):
  1329. try:
  1330. if not trusted_network(self.d, ud.url):
  1331. raise UntrustedUrl(ud.url)
  1332. logger.debug(1, "Trying Upstream")
  1333. m.download(ud, self.d)
  1334. if hasattr(m, "build_mirror_data"):
  1335. m.build_mirror_data(ud, self.d)
  1336. localpath = ud.localpath
  1337. # early checksum verify, so that if checksum mismatched,
  1338. # fetcher still have chance to fetch from mirror
  1339. update_stamp(ud, self.d)
  1340. except bb.fetch2.NetworkAccess:
  1341. raise
  1342. except BBFetchException as e:
  1343. if isinstance(e, ChecksumError):
  1344. logger.warn("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
  1345. logger.debug(1, str(e))
  1346. rename_bad_checksum(ud, e.checksum)
  1347. elif isinstance(e, NoChecksumError):
  1348. raise
  1349. else:
  1350. logger.warn('Failed to fetch URL %s, attempting MIRRORS if available' % u)
  1351. logger.debug(1, str(e))
  1352. firsterr = e
  1353. # Remove any incomplete fetch
  1354. m.clean(ud, self.d)
  1355. logger.debug(1, "Trying MIRRORS")
  1356. mirrors = mirror_from_string(self.d.getVar('MIRRORS', True))
  1357. localpath = try_mirrors(self, self.d, ud, mirrors)
  1358. if not localpath or ((not os.path.exists(localpath)) and localpath.find("*") == -1):
  1359. if firsterr:
  1360. logger.error(str(firsterr))
  1361. raise FetchError("Unable to fetch URL from any source.", u)
  1362. update_stamp(ud, self.d)
  1363. except BBFetchException as e:
  1364. if isinstance(e, ChecksumError):
  1365. logger.error("Checksum failure fetching %s" % u)
  1366. raise
  1367. finally:
  1368. bb.utils.unlockfile(lf)
  1369. def checkstatus(self, urls = []):
  1370. """
  1371. Check all urls exist upstream
  1372. """
  1373. if len(urls) == 0:
  1374. urls = self.urls
  1375. for u in urls:
  1376. ud = self.ud[u]
  1377. ud.setup_localpath(self.d)
  1378. m = ud.method
  1379. logger.debug(1, "Testing URL %s", u)
  1380. # First try checking uri, u, from PREMIRRORS
  1381. mirrors = mirror_from_string(self.d.getVar('PREMIRRORS', True))
  1382. ret = try_mirrors(self, self.d, ud, mirrors, True)
  1383. if not ret:
  1384. # Next try checking from the original uri, u
  1385. try:
  1386. ret = m.checkstatus(self, ud, self.d)
  1387. except:
  1388. # Finally, try checking uri, u, from MIRRORS
  1389. mirrors = mirror_from_string(self.d.getVar('MIRRORS', True))
  1390. ret = try_mirrors(self, self.d, ud, mirrors, True)
  1391. if not ret:
  1392. raise FetchError("URL %s doesn't work" % u, u)
  1393. def unpack(self, root, urls = []):
  1394. """
  1395. Check all urls exist upstream
  1396. """
  1397. if len(urls) == 0:
  1398. urls = self.urls
  1399. for u in urls:
  1400. ud = self.ud[u]
  1401. ud.setup_localpath(self.d)
  1402. if self.d.expand(self.localpath) is None:
  1403. continue
  1404. if ud.lockfile:
  1405. lf = bb.utils.lockfile(ud.lockfile)
  1406. ud.method.unpack(ud, root, self.d)
  1407. if ud.lockfile:
  1408. bb.utils.unlockfile(lf)
  1409. def clean(self, urls = []):
  1410. """
  1411. Clean files that the fetcher gets or places
  1412. """
  1413. if len(urls) == 0:
  1414. urls = self.urls
  1415. for url in urls:
  1416. if url not in self.ud:
  1417. self.ud[url] = FetchData(url, d)
  1418. ud = self.ud[url]
  1419. ud.setup_localpath(self.d)
  1420. if not ud.localfile and ud.localpath is None:
  1421. continue
  1422. if ud.lockfile:
  1423. lf = bb.utils.lockfile(ud.lockfile)
  1424. ud.method.clean(ud, self.d)
  1425. if ud.donestamp:
  1426. bb.utils.remove(ud.donestamp)
  1427. if ud.lockfile:
  1428. bb.utils.unlockfile(lf)
  1429. class FetchConnectionCache(object):
  1430. """
  1431. A class which represents an container for socket connections.
  1432. """
  1433. def __init__(self):
  1434. self.cache = {}
  1435. def get_connection_name(self, host, port):
  1436. return host + ':' + str(port)
  1437. def add_connection(self, host, port, connection):
  1438. cn = self.get_connection_name(host, port)
  1439. if cn not in self.cache:
  1440. self.cache[cn] = connection
  1441. def get_connection(self, host, port):
  1442. connection = None
  1443. cn = self.get_connection_name(host, port)
  1444. if cn in self.cache:
  1445. connection = self.cache[cn]
  1446. return connection
  1447. def remove_connection(self, host, port):
  1448. cn = self.get_connection_name(host, port)
  1449. if cn in self.cache:
  1450. self.cache[cn].close()
  1451. del self.cache[cn]
  1452. def close_connections(self):
  1453. for cn in self.cache.keys():
  1454. self.cache[cn].close()
  1455. del self.cache[cn]
  1456. from . import cvs
  1457. from . import git
  1458. from . import gitsm
  1459. from . import gitannex
  1460. from . import local
  1461. from . import svn
  1462. from . import wget
  1463. from . import ssh
  1464. from . import sftp
  1465. from . import perforce
  1466. from . import bzr
  1467. from . import hg
  1468. from . import osc
  1469. from . import repo
  1470. from . import clearcase
  1471. methods.append(local.Local())
  1472. methods.append(wget.Wget())
  1473. methods.append(svn.Svn())
  1474. methods.append(git.Git())
  1475. methods.append(gitsm.GitSM())
  1476. methods.append(gitannex.GitANNEX())
  1477. methods.append(cvs.Cvs())
  1478. methods.append(ssh.SSH())
  1479. methods.append(sftp.SFTP())
  1480. methods.append(perforce.Perforce())
  1481. methods.append(bzr.Bzr())
  1482. methods.append(hg.Hg())
  1483. methods.append(osc.Osc())
  1484. methods.append(repo.Repo())
  1485. methods.append(clearcase.ClearCase())