From b8c1c780dc9f59c19feb94cfa5702667cb103a7e Mon Sep 17 00:00:00 2001 From: kellito Date: Fri, 12 Jun 2026 17:05:46 +0300 Subject: [PATCH] build: ship first C-7 KF6 sed migration patch (kf6-karchive) First durable artifact from the C-7 KF6 sed migration: the inline sed -i chains in local/recipes/kde/kf6-karchive's [build].script have been captured as a durable external patch in local/patches/kf6-karchive/01-initial-migration.patch. This patch was generated by running the v2 migration script (commit 827895d32) against the live kf6-karchive recipe. The actual sed edits captured are: -ecm_install_po_files_as_qm(poqm) +#ecm_install_po_files_as_qm(poqm) The other 3 sed chains in the recipe (ki18n_install(po), .arg(mode), .arg(d->mode)) were no-ops against the karchive 6.26.0 upstream tar (the target lines either no longer exist or are already in the desired state in this upstream version). The migration script correctly captures only the real edits; no-ops produce no patch hunks. Script fix in this commit: The migration script's v2 was producing silently empty diffs on already-cooked recipes because the cookbook's `fetch` re-uses an existing source/ tree if it finds one (it does this to avoid re-extracting tars on every fetch). For C-7 migration we need the truly pristine upstream state. The fix: 1. Add an explicit `unfetch` step BEFORE the `fetch` (so the source/ dir is removed before re-extraction) 2. Set `REDBEAR_ALLOW_LOCAL_UNFETCH=1` because kf6-* and qt* recipes are local-overlay recipes under local/recipes/, and the cookbook's default policy is to never clobber a local-overlay source (the env var overrides that policy for the migration's explicit unfetch call only) 3. Apply the same env var to the post-capture `unfetch` at the end of the script The script header documents this cookbook behavior with inline comments so a future contributor doesn't re-introduce the silent-failure mode. Patch filter: The migration script's diff includes ECM-autogenerated files like .clang-format that aren't real sed edits. The captured patch was 122 lines, of which 95 were the .clang-format autogeneration. The committed patch is the filtered 24-line version that drops `.clang-format`, `.gitignore`, and any `target/` artifacts. (A future script improvement could do this filter inline.) Test count: 120 -> 122 (2 new tests in test_migrate_kf6_seds.py): - test_sets_local_unfetch_env_var: regression guard against forgetting the env var - test_unfetches_before_fetching: regression guard against calling fetch before unfetch (silent-failure mode in v2) Next steps for kf6-karchive specifically (manual, not part of this commit): 1. Edit local/recipes/kde/kf6-karchive/recipe.toml's [build].script to remove the 4 inline sed -i chains and add: REDBEAR_PATCHES_DIR="local/patches/kf6-karchive" cookbook_apply_patches "${REDBEAR_PATCHES_DIR}" 2. Cook again to verify the patch + rewritten script produce a byte-identical stage.pkgar 3. Commit the recipe rewrite + the patch together Verified: - The migration ran end-to-end on the live tree - The patch applies cleanly to the pristine upstream - 122/122 Python tests pass - The new test_sets_local_unfetch_env_var and test_unfetches_before_fetching both pass C-7 status: 1 of 56 KF6 sed-bearing recipes migrated. 55 remaining (next: kf6-attica has the smallest sed chain; after that, breeze, kf6-syntaxhighlighting). --- .../kf6-karchive/01-initial-migration.patch | 24 +++++++++++++++++++ local/scripts/migrate-kf6-seds-to-patches.sh | 19 +++++++++++++-- local/scripts/tests/test_migrate_kf6_seds.py | 24 +++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 local/patches/kf6-karchive/01-initial-migration.patch diff --git a/local/patches/kf6-karchive/01-initial-migration.patch b/local/patches/kf6-karchive/01-initial-migration.patch new file mode 100644 index 0000000000..a187ce4461 --- /dev/null +++ b/local/patches/kf6-karchive/01-initial-migration.patch @@ -0,0 +1,24 @@ +# Initial migration of the inline sed -i chains in +# /home/kellito/Builds/RedBear-OS/local/recipes/kde/kf6-karchive/'s [build].script to a durable external +# patch. Captured by local/scripts/migrate-kf6-seds-to-patches.sh +# on 2026-06-12T17:01:59+03:00. +# +# After applying this patch via cookbook_apply_patches, +# the recipe's [build].script should call: +# REDBEAR_PATCHES_DIR="/home/kellito/Builds/RedBear-OS/local/patches/kf6-karchive" +# cookbook_apply_patches "${REDBEAR_PATCHES_DIR}" +# in place of the sed -i chains that produced these edits. + + +diff -ruN '--exclude=.git' '--exclude=target' /home/kellito/Builds/RedBear-OS/local/recipes/kde/kf6-karchive//source-pristine/CMakeLists.txt /home/kellito/Builds/RedBear-OS/local/recipes/kde/kf6-karchive//source/CMakeLists.txt +--- /home/kellito/Builds/RedBear-OS/local/recipes/kde/kf6-karchive//source-pristine/CMakeLists.txt 2026-06-12 17:01:10.264180402 +0300 ++++ /home/kellito/Builds/RedBear-OS/local/recipes/kde/kf6-karchive//source/CMakeLists.txt 2026-06-12 17:01:53.102261490 +0300 +@@ -127,7 +127,7 @@ + add_subdirectory(autotests/ossfuzz) + endif() + +-ecm_install_po_files_as_qm(poqm) ++#ecm_install_po_files_as_qm(poqm) + + # create a Config.cmake and a ConfigVersion.cmake file and install them + set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF6Archive") diff --git a/local/scripts/migrate-kf6-seds-to-patches.sh b/local/scripts/migrate-kf6-seds-to-patches.sh index 868562740f..58ef876211 100755 --- a/local/scripts/migrate-kf6-seds-to-patches.sh +++ b/local/scripts/migrate-kf6-seds-to-patches.sh @@ -137,7 +137,22 @@ for recipe_dir in "${recipe_dirs[@]}"; do mkdir -p "$patch_dir" # Step 1: fetch pristine source. - if ! ./target/release/repo fetch "$name" >"$log_file" 2>&1; then + # The cookbook's `fetch` re-uses an existing source/ tree if + # it finds one (it does this to avoid re-extracting tars on + # every fetch). For C-7 migration, we need the truly + # pristine upstream state — so we must `unfetch` first + # AND set REDBEAR_ALLOW_LOCAL_UNFETCH=1 because kf6-* and + # qt* recipes are local-overlay recipes under local/recipes/ + # (the cookbook's default policy is to never clobber a + # local-overlay source). Without these, the script will + # snapshot the post-cook state and the diff will be empty. + if ! REDBEAR_ALLOW_LOCAL_UNFETCH=1 ./target/release/repo unfetch "$name" >>"$log_file" 2>&1; then + echo " FAIL: unfetch — see $log_file" + rm -rf "$pristine_dir" + failed=$((failed+1)) + continue + fi + if ! ./target/release/repo fetch "$name" >>"$log_file" 2>&1; then echo " FAIL: fetch — see $log_file" rm -rf "$pristine_dir" failed=$((failed+1)) @@ -190,7 +205,7 @@ for recipe_dir in "${recipe_dirs[@]}"; do # Reset the cooked source so the next run can fetch cleanly. # The post-cook source was already captured in the patch; we # don't need it on disk for the migration to succeed. - ./target/release/repo unfetch "$name" >>"$log_file" 2>&1 || true + REDBEAR_ALLOW_LOCAL_UNFETCH=1 ./target/release/repo unfetch "$name" >>"$log_file" 2>&1 || true migrated=$((migrated+1)) done diff --git a/local/scripts/tests/test_migrate_kf6_seds.py b/local/scripts/tests/test_migrate_kf6_seds.py index 47136aefc0..675f824042 100644 --- a/local/scripts/tests/test_migrate_kf6_seds.py +++ b/local/scripts/tests/test_migrate_kf6_seds.py @@ -182,6 +182,30 @@ class TestScriptStructure(unittest.TestCase): text = SCRIPT.read_text() self.assertIn("SKIP — patch already exists", text) + def test_sets_local_unfetch_env_var(self): + # C-7 migration requires a truly pristine source tree. + # The cookbook's default policy is to never clobber a + # local-overlay source (kf6-*, qt* all live under + # local/recipes/). The script MUST set + # REDBEAR_ALLOW_LOCAL_UNFETCH=1 to bypass that policy, + # otherwise the snapshot is the post-cook state and the + # diff comes back empty (silent failure). + text = SCRIPT.read_text() + self.assertIn("REDBEAR_ALLOW_LOCAL_UNFETCH=1", text) + + def test_unfetches_before_fetching(self): + # Cookbook `fetch` re-uses existing source/ if present. + # Migration must explicitly unfetch first to get the + # truly pristine state. Regression: a v3 that just + # calls `fetch` will silently fail on already-cooked + # recipes. + text = SCRIPT.read_text() + unfetch_pos = text.find('release/repo unfetch "$name"') + fetch_pos = text.find('release/repo fetch "$name"') + self.assertGreater(unfetch_pos, 0, "unfetch not found") + self.assertGreater(fetch_pos, 0, "fetch not found") + self.assertLess(unfetch_pos, fetch_pos, "unfetch must come before fetch") + if __name__ == "__main__": unittest.main()