Merge branch 'fix-auto_deps-stage_toml' into 'master'

Scan more directories in auto_deps

Closes installer#24, redox#1598, and redox#1600

See merge request redox-os/cookbook!517
This commit is contained in:
Jeremy Soller 2025-07-02 09:30:23 -06:00
commit 1f238c0f91
3 changed files with 62 additions and 1 deletions

1
Cargo.lock generated
View File

@ -1853,6 +1853,7 @@ dependencies = [
"pkgar-keys 0.1.17",
"redoxer",
"serde",
"tempfile",
"termion",
"toml 0.8.19",
"walkdir",

View File

@ -32,3 +32,6 @@ serde = { version = "=1.0.197", features = ["derive"] }
termion = "4"
toml = "0.8"
walkdir = "2.3.1"
[dev-dependencies]
tempfile = "3"

View File

@ -2,6 +2,7 @@ use cookbook::blake3::blake3_progress;
use cookbook::package::StageToml;
use cookbook::recipe::{BuildKind, CookRecipe, Recipe, SourceRecipe};
use cookbook::recipe_find::recipe_find;
use std::collections::VecDeque;
use std::{
collections::BTreeSet,
env, fs,
@ -505,7 +506,32 @@ fi"#,
fn auto_deps(stage_dir: &Path, dep_pkgars: &BTreeSet<(String, PathBuf)>) -> BTreeSet<String> {
let mut paths = BTreeSet::new();
for dir in &[stage_dir.join("usr/bin"), stage_dir.join("usr/lib")] {
let mut visited = BTreeSet::new();
// Base directories may need to be updated for packages that place binaries in odd locations.
let mut walk = VecDeque::from([
stage_dir.join("libexec"),
stage_dir.join("usr/bin"),
stage_dir.join("usr/games"),
stage_dir.join("usr/lib"),
]);
// Recursively (DFS) walk each directory to ensure nested libs and bins are checked.
while let Some(dir) = walk.pop_front() {
let Ok(dir) = dir.canonicalize() else {
continue;
};
if visited.contains(&dir) {
#[cfg(debug_assertions)]
eprintln!("DEBUG: auto_deps => Skipping `{dir:?}` (already visited)");
continue;
}
assert!(
visited.insert(dir.clone()),
"Directory `{:?}` should not be in visited\nVisited: {:#?}",
dir,
visited
);
let Ok(read_dir) = fs::read_dir(&dir) else {
continue;
};
@ -516,6 +542,8 @@ fn auto_deps(stage_dir: &Path, dep_pkgars: &BTreeSet<(String, PathBuf)>) -> BTre
};
if file_type.is_file() {
paths.insert(entry.path());
} else if file_type.is_dir() {
walk.push_front(entry.path());
}
}
}
@ -1185,3 +1213,32 @@ fn main() {
}
}
}
#[cfg(test)]
mod tests {
use std::os::unix;
use super::auto_deps;
#[test]
fn file_system_loop_no_infinite_loop() {
// Hierarchy with an infinite loop
let temp = tempfile::tempdir().unwrap();
let root = temp.path();
let dir = root.join("loop");
unix::fs::symlink(root, &dir).expect("Linking {dir:?} to {root:?}");
// Sanity check that we have a loop
assert_eq!(
root.canonicalize().unwrap(),
dir.canonicalize().unwrap(),
"Expected a loop where {dir:?} points to {root:?}"
);
let entries = auto_deps(root, &Default::default());
assert!(
entries.is_empty(),
"auto_deps shouldn't have yielded any libraries"
);
}
}