summaryrefslogtreecommitdiffstats
path: root/debian/bin
diff options
context:
space:
mode:
Diffstat (limited to 'debian/bin')
-rwxr-xr-xdebian/bin/check_upstream.py57
-rwxr-xr-xdebian/bin/gencontrol.py378
-rwxr-xr-xdebian/bin/release-update78
-rwxr-xr-xdebian/bin/update-modinfo46
4 files changed, 320 insertions, 239 deletions
diff --git a/debian/bin/check_upstream.py b/debian/bin/check_upstream.py
index e2931c4..d69ce75 100755
--- a/debian/bin/check_upstream.py
+++ b/debian/bin/check_upstream.py
@@ -11,7 +11,7 @@ rules_defs = dict((match.group(1), match.group(2))
sys.path.append('/usr/share/linux-support-%s/lib/python' %
rules_defs['KERNELVERSION'])
from debian_linux.firmware import FirmwareWhence
-from config import Config
+from config import Config, pattern_to_re
class DistState(Enum):
undistributable = 1
@@ -20,23 +20,30 @@ class DistState(Enum):
def is_source_available(section):
for file_info in section.files.values():
- if not (file_info.source or file_info.binary.endswith('.cis')):
+ if not (file_info.source
+ or file_info.binary.endswith('.txt')
+ or file_info.binary.endswith('.cis')):
return False
return True
def check_section(section):
- if re.search(r'^BSD\b'
- r'|^GPLv2 or OpenIB\.org BSD\b'
- r'|\bPermission\s+is\s+hereby\s+granted\s+for\s+the\s+'
- r'distribution\s+of\s+this\s+firmware\s+(?:data|image)\b'
- r'(?!\s+as\s+part\s+of)'
- r'|\bRedistribution\s+and\s+use\s+in(?:\s+source\s+and)?'
- r'\s+binary\s+forms\b'
- r'|\bPermission\s+is\s+hereby\s+granted\b[^.]+\sto'
- r'\s+deal\s+in\s+the\s+Software\s+without'
- r'\s+restriction\b'
- r'|\bredistributable\s+in\s+binary\s+form\b',
- section.licence):
+ if section.licence is None:
+ # Maybe undistributable
+ return DistState.undistributable
+ elif re.search(r'^BSD\b'
+ r'|^GPLv2 or OpenIB\.org BSD\b'
+ r'|\bPermission\s+is\s+hereby\s+granted\s+for\s+the\s+'
+ r'distribution\s+of\s+this\s+firmware\s+(?:data|image)\b'
+ r'(?!\s+as\s+part\s+of)'
+ r'|\bRedistribution\s+and\s+use\s+in(?:\s+source\s+and)?'
+ r'\s+binary\s+forms\b'
+ r'|\bPermission\s+is\s+hereby\s+granted\b[^.]+\sto'
+ r'\s+deal\s+in\s+the\s+Software\s+without'
+ r'\s+restriction\b'
+ r'|\bredistributable\s+in\s+binary\s+form\b'
+ r'|\bgrants\s+permission\s+to\s+use\s+and\s+redistribute'
+ r'\s+these\s+firmware\s+files\b',
+ section.licence):
return (DistState.free if is_source_available(section)
else DistState.non_free)
elif re.match(r'^(?:D|Red)istributable\b', section.licence):
@@ -54,10 +61,16 @@ def main(source_dir='.'):
package in config['base',]['packages']]
with open("debian/copyright") as f:
exclusions = deb822.Deb822(f).get("Files-Excluded", '').strip().split()
- packaged_files = {}
+
+ package_file_res = []
for package in config['base',]['packages']:
- for filename in config['base', package]['files']:
- packaged_files[filename] = package
+ config_entry = config['base', package]
+ package_file_res.append(
+ ([pattern_to_re(pattern)
+ for pattern in config_entry['files']],
+ [pattern_to_re(pattern)
+ for pattern in config_entry.get('files-exclude', [])])
+ )
for section in FirmwareWhence(open(os.path.join(source_dir, 'WHENCE'))):
dist_state = check_section(section)
@@ -65,9 +78,15 @@ def main(source_dir='.'):
if dist_state == DistState.non_free:
if not any(fnmatch.fnmatch(file_info.binary, exclusion)
for exclusion in exclusions):
- if file_info.binary in packaged_files:
+ if any(
+ (any(inc_re.fullmatch(file_info.binary)
+ for inc_re in inc_res)
+ and not any(exc_re.fullmatch(file_info.binary)
+ for exc_re in exc_res))
+ for inc_res, exc_res in package_file_res
+ ):
update_file(source_dir, over_dirs, file_info.binary)
- elif os.path.isfile(filename):
+ elif os.path.isfile(file_info.binary):
print('I: %s is not included in any binary package' %
file_info.binary)
else:
diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py
index 293432b..41a9d45 100755
--- a/debian/bin/gencontrol.py
+++ b/debian/bin/gencontrol.py
@@ -1,79 +1,66 @@
#!/usr/bin/env python3
+import dataclasses
import io
+import itertools
import json
import locale
import os
+import pathlib
import re
import sys
+from typing import Iterable, Optional
sys.path.insert(0, "debian/lib/python")
sys.path.append(sys.argv[1] + "/lib/python")
locale.setlocale(locale.LC_CTYPE, "C.UTF-8")
-from config import Config
-from debian_linux.debian import BinaryPackage, PackageRelation, _ControlFileDict
-from debian_linux.debian import PackageDescription as PackageDescriptionBase
+from config import Config, pattern_to_re
+from debian_linux.dataclasses_deb822 import field_deb822, read_deb822, write_deb822
+from debian_linux.debian import BinaryPackage as BinaryPackageBase, PackageDescription, PackageRelation
import debian_linux.gencontrol
-from debian_linux.gencontrol import Makefile, MakeFlags, PackagesList
-from debian_linux.utils import TextWrapper
+from debian_linux.gencontrol import MakeFlags
from debian_linux.utils import Templates as TemplatesBase
-from collections import OrderedDict
-
-class PackageDescription(PackageDescriptionBase):
- __slots__ = ()
-
- def __init__(self, value = None):
- self.short = []
- self.long = []
- if value is not None:
- value = value.split("\n", 1)
- self.append_short(value[0])
- if len(value) > 1:
- self.append(value[1])
-
- def __str__(self):
- wrap = TextWrapper(width = 74, fix_sentence_endings = True).wrap
- short = ', '.join(self.short)
- long_pars = []
- for t in self.long:
- if isinstance(t, str):
- t = wrap(t)
- long_pars.append('\n '.join(t))
- long = '\n .\n '.join(long_pars)
- return short + '\n ' + long
-
- def append_pre(self, l):
- self.long.append(l)
-
- def extend(self, desc):
- if isinstance(desc, PackageDescription):
- self.short.extend(desc.short)
- self.long.extend(desc.long)
- elif isinstance(desc, (list, tuple)):
- for i in desc:
- self.append(i)
-
-BinaryPackage._fields['Description'] = PackageDescription
-
-class Template(_ControlFileDict):
- _fields = OrderedDict((
- ('Template', str),
- ('Type', str),
- ('Default', str),
- ('Description', PackageDescriptionBase),
- ))
+
+
+# XXX Delete after this field is added in linux-support
+@dataclasses.dataclass
+class BinaryPackage(BinaryPackageBase):
+ homepage: 'Optional[str]' = field_deb822(
+ 'Homepage',
+ default=None,
+ )
+
+
+@dataclasses.dataclass
+class Template:
+ template: 'str' = field_deb822('Template')
+ type: 'str' = field_deb822('Type')
+ default: 'Optional[str]' = field_deb822(
+ 'Default',
+ default=None,
+ )
+ description: PackageDescription = field_deb822(
+ 'Description',
+ default_factory=PackageDescription,
+ )
class Templates(TemplatesBase):
- def get_templates_control(self, key: str, context: dict[str, str] = {}) -> Template:
- return Template.read_rfc822(io.StringIO(self.get(key, context)))
+ def get_control(
+ self, key: str, context: dict[str, str] = {},
+ ) -> Iterable[BinaryPackage]:
+ return read_deb822(BinaryPackage, io.StringIO(self.get(key, context)))
+
+ def get_templates_control(
+ self, key: str, context: dict[str, str] = {}
+ ) -> Iterable[Template]:
+ return read_deb822(Template, io.StringIO(self.get(key, context)))
class GenControl(debian_linux.gencontrol.Gencontrol):
def __init__(self):
- self.config = Config()
- self.templates = Templates()
+ super().__init__(Config(), Templates())
with open('debian/modinfo.json', 'r') as f:
self.modinfo = json.load(f)
@@ -85,49 +72,30 @@ class GenControl(debian_linux.gencontrol.Gencontrol):
self.firmware_modules.setdefault(firmware_filename, []) \
.append(name)
- def __call__(self):
- packages = PackagesList()
- makefile = Makefile()
-
- self.do_source(packages)
- self.do_extra(packages, makefile)
- self.do_main(packages, makefile)
-
- self.write(packages, makefile)
-
- def do_source(self, packages):
- packages['source'] = self.templates.get_source_control("control.source", {})[0]
-
- def do_extra(self, packages, makefile):
- config_entry = self.config['base',]
- vars = {}
- vars.update(config_entry)
-
- for package_binary in self.templates.get_control("control.extra", {}):
- assert package_binary['Package'].startswith('firmware-')
- package = package_binary['Package'].replace('firmware-', '')
-
- makeflags = MakeFlags()
- makeflags['FILES'] = ''
- makeflags['PACKAGE'] = package
- makefile.add_cmds('binary-indep', ["$(MAKE) -f debian/rules.real binary-indep %s" % makeflags])
-
- packages.append(package_binary)
-
- def do_main(self, packages, makefile):
+ def do_main(self):
config_entry = self.config['base',]
vars = {}
vars.update(config_entry)
makeflags = MakeFlags()
- for i in ('build', 'binary-arch', 'setup'):
- makefile.add_cmds("%s_%%" % i, ["@true"])
+ self.file_errors = False
+ self.file_packages = {}
for package in config_entry['packages']:
- self.do_package(packages, makefile, package, vars.copy(), makeflags.copy())
-
- def do_package(self, packages, makefile, package, vars, makeflags):
+ self.do_package(package, vars.copy(), makeflags.copy())
+
+ for canon_path, package_suffixes in self.file_packages.items():
+ if len(package_suffixes) > 1:
+ print(f'E: {canon_path!s} is included in multiple packages:',
+ ', '.join(f'firmware-{suffix}'
+ for suffix in package_suffixes),
+ file=sys.stderr)
+ self.file_errors = True
+ if self.file_errors:
+ raise Exception('error(s) found in file lists')
+
+ def do_package(self, package, vars, makeflags):
config_entry = self.config['base', package]
vars.update(config_entry)
vars['package'] = package
@@ -141,7 +109,9 @@ class GenControl(debian_linux.gencontrol.Gencontrol):
if optional not in vars:
vars[optional] = ''
- package_dir = "debian/config/%s" % package
+ cur_dir = pathlib.Path.cwd()
+ install_dir = pathlib.Path('debian/build/install')
+ package_dir = pathlib.Path('debian/config') / package
try:
os.unlink('debian/firmware-%s.bug-presubj' % package)
@@ -149,98 +119,107 @@ class GenControl(debian_linux.gencontrol.Gencontrol):
pass
os.symlink('bug-presubj', 'debian/firmware-%s.bug-presubj' % package)
- files_orig = config_entry['files']
+ files_include = [(pattern, pattern_to_re(pattern))
+ for pattern in config_entry['files']]
+ files_exclude = [pattern_to_re(pattern)
+ for pattern in config_entry.get('files-excluded', [])]
+ files_added = set()
+ files_unused = set()
files_real = {}
- files_unused = []
links = {}
links_rev = {}
- # Look for additional and replacement files in binary package config
- for root, dirs, files in os.walk(package_dir):
- try:
- dirs.remove('.svn')
- except ValueError:
- pass
- for f in files:
- cur_path = root + '/' + f
- if root != package_dir:
- f = root[len(package_dir) + 1 : ] + '/' + f
- if os.path.islink(cur_path):
- if f in files_orig:
- links[f] = os.readlink(cur_path)
- continue
- f1 = f.rsplit('-', 1)
- if f in files_orig:
- files_real[f] = f, cur_path, None
- continue
- if len(f1) > 1:
- f_base, f_version = f1
- if f_base in files_orig:
- if f_base in files_real:
- raise RuntimeError("Multiple files for %s" % f_base)
- files_real[f_base] = f_base, package_dir + '/' + f, \
- f_version
+ # List all additional and replacement files in binary package
+ # config so we can:
+ # - match dangling symlinks which pathlib.Path.glob() would ignore
+ # - warn if any are unused
+ for root, dir_names, file_names in os.walk(package_dir):
+ root = pathlib.Path(root)
+ for name in file_names:
+ if not (root == package_dir \
+ and name in ['defines', 'LICENSE.install',
+ 'update.py', 'update.sh']):
+ canon_path = root.relative_to(package_dir) / name
+ files_added.add(canon_path)
+ files_unused.add(canon_path)
+
+ for pattern, pattern_re in files_include:
+ matched = False
+ matched_more = False
+
+ for paths, is_added in [
+ (((canon_path, package_dir / canon_path)
+ for canon_path in files_added
+ if pattern_re.fullmatch(str(canon_path))),
+ True),
+ (((cur_path.relative_to(install_dir), cur_path)
+ for cur_path in install_dir.glob(pattern)),
+ False)
+ ]:
+ for canon_path, cur_path in paths:
+ canon_name = str(canon_path)
+ if any(exc_pattern_re.fullmatch(canon_name)
+ for exc_pattern_re in files_exclude):
+ continue
+
+ matched = True
+
+ # Skip if already matched by earlier pattern or in
+ # other directory
+ if canon_path in files_real or canon_path in links:
continue
- # Whitelist files not expected to be installed as firmware
- if f in ['defines', 'LICENSE.install',
- 'update.py', 'update.sh']:
- continue
- files_unused.append(f)
-
- # Take all the other files from upstream
- for f in files_orig:
- if f not in files_real and f not in links:
- f_upstream = os.path.join('debian/build/install', f)
- if os.path.islink(f_upstream):
- links[f] = os.readlink(f_upstream)
- elif os.path.isfile(f_upstream):
- files_real[f] = f, f_upstream, None
-
- for f in links:
- link_target = os.path.normpath(os.path.join(f, '..', links[f]))
- links_rev.setdefault(link_target, []).append(f)
+
+ matched_more = True
+ if is_added:
+ files_unused.remove(canon_path)
+ if cur_path.is_symlink():
+ links[canon_path] = cur_path.readlink()
+ elif cur_path.is_file():
+ files_real[canon_path] = cur_path
+
+ self.file_packages.setdefault(canon_path, []) \
+ .append(package)
+
+ # Non-matching pattern is an error
+ if not matched:
+ print(f'E: {package}: {pattern} did not match anything',
+ file=sys.stderr)
+ self.file_errors = True
+ # Redundant pattern deserves a warning
+ elif not matched_more:
+ print(f'W: {package}: pattern {pattern} is redundant with earlier patterns',
+ file=sys.stderr)
+
+ for canon_path in links:
+ link_target = ((canon_path.parent / links[canon_path])
+ .resolve(strict=False)
+ .relative_to(cur_dir))
+ links_rev.setdefault(link_target, []).append(canon_path)
if files_unused:
- print('W: %s: unused files:' % package, ' '.join(files_unused),
+ print(f'W: {package}: unused files:',
+ ', '.join(str(path) for path in files_unused),
file=sys.stderr)
- makeflags['FILES'] = ' '.join(["%s:%s" % (i[1], i[0]) for i in sorted(files_real.values())])
- vars['files_real'] = ' '.join(["/lib/firmware/%s" % i for i in config_entry['files']])
+ makeflags['FILES'] = \
+ ' '.join([f'"{source}":"{dest}"'
+ for dest, source in sorted(files_real.items())]) \
+ .replace(',', '[comma]')
+ makeflags['LINKS'] = \
+ ' '.join([f'"{link}":"{target}"'
+ for link, target in sorted(links.items())]) \
+ .replace(',', '[comma]')
- makeflags['LINKS'] = ' '.join(["%s:%s" % (link, target)
- for link, target in sorted(links.items())])
-
- files_desc = ["Contents:"]
firmware_meta_temp = self.templates.get("metainfo.xml.firmware")
firmware_meta_list = []
module_names = set()
- wrap = TextWrapper(width = 71, fix_sentence_endings = True,
- initial_indent = ' * ',
- subsequent_indent = ' ').wrap
- for f in config_entry['files']:
+ for canon_path in sorted(itertools.chain(files_real, links)):
+ canon_name = str(canon_path)
firmware_meta_list.append(self.substitute(firmware_meta_temp,
- {'filename': f}))
- for module_name in self.firmware_modules.get(f, []):
+ {'filename': canon_name}))
+ for module_name in self.firmware_modules.get(canon_name, []):
module_names.add(module_name)
- if f in links:
- continue
- f, f_real, version = files_real[f]
- c = self.config.get(('base', package, f), {})
- desc = c.get('desc')
- if version is None:
- version = c.get('version')
- try:
- f = f + ', ' + ', '.join(sorted(links_rev[f]))
- except KeyError:
- pass
- if desc and version:
- desc = "%s, version %s (%s)" % (desc, version, f)
- elif desc:
- desc = "%s (%s)" % (desc, f)
- else:
- desc = "%s" % f
- files_desc.extend(wrap(desc))
modaliases = set()
for module_name in module_names:
@@ -252,35 +231,45 @@ class GenControl(debian_linux.gencontrol.Gencontrol):
for alias in sorted(list(modaliases))
]
- packages_binary = self.templates.get_control("control.binary", vars)
+ packages_binary = list(self.templates.get_control("binary.control", vars))
- packages_binary[0]['Description'].append_pre(files_desc)
+ scripts = {}
if 'initramfs-tools' in config_entry.get('support', []):
postinst = self.templates.get('postinst.initramfs-tools')
- open("debian/firmware-%s.postinst" % package, 'w').write(self.substitute(postinst, vars))
+ scripts.setdefault("postinst", []).append(self.substitute(postinst, vars))
if 'license-accept' in config_entry:
license = open("%s/LICENSE.install" % package_dir, 'r').read()
preinst = self.templates.get('preinst.license')
- preinst_filename = "debian/firmware-%s.preinst" % package
- open(preinst_filename, 'w').write(self.substitute(preinst, vars))
+ scripts.setdefault("preinst", []).append(self.substitute(preinst, vars))
- templates = self.templates.get_templates_control('templates.license', vars)
- templates[0]['Description'].append(re.sub('\n\n', '\n.\n', license))
+ templates = list(self.templates.get_templates_control('templates.license', vars))
+ templates[0].description.append(re.sub('\n\n', '\n.\n', license))
templates_filename = "debian/firmware-%s.templates" % package
- self.write_rfc822(open(templates_filename, 'w'), templates)
+ write_deb822(templates, open(templates_filename, 'w'))
- desc = packages_binary[0]['Description']
+ desc = packages_binary[0].description
desc.append(
"""This firmware is covered by the %s.
You must agree to the terms of this license before it is installed."""
% vars['license-title'])
- packages_binary[0]['Pre-Depends'] = PackageRelation('debconf | debconf-2.0')
+ packages_binary[0].pre_depends = PackageRelation('debconf | debconf-2.0')
+
+ if config_entry.get('usrmovemitigation', []):
+ vars['files'] = ' '.join(config_entry['usrmovemitigation'])
+ for script in ("preinst", "postinst"):
+ script_template = self.templates.get(script + '.usrmovemitigation')
+ script_content = self.substitute(script_template, vars)
+ scripts.setdefault(script, []).append(script_content)
+ del vars['files']
- packages.extend(packages_binary)
+ for script, script_contents in scripts.items():
+ script_contents.insert(0, "#!/bin/sh\n\nset -e\n")
+ script_contents.append("#DEBHELPER#\n\nexit 0\n")
+ open("debian/firmware-%s.%s" % (package, script), "w").write("\n".join(script_contents))
- makefile.add_cmds('binary-indep', ["$(MAKE) -f debian/rules.real binary-indep %s" % makeflags])
+ self.bundle.add_packages(packages_binary, (package,), makeflags)
vars['firmware-list'] = ''.join(firmware_meta_list)
vars['modalias-list'] = ''.join(modalias_meta_list)
@@ -292,6 +281,21 @@ You must agree to the terms of this license before it is installed."""
# XXX Might need to escape some characters
open("debian/firmware-%s.metainfo.xml" % package, 'w').write(self.substitute(package_meta_temp, vars))
+ # XXX Delete after updating to linux-support-6.11
+ def do_extra(self) -> None:
+ try:
+ packages_extra = self.templates.get_control("extra.control", self.vars)
+ except KeyError:
+ return
+
+ for package in packages_extra:
+ package.meta_rules_target = 'meta'
+ if not package.architecture:
+ raise RuntimeError('Require Architecture in debian/templates/extra.control')
+ for arch in package.architecture:
+ self.bundle.add_packages([package], (arch, ),
+ MakeFlags(), arch=arch, check_packages=False)
+
def process_template(self, in_entry, vars):
e = Template()
for key, value in in_entry.items():
@@ -319,23 +323,5 @@ You must agree to the terms of this license before it is installed."""
return vars[match.group(2)]
return re.sub(r'@(\??)([-_a-z]+)@', subst, str(s))
- def write(self, packages, makefile):
- self.write_control(packages.values())
- self.write_makefile(makefile)
-
- def write_control(self, list):
- self.write_rfc822(open("debian/control", 'w'), list)
-
- def write_makefile(self, makefile):
- f = open("debian/rules.gen", 'w')
- makefile.write(f)
- f.close()
-
- def write_rfc822(self, f, list):
- for entry in list:
- for key, value in entry.items():
- f.write("%s: %s\n" % (key, value))
- f.write('\n')
-
if __name__ == '__main__':
GenControl()()
diff --git a/debian/bin/release-update b/debian/bin/release-update
index 5eb75cd..ee564c4 100755
--- a/debian/bin/release-update
+++ b/debian/bin/release-update
@@ -8,12 +8,62 @@ import locale
from debian_linux.debian import Changelog, Version
-def print_stable_log(log, cur_ver, new_ver):
- log.flush() # serialise our output with git's
- subprocess.check_call(['git', 'log', '--reverse', '--no-merges',
- '--pretty= - %s',
- '{}..{}'.format(cur_ver, new_ver)],
- stdout=log)
+from config import Config, pattern_to_re
+
+
+# Convert Python glob pattern to Git patterns. Notable difference is
+# that in Python globbing '**/' matches a directory and its
+# descendants, but in Git it only matches descendants. Assume there
+# is at most one '**' in a pattern.
+def pattern_to_git_patterns(pattern):
+ yield f':{pattern}'
+ if '**/' in pattern:
+ yield f':{ pattern.replace("**/", "") }'
+
+
+# Convert Python glob pattern to Git reegexp. This assumes
+# pattern_to_re() produces compatible regular expressions except for
+# the use of '(?:...)' which we fix up.
+def pattern_to_git_re(pattern):
+ return pattern_to_re(pattern).pattern.replace('(?:', '(')
+
+
+def print_stable_log(log, cur_ver, new_ver, files_include):
+ inc_git_patterns = []
+ inc_git_res = []
+ for pattern in files_include:
+ inc_git_patterns.extend(pattern_to_git_patterns(pattern))
+ inc_git_res.append(pattern_to_git_re(pattern))
+
+ git_rev_range = f'{cur_ver}..{new_ver}'
+
+ # List commits changing files that we include
+ with subprocess.Popen(['git', 'log', '--no-merges', '--pretty=%s',
+ git_rev_range, '--'] + inc_git_patterns,
+ stdout=subprocess.PIPE, text=True) \
+ as proc:
+ lines = proc.stdout.readlines()
+
+ # List commits changing links that we include
+ with subprocess.Popen(['git', 'log', '--no-merges', '--pretty=%s',
+ '-G', f'^Link: *({ "|".join(inc_git_res) }) ->',
+ git_rev_range, '--', 'WHENCE'],
+ stdout=subprocess.PIPE, text=True) \
+ as proc:
+ lines.extend(proc.stdout.readlines())
+
+ # Strip useless subject prefix
+ strip_re = re.compile(r'^linux-firmware: *')
+ lines = [strip_re.sub('', line) for line in lines]
+
+ # Sort and de-dupe lines
+ lines.sort(key=str.casefold)
+ last_line = None
+ for line in lines:
+ if line != last_line:
+ log.write(f' - {line}')
+ last_line = line
+
def main(repo, new_ver):
locale.setlocale(locale.LC_CTYPE, "C.UTF-8")
@@ -26,6 +76,16 @@ def main(repo, new_ver):
if cur_ver == new_ver:
sys.exit(0)
+ # Get list of file patterns that we include. Don't get exclusions
+ # because in some cases files are excluded from one binary package
+ # so they can be included in another, and I don't think we can
+ # construct a single pattern list that exactly matches our include/
+ # exclude behaviour.
+ config = Config()
+ files_include = sum((config['base', package]['files']
+ for package in config['base',]['packages']),
+ [])
+
new_pkg_ver = new_ver + '-1'
# Three possible cases:
@@ -68,12 +128,14 @@ def main(repo, new_ver):
# Case 2(a)
if line_no == 3 and line != intro_line:
new_log.write(intro_line)
- print_stable_log(new_log, cur_ver, new_ver)
+ print_stable_log(new_log, cur_ver, new_ver,
+ files_include)
new_log.write('\n')
inserted = True
# Case 1 or 2(b)
elif line_no > 3 and line == '\n':
- print_stable_log(new_log, cur_ver, new_ver)
+ print_stable_log(new_log, cur_ver, new_ver,
+ files_include)
inserted = True
# Check that we inserted before hitting the end of the
diff --git a/debian/bin/update-modinfo b/debian/bin/update-modinfo
index ea37486..1470dd9 100755
--- a/debian/bin/update-modinfo
+++ b/debian/bin/update-modinfo
@@ -2,6 +2,7 @@
# Update the module information used to generate related device IDs
+import itertools
import json
import os.path
import subprocess
@@ -28,34 +29,47 @@ def get_module_info(filename, attr_name):
return output.rstrip('\n').split('\n')
-def main(kernel_id=None):
- if kernel_id is None:
- kernel_dir = '/lib/modules/' + os.uname().release
- elif '/' not in kernel_id:
- kernel_dir = '/lib/modules/' + kernel_id
+class JSONEncoderWithSet(json.JSONEncoder):
+ def default(self, o):
+ if isinstance(o, set):
+ return sorted(o)
+ return super().default(o)
+
+
+def main(*kernel_ids):
+ if not kernel_ids:
+ kernel_dirs = '/lib/modules/' + os.uname().release
else:
- kernel_dir = kernel_id
+ kernel_dirs = [('/lib/modules/' + kernel_id
+ if '/' not in kernel_id
+ else kernel_id)
+ for kernel_id in kernel_ids]
modinfo = {}
- for name, filename in iter_modules(kernel_dir):
+ for name, filename in itertools.chain.from_iterable(
+ iter_modules(kernel_dir) for kernel_dir in kernel_dirs):
# We only care about modules that might request firmware
- firmware = get_module_info(filename, 'firmware')
+ firmware = set(get_module_info(filename, 'firmware'))
if not firmware:
continue
# We only care about aliases generated from device IDs, which
# start with <type> ":"
- aliases = [alias
- for alias in get_module_info(filename, 'alias')
- if ':' in alias]
+ aliases = set(alias
+ for alias in get_module_info(filename, 'alias')
+ if ':' in alias)
- modinfo[name] = {
- 'alias': aliases,
- 'firmware': firmware,
- }
+ if name not in modinfo:
+ modinfo[name] = {
+ 'alias': aliases,
+ 'firmware': firmware,
+ }
+ else:
+ modinfo[name]['alias'] |= aliases
+ modinfo[name]['firmware'] |= firmware
with open('debian/modinfo.json', 'w') as f:
- json.dump(modinfo, f, indent=2, sort_keys=True)
+ json.dump(modinfo, f, indent=2, sort_keys=True, cls=JSONEncoderWithSet)
if __name__ == '__main__':