Skip to content

Commit

Permalink
lock plugin: update corresponding lockfiles
Browse files Browse the repository at this point in the history
As we now track from which lockfile a repos lock originates, we also
want to update it there. This is a two-staged process:

1. update all locks of "locked" repos
2. add locks for not-yet-locked repos to top lockfile

In step 2 we further need to handle the case that the default lockfile
does not yet exist, and the case that it already exists. In case it does
not exist, it will be created. Otherwise it will be updated.

Co-developed-by: Frieder Schrempf <[email protected]>
Signed-off-by: Felix Moessbauer <[email protected]>
  • Loading branch information
fmoessbauer committed Feb 12, 2025
1 parent 2f8a401 commit 0920027
Showing 1 changed file with 85 additions and 18 deletions.
103 changes: 85 additions & 18 deletions kas/plugins/lock.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# kas - setup tool for bitbake based projects
#
# Copyright (c) Siemens AG, 2017-2024
# Copyright (c) Siemens AG, 2017-2025
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -48,8 +48,9 @@
import logging
import os
from kas.context import get_context
from kas.includehandler import ConfigFile
from kas.plugins.checkout import Checkout
from kas.plugins.dump import Dump, IoTarget
from kas.plugins.dump import Dump, IoTarget, LOCKFILE_VERSION_MIN

__license__ = 'MIT'
__copyright__ = 'Copyright (c) Siemens AG, 2024'
Expand All @@ -70,6 +71,62 @@ def setup_parser(cls, parser):
super().setup_parser(parser)
Dump.setup_parser_format_args(parser)

def _update_lockfile(self, lockfile, repos_to_lock, update_only, args):
"""
Update all locks in the given lockfile.
If update_only, no new locks are added.
"""
output = IoTarget(target=lockfile, managed=True)
lockfile_config = lockfile.config
changed = False

if 'overrides' not in lockfile_config:
lockfile_config['overrides'] = {'repos': {}}
if 'repos' not in lockfile_config['overrides']:
lockfile_config['overrides']['repos'] = {}
lock_header_vers = lockfile_config['header']['version']
if lock_header_vers < LOCKFILE_VERSION_MIN:
logging.warning('Lockfile uses too-old header version (%s). '
'Updating to version %d',
lock_header_vers, LOCKFILE_VERSION_MIN)
lockfile_config['header']['version'] = LOCKFILE_VERSION_MIN

for k, v in lockfile_config['overrides']['repos'].items():
for rk, r in repos_to_lock:
if k == rk:
if v['commit'] == r.revision:
logging.info('Lock of %s is up-to-date: %s',
r.name, r.revision)
elif not lockfile.is_external:
logging.info('Updating lock of %s: %s -> %s',
r.name, v['commit'], r.revision)
v['commit'] = r.revision
changed = True
else:
logging.warning(
'Repo %s is locked in remote lockfile %s. '
'Not updating.', r.name, lockfile.filename)
continue
repos_to_lock.remove((rk, r))

if not update_only:
for k, r in repos_to_lock:
logging.info('Adding lock of %s: %s', r.name, r.revision)
lockfile_config['overrides']['repos'][k] = \
{'commit': r.revision}
changed = True

if not changed:
return repos_to_lock

logging.info('Updating lockfile %s',
os.path.relpath(lockfile.filename, os.getcwd()))
output = IoTarget(target=lockfile.filename, managed=True)
format = "json" if lockfile.filename.suffix == '.json' else "yaml"
Dump.dump_config(lockfile_config, output, format,
args.indent, args.sort)
return repos_to_lock

def run(self, args):
def _filter_enabled(repos):
return [(k, r) for k, r in repos if not r.operations_disabled]
Expand All @@ -83,22 +140,32 @@ def _filter_enabled(repos):

super().run(args)
ctx = get_context()
config_expanded = {'header': {'version': 14}}
repos = ctx.config.repo_dict.items()

# when locking, only consider repos managed by kas
repos = _filter_enabled(repos)
config_expanded['overrides'] = \
{'repos': {k: {'commit': r.revision} for k, r in repos}}

lockfile = ctx.config.handler.get_lockfile()
output = IoTarget(target=lockfile, managed=True)
format = "json" if lockfile.suffix == '.json' else "yaml"

Dump.dump_config(config_expanded, output, format,
args.indent, args.sort)
logging.info('Lockfile created: %s',
os.path.relpath(lockfile, os.getcwd()))
self.repos = ctx.config.repo_dict.items()
# when locking, only consider floating repos managed by kas
repos_to_lock = [(k, r) for k, r in _filter_enabled(self.repos)
if not r.commit]
if not repos_to_lock:
logging.info('No floating repos found. Nothing to lock.')
return

# first update all locks we have without creating new ones
lockfiles = ctx.config.get_lockfiles()
for lock in lockfiles:
repos_to_lock = self._update_lockfile(lock, repos_to_lock,
True, args)
# then add new locks for the remaining repos to the default lockfile
if repos_to_lock:
logging.warning('The following repos are not covered by any '
'lockfile. Adding to top lockfile: %s',
', '.join([r.name for _, r in repos_to_lock]))
lockpath = ctx.config.handler.get_lock_filename()
if len(lockfiles) and lockfiles[0].filename == lockpath:
lock = lockfiles[0]
else:
lock = ConfigFile(lockpath, is_external=False,
is_lockfile=True)
lock.config['header'] = {'version': LOCKFILE_VERSION_MIN}
self._update_lockfile(lock, repos_to_lock, False, args)


__KAS_PLUGINS__ = [Lock]

0 comments on commit 0920027

Please sign in to comment.