cook: don't stage submodules; refresh staged source in place
Two defects in the out-of-tree staging from 221a91cba4/a3d9240d62, both found
by actually running it rather than by inspection.
1. Submodules were staged. `git ls-files --error-unmatch` succeeds on a
gitlink, so relibc looked like an ordinary tracked tree and was copied
wholesale, losing the nested-repo context cargo needs -- crt0, crti, crtn
and ld_so all failed to build. Fork submodules are already covered by the
stricter REFUSING-TO-BUILD dirty gate, so skipping them loses no protection.
2. `rm -rf` before the copy made the staged path vanish mid-build. Qt bakes its
COOKBOOK_SOURCE into installed cmake files (QtSeparateDebugInfo.cmake
try_compile()s ${QT_SOURCE_TREE}/config.tests/...), so once that path was the
staged tree, rebuilding qtbase pulled it out from under consumers:
CMake Error: The source ".../qtbase/.../source-staged/config.tests/
binary_for_strip/CMakeLists.txt" does not ...
(qtsvg and qtshadertools). Now rsync -a --delete refreshes in place: same
pristine result, but the directory never stops existing. Verified with 4000
probes across a full kirigami rebuild -- 0 observations of it missing.
Staging is confirmed working: a 26-package run staged 10 trees, skipped relibc,
and left 0 dirty tracked source files (previously 22-29).
This commit is contained in:
+42
-6
@@ -987,7 +987,22 @@ pub fn build(
|
||||
// vendored tree look untracked, so staging silently never fired and
|
||||
// builds kept mutating the git-tracked source.
|
||||
let source_real = source_dir.canonicalize().unwrap_or_else(|_| source_dir.to_path_buf());
|
||||
let source_is_tracked = std::env::var_os("REDBEAR_IN_TREE_BUILD").is_none()
|
||||
|
||||
// Never stage a SUBMODULE. `git ls-files --error-unmatch` succeeds
|
||||
// on a submodule's gitlink, so relibc & co. looked like ordinary
|
||||
// tracked trees and got copied wholesale -- which broke their cargo
|
||||
// builds (crt0/crti/crtn/ld_so all failed) because the nested repo
|
||||
// context did not survive the copy.
|
||||
//
|
||||
// Skipping them is principled, not a workaround: each fork
|
||||
// submodule is already covered by the stricter REFUSING-TO-BUILD
|
||||
// dirty gate, which forbids uncommitted edits outright. Vendored
|
||||
// recipe `source/` trees have no such guarantee, and they are the
|
||||
// ones recipes actually rewrite.
|
||||
let source_is_submodule = source_real.join(".git").exists();
|
||||
|
||||
let source_is_tracked = !source_is_submodule
|
||||
&& std::env::var_os("REDBEAR_IN_TREE_BUILD").is_none()
|
||||
&& Command::new("git")
|
||||
.arg("ls-files")
|
||||
.arg("--error-unmatch")
|
||||
@@ -1000,17 +1015,38 @@ pub fn build(
|
||||
|
||||
let effective_source = if source_is_tracked {
|
||||
let staged = get_sub_target_dir(target_dir, "source-staged");
|
||||
let _ = fs::remove_dir_all(&staged);
|
||||
let status = Command::new("cp")
|
||||
|
||||
// Refresh IN PLACE; never remove the directory first.
|
||||
//
|
||||
// Qt bakes its COOKBOOK_SOURCE path into installed cmake files
|
||||
// (QtSeparateDebugInfo.cmake try_compile()s against
|
||||
// ${QT_SOURCE_TREE}/config.tests/...). Once that path is the
|
||||
// staged tree, a `rm -rf` at the start of a rebuild makes it
|
||||
// vanish underneath consumers that are configuring against it:
|
||||
// CMake Error: The source ".../qtbase/.../source-staged/
|
||||
// config.tests/binary_for_strip/CMakeLists.txt" does not ...
|
||||
// (qtsvg and qtshadertools, both mid-configure).
|
||||
//
|
||||
// rsync --delete gives the same pristine result -- files the
|
||||
// last build's seds added are removed, modified ones are
|
||||
// restored from the tracked tree -- while the directory itself
|
||||
// continues to exist throughout.
|
||||
let _ = fs::create_dir_all(&staged);
|
||||
let mut src_slash = source_real.clone().into_os_string();
|
||||
src_slash.push("/");
|
||||
let mut dst_slash = staged.clone().into_os_string();
|
||||
dst_slash.push("/");
|
||||
let status = Command::new("rsync")
|
||||
.arg("-a")
|
||||
.arg("--reflink=auto")
|
||||
.arg(&source_real)
|
||||
.arg("--delete")
|
||||
.arg(src_slash)
|
||||
.arg(dst_slash)
|
||||
.arg(&staged)
|
||||
.status()
|
||||
.map_err(|e| format!("failed to stage source out of tree: {e}"))?;
|
||||
if !status.success() {
|
||||
return Err(format!(
|
||||
"failed to stage source out of tree: cp exited {status}"
|
||||
"failed to stage source out of tree: rsync exited {status}"
|
||||
));
|
||||
}
|
||||
log_to_pty!(
|
||||
|
||||
Reference in New Issue
Block a user