| Message ID | 20241108231236.2838-2-git@jdknight.me |
|---|---|
| State | Superseded |
| Headers | show |
| Series | [v2,1/2] linux: support each linux latest lts version | expand |
On 09/11/2024 00:12, James Knight wrote: > Provides a helper script which can be used to quickly synchronize the > kernel versions defined in the Linux's `Config.in` file based on the > contents populated inside `linux.hash`. > > The goal of this script is to help the maintenance effort required when > possibly supporting all active Linux LTS versions in the tree at a > given time. > > Signed-off-by: James Knight <git@jdknight.me> I just merged a script that does it much better, because it downloads the sha file from kernel.org and updates the hash file from that. See utils/bump-stable-kernel-versions Regards, Arnout > --- > Changes v1 -> v2: > - Introduced in the v2 of this series. > > This is optional. No worries if not desired. > --- > support/scripts/sync-kernel-versions.py | 142 ++++++++++++++++++++++++ > 1 file changed, 142 insertions(+) > create mode 100755 support/scripts/sync-kernel-versions.py > > diff --git a/support/scripts/sync-kernel-versions.py b/support/scripts/sync-kernel-versions.py > new file mode 100755 > index 0000000000000000000000000000000000000000..2684b052657b0b98ac0265cd1b74a514d03ba9ca > --- /dev/null > +++ b/support/scripts/sync-kernel-versions.py > @@ -0,0 +1,142 @@ > +#!/usr/bin/env python3 > +# > +# Provides a script to allow the automatic updating of a Linux > +# package's `Config.in` file based on the version information detailed > +# in a `linux.hash` file. > + > +from pathlib import Path > +import argparse > +import re > + > + > +# searching for a version pattern inside a `linux.hash` file > +LINUX_VERSION_PATTERN = r'.*-([1-9]+.*)\.t.*' > + > + > +def main(): > + # argument parsing > + parser = argparse.ArgumentParser() > + parser.add_argument('--dry-run', action='store_true', > + help='Do not change any files') > + parser.add_argument('--verbose', action='store_true', > + help='Output additional information') > + args = parser.parse_args() > + > + # helpers > + def verbose(msg): > + if args.verbose: > + print(f'(verbose) {msg}') > + > + # find the linux package folder > + br_dir = Path(__file__).parent.parent.parent > + > + linux_pkg_dir = br_dir / 'linux' > + if not linux_pkg_dir.is_dir(): > + print('unable to find the linux package folder') > + return 1 > + > + linux_conf = linux_pkg_dir / 'Config.in' > + if not linux_conf.is_file(): > + print('unable to find the linux configuration file') > + return 1 > + > + linux_hash = linux_pkg_dir / 'linux.hash' > + if not linux_hash.is_file(): > + print('unable to find the linux hash file') > + return 1 > + > + # extract expected linux entries from the hash file > + try: > + with linux_hash.open(encoding='utf-8') as f: > + raw_hash_output = f.readlines() > + except OSError as e: > + print(f'error reading file {linux_hash}: {e}') > + return 1 > + > + entries = {} > + for hash_entry in raw_hash_output: > + if hash_entry.startswith('sha'): > + _, _, fname = hash_entry.strip().split(maxsplit=2) > + if fname.startswith('linux-'): > + verbose(f'detected linux entry: {fname}') > + > + match = re.search(LINUX_VERSION_PATTERN, fname) > + if match: > + vnum = match.group(1) > + ventry = extract_ventry(vnum) > + entries[ventry] = vnum > + verbose(f'detected linux version ({fname}): {vnum}') > + else: > + verbose(f'unable to detect linux version: {fname}') > + > + # read the existing Linux configuration file > + conf_contents = [] > + has_updated = False > + process_cfg = None > + try: > + with linux_conf.open(encoding='utf-8') as f: > + lines = f.read().splitlines() > + for line in lines: > + # wait until we are processing the kernel version section > + if process_cfg is None: > + if 'config BR2_LINUX_KERNEL_VERSION' in line: > + process_cfg = True > + > + # if we are processing, check each version entry for any > + # updates that are required > + elif process_cfg: > + # stop if the section is done > + if not line: > + process_cfg = False > + # check if this is a linux configuration entry that > + # might need to be updated > + elif 'default "' in line: > + front, raw_version, tail = line.split(maxsplit=2) > + vnum = raw_version.replace('"', '') > + if '.' in vnum: > + ventry = extract_ventry(vnum) > + if ventry in entries: > + new_vnum = entries[ventry] > + # if the version is outdated, replace the line > + if vnum != new_vnum: > + print(f'Sync: {vnum} -> {new_vnum}') > + line = f'\t{front} "{new_vnum}" {tail}' > + has_updated = True > + > + conf_contents.append(line) > + > + except OSError as e: > + print(f'error reading file {linux_conf}: {e}') > + return 1 > + > + # update the linux configuration file if we have new changes > + if has_updated and not args.dry_run: > + print(f'Updating: {linux_conf}') > + try: > + with linux_conf.open('w', encoding='utf-8', newline='') as f: > + for line in conf_contents: > + f.write(f'{line}\n') > + > + except OSError as e: > + print(f'error writing file {linux_conf}: {e}') > + return 1 > + > + if not has_updated: > + print('No outdated versions.') > + > + return 0 > + > + > +def extract_ventry(vnum): > + vmaj, vmin, _ = vnum.split('.', maxsplit=2) > + > + ventry = f'{vmaj}.{vmin}' > + if '-' in vnum: > + _, postfix = vnum.split('-', maxsplit=1) > + ventry += f'-{postfix}' > + > + return ventry > + > + > +if __name__ == "__main__": > + raise SystemExit(main())
diff --git a/support/scripts/sync-kernel-versions.py b/support/scripts/sync-kernel-versions.py new file mode 100755 index 0000000000000000000000000000000000000000..2684b052657b0b98ac0265cd1b74a514d03ba9ca --- /dev/null +++ b/support/scripts/sync-kernel-versions.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# +# Provides a script to allow the automatic updating of a Linux +# package's `Config.in` file based on the version information detailed +# in a `linux.hash` file. + +from pathlib import Path +import argparse +import re + + +# searching for a version pattern inside a `linux.hash` file +LINUX_VERSION_PATTERN = r'.*-([1-9]+.*)\.t.*' + + +def main(): + # argument parsing + parser = argparse.ArgumentParser() + parser.add_argument('--dry-run', action='store_true', + help='Do not change any files') + parser.add_argument('--verbose', action='store_true', + help='Output additional information') + args = parser.parse_args() + + # helpers + def verbose(msg): + if args.verbose: + print(f'(verbose) {msg}') + + # find the linux package folder + br_dir = Path(__file__).parent.parent.parent + + linux_pkg_dir = br_dir / 'linux' + if not linux_pkg_dir.is_dir(): + print('unable to find the linux package folder') + return 1 + + linux_conf = linux_pkg_dir / 'Config.in' + if not linux_conf.is_file(): + print('unable to find the linux configuration file') + return 1 + + linux_hash = linux_pkg_dir / 'linux.hash' + if not linux_hash.is_file(): + print('unable to find the linux hash file') + return 1 + + # extract expected linux entries from the hash file + try: + with linux_hash.open(encoding='utf-8') as f: + raw_hash_output = f.readlines() + except OSError as e: + print(f'error reading file {linux_hash}: {e}') + return 1 + + entries = {} + for hash_entry in raw_hash_output: + if hash_entry.startswith('sha'): + _, _, fname = hash_entry.strip().split(maxsplit=2) + if fname.startswith('linux-'): + verbose(f'detected linux entry: {fname}') + + match = re.search(LINUX_VERSION_PATTERN, fname) + if match: + vnum = match.group(1) + ventry = extract_ventry(vnum) + entries[ventry] = vnum + verbose(f'detected linux version ({fname}): {vnum}') + else: + verbose(f'unable to detect linux version: {fname}') + + # read the existing Linux configuration file + conf_contents = [] + has_updated = False + process_cfg = None + try: + with linux_conf.open(encoding='utf-8') as f: + lines = f.read().splitlines() + for line in lines: + # wait until we are processing the kernel version section + if process_cfg is None: + if 'config BR2_LINUX_KERNEL_VERSION' in line: + process_cfg = True + + # if we are processing, check each version entry for any + # updates that are required + elif process_cfg: + # stop if the section is done + if not line: + process_cfg = False + # check if this is a linux configuration entry that + # might need to be updated + elif 'default "' in line: + front, raw_version, tail = line.split(maxsplit=2) + vnum = raw_version.replace('"', '') + if '.' in vnum: + ventry = extract_ventry(vnum) + if ventry in entries: + new_vnum = entries[ventry] + # if the version is outdated, replace the line + if vnum != new_vnum: + print(f'Sync: {vnum} -> {new_vnum}') + line = f'\t{front} "{new_vnum}" {tail}' + has_updated = True + + conf_contents.append(line) + + except OSError as e: + print(f'error reading file {linux_conf}: {e}') + return 1 + + # update the linux configuration file if we have new changes + if has_updated and not args.dry_run: + print(f'Updating: {linux_conf}') + try: + with linux_conf.open('w', encoding='utf-8', newline='') as f: + for line in conf_contents: + f.write(f'{line}\n') + + except OSError as e: + print(f'error writing file {linux_conf}: {e}') + return 1 + + if not has_updated: + print('No outdated versions.') + + return 0 + + +def extract_ventry(vnum): + vmaj, vmin, _ = vnum.split('.', maxsplit=2) + + ventry = f'{vmaj}.{vmin}' + if '-' in vnum: + _, postfix = vnum.split('-', maxsplit=1) + ventry += f'-{postfix}' + + return ventry + + +if __name__ == "__main__": + raise SystemExit(main())
Provides a helper script which can be used to quickly synchronize the kernel versions defined in the Linux's `Config.in` file based on the contents populated inside `linux.hash`. The goal of this script is to help the maintenance effort required when possibly supporting all active Linux LTS versions in the tree at a given time. Signed-off-by: James Knight <git@jdknight.me> --- Changes v1 -> v2: - Introduced in the v2 of this series. This is optional. No worries if not desired. --- support/scripts/sync-kernel-versions.py | 142 ++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100755 support/scripts/sync-kernel-versions.py