bundlewrap/libs/apt.py

105 lines
3.1 KiB
Python

from re import match
from glob import glob
from os.path import join, basename, exists
def format_variables(node, string):
return string.format(
codename=node.metadata.get('os_codename'),
version=node.os_version[0],
)
def find_keyfile_extension(node, key_name):
formatted_key_name = format_variables(node, key_name)
for extension in ('asc', 'gpg'):
if exists(join(node.repo.path, 'data', 'apt', 'keys', f'{formatted_key_name}.{extension}')):
return extension
else:
raise Exception(f"no keyfile '{formatted_key_name}.(asc|gpg)' found")
# https://manpages.ubuntu.com/manpages/latest/en/man5/apt.conf.5.html
def render_apt_conf(section, depth=0):
buffer = ''
for k,v in sorted(section.items()):
if isinstance(v, dict):
# element is a sub section
assert match(r'^[a-zA-Z/\-\:\.\_\+]*$', k) and not match(r'::', k)
buffer += ' '*4*depth + k + ' {\n'
buffer += render_apt_conf(v, depth=depth+1)
buffer += ' '*4*depth + '}\n'
elif isinstance(v, (set, list)):
# element is a value list
buffer += ' '*4*depth + k + ' {\n'
for e in sorted(v):
buffer += ' '*4*(depth+1) + '"' + e + '";\n'
buffer += ' '*4*depth + '}\n'
else:
# element is a single value
buffer += ' '*4*depth + k + ' "' + v + '";\n'
return buffer
# https://manpages.debian.org/latest/apt/sources.list.5.de.html
# https://repolib.readthedocs.io/en/latest/deb822-format.html
def render_source(node, source_name):
config = node.metadata.get(f'apt/sources/{source_name}')
lines = []
keys_and_types = {
'types': (set, list),
'urls': (set, list),
'suites': (set, list),
'components': (set, list),
'options': dict,
'key': str,
}
for key, value in config.items():
if key not in keys_and_types:
raise Exception(f"{node}: invalid source '{source_name}' conf key: '{key}' (expecting one of: {', '.join(keys_and_types)})")
elif not isinstance(value, keys_and_types[key]):
raise Exception(f"{node}: invalid source '{source_name}' conf value type for '{key}': '{type(value)}' (expecting: '{keys_and_types[key]}')")
# X-Repolib-Name
lines.append(
f'X-Repolib-Name: ' + source_name
)
# types
lines.append(
f'Types: ' + ' '.join(sorted(config.get('types', {'deb'})))
)
# url
lines.append(
f'URIs: ' + ' '.join(sorted(config['urls']))
)
# suites
lines.append(
f'Suites: ' + ' '.join(sorted(config['suites']))
)
# components
if 'components' in config:
lines.append(
f'Components: ' + ' '.join(sorted(config['components']))
)
# options
for key, value in sorted(config['options'].items()):
if isinstance(value, (set, list)):
value = ' '.join(value)
lines.append(
f'{key}: ' + value
)
# render to string and format variables
return format_variables(node, '\n'.join(lines) + '\n')