summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb')
-rw-r--r--bitbake/lib/bb/__init__.py2
-rw-r--r--bitbake/lib/bb/event.py10
-rw-r--r--bitbake/lib/bb/fetch2/__init__.py50
-rw-r--r--bitbake/lib/bb/fetch2/az.py4
-rw-r--r--bitbake/lib/bb/fetch2/git.py13
-rw-r--r--bitbake/lib/bb/parse/ast.py41
-rw-r--r--bitbake/lib/bb/parse/parse_py/BBHandler.py10
-rw-r--r--bitbake/lib/bb/parse/parse_py/ConfHandler.py2
-rw-r--r--bitbake/lib/bb/runqueue.py3
-rw-r--r--bitbake/lib/bb/tests/fetch.py40
-rw-r--r--bitbake/lib/bb/ui/knotty.py6
11 files changed, 135 insertions, 46 deletions
diff --git a/bitbake/lib/bb/__init__.py b/bitbake/lib/bb/__init__.py
index c95c91a4cb..62ceaaef6e 100644
--- a/bitbake/lib/bb/__init__.py
+++ b/bitbake/lib/bb/__init__.py
@@ -9,7 +9,7 @@
9# SPDX-License-Identifier: GPL-2.0-only 9# SPDX-License-Identifier: GPL-2.0-only
10# 10#
11 11
12__version__ = "2.12.0" 12__version__ = "2.15.0"
13 13
14import sys 14import sys
15if sys.version_info < (3, 9, 0): 15if sys.version_info < (3, 9, 0):
diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py
index a12adbc937..b29f0a5568 100644
--- a/bitbake/lib/bb/event.py
+++ b/bitbake/lib/bb/event.py
@@ -431,6 +431,16 @@ class RecipeEvent(Event):
431 self.fn = fn 431 self.fn = fn
432 Event.__init__(self) 432 Event.__init__(self)
433 433
434class RecipePreDeferredInherits(RecipeEvent):
435 """
436 Called before deferred inherits are processed so code can snoop on class extensions for example
437 Limitations: It won't see inherits of inherited classes and the data is unexpanded
438 """
439 def __init__(self, fn, inherits):
440 self.fn = fn
441 self.inherits = inherits
442 Event.__init__(self)
443
434class RecipePreFinalise(RecipeEvent): 444class RecipePreFinalise(RecipeEvent):
435 """ Recipe Parsing Complete but not yet finalised""" 445 """ Recipe Parsing Complete but not yet finalised"""
436 446
diff --git a/bitbake/lib/bb/fetch2/__init__.py b/bitbake/lib/bb/fetch2/__init__.py
index 2de4f4f8c0..0ad987c596 100644
--- a/bitbake/lib/bb/fetch2/__init__.py
+++ b/bitbake/lib/bb/fetch2/__init__.py
@@ -1117,7 +1117,10 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
1117 origud.method.build_mirror_data(origud, ld) 1117 origud.method.build_mirror_data(origud, ld)
1118 return origud.localpath 1118 return origud.localpath
1119 # Otherwise the result is a local file:// and we symlink to it 1119 # Otherwise the result is a local file:// and we symlink to it
1120 ensure_symlink(ud.localpath, origud.localpath) 1120 # This may also be a link to a shallow archive
1121 # When using shallow mode, add a symlink to the original fullshallow
1122 # path to ensure a valid symlink even in the `PREMIRRORS` case
1123 origud.method.update_mirror_links(ud, origud)
1121 update_stamp(origud, ld) 1124 update_stamp(origud, ld)
1122 return ud.localpath 1125 return ud.localpath
1123 1126
@@ -1151,25 +1154,6 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
1151 if ud.lockfile and ud.lockfile != origud.lockfile: 1154 if ud.lockfile and ud.lockfile != origud.lockfile:
1152 bb.utils.unlockfile(lf) 1155 bb.utils.unlockfile(lf)
1153 1156
1154
1155def ensure_symlink(target, link_name):
1156 if not os.path.exists(link_name):
1157 dirname = os.path.dirname(link_name)
1158 bb.utils.mkdirhier(dirname)
1159 if os.path.islink(link_name):
1160 # Broken symbolic link
1161 os.unlink(link_name)
1162
1163 # In case this is executing without any file locks held (as is
1164 # the case for file:// URLs), two tasks may end up here at the
1165 # same time, in which case we do not want the second task to
1166 # fail when the link has already been created by the first task.
1167 try:
1168 os.symlink(target, link_name)
1169 except FileExistsError:
1170 pass
1171
1172
1173def try_mirrors(fetch, d, origud, mirrors, check = False): 1157def try_mirrors(fetch, d, origud, mirrors, check = False):
1174 """ 1158 """
1175 Try to use a mirrored version of the sources. 1159 Try to use a mirrored version of the sources.
@@ -1589,11 +1573,11 @@ class FetchMethod(object):
1589 datafile = None 1573 datafile = None
1590 if output: 1574 if output:
1591 for line in output.decode().splitlines(): 1575 for line in output.decode().splitlines():
1592 if line.startswith('data.tar.'): 1576 if line.startswith('data.tar.') or line == 'data.tar':
1593 datafile = line 1577 datafile = line
1594 break 1578 break
1595 else: 1579 else:
1596 raise UnpackError("Unable to unpack deb/ipk package - does not contain data.tar.* file", urldata.url) 1580 raise UnpackError("Unable to unpack deb/ipk package - does not contain data.tar* file", urldata.url)
1597 else: 1581 else:
1598 raise UnpackError("Unable to unpack deb/ipk package - could not list contents", urldata.url) 1582 raise UnpackError("Unable to unpack deb/ipk package - could not list contents", urldata.url)
1599 cmd = 'ar x %s %s && %s -p -f %s && rm %s' % (file, datafile, tar_cmd, datafile, datafile) 1583 cmd = 'ar x %s %s && %s -p -f %s && rm %s' % (file, datafile, tar_cmd, datafile, datafile)
@@ -1655,6 +1639,28 @@ class FetchMethod(object):
1655 """ 1639 """
1656 bb.utils.remove(urldata.localpath) 1640 bb.utils.remove(urldata.localpath)
1657 1641
1642 def ensure_symlink(self, target, link_name):
1643 if not os.path.exists(link_name):
1644 dirname = os.path.dirname(link_name)
1645 bb.utils.mkdirhier(dirname)
1646 if os.path.islink(link_name):
1647 # Broken symbolic link
1648 os.unlink(link_name)
1649
1650 # In case this is executing without any file locks held (as is
1651 # the case for file:// URLs), two tasks may end up here at the
1652 # same time, in which case we do not want the second task to
1653 # fail when the link has already been created by the first task.
1654 try:
1655 os.symlink(target, link_name)
1656 except FileExistsError:
1657 pass
1658
1659 def update_mirror_links(self, ud, origud):
1660 # For local file:// results, create a symlink to them
1661 # This may also be a link to a shallow archive
1662 self.ensure_symlink(ud.localpath, origud.localpath)
1663
1658 def try_premirror(self, urldata, d): 1664 def try_premirror(self, urldata, d):
1659 """ 1665 """
1660 Should premirrors be used? 1666 Should premirrors be used?
diff --git a/bitbake/lib/bb/fetch2/az.py b/bitbake/lib/bb/fetch2/az.py
index 346124a8bf..1d3664f213 100644
--- a/bitbake/lib/bb/fetch2/az.py
+++ b/bitbake/lib/bb/fetch2/az.py
@@ -36,6 +36,8 @@ class Az(Wget):
36 36
37 az_sas = d.getVar('AZ_SAS') 37 az_sas = d.getVar('AZ_SAS')
38 if az_sas and az_sas not in ud.url: 38 if az_sas and az_sas not in ud.url:
39 if not az_sas.startswith('?'):
40 raise FetchError("When using AZ_SAS, it must start with a '?' character to mark the start of the query-parameters.")
39 ud.url += az_sas 41 ud.url += az_sas
40 42
41 return Wget.checkstatus(self, fetch, ud, d, try_again) 43 return Wget.checkstatus(self, fetch, ud, d, try_again)
@@ -62,6 +64,8 @@ class Az(Wget):
62 az_sas = d.getVar('AZ_SAS') 64 az_sas = d.getVar('AZ_SAS')
63 65
64 if az_sas: 66 if az_sas:
67 if not az_sas.startswith('?'):
68 raise FetchError("When using AZ_SAS, it must start with a '?' character to mark the start of the query-parameters.")
65 azuri = '%s%s%s%s' % ('https://', ud.host, ud.path, az_sas) 69 azuri = '%s%s%s%s' % ('https://', ud.host, ud.path, az_sas)
66 else: 70 else:
67 azuri = '%s%s%s' % ('https://', ud.host, ud.path) 71 azuri = '%s%s%s' % ('https://', ud.host, ud.path)
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index 784a45bda2..14ec45a3f6 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -199,6 +199,8 @@ class Git(FetchMethod):
199 ud.shallow_skip_fast = False 199 ud.shallow_skip_fast = False
200 ud.shallow = d.getVar("BB_GIT_SHALLOW") == "1" 200 ud.shallow = d.getVar("BB_GIT_SHALLOW") == "1"
201 ud.shallow_extra_refs = (d.getVar("BB_GIT_SHALLOW_EXTRA_REFS") or "").split() 201 ud.shallow_extra_refs = (d.getVar("BB_GIT_SHALLOW_EXTRA_REFS") or "").split()
202 if 'tag' in ud.parm:
203 ud.shallow_extra_refs.append("refs/tags/" + ud.parm['tag'])
202 204
203 depth_default = d.getVar("BB_GIT_SHALLOW_DEPTH") 205 depth_default = d.getVar("BB_GIT_SHALLOW_DEPTH")
204 if depth_default is not None: 206 if depth_default is not None:
@@ -348,6 +350,13 @@ class Git(FetchMethod):
348 def tarball_need_update(self, ud): 350 def tarball_need_update(self, ud):
349 return ud.write_tarballs and not os.path.exists(ud.fullmirror) 351 return ud.write_tarballs and not os.path.exists(ud.fullmirror)
350 352
353 def update_mirror_links(self, ud, origud):
354 super().update_mirror_links(ud, origud)
355 # When using shallow mode, add a symlink to the original fullshallow
356 # path to ensure a valid symlink even in the `PREMIRRORS` case
357 if ud.shallow and not os.path.exists(origud.fullshallow):
358 self.ensure_symlink(ud.localpath, origud.fullshallow)
359
351 def try_premirror(self, ud, d): 360 def try_premirror(self, ud, d):
352 # If we don't do this, updating an existing checkout with only premirrors 361 # If we don't do this, updating an existing checkout with only premirrors
353 # is not possible 362 # is not possible
@@ -626,8 +635,6 @@ class Git(FetchMethod):
626 for line in all_refs_remote: 635 for line in all_refs_remote:
627 all_refs.append(line.split()[-1]) 636 all_refs.append(line.split()[-1])
628 extra_refs = [] 637 extra_refs = []
629 if 'tag' in ud.parm:
630 extra_refs.append(ud.parm['tag'])
631 for r in ud.shallow_extra_refs: 638 for r in ud.shallow_extra_refs:
632 if not ud.bareclone: 639 if not ud.bareclone:
633 r = r.replace('refs/heads/', 'refs/remotes/origin/') 640 r = r.replace('refs/heads/', 'refs/remotes/origin/')
@@ -653,7 +660,7 @@ class Git(FetchMethod):
653 subdir = ud.parm.get("subdir") 660 subdir = ud.parm.get("subdir")
654 subpath = ud.parm.get("subpath") 661 subpath = ud.parm.get("subpath")
655 readpathspec = "" 662 readpathspec = ""
656 def_destsuffix = "git/" 663 def_destsuffix = (d.getVar("BB_GIT_DEFAULT_DESTSUFFIX") or "git") + "/"
657 664
658 if subpath: 665 if subpath:
659 readpathspec = ":%s" % subpath 666 readpathspec = ":%s" % subpath
diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py
index 290ed45048..49a0788038 100644
--- a/bitbake/lib/bb/parse/ast.py
+++ b/bitbake/lib/bb/parse/ast.py
@@ -340,16 +340,15 @@ class InheritDeferredNode(AstNode):
340 self.inherit = (classes, filename, lineno) 340 self.inherit = (classes, filename, lineno)
341 341
342 def eval(self, data): 342 def eval(self, data):
343 inherits = data.getVar('__BBDEFINHERITS', False) or [] 343 bb.parse.BBHandler.inherit_defer(*self.inherit, data)
344 inherits.append(self.inherit)
345 data.setVar('__BBDEFINHERITS', inherits)
346 344
347class AddFragmentsNode(AstNode): 345class AddFragmentsNode(AstNode):
348 def __init__(self, filename, lineno, fragments_path_prefix, fragments_variable, flagged_variables_list_variable): 346 def __init__(self, filename, lineno, fragments_path_prefix, fragments_variable, flagged_variables_list_variable, builtin_fragments_variable):
349 AstNode.__init__(self, filename, lineno) 347 AstNode.__init__(self, filename, lineno)
350 self.fragments_path_prefix = fragments_path_prefix 348 self.fragments_path_prefix = fragments_path_prefix
351 self.fragments_variable = fragments_variable 349 self.fragments_variable = fragments_variable
352 self.flagged_variables_list_variable = flagged_variables_list_variable 350 self.flagged_variables_list_variable = flagged_variables_list_variable
351 self.builtin_fragments_variable = builtin_fragments_variable
353 352
354 def eval(self, data): 353 def eval(self, data):
355 # No need to use mark_dependency since we would only match a fragment 354 # No need to use mark_dependency since we would only match a fragment
@@ -362,13 +361,23 @@ class AddFragmentsNode(AstNode):
362 return candidate_fragment_path 361 return candidate_fragment_path
363 return None 362 return None
364 363
364 def check_and_set_builtin_fragment(fragment, data, builtin_fragments):
365 prefix, value = fragment.split('/', 1)
366 if prefix in builtin_fragments.keys():
367 data.setVar(builtin_fragments[prefix], value)
368 return True
369 return False
370
365 fragments = data.getVar(self.fragments_variable) 371 fragments = data.getVar(self.fragments_variable)
366 layers = data.getVar('BBLAYERS') 372 layers = data.getVar('BBLAYERS')
367 flagged_variables = data.getVar(self.flagged_variables_list_variable).split() 373 flagged_variables = data.getVar(self.flagged_variables_list_variable).split()
374 builtin_fragments = {f[0]:f[1] for f in [f.split(':') for f in data.getVar(self.builtin_fragments_variable).split()] }
368 375
369 if not fragments: 376 if not fragments:
370 return 377 return
371 for f in fragments.split(): 378 for f in fragments.split():
379 if check_and_set_builtin_fragment(f, data, builtin_fragments):
380 continue
372 layerid, fragment_name = f.split('/', 1) 381 layerid, fragment_name = f.split('/', 1)
373 full_fragment_name = data.expand("{}/{}.conf".format(self.fragments_path_prefix, fragment_name)) 382 full_fragment_name = data.expand("{}/{}.conf".format(self.fragments_path_prefix, fragment_name))
374 fragment_path = find_fragment(layers, layerid, full_fragment_name) 383 fragment_path = find_fragment(layers, layerid, full_fragment_name)
@@ -432,7 +441,8 @@ def handleAddFragments(statements, filename, lineno, m):
432 fragments_path_prefix = m.group(1) 441 fragments_path_prefix = m.group(1)
433 fragments_variable = m.group(2) 442 fragments_variable = m.group(2)
434 flagged_variables_list_variable = m.group(3) 443 flagged_variables_list_variable = m.group(3)
435 statements.append(AddFragmentsNode(filename, lineno, fragments_path_prefix, fragments_variable, flagged_variables_list_variable)) 444 builtin_fragments_variable = m.group(4)
445 statements.append(AddFragmentsNode(filename, lineno, fragments_path_prefix, fragments_variable, flagged_variables_list_variable, builtin_fragments_variable))
436 446
437def runAnonFuncs(d): 447def runAnonFuncs(d):
438 code = [] 448 code = []
@@ -471,6 +481,17 @@ def finalize(fn, d, variant = None):
471 if d.getVar("_FAILPARSINGERRORHANDLED", False) == True: 481 if d.getVar("_FAILPARSINGERRORHANDLED", False) == True:
472 raise bb.BBHandledException() 482 raise bb.BBHandledException()
473 483
484 inherits = [x[0] for x in (d.getVar('__BBDEFINHERITS', False) or [('',)])]
485 bb.event.fire(bb.event.RecipePreDeferredInherits(fn, inherits), d)
486
487 while True:
488 inherits = d.getVar('__BBDEFINHERITS', False) or []
489 if not inherits:
490 break
491 inherit, filename, lineno = inherits.pop(0)
492 d.setVar('__BBDEFINHERITS', inherits)
493 bb.parse.BBHandler.inherit(inherit, filename, lineno, d, deferred=True)
494
474 for var in d.getVar('__BBHANDLERS', False) or []: 495 for var in d.getVar('__BBHANDLERS', False) or []:
475 # try to add the handler 496 # try to add the handler
476 handlerfn = d.getVarFlag(var, "filename", False) 497 handlerfn = d.getVarFlag(var, "filename", False)
@@ -525,14 +546,6 @@ def multi_finalize(fn, d):
525 logger.debug("Appending .bbappend file %s to %s", append, fn) 546 logger.debug("Appending .bbappend file %s to %s", append, fn)
526 bb.parse.BBHandler.handle(append, d, True) 547 bb.parse.BBHandler.handle(append, d, True)
527 548
528 while True:
529 inherits = d.getVar('__BBDEFINHERITS', False) or []
530 if not inherits:
531 break
532 inherit, filename, lineno = inherits.pop(0)
533 d.setVar('__BBDEFINHERITS', inherits)
534 bb.parse.BBHandler.inherit(inherit, filename, lineno, d, deferred=True)
535
536 onlyfinalise = d.getVar("__ONLYFINALISE", False) 549 onlyfinalise = d.getVar("__ONLYFINALISE", False)
537 550
538 safe_d = d 551 safe_d = d
@@ -568,7 +581,7 @@ def multi_finalize(fn, d):
568 d.setVar("BBEXTENDVARIANT", variantmap[name]) 581 d.setVar("BBEXTENDVARIANT", variantmap[name])
569 else: 582 else:
570 d.setVar("PN", "%s-%s" % (pn, name)) 583 d.setVar("PN", "%s-%s" % (pn, name))
571 bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d) 584 bb.parse.BBHandler.inherit_defer(extendedmap[name], fn, 0, d)
572 585
573 safe_d.setVar("BBCLASSEXTEND", extended) 586 safe_d.setVar("BBCLASSEXTEND", extended)
574 _create_variants(datastores, extendedmap.keys(), extendfunc, onlyfinalise) 587 _create_variants(datastores, extendedmap.keys(), extendfunc, onlyfinalise)
diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
index 4bdb11994f..008fec2308 100644
--- a/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -42,12 +42,22 @@ def supports(fn, d):
42 """Return True if fn has a supported extension""" 42 """Return True if fn has a supported extension"""
43 return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"] 43 return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"]
44 44
45def inherit_defer(expression, fn, lineno, d):
46 inherit = (expression, fn, lineno)
47 inherits = d.getVar('__BBDEFINHERITS', False) or []
48 inherits.append(inherit)
49 d.setVar('__BBDEFINHERITS', inherits)
50
45def inherit(files, fn, lineno, d, deferred=False): 51def inherit(files, fn, lineno, d, deferred=False):
46 __inherit_cache = d.getVar('__inherit_cache', False) or [] 52 __inherit_cache = d.getVar('__inherit_cache', False) or []
47 #if "${" in files and not deferred: 53 #if "${" in files and not deferred:
48 # bb.warn("%s:%s has non deferred conditional inherit" % (fn, lineno)) 54 # bb.warn("%s:%s has non deferred conditional inherit" % (fn, lineno))
49 files = d.expand(files).split() 55 files = d.expand(files).split()
50 for file in files: 56 for file in files:
57 defer = (d.getVar("BB_DEFER_BBCLASSES") or "").split()
58 if not deferred and file in defer:
59 inherit_defer(file, fn, lineno, d)
60 continue
51 classtype = d.getVar("__bbclasstype", False) 61 classtype = d.getVar("__bbclasstype", False)
52 origfile = file 62 origfile = file
53 for t in ["classes-" + classtype, "classes"]: 63 for t in ["classes-" + classtype, "classes"]:
diff --git a/bitbake/lib/bb/parse/parse_py/ConfHandler.py b/bitbake/lib/bb/parse/parse_py/ConfHandler.py
index 675838d845..9ddbae123d 100644
--- a/bitbake/lib/bb/parse/parse_py/ConfHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/ConfHandler.py
@@ -48,7 +48,7 @@ __export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/~]+)$" )
48__unset_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)$" ) 48__unset_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)$" )
49__unset_flag_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)\[([a-zA-Z0-9\-_+.][a-zA-Z0-9\-_+.@]+)\]$" ) 49__unset_flag_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)\[([a-zA-Z0-9\-_+.][a-zA-Z0-9\-_+.@]+)\]$" )
50__addpylib_regexp__ = re.compile(r"addpylib\s+(.+)\s+(.+)" ) 50__addpylib_regexp__ = re.compile(r"addpylib\s+(.+)\s+(.+)" )
51__addfragments_regexp__ = re.compile(r"addfragments\s+(.+)\s+(.+)\s+(.+)" ) 51__addfragments_regexp__ = re.compile(r"addfragments\s+(.+)\s+(.+)\s+(.+)\s+(.+)" )
52 52
53def init(data): 53def init(data):
54 return 54 return
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 8fadc8338e..80f3d3282f 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -3034,14 +3034,13 @@ def build_scenequeue_data(sqdata, rqdata, sqrq):
3034 rqdata.init_progress_reporter.next_stage(len(rqdata.runtaskentries)) 3034 rqdata.init_progress_reporter.next_stage(len(rqdata.runtaskentries))
3035 3035
3036 # Sanity check all dependencies could be changed to setscene task references 3036 # Sanity check all dependencies could be changed to setscene task references
3037 for taskcounter, tid in enumerate(rqdata.runtaskentries): 3037 for tid in rqdata.runtaskentries:
3038 if tid in rqdata.runq_setscene_tids: 3038 if tid in rqdata.runq_setscene_tids:
3039 pass 3039 pass
3040 elif sq_revdeps_squash[tid]: 3040 elif sq_revdeps_squash[tid]:
3041 bb.msg.fatal("RunQueue", "Something went badly wrong during scenequeue generation, halting. Please report this problem.") 3041 bb.msg.fatal("RunQueue", "Something went badly wrong during scenequeue generation, halting. Please report this problem.")
3042 else: 3042 else:
3043 del sq_revdeps_squash[tid] 3043 del sq_revdeps_squash[tid]
3044 rqdata.init_progress_reporter.update(taskcounter)
3045 3044
3046 rqdata.init_progress_reporter.next_stage() 3045 rqdata.init_progress_reporter.next_stage()
3047 3046
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py
index 0091723601..077472b8b3 100644
--- a/bitbake/lib/bb/tests/fetch.py
+++ b/bitbake/lib/bb/tests/fetch.py
@@ -2238,6 +2238,33 @@ class GitShallowTest(FetcherTest):
2238 self.assertIn("Unable to find revision v0.0 even from upstream", cm.output[0]) 2238 self.assertIn("Unable to find revision v0.0 even from upstream", cm.output[0])
2239 2239
2240 @skipIfNoNetwork() 2240 @skipIfNoNetwork()
2241 def test_git_shallow_fetch_premirrors(self):
2242 url = "git://git.openembedded.org/bitbake;branch=master;protocol=https"
2243
2244 # Create a separate premirror directory within tempdir
2245 premirror = os.path.join(self.tempdir, "premirror")
2246 os.mkdir(premirror)
2247
2248 # Fetch a non-shallow clone into the premirror subdir
2249 self.d.setVar('BB_GIT_SHALLOW', '0')
2250 self.d.setVar("DL_DIR", premirror)
2251 fetcher, ud = self.fetch(url)
2252
2253 # Fetch a shallow clone from the premirror subdir with unpacking
2254 # using the original recipe URL and the premirror mapping
2255 self.d.setVar('BB_GIT_SHALLOW', '1')
2256 self.d.setVar("DL_DIR", self.dldir)
2257 self.d.setVar('BB_FETCH_PREMIRRORONLY', '1')
2258 self.d.setVar('BB_NO_NETWORK', '1')
2259 self.d.setVar('BB_GENERATE_MIRROR_TARBALLS', '0')
2260 self.d.setVar("PREMIRRORS", "git://.*/.* git://{0};protocol=file".format(premirror + "/git2/" + ud.host + ud.path.replace("/", ".")))
2261 fetcher = self.fetch_and_unpack(url)
2262
2263 # Verify that the unpacked sources are shallow clones
2264 self.assertRevCount(1)
2265 assert os.path.exists(os.path.join(self.gitdir, '.git', 'shallow'))
2266
2267 @skipIfNoNetwork()
2241 def test_bitbake(self): 2268 def test_bitbake(self):
2242 self.git('remote add --mirror=fetch origin https://github.com/openembedded/bitbake', cwd=self.srcdir) 2269 self.git('remote add --mirror=fetch origin https://github.com/openembedded/bitbake', cwd=self.srcdir)
2243 self.git('config core.bare true', cwd=self.srcdir) 2270 self.git('config core.bare true', cwd=self.srcdir)
@@ -2281,6 +2308,19 @@ class GitShallowTest(FetcherTest):
2281 self.assertRevCount(1) 2308 self.assertRevCount(1)
2282 assert os.path.exists(os.path.join(self.gitdir, '.git', 'shallow')) 2309 assert os.path.exists(os.path.join(self.gitdir, '.git', 'shallow'))
2283 2310
2311 def test_shallow_succeeds_with_tag_containing_slash(self):
2312 self.add_empty_file('a')
2313 self.add_empty_file('b')
2314 self.git('tag t1/t2/t3', cwd=self.srcdir)
2315 self.assertRevCount(2, cwd=self.srcdir)
2316
2317 srcrev = self.git('rev-parse HEAD', cwd=self.srcdir).strip()
2318 self.d.setVar('SRCREV', srcrev)
2319 uri = self.d.getVar('SRC_URI').split()[0]
2320 uri = '%s;tag=t1/t2/t3' % uri
2321 self.fetch_shallow(uri)
2322 self.assertRevCount(1)
2323
2284class GitLfsTest(FetcherTest): 2324class GitLfsTest(FetcherTest):
2285 def skipIfNoGitLFS(): 2325 def skipIfNoGitLFS():
2286 if not shutil.which('git-lfs'): 2326 if not shutil.which('git-lfs'):
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 2fff1b3669..9a589a5c8e 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -353,7 +353,7 @@ def print_event_log(event, includelogs, loglines, termfilter):
353 termfilter.clearFooter() 353 termfilter.clearFooter()
354 bb.error("Logfile of failure stored in: %s" % logfile) 354 bb.error("Logfile of failure stored in: %s" % logfile)
355 if includelogs and not event.errprinted: 355 if includelogs and not event.errprinted:
356 print("Log data follows:") 356 bb.plain("Log data follows:")
357 f = open(logfile, "r") 357 f = open(logfile, "r")
358 lines = [] 358 lines = []
359 while True: 359 while True:
@@ -366,11 +366,11 @@ def print_event_log(event, includelogs, loglines, termfilter):
366 if len(lines) > int(loglines): 366 if len(lines) > int(loglines):
367 lines.pop(0) 367 lines.pop(0)
368 else: 368 else:
369 print('| %s' % l) 369 bb.plain('| %s' % l)
370 f.close() 370 f.close()
371 if lines: 371 if lines:
372 for line in lines: 372 for line in lines:
373 print(line) 373 bb.plain(line)
374 374
375def _log_settings_from_server(server, observe_only): 375def _log_settings_from_server(server, observe_only):
376 # Get values of variables which control our output 376 # Get values of variables which control our output