-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
patching: Rewriter: actually delete empty patch files on rewrite #9209
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
base: main
Are you sure you want to change the base?
patching: Rewriter: actually delete empty patch files on rewrite #9209
Conversation
- so patches-to-git filtering is actually useful
📝 WalkthroughWalkthroughThe patching module now logs failed or unrewritten patches at warning level instead of info and deletes their corresponding patch files from disk as cleanup. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @lib/tools/patching.py:
- Around line 377-381: The loop over FAILED_PATCHES may call
os.remove(failed_patch.parent.full_file_path()) multiple times for the same file
and has no error handling; change the logic to collect unique parent paths (use
failed_patch.parent.full_file_path() or a set of parent identifiers) and iterate
once per unique path, call log.warning once per path (including the failing
patch counters if desired), and wrap os.remove(...) in a try/except that catches
OSError/FileNotFoundError to log an error via log.exception or log.error instead
of letting the script crash.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
lib/tools/patching.py
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: EvilOlaf
Repo: armbian/build PR: 8968
File: patch/u-boot/u-boot-sunxi/arm64-dts-sun50i-h6-orangepi.dtsi-Rollback-r_rsb-to-r_i2c.patch:36-36
Timestamp: 2025-11-20T18:20:11.985Z
Learning: The rewrite-patches tool (REWRITE_PATCHES=yes) in the Armbian build system can inadvertently introduce semantic changes when the u-boot/kernel git base revision differs from expected state. The tool applies patches, commits them, and re-exports them using git format-patch, which can cause the re-exported patch to reflect the base revision's state rather than preserving the original patch intent. This is particularly problematic for device tree changes like interrupt specifications. The tool currently lacks validation mechanisms to detect such semantic drift, and affected patches must be manually corrected after rewriting.
Learnt from: igorpecovnik
Repo: armbian/build PR: 8705
File: .github/workflows/rewrite-kernel-configs.yml:96-169
Timestamp: 2025-10-03T11:42:46.660Z
Learning: In the Armbian build repository's kernel config rewrite workflow (.github/workflows/rewrite-kernel-configs.yml), deletion of kernel config files does not need to be handled. The workflow intentionally only captures ACMR (added/copied/modified/renamed) changes and does not need to propagate deletions to the aggregator.
Learnt from: amazingfate
Repo: armbian/build PR: 8619
File: config/sources/families/rockchip.conf:65-72
Timestamp: 2025-09-14T11:37:35.089Z
Learning: In the Armbian build system, patch directories referenced in BOOTPATCHDIR and KERNELPATCHDIR configurations can be non-existent without causing build failures. Empty patch directories are also ignored by git, so missing patch directories should not be flagged as errors during code review.
Learnt from: EvilOlaf
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-12-17T05:09:02.306Z
Learning: In the Armbian build system, kernel patches (e.g., in patch/kernel/archive/sunxi-6.18/patches.armbian/) contain device tree overlays and other code that have existed for years and are maintained/ported across kernel versions. When reviewing PRs that modify these patch files, focus on the actual changes being made (e.g., Makefile fixes, new additions) rather than reviewing the entire existing content within the patch as if it were new code. The patch file contents are existing, stable code unless explicitly modified in the PR diff.
Learnt from: igorpecovnik
Repo: armbian/build PR: 8705
File: .github/workflows/rewrite-kernel-configs.yml:217-220
Timestamp: 2025-10-04T17:59:19.369Z
Learning: In the Armbian build repository's kernel config rewrite workflow (.github/workflows/rewrite-kernel-configs.yml), the workflow is designed to rewrite existing kernel configs only. New/untracked files can be safely ignored, so using `git diff --quiet` (which ignores untracked files) is the correct approach for detecting changes rather than `git status --porcelain`.
Learnt from: leggewie
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-08-29T18:44:47.732Z
Learning: When creating GitHub issues for code improvements in the Armbian build project, include the relevant patches/diffs in the issue description or open a PR directly instead of just describing the changes. This makes it more efficient for the assignee to handle the improvements.
Learnt from: EvilOlaf
Repo: armbian/build PR: 8428
File: config/boards/lckfb-taishanpi.csc:5-9
Timestamp: 2025-07-25T03:51:50.830Z
Learning: When reviewing PRs in the Armbian build system, U-Boot defconfig files and patches may be added as part of the PR changes but might not be visible in the current repository clone state during review. It's important to check the actual PR file changes directly via GitHub API (https://api.github.com/repos/armbian/build/pulls/{pr_number}/files) to get the complete picture of what files are being added or modified, especially for U-Boot patches that will be applied during the build process.
Learnt from: rpardini
Repo: armbian/build PR: 9180
File: patch/kernel/archive/sm8250-6.18/0000.patching_config.yaml:4-8
Timestamp: 2026-01-07T18:21:35.944Z
Learning: In Armbian patch/kernel/archive/**/0000.patching_config.yaml files, the version metadata fields (name, branch, last-known-good-tag, kind, type) under the "info stuff" comment are not used by the patching scripts. When reviewing these files, do not suggest updating or fixing these metadata fields. Instead, suggest removing them entirely as they serve no functional purpose.
Learnt from: EvilOlaf
Repo: armbian/build PR: 9096
File: patch/kernel/archive/sunxi-6.18/patches.armbian/arm64-dts-sun50i-h616-add-overlays.patch:4-5
Timestamp: 2025-12-17T15:46:22.709Z
Learning: In Armbian kernel patches, when patches are renamed or reorganized, the old Subject line may be intentionally preserved in the patch header (as a second Subject line) for archival/historical purposes to document the previous patch name. This is an Armbian-specific practice for tracking patch evolution and should not be flagged as an error when the maintainer has intentionally included it for documentation.
| for failed_patch in FAILED_PATCHES: | ||
| log.info( | ||
| f"Consider removing {failed_patch.parent.full_file_path()}(:{failed_patch.counter}); " | ||
| f"it was not applied successfully.") | ||
| log.warning( | ||
| f"Removing {failed_patch.parent.full_file_path()}(:{failed_patch.counter}); " | ||
| f" it failed to apply/was not rewritten.") | ||
| os.remove(failed_patch.parent.full_file_path()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Duplicate file deletion attempts will crash the script.
This code will attempt to delete the same patch file multiple times if that file contains multiple patches (mbox format) that both fail to apply or weren't rewritten. The second os.remove() call will raise a FileNotFoundError, terminating the script.
Additionally, there's no error handling around os.remove(), so any deletion failure (permissions, file locked, etc.) will also crash the script.
🐛 Proposed fix: deduplicate parent files and add error handling
FAILED_PATCHES = [one_patch for one_patch in VALID_PATCHES if (not one_patch.applied_ok) or (one_patch.rewritten_patch is None)]
+ # Deduplicate parent files to avoid attempting to delete the same file multiple times
+ failed_patch_files_to_delete = set()
for failed_patch in FAILED_PATCHES:
- log.warning(
- f"Removing {failed_patch.parent.full_file_path()}(:{failed_patch.counter}); "
- f" it failed to apply/was not rewritten.")
- os.remove(failed_patch.parent.full_file_path())
+ failed_patch_files_to_delete.add(failed_patch.parent.full_file_path())
+
+ for patch_file_path in failed_patch_files_to_delete:
+ log.warning(f"Removing {patch_file_path}; it failed to apply/was not rewritten.")
+ try:
+ os.remove(patch_file_path)
+ except FileNotFoundError:
+ log.debug(f"File {patch_file_path} already removed.")
+ except OSError as e:
+ log.error(f"Failed to remove {patch_file_path}: {e}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for failed_patch in FAILED_PATCHES: | |
| log.info( | |
| f"Consider removing {failed_patch.parent.full_file_path()}(:{failed_patch.counter}); " | |
| f"it was not applied successfully.") | |
| log.warning( | |
| f"Removing {failed_patch.parent.full_file_path()}(:{failed_patch.counter}); " | |
| f" it failed to apply/was not rewritten.") | |
| os.remove(failed_patch.parent.full_file_path()) | |
| FAILED_PATCHES = [one_patch for one_patch in VALID_PATCHES if (not one_patch.applied_ok) or (one_patch.rewritten_patch is None)] | |
| # Deduplicate parent files to avoid attempting to delete the same file multiple times | |
| failed_patch_files_to_delete = set() | |
| for failed_patch in FAILED_PATCHES: | |
| failed_patch_files_to_delete.add(failed_patch.parent.full_file_path()) | |
| for patch_file_path in failed_patch_files_to_delete: | |
| log.warning(f"Removing {patch_file_path}; it failed to apply/was not rewritten.") | |
| try: | |
| os.remove(patch_file_path) | |
| except FileNotFoundError: | |
| log.debug(f"File {patch_file_path} already removed.") | |
| except OSError as e: | |
| log.error(f"Failed to remove {patch_file_path}: {e}") |
🤖 Prompt for AI Agents
In @lib/tools/patching.py around lines 377 - 381, The loop over FAILED_PATCHES
may call os.remove(failed_patch.parent.full_file_path()) multiple times for the
same file and has no error handling; change the logic to collect unique parent
paths (use failed_patch.parent.full_file_path() or a set of parent identifiers)
and iterate once per unique path, call log.warning once per path (including the
failing patch counters if desired), and wrap os.remove(...) in a try/except that
catches OSError/FileNotFoundError to log an error via log.exception or log.error
instead of letting the script crash.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.