deb: classify the staged listing through the context
The fallback listing of find_package_directory called Path::is_dir on entries returned by list_files — a host-side stat. For an unshare context (every local build) those paths are rooted inside the chroot and do not exist at the same host path, so every entry came out a non-directory, the 'Found directories' list silently stayed empty and the failure degraded to the list-less 'Could not find package directory' variant, hiding the actual layout (seen building bc from an ubuntu/devel checkout whose staged tree was named 'tree'). Classify entries through the new ContextDriver::is_dir, and log every entry instead of only those matching the broken host stat.
This commit is contained in:
+52
-5
@@ -413,11 +413,13 @@ pub(crate) fn find_package_directory(
|
||||
let entries = ctx.list_files(package_parent)?;
|
||||
let mut found_dirs = Vec::new();
|
||||
for entry in entries {
|
||||
if entry.is_dir() {
|
||||
if let Some(file_name) = entry.file_name() {
|
||||
found_dirs.push(file_name.to_string_lossy().into_owned());
|
||||
}
|
||||
log::debug!(" - {}", entry.display());
|
||||
// list_files yields context-relative paths (e.g. rooted inside
|
||||
// the chroot for an unshare context): classify through the
|
||||
// context, a host-side stat would miss every entry.
|
||||
let is_dir = ctx.is_dir(&entry)?;
|
||||
log::debug!(" - {}", entry.display());
|
||||
if is_dir && let Some(file_name) = entry.file_name() {
|
||||
found_dirs.push(file_name.to_string_lossy().into_owned());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,6 +503,51 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// An unshare context mapped over `chroot_root`, parented on a local
|
||||
/// context like the ephemeral build contexts are: exists/list_files/
|
||||
/// is_dir answer through the path mapping, no namespace privileges
|
||||
/// needed.
|
||||
fn unshare_test_context(chroot_root: &Path) -> Context {
|
||||
let base = Context::new(crate::context::ContextConfig::Local).unwrap();
|
||||
Context::with_parent(
|
||||
crate::context::ContextConfig::Unshare {
|
||||
path: chroot_root.to_string_lossy().to_string(),
|
||||
parent: None,
|
||||
},
|
||||
Arc::new(base),
|
||||
)
|
||||
}
|
||||
|
||||
/// The staging-area listing must classify entries through the context:
|
||||
/// an unshare context returns build-root-relative paths that a host-side
|
||||
/// stat never sees (they live under the chroot root on the host), which
|
||||
/// used to silently empty the 'Found directories' list of the search
|
||||
/// failure message — and with it every hint about the actual layout.
|
||||
#[test]
|
||||
fn find_package_directory_lists_staged_directories_through_the_context() {
|
||||
let chroot = tempfile::tempdir().unwrap();
|
||||
// Staged parent holding a single tree whose name matches none of
|
||||
// the search patterns (the embedded-caller layout: <job>/tree)
|
||||
let staged_parent = chroot.path().join("tmp/pkh-build-1/j-42");
|
||||
std::fs::create_dir_all(staged_parent.join("tree/debian")).unwrap();
|
||||
|
||||
let ctx = unshare_test_context(chroot.path());
|
||||
let err = find_package_directory(
|
||||
Path::new("/tmp/pkh-build-1/j-42"),
|
||||
"bc",
|
||||
"1.07.1-1ubuntu1",
|
||||
"questing",
|
||||
&ctx,
|
||||
)
|
||||
.expect_err("no candidate matches a tree named 'tree'");
|
||||
|
||||
let message = err.to_string();
|
||||
assert!(
|
||||
message.contains("Found directories: tree"),
|
||||
"error should list the staged directories through the context: {message}"
|
||||
);
|
||||
}
|
||||
|
||||
async fn test_build_end_to_end(
|
||||
package: &str,
|
||||
series: &str,
|
||||
|
||||
Reference in New Issue
Block a user