Skip to content

patching: integrate b4-based lore link processing #8257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions lib/tools/common/b4_caller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# ‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2023 Ricardo Pardini <[email protected]>
# This file is a part of the Armbian Build Framework https://github.com/armbian/build/
# ‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹
import argparse
import logging

import b4
import b4.mbox

log: logging.Logger = logging.getLogger("b4_caller")

#
# Automatic grabbing of patches from mailing lists, using 'b4' tool 'am' command.
# Patches will be grabbed and written to disk in the order they are listed here, before any other processing is done.
#b4-am:
# - { prefix: "0666", lore: "https://lore.kernel.org/r/20230706-topic-amlogic-upstream-dt-fixes-take3-v1-0-63ed070eeab2@linaro.org" }

def get_patch_via_b4(lore_link):
# Fool get_msgid with a fake argparse.Namespace
msgid_args = argparse.Namespace()
msgid_args.msgid = lore_link
msgid = b4.get_msgid(msgid_args)
log.debug(f"msgid: {msgid}")

msgs = b4.get_pi_thread_by_msgid(msgid)

count = len(msgs)
log.debug('Analyzing %s messages in the thread', count)

lmbx = b4.LoreMailbox()
for msg in msgs:
lmbx.add_message(msg)

lser = lmbx.get_series()

# hack at the "main config" to avoid attestation etc; b4's config is a global MAIN_CONFIG
config = b4.get_main_config()
config['attestation-policy'] = "off"

# hack at the "user config", since there is not really an user here; its a global USER_CONFIG
uconfig = b4.get_user_config()
uconfig['name'] = "Armbian Autopatcher"
uconfig['email'] = "[email protected]"
log.debug(f"uconfig: {uconfig}")

# prepare for git am
am_msgs = lser.get_am_ready(addlink=True, linkmask='https://lore.kernel.org/r/%s')
log.debug('Total patches: %s', len(am_msgs))

top_msgid = None
for lmsg in lser.patches:
if lmsg is not None:
top_msgid = lmsg.msgid
break

if top_msgid is None:
raise Exception(f"Could not find any patches in the series '{lore_link}'.")

# slug for possibly naming the file
slug = lser.get_slug(extended=True)
log.debug('slug: %s', slug)

# final contents of patch file for our purposes
body = b''

for msg in am_msgs:
body += b'From git@z Thu Jan 1 00:00:00 1970\n' # OH! the b4-marker!
body += b4.LoreMessage.get_msg_as_bytes(msg, headers='decode')

log.info("Done")

return {"body": body, "slug": slug}

16 changes: 16 additions & 0 deletions lib/tools/common/patching_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ def __str__(self):
return f"PatchingOverlayDirectoryConfig(source={self.source}, target={self.target})"


class PatchingB4AMConfig:
def __init__(self, data: dict):
self.prefix: str = data.get("prefix", None)
self.lore: str = data.get("lore", None)

def __str__(self):
return f"PatchingB4AMConfig(prefix={self.prefix}, lore={self.lore})"


class PatchingToGitConfig:
def __init__(self, data: dict):
self.do_not_commit_files: list[str] = data.get("do-not-commit-files", [])
Expand Down Expand Up @@ -79,6 +88,13 @@ def __init__(self, yaml_config_file_paths: list[str]):
]
self.has_overlay_directories: bool = len(self.overlay_directories) > 0

# 'b4' auto 'am' patching config
# DTS directories to copy config
self.b4_am_configs: list[PatchingB4AMConfig] = [
PatchingB4AMConfig(data) for data in self.yaml_config.get("b4-am", [])
]
self.has_b4_am_configs: bool = len(self.b4_am_configs) > 0

def read_yaml_config(self, yaml_config_file_path):
with open(yaml_config_file_path) as f:
yaml_config = yaml.load(f, Loader=yaml.FullLoader)
Expand Down
37 changes: 35 additions & 2 deletions lib/tools/patching.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# This file is a part of the Armbian Build Framework
# https://github.com/armbian/build/
#
import glob
import logging
import os

Expand All @@ -18,6 +19,7 @@
from git import Repo

import common.armbian_utils as armbian_utils
import common.b4_caller as b4_caller
import common.dt_makefile_patcher as dt_makefile_patcher
import common.patching_utils as patching_utils
from common.md_asset_log import SummarizedMarkdownWriter
Expand Down Expand Up @@ -71,7 +73,7 @@
exit_with_exception: "Exception | None" = None

# Some path possibilities
CONST_PATCH_ROOT_DIRS = []
CONST_PATCH_ROOT_DIRS: list[patching_utils.PatchRootDir] = []

for patch_dir_to_apply in PATCH_DIRS_TO_APPLY:
if USERPATCHES_PATH is not None:
Expand Down Expand Up @@ -121,6 +123,37 @@
# load the configs and merge them.
pconfig: PatchingConfig = PatchingConfig(all_yaml_config_files)

# First of all, process the b4 configuration, which might produce new files on disk.
if pconfig.has_b4_am_configs:
log.info("Processing b4 configuration...")
for b4_config in pconfig.b4_am_configs:
# Check in all dirs in CONST_PATCH_ROOT_DIRS if a file with the prefix exists. If so, skip it.
skip_config = False
for one_root_dir in CONST_PATCH_ROOT_DIRS:
glob_pattern = f"{one_root_dir.abs_dir}/{b4_config.prefix}*.patch"
log.debug(f"Checking for existing b4 patch files with glob: '{glob_pattern}'")
if glob.glob(glob_pattern):
log.info(f"Skipping b4 configuration '{b4_config.prefix}' as it already exists in '{one_root_dir.abs_dir}'.")
skip_config = True
break
if skip_config:
continue
# Grab data using b4, and write it to the second directory in CONST_PATCH_ROOT_DIRS (the first would be user patches).
log.info(f"Processing b4 configuration: '{b4_config.prefix}' {b4_config.lore}")
b4_patch_body_slug = b4_caller.get_patch_via_b4(b4_config.lore)
target_dir = CONST_PATCH_ROOT_DIRS[1].abs_dir # user patches dir
target_file = os.path.join(target_dir, f"{b4_config.prefix}-{b4_patch_body_slug['slug']}.patch")
log.debug(f"Writing b4 patch to file: '{target_file}'")
with open(target_file, 'wb') as f:
f.write(b4_patch_body_slug["body"])
log.info(f"Written b4 patch to file: '{target_file}'")
# if we wrote something, force the patching operation to be a rewrite against the git repo, sans archeology.
git_archeology = False
apply_patches_to_git = True
rewrite_patches_in_place = True

log.info("Processing b4 configuration... Done.")

PATCH_FILES_FIRST: list[patching_utils.PatchFileInDir] = []
EXTRA_PATCH_FILES_FIRST: list[str] = armbian_utils.parse_env_for_tokens("EXTRA_PATCH_FILES_FIRST")
EXTRA_PATCH_HASHES_FIRST: list[str] = armbian_utils.parse_env_for_tokens("EXTRA_PATCH_HASHES_FIRST")
Expand Down Expand Up @@ -359,7 +392,7 @@
if one_patch.rewritten_patch is None:
log.warning(f"Skipping patch {one_patch} from rewrite because it was not rewritten.")
continue

# Skip the patch if it doesn't need rebasing
if rewrite_only_patches_needing_rebase:
if "needs_rebase" not in one_patch.problems:
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ Jinja2 == 3.1.6 # for templating
rich == 14.0.0 # for rich text formatting
dtschema == 2025.2 # for checking dts files and dt bindings
yamllint == 1.37.1 # for checking dts files and dt bindings
b4==0.12.3 # b4: patch/mailing list workhorse from kernel.org