includehandler: Fix repo path detection for local includes
So far, repository paths for local includes were derived from the path name of the config file containing the include, rather than using the actual repository root as specified in the documentation. No one complained so far, some layers simply adjusted their includes to this inconsistency which was only discovered during refactorings. Fix this issue by passing also the repository path along with the config filename down the recursive _internal_include_handler calls. The top-level repo path now needs to be retrieved before the creation of IncludeHandler and passed to it then. This has the side effect of enabling deviating top-level repo paths, a feature that will be used by the upcoming changes for a .config.yaml file in KAS_WORK_DIR. As there are existing users of the old behavior out there, fall back to it if a local include cannot be found under the correct path and warn if this succeeds. This allows smooth migration of layers to the right pattern as they update their kas version. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
This commit is contained in:
parent
8a1c27bc92
commit
2077900b4e
@ -1,6 +1,6 @@
|
|||||||
# kas - setup tool for bitbake based projects
|
# kas - setup tool for bitbake based projects
|
||||||
#
|
#
|
||||||
# Copyright (c) Siemens AG, 2017-2020
|
# Copyright (c) Siemens AG, 2017-2021
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -28,7 +28,7 @@ from .repos import Repo
|
|||||||
from .includehandler import IncludeHandler, IncludeException
|
from .includehandler import IncludeHandler, IncludeException
|
||||||
|
|
||||||
__license__ = 'MIT'
|
__license__ = 'MIT'
|
||||||
__copyright__ = 'Copyright (c) Siemens AG, 2017-2018'
|
__copyright__ = 'Copyright (c) Siemens AG, 2017-2021'
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@ -41,6 +41,8 @@ class Config:
|
|||||||
self._config = {}
|
self._config = {}
|
||||||
self.filenames = [os.path.abspath(configfile)
|
self.filenames = [os.path.abspath(configfile)
|
||||||
for configfile in filename.split(':')]
|
for configfile in filename.split(':')]
|
||||||
|
self.top_repo_path = Repo.get_root_path(
|
||||||
|
os.path.dirname(self.filenames[0]))
|
||||||
|
|
||||||
repo_paths = [Repo.get_root_path(os.path.dirname(configfile),
|
repo_paths = [Repo.get_root_path(os.path.dirname(configfile),
|
||||||
fallback=False)
|
fallback=False)
|
||||||
@ -50,7 +52,7 @@ class Config:
|
|||||||
'belong to the same repository or all '
|
'belong to the same repository or all '
|
||||||
'must be outside of versioning control')
|
'must be outside of versioning control')
|
||||||
|
|
||||||
self.handler = IncludeHandler(self.filenames)
|
self.handler = IncludeHandler(self.filenames, self.top_repo_path)
|
||||||
self.repo_dict = self._get_repo_dict()
|
self.repo_dict = self._get_repo_dict()
|
||||||
|
|
||||||
def get_build_system(self):
|
def get_build_system(self):
|
||||||
@ -88,13 +90,12 @@ class Config:
|
|||||||
repo_config_dict = self._config.get('repos', {})
|
repo_config_dict = self._config.get('repos', {})
|
||||||
repo_defaults = self._config.get('defaults', {}).get('repos', {})
|
repo_defaults = self._config.get('defaults', {}).get('repos', {})
|
||||||
repo_dict = {}
|
repo_dict = {}
|
||||||
repo_fallback_path = os.path.dirname(self.filenames[0])
|
|
||||||
for repo in repo_config_dict:
|
for repo in repo_config_dict:
|
||||||
repo_config_dict[repo] = repo_config_dict[repo] or {}
|
repo_config_dict[repo] = repo_config_dict[repo] or {}
|
||||||
repo_dict[repo] = Repo.factory(repo,
|
repo_dict[repo] = Repo.factory(repo,
|
||||||
repo_config_dict[repo],
|
repo_config_dict[repo],
|
||||||
repo_defaults,
|
repo_defaults,
|
||||||
repo_fallback_path)
|
self.top_repo_path)
|
||||||
|
|
||||||
return repo_dict
|
return repo_dict
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# kas - setup tool for bitbake based projects
|
# kas - setup tool for bitbake based projects
|
||||||
#
|
#
|
||||||
# Copyright (c) Siemens AG, 2017-2018
|
# Copyright (c) Siemens AG, 2017-2021
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -37,7 +37,7 @@ from . import __file_version__, __compatible_file_version__
|
|||||||
from . import CONFIGSCHEMA
|
from . import CONFIGSCHEMA
|
||||||
|
|
||||||
__license__ = 'MIT'
|
__license__ = 'MIT'
|
||||||
__copyright__ = 'Copyright (c) Siemens AG, 2017-2018'
|
__copyright__ = 'Copyright (c) Siemens AG, 2017-2021'
|
||||||
|
|
||||||
|
|
||||||
class LoadConfigException(Exception):
|
class LoadConfigException(Exception):
|
||||||
@ -126,8 +126,9 @@ class IncludeHandler:
|
|||||||
The includes are read and merged from the deepest level upwards.
|
The includes are read and merged from the deepest level upwards.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, top_files):
|
def __init__(self, top_files, top_repo_path):
|
||||||
self.top_files = top_files
|
self.top_files = top_files
|
||||||
|
self.top_repo_path = top_repo_path
|
||||||
|
|
||||||
def get_config(self, repos=None):
|
def get_config(self, repos=None):
|
||||||
"""
|
"""
|
||||||
@ -143,7 +144,7 @@ class IncludeHandler:
|
|||||||
|
|
||||||
repos = repos or {}
|
repos = repos or {}
|
||||||
|
|
||||||
def _internal_include_handler(filename):
|
def _internal_include_handler(filename, repo_path):
|
||||||
"""
|
"""
|
||||||
Recursively loads include files and finds missing repos.
|
Recursively loads include files and finds missing repos.
|
||||||
|
|
||||||
@ -185,10 +186,21 @@ class IncludeHandler:
|
|||||||
includefile = include
|
includefile = include
|
||||||
else:
|
else:
|
||||||
includefile = os.path.abspath(
|
includefile = os.path.abspath(
|
||||||
os.path.join(
|
os.path.join(repo_path, include))
|
||||||
os.path.dirname(filename),
|
if not os.path.exists(includefile):
|
||||||
|
alternate = os.path.abspath(
|
||||||
|
os.path.join(os.path.dirname(filename),
|
||||||
include))
|
include))
|
||||||
(cfg, rep) = _internal_include_handler(includefile)
|
if os.path.exists(alternate):
|
||||||
|
logging.warning(
|
||||||
|
'Falling back to file-relative addressing '
|
||||||
|
'of local include "%s"', include)
|
||||||
|
logging.warning(
|
||||||
|
'Update your layer to repo-relative '
|
||||||
|
'addressing to avoid this warning')
|
||||||
|
includefile = alternate
|
||||||
|
(cfg, rep) = _internal_include_handler(includefile,
|
||||||
|
repo_path)
|
||||||
configs.extend(cfg)
|
configs.extend(cfg)
|
||||||
missing_repos.extend(rep)
|
missing_repos.extend(rep)
|
||||||
elif isinstance(include, Mapping):
|
elif isinstance(include, Mapping):
|
||||||
@ -206,11 +218,10 @@ class IncludeHandler:
|
|||||||
raise IncludeException(
|
raise IncludeException(
|
||||||
'"file" is not specified: {}'
|
'"file" is not specified: {}'
|
||||||
.format(include))
|
.format(include))
|
||||||
|
abs_includedir = os.path.abspath(includedir)
|
||||||
(cfg, rep) = _internal_include_handler(
|
(cfg, rep) = _internal_include_handler(
|
||||||
os.path.abspath(
|
os.path.join(abs_includedir, includefile),
|
||||||
os.path.join(
|
abs_includedir)
|
||||||
includedir,
|
|
||||||
includefile)))
|
|
||||||
configs.extend(cfg)
|
configs.extend(cfg)
|
||||||
missing_repos.extend(rep)
|
missing_repos.extend(rep)
|
||||||
else:
|
else:
|
||||||
@ -261,7 +272,8 @@ class IncludeHandler:
|
|||||||
configs = []
|
configs = []
|
||||||
missing_repos = []
|
missing_repos = []
|
||||||
for configfile in self.top_files:
|
for configfile in self.top_files:
|
||||||
cfgs, reps = _internal_include_handler(configfile)
|
cfgs, reps = _internal_include_handler(configfile,
|
||||||
|
self.top_repo_path)
|
||||||
configs.extend(cfgs)
|
configs.extend(cfgs)
|
||||||
for repo in reps:
|
for repo in reps:
|
||||||
if repo not in missing_repos:
|
if repo not in missing_repos:
|
||||||
|
@ -139,7 +139,7 @@ header:
|
|||||||
monkeypatch.setattr(includehandler, 'CONFIGSCHEMA', {})
|
monkeypatch.setattr(includehandler, 'CONFIGSCHEMA', {})
|
||||||
for test in testvector:
|
for test in testvector:
|
||||||
with patch_open(includehandler, dictionary=test['fdict']):
|
with patch_open(includehandler, dictionary=test['fdict']):
|
||||||
ginc = includehandler.IncludeHandler(['x.yml'])
|
ginc = includehandler.IncludeHandler(['x.yml'], '.')
|
||||||
config, missing = ginc.get_config(repos=test['rdict'])
|
config, missing = ginc.get_config(repos=test['rdict'])
|
||||||
|
|
||||||
# Remove header, because we dont want to compare it:
|
# Remove header, because we dont want to compare it:
|
||||||
@ -347,7 +347,7 @@ v: {v2: y, v3: y, v5: y}'''),
|
|||||||
os.path.abspath('z.yml'): header.format('''
|
os.path.abspath('z.yml'): header.format('''
|
||||||
v: {v3: z, v4: z}''')}
|
v: {v3: z, v4: z}''')}
|
||||||
with patch_open(includehandler, dictionary=data):
|
with patch_open(includehandler, dictionary=data):
|
||||||
ginc = includehandler.IncludeHandler(['x.yml'])
|
ginc = includehandler.IncludeHandler(['x.yml'], '.')
|
||||||
config, _ = ginc.get_config()
|
config, _ = ginc.get_config()
|
||||||
keys = list(config['v'].keys())
|
keys = list(config['v'].keys())
|
||||||
index = {keys[i]: i for i in range(len(keys))}
|
index = {keys[i]: i for i in range(len(keys))}
|
||||||
|
Loading…
Reference in New Issue
Block a user