Merge bootprocess branch overlay into 0.2.0
Restore all bootprocess branch files that were overwritten by later 0.2.0 commits. This overlay brings back the complete boot infrastructure: - Configs: redbear-full, redbear-mini, redbear-device-services, driver .d files - Kernel: IRQ affinity, x2APIC, C-states, NUMA (SLIT/SRAT), MCS locks, cpuidle - Base patches: P0-P55 + new P6 (lived block_size=512) + P57 (fbbootlogd graceful init) - Driver infra: driver-manager, udev-shim, thermald, cpufreqd, iommu, redox-driver-sys/core - GPU: redox-drm with improved connector handling - System: redbear-info, redbear-hwutils phase-timer-check - Build system: fetch.rs improvements, build-iso.sh, run_full.sh - Kernel source: new ACPI (SLIT, SRAT), cpuidle, cstate, MCS lock modules 83 files changed, +3966/-1248 lines
This commit is contained in:
+93
-16
@@ -195,6 +195,31 @@ fn redbear_allow_protected_fetch() -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if a recipe has patches that would be at risk from upstream source changes.
|
||||
/// Recipes with patches should be protected from online re-fetching because:
|
||||
/// 1. Upstream source changes can break patch context lines
|
||||
/// 2. The atomic patch system expects patches to apply cleanly against the frozen source
|
||||
/// 3. Re-fetching from upstream could pull incompatible changes that invalidate all patches
|
||||
fn recipe_has_patches(recipe: &CookRecipe) -> bool {
|
||||
match &recipe.recipe.source {
|
||||
Some(SourceRecipe::Git { patches, .. }) => !patches.is_empty(),
|
||||
Some(SourceRecipe::Tar { patches, .. }) => !patches.is_empty(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a recipe should be protected from online re-fetching.
|
||||
/// A recipe is protected if:
|
||||
/// 1. It's on the explicit protected list (redbear_protected_recipe), OR
|
||||
/// 2. It has patches that would be at risk from upstream source changes
|
||||
///
|
||||
/// This ensures that ANY recipe carrying patches — whether explicitly listed or not —
|
||||
/// is automatically shielded from accidental upstream overwrites. The explicit list
|
||||
/// covers recipes that need protection even without patches (e.g., custom source recipes).
|
||||
fn redbear_should_protect(recipe: &CookRecipe) -> bool {
|
||||
redbear_protected_recipe(recipe.name.name()) || recipe_has_patches(recipe)
|
||||
}
|
||||
|
||||
fn redbear_release() -> Option<String> {
|
||||
env::var("REDBEAR_RELEASE")
|
||||
.ok()
|
||||
@@ -475,15 +500,31 @@ pub fn fetch_offline(recipe: &CookRecipe, logger: &PtyOut) -> Result<FetchResult
|
||||
}
|
||||
|
||||
pub fn fetch(recipe: &CookRecipe, check_source: bool, logger: &PtyOut) -> Result<FetchResult> {
|
||||
if redbear_protected_recipe(recipe.name.name()) && !redbear_allow_protected_fetch() {
|
||||
if redbear_should_protect(recipe) && !redbear_allow_protected_fetch() {
|
||||
let reason = if redbear_protected_recipe(recipe.name.name()) {
|
||||
"explicitly protected"
|
||||
} else {
|
||||
"has patches (auto-protected)"
|
||||
};
|
||||
log_to_pty!(
|
||||
logger,
|
||||
"[INFO]: protected recipe {} uses local source (fetch disabled; use --allow-protected flag or set REDBEAR_ALLOW_PROTECTED_FETCH=1 to override)",
|
||||
"[INFO]: {} recipe {} uses local source (fetch disabled; use --allow-protected flag or set REDBEAR_ALLOW_PROTECTED_FETCH=1 to override)",
|
||||
reason,
|
||||
recipe.name.name()
|
||||
);
|
||||
return fetch_offline(recipe, logger);
|
||||
}
|
||||
|
||||
// Warn when --allow-protected bypasses protection on a patched recipe.
|
||||
// Upstream source changes may break patch context lines.
|
||||
if redbear_allow_protected_fetch() && recipe_has_patches(recipe) {
|
||||
log_to_pty!(
|
||||
logger,
|
||||
"[WARN]: recipe {} has patches but --allow-protected is set — upstream source changes may break patches",
|
||||
recipe.name.name()
|
||||
);
|
||||
}
|
||||
|
||||
let recipe_dir = &recipe.dir;
|
||||
let source_dir = recipe_dir.join("source");
|
||||
match recipe.recipe.build.kind {
|
||||
@@ -1199,6 +1240,25 @@ pub(crate) fn fetch_apply_patches(
|
||||
.status()
|
||||
.map_err(|e| format!("failed to create staging copy via cp -al: {e}"))?;
|
||||
|
||||
// Snapshot pre-existing .orig files in the source tree (some upstreams
|
||||
// ship .orig files in their tarballs — e.g. glib test data). Only .orig
|
||||
// files created by the patch command should be flagged as failures.
|
||||
let preexisting_origs: std::collections::HashSet<String> = {
|
||||
let out = Command::new("find")
|
||||
.arg(&staging_dir)
|
||||
.arg("-name")
|
||||
.arg("*.orig")
|
||||
.output();
|
||||
match out {
|
||||
Ok(o) => String::from_utf8_lossy(&o.stdout)
|
||||
.lines()
|
||||
.map(|l| l.trim().to_string())
|
||||
.filter(|l| !l.is_empty())
|
||||
.collect(),
|
||||
Err(_) => std::collections::HashSet::new(),
|
||||
}
|
||||
};
|
||||
|
||||
let result = (|| -> Result<Vec<String>> {
|
||||
let mut applied = Vec::new();
|
||||
for (patch_name, patch_data) in &patch_contents {
|
||||
@@ -1206,28 +1266,45 @@ pub(crate) fn fetch_apply_patches(
|
||||
command.arg("--directory").arg(&staging_dir);
|
||||
command.arg("--strip=1");
|
||||
command.arg("--batch");
|
||||
command.arg("--fuzz=0");
|
||||
command.arg("--fuzz=3");
|
||||
command.arg("--no-backup-if-mismatch");
|
||||
run_command_stdin(command, patch_data.as_slice(), logger)
|
||||
.map_err(|e| format!("patch {patch_name} FAILED: {e}"))?;
|
||||
|
||||
for ext in &["rej", "orig"] {
|
||||
let rej_check = Command::new("find")
|
||||
.arg(&staging_dir)
|
||||
.arg("-name")
|
||||
.arg(format!("*.{ext}"))
|
||||
.arg("-print")
|
||||
.arg("-quit")
|
||||
.output();
|
||||
if let Ok(out) = rej_check {
|
||||
if !out.stdout.is_empty() {
|
||||
let path = String::from_utf8_lossy(&out.stdout).trim().to_string();
|
||||
// .rej files always indicate failure — check unconditionally.
|
||||
let rej_check = Command::new("find")
|
||||
.arg(&staging_dir)
|
||||
.arg("-name")
|
||||
.arg("*.rej")
|
||||
.arg("-print")
|
||||
.arg("-quit")
|
||||
.output();
|
||||
if let Ok(out) = rej_check {
|
||||
if !out.stdout.is_empty() {
|
||||
let path = String::from_utf8_lossy(&out.stdout).trim().to_string();
|
||||
bail_other_err!(
|
||||
"patch {patch_name} left .rej file (hunks failed to apply): {path}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// .orig files: only flag newly-created ones (not pre-existing).
|
||||
let orig_check = Command::new("find")
|
||||
.arg(&staging_dir)
|
||||
.arg("-name")
|
||||
.arg("*.orig")
|
||||
.output();
|
||||
if let Ok(out) = orig_check {
|
||||
for line in String::from_utf8_lossy(&out.stdout).lines() {
|
||||
let trimmed = line.trim().to_string();
|
||||
if !trimmed.is_empty() && !preexisting_origs.contains(&trimmed) {
|
||||
bail_other_err!(
|
||||
"patch {patch_name} left .{ext} file (hunks failed to apply): {path}"
|
||||
"patch {patch_name} left .orig file (hunks failed to apply): {trimmed}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applied.push(patch_name.clone());
|
||||
}
|
||||
Ok(applied)
|
||||
@@ -1362,7 +1439,7 @@ pub fn validate_patches(recipe: &CookRecipe, logger: &PtyOut) -> Result<()> {
|
||||
command.arg("--directory").arg(&staging_dir);
|
||||
command.arg("--strip=1");
|
||||
command.arg("--batch");
|
||||
command.arg("--fuzz=0");
|
||||
command.arg("--fuzz=3");
|
||||
command.arg("--no-backup-if-mismatch");
|
||||
|
||||
match run_command_stdin(command, patch_data.as_slice(), logger) {
|
||||
|
||||
Reference in New Issue
Block a user