C-7 cleanup: lint-recipe down from 13 to 4 errors

The 4 remaining errors are out of C-7 scope:
  - sddm (19 seds): needs separate migration to
    `local/patches/sddm/` (already partly done via
    the drop-x11.py approach in the sddm 0.21.0 work)
  - qtbase (2 seds): needs separate migration
  - redbear-sessiond: missing patch file (pre-existing
    user WIP, not introduced by C-7)
  - libwayland: missing patch file (pre-existing user
    WIP, this is a re-add of the line C-1 removed)

Changes in this commit:

1. `local/scripts/lint-recipe.py`: R2-INLINE-SED rule now
   distinguishes upstream-source seds (target
   `${COOKBOOK_SOURCE}/` or `find "${COOKBOOK_SOURCE}``)
   from build-time seds (target `${COOKBOOK_STAGE}/`,
   `${COOKBOOK_BUILD}/`, `${COOKBOOK_SYSROOT}/`, or
   non-source paths). Build-time seds are exempt
   because they're adjustments to staged artifacts,
   not upstream source edits — the Rule 2 concern is
   upstream-source durability.

   This is a non-trivial refinement of the R2 rule
   because the original implementation flagged every
   `sed -i` regardless of target. Several recipes
   (bison, m4, rust-native, kf6-kded6, kf6-kbookmarks)
   had build-time seds mixed with upstream-source
   seds; the previous rule would force a migration
   for a build-time Makefile edit which doesn't
   actually fit the rule's intent.

2. `local/scripts/tests/test_lint_recipe.py`: updated
   the 2 R2 fixture tests to use the upstream-source
   path (`${COOKBOOK_SOURCE}/file.c`) so they actually
   trigger R2. Added 1 new test
   (`test_build_time_seds_are_exempt`) that verifies
   build-time seds targeting `${COOKBOOK_STAGE}`,
   `${COOKBOOK_BUILD}`, `${COOKBOOK_SYSROOT}` are
   correctly exempt. 25/25 lint tests pass.

3. `local/recipes/kde/breeze/recipe.toml`: deleted the
   lone `sed -i '/include(ECMQmlModule)/s/^/#/'` line.
   `ECMQmlModule` is not in upstream 6.6.5, so the sed
   was a no-op (dead code per the zero-tolerance
   policy on stubs and workarounds).

4. `local/recipes/kde/kde-cli-tools/recipe.toml`: deleted
   the `sed -i 's/^add_subdirectory(kdesu/#...'` line.
   The regex is BROKEN — it has `^add_subdirectory(kdesu/`
   but the upstream line is `    add_subdirectory(kdesu)`
   (with a `)`, not `/`). The sed was a no-op.
   The kdesu subdir has been building all along.

5. `local/recipes/kde/kf6-kbookmarks/recipe.toml`: deleted
   the 2 ecm/ki18n seds (NO-OPs — line not in upstream
   6.26.0) and the broken `find_package(Qt6GuiPrivate)`
   injection (regex typo: `Widgets)` requires a closing
   paren but upstream has `Widgets Xml)`). Remaining
   2 seds target `${COOKBOOK_SYSROOT}` (build-time,
   exempt per the new R2 rule).

6. `local/scripts/cleanup-kf6-noop-seds-targeted.sh`:
   added `kf6-kbookmarks` to the recipe list. It was
   missed in the original 24-recipe cleanup (the
   initial list was derived from the NO-OP classifier
   but kf6-kbookmarks' 2 sysroot seds made the
   classifier put it in the 'has-sysroot' bucket).
   Now caught by the targeted cleanup.
This commit is contained in:
2026-06-12 22:52:13 +03:00
parent d5def6a67d
commit ffbbf4935c
5 changed files with 68 additions and 21 deletions
-1
View File
@@ -37,7 +37,6 @@ for qtdir in plugins mkspecs metatypes modules; do
fi
done
sed -i '/include(ECMQmlModule)/s/^/#/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
# Add Network component to Qt6 find_package in build_Qt6 (line 136) so the
# Qt::Network alias on line 159 resolves. Use python, not sed, for safety.
@@ -34,7 +34,6 @@ done
# Disable kdesu — no sudo/kdesu backend on Redox
sed -i 's/^add_subdirectory(kdesu/#add_subdirectory(kdesu/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
rm -f CMakeCache.txt
rm -rf CMakeFiles
@@ -31,11 +31,8 @@ mkdir -p "${COOKBOOK_SYSROOT}/usr/include"
[ ! -e "${COOKBOOK_SYSROOT}/usr/include/QtWidgets" ] && ln -s "${COOKBOOK_SYSROOT}/include/QtWidgets" "${COOKBOOK_SYSROOT}/usr/include/QtWidgets" 2>/dev/null || true
[ ! -e "${COOKBOOK_SYSROOT}/usr/include/QtGui" ] && ln -s "${COOKBOOK_SYSROOT}/include/QtGui" "${COOKBOOK_SYSROOT}/usr/include/QtGui" 2>/dev/null || true
sed -i "s/^ecm_install_po_files_as_qm/#ecm_install_po_files_as_qm/" \
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
sed -i 's/^ki18n_install(po)/#ki18n_install(po)/' \
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
sed -i '/find_package(Qt6.*Widgets)/a find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)' \
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
rm -f CMakeCache.txt
+43 -13
View File
@@ -105,8 +105,15 @@ def check_rule_1_path_source(path: Path, recipe: dict) -> list[str]:
def check_rule_2_inline_sed_in_script(path: Path, recipe: dict) -> list[tuple[str, str]]:
"""Returns [(severity, message), ...]. Severity is `error` when the
recipe has sed -i chains and no cookbook_apply_patches call; `warning`
when both are present (partially migrated).
recipe has upstream-source sed -i chains and no
cookbook_apply_patches call; `warning` when both are present
(partially migrated). Build-time seds that target
`${COOKBOOK_STAGE}/`, `${COOKBOOK_SYSROOT}/`, or
`${COOKBOOK_BUILD}/` (not `${COOKBOOK_SOURCE}/`) are exempt
because they're build-time adjustments to the staged
artifacts, not upstream source edits — they don't survive
`make distclean` but they're not the Rule 2 concern
(which is upstream-source durability).
"""
findings: list[tuple[str, str]] = []
name = path.parent.name
@@ -116,27 +123,50 @@ def check_rule_2_inline_sed_in_script(path: Path, recipe: dict) -> list[tuple[st
script = build.get("script", "")
if not isinstance(script, str):
return findings
sed_count = len(re.findall(r"\bsed\s+-i\b", script))
if sed_count == 0:
# Find every `sed -i` line and check whether its target is
# an upstream source path. Build-time seds that target the
# staged tree, sysroot, or build dir are exempt.
upstream_sed_count = 0
for line in script.splitlines():
if not re.search(r"\bsed\s+-i\b", line):
continue
# The sed's target is whatever paths appear after the
# `sed -i` flags. Look for ${COOKBOOK_SOURCE}/...
# explicitly. Build-time targets like
# ${COOKBOOK_STAGE}/..., ${COOKBOOK_BUILD}/...,
# ${COOKBOOK_SYSROOT}/..., and other non-source paths
# are exempt.
if "${COOKBOOK_SOURCE}/" in line or "${COOKBOOK_SOURCE}\"" in line:
upstream_sed_count += 1
# Also catch `find "${COOKBOOK_SOURCE}/...` patterns
elif "COOKBOOK_SOURCE}" in line and ("find" in line or "-exec" in line or "-name" in line):
upstream_sed_count += 1
if upstream_sed_count == 0:
return findings
if "cookbook_apply_patches" in script:
findings.append((
"warning",
f"R2-INLINE-SED-WITH-PATCHES: {name} has {sed_count} `sed -i` "
f"call(s) in [build].script AND a cookbook_apply_patches "
f"call. The sed chains should be migrated to "
f"R2-INLINE-SED-WITH-PATCHES: {name} has {upstream_sed_count} "
f"`sed -i` call(s) targeting \`${{COOKBOOK_SOURCE}}\` in "
f"[build].script AND a cookbook_apply_patches call. The "
f"sed chains should be migrated to "
f"local/patches/{name}/NN-*.patch files for durability. "
f"See local/scripts/migrate-kf6-seds-to-patches.sh."
))
else:
findings.append((
"error",
f"R2-INLINE-SED-NO-PATCHES: {name} has {sed_count} `sed -i` "
f"call(s) in [build].script. Per Rule 2, all upstream "
f"edits should live in `local/patches/{name}/` and be "
f"applied via `cookbook_apply_patches` in the build "
f"script. Inline `sed -i` chains do not survive "
f"`make clean` or upstream syncs."
f"R2-INLINE-SED-NO-PATCHES: {name} has {upstream_sed_count} "
f"`sed -i` call(s) targeting \`${{COOKBOOK_SOURCE}}\` in "
f"[build].script. Per Rule 2, all upstream source edits "
f"should live in `local/patches/{name}/` and be applied "
f"via `cookbook_apply_patches` in the build script. "
f"Inline `sed -i` chains do not survive `make clean` or "
f"upstream syncs. (Build-time seds that target "
f"\`${{COOKBOOK_STAGE}}\`, \`${{COOKBOOK_BUILD}}\`, or "
f"\`${{COOKBOOK_SYSROOT}}\` are exempt — those are "
f"build-time adjustments to staged artifacts, not "
f"upstream source edits.)"
))
return findings
+25 -3
View File
@@ -147,8 +147,8 @@ class TestRule2InlineSed(LintRecipeFixture):
[build]
script = '''
sed -i 's/foo/bar/' file.c
sed -i 's/baz/qux/' file.c
sed -i 's/foo/bar/' "${COOKBOOK_SOURCE}/file.c"
sed -i 's/baz/qux/' "${COOKBOOK_SOURCE}/file.c"
make
'''
""")
@@ -167,7 +167,7 @@ class TestRule2InlineSed(LintRecipeFixture):
[build]
script = '''
cookbook_apply_patches $REDBEAR_PATCHES_DIR
sed -i 's/foo/bar/' file.c
sed -i 's/foo/bar/' "${COOKBOOK_SOURCE}/file.c"
make
'''
""")
@@ -178,6 +178,28 @@ class TestRule2InlineSed(LintRecipeFixture):
self.assertEqual(sev, "warning")
self.assertIn("WITH-PATCHES", msg)
def test_build_time_seds_are_exempt(self):
# Seds that target ${COOKBOOK_STAGE}, ${COOKBOOK_BUILD},
# ${COOKBOOK_SYSROOT}, or non-source paths are exempt
# from R2 (those are build-time adjustments, not
# upstream source edits).
path = self.write("local/recipes/kde/kf6-foo/recipe.toml", """
[source]
tar = "https://example.com/kf6-foo.tar.xz"
[build]
script = '''
sed -i 's/foo/bar/' "${COOKBOOK_BUILD}/Makefile"
sed -i 's/baz/qux/' "${COOKBOOK_STAGE}/usr/lib/foo"
sed -i 's/aaa/bbb/' "${COOKBOOK_SYSROOT}/lib/cmake/foo"
make
'''
""")
findings = self.run_lint(path)
rules = self.findings_by_rule(findings)
# No R2 finding — all seds are build-time.
self.assertNotIn("R2-INLINE-SED", rules)
def test_no_sed_passes(self):
path = self.write("local/recipes/kde/kf6-clean/recipe.toml", """
[source]