__init__.py 66 KB

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