@@ -24,6 +24,24 @@ def common_setup():
os.environ['GIT_ASKPASS'] = ''
os.environ['GIT_TERMINAL_PROMPT'] = '0'
+def create_distro_packages_list(distro_check, fetchdir, d):
+ """
+ Download the distros' package lists with OE-Core's oe.distro_check,
+ keeping this process's environment as it was.
+
+ distro_check's create_socket() calls bb.utils.export_proxies(), which
+ exports PATH and HOME from the datastore along with the proxy
+ variables. OE-Core's PATH puts its scripts/git wrapper first, with no
+ python3 beside it, so left in place it breaks every later git command
+ in this process.
+ """
+ saved_environ = os.environ.copy()
+ try:
+ distro_check.create_distro_packages_list(fetchdir, d)
+ finally:
+ os.environ.clear()
+ os.environ.update(saved_environ)
+
def get_logger(name, settings):
from logging.handlers import RotatingFileHandler
@@ -17,7 +17,8 @@ from datetime import datetime
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__))))
from common import common_setup, load_recipes, \
- get_pv_type, get_logger, DryRunRollbackException
+ get_pv_type, get_logger, DryRunRollbackException, \
+ create_distro_packages_list
common_setup()
from layerindex import utils
@@ -138,7 +139,7 @@ if __name__=="__main__":
# Only need to do this once
from oe import distro_check
logger.debug("Downloading distro's package information ...")
- distro_check.create_distro_packages_list(fetchdir, d)
+ create_distro_packages_list(distro_check, fetchdir, d)
pkglst_dir = os.path.join(fetchdir, "package_lists")
RecipeDistro.objects.filter(recipe__layerbranch = layerbranch).delete()
new file mode 100644
@@ -0,0 +1,45 @@
+# layerindex-web - tests for create_distro_packages_list() in rrs/tools/common.py
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+import os
+import sys
+import types
+
+import pytest
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'rrs', 'tools'))
+
+import common
+
+
+def fake_distro_check(fail=False):
+ # Like OE-Core's create_socket(): bb.utils.export_proxies() writes the
+ # datastore's PATH and HOME into os.environ
+ def create_distro_packages_list(fetchdir, d):
+ os.environ['PATH'] = '/oe-core/scripts:/build/tmp/hosttools'
+ os.environ['HOME'] = '/build'
+ os.environ['http_proxy'] = 'http://proxy.example.com:3128'
+ if fail:
+ raise OSError('HTTP Error 404: Not Found')
+ return types.SimpleNamespace(create_distro_packages_list=create_distro_packages_list)
+
+
+@pytest.mark.parametrize('fail', [False, True])
+def test_create_distro_packages_list_keeps_the_environment(monkeypatch, fail):
+ # [YOCTO #16506] OE-Core's PATH left in the environment made the next
+ # layer branch's git commands run OE-Core's scripts/git without python3
+ monkeypatch.setenv('PATH', '/usr/local/bin:/usr/bin:/bin')
+ monkeypatch.setenv('HOME', '/home/layers')
+ monkeypatch.delenv('http_proxy', raising=False)
+ before = dict(os.environ)
+
+ if fail:
+ with pytest.raises(OSError):
+ common.create_distro_packages_list(fake_distro_check(fail=True), '/fetch', None)
+ else:
+ common.create_distro_packages_list(fake_distro_check(), '/fetch', None)
+
+ assert dict(os.environ) == before
OE-Core's distro_check calls bb.utils.export_proxies(), which also exports the datastore's PATH and HOME. OE-Core's PATH puts its scripts/git wrapper first with no python3 beside it, so once the package lists were fetched for the first layer branch, every git command for the next one failed with "/usr/bin/env: 'python3': No such file or directory". Restore the environment after fetching the lists. [YOCTO #16506] AI-Generated: Claude Opus 5.5 Signed-off-by: Tim Orling <tim.orling@konsulko.com> --- rrs/tools/common.py | 18 +++++++++++++ rrs/tools/rrs_distros.py | 5 ++-- tests/test_rrs_distros_environ.py | 45 +++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/test_rrs_distros_environ.py