summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/fetch2
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/fetch2')
-rw-r--r--bitbake/lib/bb/fetch2/__init__.py5
-rw-r--r--bitbake/lib/bb/fetch2/git.py54
-rw-r--r--bitbake/lib/bb/fetch2/wget.py24
3 files changed, 63 insertions, 20 deletions
diff --git a/bitbake/lib/bb/fetch2/__init__.py b/bitbake/lib/bb/fetch2/__init__.py
index dc99914cd9..3e6555bd67 100644
--- a/bitbake/lib/bb/fetch2/__init__.py
+++ b/bitbake/lib/bb/fetch2/__init__.py
@@ -562,6 +562,9 @@ def verify_checksum(ud, d, precomputed={}):
562 562
563 checksum_expected = getattr(ud, "%s_expected" % checksum_id) 563 checksum_expected = getattr(ud, "%s_expected" % checksum_id)
564 564
565 if checksum_expected == '':
566 checksum_expected = None
567
565 return { 568 return {
566 "id": checksum_id, 569 "id": checksum_id,
567 "name": checksum_name, 570 "name": checksum_name,
@@ -612,7 +615,7 @@ def verify_checksum(ud, d, precomputed={}):
612 615
613 for ci in checksum_infos: 616 for ci in checksum_infos:
614 if ci["expected"] and ci["expected"] != ci["data"]: 617 if ci["expected"] and ci["expected"] != ci["data"]:
615 messages.append("File: '%s' has %s checksum %s when %s was " \ 618 messages.append("File: '%s' has %s checksum '%s' when '%s' was " \
616 "expected" % (ud.localpath, ci["id"], ci["data"], ci["expected"])) 619 "expected" % (ud.localpath, ci["id"], ci["data"], ci["expected"]))
617 bad_checksum = ci["data"] 620 bad_checksum = ci["data"]
618 621
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index 8740e9c05f..cad1ae8207 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -44,7 +44,8 @@ Supported SRC_URI options are:
44 44
45- nobranch 45- nobranch
46 Don't check the SHA validation for branch. set this option for the recipe 46 Don't check the SHA validation for branch. set this option for the recipe
47 referring to commit which is valid in tag instead of branch. 47 referring to commit which is valid in any namespace (branch, tag, ...)
48 instead of branch.
48 The default is "0", set nobranch=1 if needed. 49 The default is "0", set nobranch=1 if needed.
49 50
50- usehead 51- usehead
@@ -63,10 +64,12 @@ import errno
63import fnmatch 64import fnmatch
64import os 65import os
65import re 66import re
67import shlex
66import subprocess 68import subprocess
67import tempfile 69import tempfile
68import bb 70import bb
69import bb.progress 71import bb.progress
72from contextlib import contextmanager
70from bb.fetch2 import FetchMethod 73from bb.fetch2 import FetchMethod
71from bb.fetch2 import runfetchcmd 74from bb.fetch2 import runfetchcmd
72from bb.fetch2 import logger 75from bb.fetch2 import logger
@@ -140,6 +143,10 @@ class Git(FetchMethod):
140 ud.proto = 'file' 143 ud.proto = 'file'
141 else: 144 else:
142 ud.proto = "git" 145 ud.proto = "git"
146 if ud.host == "github.com" and ud.proto == "git":
147 # github stopped supporting git protocol
148 # https://github.blog/2021-09-01-improving-git-protocol-security-github/#no-more-unauthenticated-git
149 ud.proto = "https"
143 150
144 if not ud.proto in ('git', 'file', 'ssh', 'http', 'https', 'rsync'): 151 if not ud.proto in ('git', 'file', 'ssh', 'http', 'https', 'rsync'):
145 raise bb.fetch2.ParameterError("Invalid protocol type", ud.url) 152 raise bb.fetch2.ParameterError("Invalid protocol type", ud.url)
@@ -219,7 +226,12 @@ class Git(FetchMethod):
219 ud.shallow = False 226 ud.shallow = False
220 227
221 if ud.usehead: 228 if ud.usehead:
222 ud.unresolvedrev['default'] = 'HEAD' 229 # When usehead is set let's associate 'HEAD' with the unresolved
230 # rev of this repository. This will get resolved into a revision
231 # later. If an actual revision happens to have also been provided
232 # then this setting will be overridden.
233 for name in ud.names:
234 ud.unresolvedrev[name] = 'HEAD'
223 235
224 ud.basecmd = d.getVar("FETCHCMD_git") or "git -c core.fsyncobjectfiles=0" 236 ud.basecmd = d.getVar("FETCHCMD_git") or "git -c core.fsyncobjectfiles=0"
225 237
@@ -342,7 +354,7 @@ class Git(FetchMethod):
342 # We do this since git will use a "-l" option automatically for local urls where possible 354 # We do this since git will use a "-l" option automatically for local urls where possible
343 if repourl.startswith("file://"): 355 if repourl.startswith("file://"):
344 repourl = repourl[7:] 356 repourl = repourl[7:]
345 clone_cmd = "LANG=C %s clone --bare --mirror \"%s\" %s --progress" % (ud.basecmd, repourl, ud.clonedir) 357 clone_cmd = "LANG=C %s clone --bare --mirror %s %s --progress" % (ud.basecmd, shlex.quote(repourl), ud.clonedir)
346 if ud.proto.lower() != 'file': 358 if ud.proto.lower() != 'file':
347 bb.fetch2.check_network_access(d, clone_cmd, ud.url) 359 bb.fetch2.check_network_access(d, clone_cmd, ud.url)
348 progresshandler = GitProgressHandler(d) 360 progresshandler = GitProgressHandler(d)
@@ -354,8 +366,12 @@ class Git(FetchMethod):
354 if "origin" in output: 366 if "origin" in output:
355 runfetchcmd("%s remote rm origin" % ud.basecmd, d, workdir=ud.clonedir) 367 runfetchcmd("%s remote rm origin" % ud.basecmd, d, workdir=ud.clonedir)
356 368
357 runfetchcmd("%s remote add --mirror=fetch origin \"%s\"" % (ud.basecmd, repourl), d, workdir=ud.clonedir) 369 runfetchcmd("%s remote add --mirror=fetch origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=ud.clonedir)
358 fetch_cmd = "LANG=C %s fetch -f --progress \"%s\" refs/*:refs/*" % (ud.basecmd, repourl) 370
371 if ud.nobranch:
372 fetch_cmd = "LANG=C %s fetch -f --progress %s refs/*:refs/*" % (ud.basecmd, shlex.quote(repourl))
373 else:
374 fetch_cmd = "LANG=C %s fetch -f --progress %s refs/heads/*:refs/heads/* refs/tags/*:refs/tags/*" % (ud.basecmd, shlex.quote(repourl))
359 if ud.proto.lower() != 'file': 375 if ud.proto.lower() != 'file':
360 bb.fetch2.check_network_access(d, fetch_cmd, ud.url) 376 bb.fetch2.check_network_access(d, fetch_cmd, ud.url)
361 progresshandler = GitProgressHandler(d) 377 progresshandler = GitProgressHandler(d)
@@ -388,7 +404,7 @@ class Git(FetchMethod):
388 tmpdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR')) 404 tmpdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR'))
389 try: 405 try:
390 # Do the checkout. This implicitly involves a Git LFS fetch. 406 # Do the checkout. This implicitly involves a Git LFS fetch.
391 self.unpack(ud, tmpdir, d) 407 Git.unpack(self, ud, tmpdir, d)
392 408
393 # Scoop up a copy of any stuff that Git LFS downloaded. Merge them into 409 # Scoop up a copy of any stuff that Git LFS downloaded. Merge them into
394 # the bare clonedir. 410 # the bare clonedir.
@@ -408,6 +424,20 @@ class Git(FetchMethod):
408 bb.utils.remove(tmpdir, recurse=True) 424 bb.utils.remove(tmpdir, recurse=True)
409 425
410 def build_mirror_data(self, ud, d): 426 def build_mirror_data(self, ud, d):
427
428 # Create as a temp file and move atomically into position to avoid races
429 @contextmanager
430 def create_atomic(filename):
431 fd, tfile = tempfile.mkstemp(dir=os.path.dirname(filename))
432 try:
433 yield tfile
434 umask = os.umask(0o666)
435 os.umask(umask)
436 os.chmod(tfile, (0o666 & ~umask))
437 os.rename(tfile, filename)
438 finally:
439 os.close(fd)
440
411 if ud.shallow and ud.write_shallow_tarballs: 441 if ud.shallow and ud.write_shallow_tarballs:
412 if not os.path.exists(ud.fullshallow): 442 if not os.path.exists(ud.fullshallow):
413 if os.path.islink(ud.fullshallow): 443 if os.path.islink(ud.fullshallow):
@@ -418,7 +448,8 @@ class Git(FetchMethod):
418 self.clone_shallow_local(ud, shallowclone, d) 448 self.clone_shallow_local(ud, shallowclone, d)
419 449
420 logger.info("Creating tarball of git repository") 450 logger.info("Creating tarball of git repository")
421 runfetchcmd("tar -czf %s ." % ud.fullshallow, d, workdir=shallowclone) 451 with create_atomic(ud.fullshallow) as tfile:
452 runfetchcmd("tar -czf %s ." % tfile, d, workdir=shallowclone)
422 runfetchcmd("touch %s.done" % ud.fullshallow, d) 453 runfetchcmd("touch %s.done" % ud.fullshallow, d)
423 finally: 454 finally:
424 bb.utils.remove(tempdir, recurse=True) 455 bb.utils.remove(tempdir, recurse=True)
@@ -427,7 +458,8 @@ class Git(FetchMethod):
427 os.unlink(ud.fullmirror) 458 os.unlink(ud.fullmirror)
428 459
429 logger.info("Creating tarball of git repository") 460 logger.info("Creating tarball of git repository")
430 runfetchcmd("tar -czf %s ." % ud.fullmirror, d, workdir=ud.clonedir) 461 with create_atomic(ud.fullmirror) as tfile:
462 runfetchcmd("tar -czf %s ." % tfile, d, workdir=ud.clonedir)
431 runfetchcmd("touch %s.done" % ud.fullmirror, d) 463 runfetchcmd("touch %s.done" % ud.fullmirror, d)
432 464
433 def clone_shallow_local(self, ud, dest, d): 465 def clone_shallow_local(self, ud, dest, d):
@@ -533,7 +565,7 @@ class Git(FetchMethod):
533 raise bb.fetch2.UnpackError("No up to date source found: " + "; ".join(source_error), ud.url) 565 raise bb.fetch2.UnpackError("No up to date source found: " + "; ".join(source_error), ud.url)
534 566
535 repourl = self._get_repo_url(ud) 567 repourl = self._get_repo_url(ud)
536 runfetchcmd("%s remote set-url origin \"%s\"" % (ud.basecmd, repourl), d, workdir=destdir) 568 runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=destdir)
537 569
538 if self._contains_lfs(ud, d, destdir): 570 if self._contains_lfs(ud, d, destdir):
539 if need_lfs and not self._find_git_lfs(d): 571 if need_lfs and not self._find_git_lfs(d):
@@ -661,8 +693,8 @@ class Git(FetchMethod):
661 d.setVar('_BB_GIT_IN_LSREMOTE', '1') 693 d.setVar('_BB_GIT_IN_LSREMOTE', '1')
662 try: 694 try:
663 repourl = self._get_repo_url(ud) 695 repourl = self._get_repo_url(ud)
664 cmd = "%s ls-remote \"%s\" %s" % \ 696 cmd = "%s ls-remote %s %s" % \
665 (ud.basecmd, repourl, search) 697 (ud.basecmd, shlex.quote(repourl), search)
666 if ud.proto.lower() != 'file': 698 if ud.proto.lower() != 'file':
667 bb.fetch2.check_network_access(d, cmd, repourl) 699 bb.fetch2.check_network_access(d, cmd, repourl)
668 output = runfetchcmd(cmd, d, True) 700 output = runfetchcmd(cmd, d, True)
diff --git a/bitbake/lib/bb/fetch2/wget.py b/bitbake/lib/bb/fetch2/wget.py
index f7d1de26b7..368c644337 100644
--- a/bitbake/lib/bb/fetch2/wget.py
+++ b/bitbake/lib/bb/fetch2/wget.py
@@ -52,6 +52,12 @@ class WgetProgressHandler(bb.progress.LineFilterProgressHandler):
52 52
53 53
54class Wget(FetchMethod): 54class Wget(FetchMethod):
55
56 # CDNs like CloudFlare may do a 'browser integrity test' which can fail
57 # with the standard wget/urllib User-Agent, so pretend to be a modern
58 # browser.
59 user_agent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0"
60
55 """Class to fetch urls via 'wget'""" 61 """Class to fetch urls via 'wget'"""
56 def supports(self, ud, d): 62 def supports(self, ud, d):
57 """ 63 """
@@ -91,10 +97,9 @@ class Wget(FetchMethod):
91 97
92 fetchcmd = self.basecmd 98 fetchcmd = self.basecmd
93 99
94 if 'downloadfilename' in ud.parm: 100 localpath = os.path.join(d.getVar("DL_DIR"), ud.localfile) + ".tmp"
95 localpath = os.path.join(d.getVar("DL_DIR"), ud.localfile) 101 bb.utils.mkdirhier(os.path.dirname(localpath))
96 bb.utils.mkdirhier(os.path.dirname(localpath)) 102 fetchcmd += " -O %s" % shlex.quote(localpath)
97 fetchcmd += " -O %s" % shlex.quote(localpath)
98 103
99 if ud.user and ud.pswd: 104 if ud.user and ud.pswd:
100 fetchcmd += " --user=%s --password=%s --auth-no-challenge" % (ud.user, ud.pswd) 105 fetchcmd += " --user=%s --password=%s --auth-no-challenge" % (ud.user, ud.pswd)
@@ -108,6 +113,10 @@ class Wget(FetchMethod):
108 113
109 self._runwget(ud, d, fetchcmd, False) 114 self._runwget(ud, d, fetchcmd, False)
110 115
116 # Remove the ".tmp" and move the file into position atomically
117 # Our lock prevents multiple writers but mirroring code may grab incomplete files
118 os.rename(localpath, localpath[:-4])
119
111 # Sanity check since wget can pretend it succeed when it didn't 120 # Sanity check since wget can pretend it succeed when it didn't
112 # Also, this used to happen if sourceforge sent us to the mirror page 121 # Also, this used to happen if sourceforge sent us to the mirror page
113 if not os.path.exists(ud.localpath): 122 if not os.path.exists(ud.localpath):
@@ -300,7 +309,7 @@ class Wget(FetchMethod):
300 # Some servers (FusionForge, as used on Alioth) require that the 309 # Some servers (FusionForge, as used on Alioth) require that the
301 # optional Accept header is set. 310 # optional Accept header is set.
302 r.add_header("Accept", "*/*") 311 r.add_header("Accept", "*/*")
303 r.add_header("User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/9.10 (karmic) Firefox/3.6.12") 312 r.add_header("User-Agent", self.user_agent)
304 def add_basic_auth(login_str, request): 313 def add_basic_auth(login_str, request):
305 '''Adds Basic auth to http request, pass in login:password as string''' 314 '''Adds Basic auth to http request, pass in login:password as string'''
306 import base64 315 import base64
@@ -319,7 +328,7 @@ class Wget(FetchMethod):
319 except (TypeError, ImportError, IOError, netrc.NetrcParseError): 328 except (TypeError, ImportError, IOError, netrc.NetrcParseError):
320 pass 329 pass
321 330
322 with opener.open(r) as response: 331 with opener.open(r, timeout=30) as response:
323 pass 332 pass
324 except urllib.error.URLError as e: 333 except urllib.error.URLError as e:
325 if try_again: 334 if try_again:
@@ -404,9 +413,8 @@ class Wget(FetchMethod):
404 """ 413 """
405 f = tempfile.NamedTemporaryFile() 414 f = tempfile.NamedTemporaryFile()
406 with tempfile.TemporaryDirectory(prefix="wget-index-") as workdir, tempfile.NamedTemporaryFile(dir=workdir, prefix="wget-listing-") as f: 415 with tempfile.TemporaryDirectory(prefix="wget-index-") as workdir, tempfile.NamedTemporaryFile(dir=workdir, prefix="wget-listing-") as f:
407 agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/9.10 (karmic) Firefox/3.6.12"
408 fetchcmd = self.basecmd 416 fetchcmd = self.basecmd
409 fetchcmd += " -O " + f.name + " --user-agent='" + agent + "' '" + uri + "'" 417 fetchcmd += " -O " + f.name + " --user-agent='" + self.user_agent + "' '" + uri + "'"
410 try: 418 try:
411 self._runwget(ud, d, fetchcmd, True, workdir=workdir) 419 self._runwget(ud, d, fetchcmd, True, workdir=workdir)
412 fetchresult = f.read() 420 fetchresult = f.read()