diff --git a/src/cook/fetch.rs b/src/cook/fetch.rs index 8304992026..6402f5d71e 100644 --- a/src/cook/fetch.rs +++ b/src/cook/fetch.rs @@ -510,6 +510,53 @@ pub fn fetch_offline(recipe: &CookRecipe, logger: &PtyOut) -> Result, + shallow_clone: bool, + logger: &PtyOut, +) -> Result<()> { + let source_dir_tmp = recipe_dir.join("source.tmp"); + if source_dir_tmp.exists() { + std::fs::remove_dir_all(&source_dir_tmp).ok(); + } + create_dir_clean(&source_dir_tmp)?; + + let mut command = Command::new("git"); + command + .arg("clone") + .arg("--recursive") + .arg(translate_mirror(git)); + if let Some(branch) = branch { + command.arg("--branch").arg(branch); + } + if shallow_clone { + command + .arg("--filter=tree:0") + .arg("--also-filter-submodules"); + } + command.arg(&source_dir_tmp); + if let Err(e) = run_command(command, logger) { + if !is_redox() { + return Err(e); + } + let mut cmds = vec!["update", "--init"]; + if shallow_clone { + cmds.push("--filter=tree:0"); + } + manual_git_recursive_submodule(logger, &source_dir_tmp, cmds)?; + } + rename(&source_dir_tmp, source_dir)?; + Ok(()) +} + pub fn fetch(recipe: &CookRecipe, check_source: bool, logger: &PtyOut) -> Result { if redbear_protected_recipe(recipe.name.name()) && !redbear_allow_protected_fetch() { log_to_pty!( @@ -587,51 +634,39 @@ pub fn fetch(recipe: &CookRecipe, check_source: bool, logger: &PtyOut) -> Result //TODO: use libgit? let shallow_clone = *shallow_clone == Some(true); let cached = if !source_dir.is_dir() { - // Create source.tmp - let source_dir_tmp = recipe_dir.join("source.tmp"); - create_dir_clean(&source_dir_tmp)?; - - // Clone the repository to source.tmp - let mut command = Command::new("git"); - command - .arg("clone") - .arg("--recursive") - .arg(translate_mirror(&git)); - if let Some(branch) = branch { - command.arg("--branch").arg(branch); - } - if shallow_clone { - command - .arg("--filter=tree:0") - .arg("--also-filter-submodules"); - } - command.arg(&source_dir_tmp); - if let Err(e) = run_command(command, logger) { - if !is_redox() { - return Err(e); - } - // TODO: RedoxFS has a race condition problem with `--recursive` and running in multi CPU. - // It is appear that running the submodule update separately fixes it. Remove this when - // `git clone https://gitlab.redox-os.org/redox-os/relibc --recursive` proven to work in Redox OS. - let mut cmds = vec!["update", "--init"]; - if shallow_clone { - cmds.push("--filter=tree:0"); - } - manual_git_recursive_submodule(logger, &source_dir_tmp, cmds)?; - } - - // Move source.tmp to source atomically - rename(&source_dir_tmp, &source_dir)?; - + reclone_git_source( + &recipe_dir, + &source_dir, + &git, + &branch, + shallow_clone, + logger, + )?; false } else if !check_source { true } else { if !source_dir.join(".git").is_dir() { - bail_other_err!( - "{:?} is not a git repository, but recipe indicated git source", - source_dir.display() + // Self-heal: source dir exists but has no .git (e.g., a + // cleanup pass removed embedded .git directories from + // build-cache sources, or the dir was extracted from an + // archive). Wipe and re-clone from the recipe's git URL + // instead of hard-failing — without this, every damaged + // build-cache source required manual intervention. + log_to_pty!( + logger, + " source dir {:?} exists but has no .git; re-cloning from {:?}", + source_dir.display(), + git ); + reclone_git_source( + &recipe_dir, + &source_dir, + &git, + &branch, + shallow_clone, + logger, + )?; } // Reset origin