menu plugin: track root repo dir

This patch adds a new top-level schema node `_source_dir` which is used
to track the top repo dir on auto-generated kas files. This node is
generated by the kas menu plugin and provides the absolute path to the
top repo dir at time of invoking the plugin. When later calling any other
kas operation that performs a checkout, this node is evaluated and the
top repo dir is set accordingly. This tracking is required when the
build command is executed from another dir than the top repo dir, as the
repo-dir cannot be computed by kas in this case (the .config.yaml file
is in the KAS_WORK_DIR, not in the repo dir).

Proposed-by: Peter Hoyes <Peter.Hoyes@arm.com>
Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
[Jan: aligned format-changelog text, simplified load_config returning]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
This commit is contained in:
Felix Moessbauer 2023-05-26 06:39:42 +02:00 committed by Jan Kiszka
parent ea0baa06d0
commit 76db0706f3
6 changed files with 37 additions and 11 deletions

View File

@ -138,3 +138,5 @@ Added
~~~~~ ~~~~~
- The ``overrides`` top-level entry can be used to pin floating repo refspecs. - The ``overrides`` top-level entry can be used to pin floating repo refspecs.
- ``_source_dir`` top-level entry is auto-generated when using the menu plugin
and provides the path to the top repo at time of invoking the plugin.

View File

@ -533,3 +533,8 @@ Configuration reference
corresponds to a Kconfig configuration variable and can be of the types corresponds to a Kconfig configuration variable and can be of the types
string, boolean or integer. The content of this key is typically string, boolean or integer. The content of this key is typically
maintained by the ``kas menu`` plugin in a ``.config.yaml`` file. maintained by the ``kas menu`` plugin in a ``.config.yaml`` file.
* ``_source_dir``:: string [optional]
This entry is auto-generated by the menu plugin and provides the path to
the top repo at time of invoking the plugin. It must not be set
manually and might only be defined in the top-level ``.config.yaml`` file.

View File

@ -46,7 +46,7 @@ class 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( top_repo_path = Repo.get_root_path(
os.path.dirname(self.filenames[0])) 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),
@ -61,7 +61,7 @@ class Config:
update = ctx.args.update if hasattr(ctx.args, 'update') else False update = ctx.args.update if hasattr(ctx.args, 'update') else False
self.handler = IncludeHandler(self.filenames, self.handler = IncludeHandler(self.filenames,
self.top_repo_path, top_repo_path,
not update) not update)
self.repo_dict = self._get_repo_dict() self.repo_dict = self._get_repo_dict()
@ -111,10 +111,11 @@ class Config:
overrides = self._config.get('overrides', {}) \ overrides = self._config.get('overrides', {}) \
.get('repos', {}).get(name, {}) .get('repos', {}).get(name, {})
config = self.get_repos_config()[name] or {} config = self.get_repos_config()[name] or {}
top_repo_path = self.handler.get_top_repo_path()
return Repo.factory(name, return Repo.factory(name,
config, config,
repo_defaults, repo_defaults,
self.top_repo_path, top_repo_path,
overrides) overrides)
def _get_repo_dict(self): def _get_repo_dict(self):

View File

@ -41,6 +41,8 @@ from . import CONFIGSCHEMA
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) Siemens AG, 2017-2021' __copyright__ = 'Copyright (c) Siemens AG, 2017-2021'
SOURCE_DIR_OVERRIDE_KEY = '_source_dir'
class LoadConfigException(KasUserError): class LoadConfigException(KasUserError):
""" """
@ -100,7 +102,7 @@ def load_config(filename):
logging.warning('Obsolete ''proxy_config'' detected. ' logging.warning('Obsolete ''proxy_config'' detected. '
'This has no effect and will be rejected soon.') 'This has no effect and will be rejected soon.')
return config return (config, config.get(SOURCE_DIR_OVERRIDE_KEY, None))
class IncludeException(KasUserError): class IncludeException(KasUserError):
@ -145,6 +147,9 @@ class IncludeHandler:
file = Path(self.top_files[0]) file = Path(self.top_files[0])
return file.parent / (file.stem + '.lock' + file.suffix) return file.parent / (file.stem + '.lock' + file.suffix)
def get_top_repo_path(self):
return self.top_repo_path
def get_config(self, repos=None): def get_config(self, repos=None):
""" """
Parameters: Parameters:
@ -188,7 +193,12 @@ class IncludeHandler:
missing_repos = [] missing_repos = []
configs = [] configs = []
try: try:
current_config = load_config(filename) current_config, src_dir = load_config(filename)
# src_dir must only be set by auto-generated config file
if src_dir:
self.top_repo_path = src_dir
repo_path = src_dir
except FileNotFoundError: except FileNotFoundError:
raise LoadConfigException('Configuration file not found', raise LoadConfigException('Configuration file not found',
filename) filename)

View File

@ -75,7 +75,9 @@ from kconfiglib import Kconfig, Symbol, Choice, KconfigError, \
from kas import __version__, __file_version__ from kas import __version__, __file_version__
from kas.context import create_global_context from kas.context import create_global_context
from kas.config import CONFIG_YAML_FILE from kas.config import CONFIG_YAML_FILE
from kas.includehandler import load_config as load_config_yaml from kas.repos import Repo
from kas.includehandler import load_config as load_config_yaml, \
SOURCE_DIR_OVERRIDE_KEY
from kas.plugins.build import Build from kas.plugins.build import Build
from kas.kasusererror import KasUserError from kas.kasusererror import KasUserError
@ -140,7 +142,7 @@ class Menu:
def load_config(self, filename): def load_config(self, filename):
try: try:
self.orig_config = load_config_yaml(filename) self.orig_config, _ = load_config_yaml(filename)
except FileNotFoundError: except FileNotFoundError:
self.orig_config = {} self.orig_config = {}
return return
@ -163,7 +165,7 @@ class Menu:
else: # string else: # string
sym.set_value(symvalue) sym.set_value(symvalue)
def save_config(self, filename): def save_config(self, filename, top_repo_dir):
kas_includes = [] kas_includes = []
kas_targets = [] kas_targets = []
kas_build_system = None kas_build_system = None
@ -214,7 +216,8 @@ class Menu:
'version': __file_version__, 'version': __file_version__,
'includes': kas_includes 'includes': kas_includes
}, },
'menu_configuration': menu_configuration 'menu_configuration': menu_configuration,
SOURCE_DIR_OVERRIDE_KEY: top_repo_dir
} }
if kas_build_system: if kas_build_system:
config['build_system'] = kas_build_system config['build_system'] = kas_build_system
@ -260,11 +263,13 @@ class Menu:
ctx = create_global_context(args) ctx = create_global_context(args)
kconfig_file = os.path.abspath(args.kconfig)
try: try:
self.kconf = Kconfig(args.kconfig, warn_to_stderr=False) self.kconf = Kconfig(kconfig_file, warn_to_stderr=False)
except (KconfigError, FileNotFoundError) as err: except (KconfigError, FileNotFoundError) as err:
raise KConfigLoadError(str(err)) raise KConfigLoadError(str(err))
top_repo_path = Repo.get_root_path(os.path.dirname(kconfig_file))
config_filename = os.path.join(ctx.kas_work_dir, CONFIG_YAML_FILE) config_filename = os.path.join(ctx.kas_work_dir, CONFIG_YAML_FILE)
self.load_config(config_filename) self.load_config(config_filename)
@ -276,7 +281,7 @@ class Menu:
if action == 'exit': if action == 'exit':
return return
self.save_config(config_filename) self.save_config(config_filename, top_repo_path)
self.dump_kconf_warnings() self.dump_kconf_warnings()
if action == 'build': if action == 'build':

View File

@ -269,6 +269,9 @@
} }
] ]
} }
},
"_source_dir": {
"type": "string"
} }
} }
} }