diff --git a/local/recipes/kde/breeze/recipe.toml b/local/recipes/kde/breeze/recipe.toml index da4b5ad3e9..44f5e521d0 100644 --- a/local/recipes/kde/breeze/recipe.toml +++ b/local/recipes/kde/breeze/recipe.toml @@ -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. diff --git a/local/recipes/kde/kde-cli-tools/recipe.toml b/local/recipes/kde/kde-cli-tools/recipe.toml index 94773a4b66..4ea12e618c 100644 --- a/local/recipes/kde/kde-cli-tools/recipe.toml +++ b/local/recipes/kde/kde-cli-tools/recipe.toml @@ -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 diff --git a/local/recipes/kde/kf6-kbookmarks/recipe.toml b/local/recipes/kde/kf6-kbookmarks/recipe.toml index 1f15d26b4b..57c9fee238 100644 --- a/local/recipes/kde/kf6-kbookmarks/recipe.toml +++ b/local/recipes/kde/kf6-kbookmarks/recipe.toml @@ -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 diff --git a/local/scripts/lint-recipe.py b/local/scripts/lint-recipe.py index c88d7e1070..823a681ba0 100644 --- a/local/scripts/lint-recipe.py +++ b/local/scripts/lint-recipe.py @@ -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 diff --git a/local/scripts/tests/test_lint_recipe.py b/local/scripts/tests/test_lint_recipe.py index 14d7c1ef5b..6b2ceee028 100644 --- a/local/scripts/tests/test_lint_recipe.py +++ b/local/scripts/tests/test_lint_recipe.py @@ -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]