build: stop turning read failures into silently wrong metadata

Two read_file(...).unwrap_or_default() calls masqueraded IO errors as
empty data: an unreadable debian/files became 'binary build with no
binary artifacts found; cannot distribute', and an unreadable dpkg
status file produced an empty Installed-Build-Depends. Tolerate a
missing debian/files (first build in a fresh tree) but propagate real
read errors, and hard-error on an unreadable status file like the
source-build path does. installed_build_depends_from_content also
returned a bare newline for zero entries, defeating render_buildinfo's
empty-guard and emitting a malformed 'Installed-Build-Depends:' field
with a blank continuation; it now returns an empty string so the field
is omitted.
This commit is contained in:
2026-09-17 18:44:33 +02:00
parent 06e591c665
commit 36875513ee
2 changed files with 147 additions and 5 deletions
+69
View File
@@ -207,6 +207,13 @@ pub fn installed_build_depends_from_content(
entries.sort_by(|a, b| a.0.cmp(&b.0).then_with(|| a.1.cmp(&b.1)));
entries.dedup_by(|a, b| a.0 == b.0);
// With no reachable entries, return an empty value so `render_buildinfo`
// omits the field entirely; a leading `\n` alone would render a
// malformed `Installed-Build-Depends:` with only a blank continuation.
if entries.is_empty() {
return Ok(String::new());
}
// Leading `\n`: pre-wrapped multiline field, dpkg-style.
let mut out = String::from("\n");
out.push_str(
@@ -378,6 +385,68 @@ Architecture: amd64
assert!(!ibd.contains("not-installed"));
}
/// With no installed entries reachable (empty status database), the
/// computed value must be EMPTY so `render_buildinfo` omits the
/// `Installed-Build-Depends` field entirely, instead of emitting a
/// malformed field with only a blank continuation line.
#[test]
fn installed_build_depends_without_entries_is_empty_and_omitted() {
let ibd = installed_build_depends_from_content("", &["libc6"]).unwrap();
assert_eq!(
ibd, "",
"zero entries must yield an empty value, not \"\\n\""
);
let input = BuildInfoInput {
source: "hello".to_string(),
binaries: vec!["hello".to_string()],
architecture: "amd64".to_string(),
version: "1.0".to_string(),
binary_only_changes: None,
build_origin: "debian".to_string(),
build_architecture: "amd64".to_string(),
build_date: "Sat, 22 Aug 2026 23:08:42 +0200".to_string(),
checksums: FileChecksums::new(),
installed_build_depends: ibd,
environment: String::new(),
};
let p = render_buildinfo(&input);
assert!(
p.get("Installed-Build-Depends").is_none(),
"empty value must omit the field entirely"
);
}
/// With installed entries, the value keeps the dpkg-style leading `\n`
/// (pre-wrapped multiline field) and the field is rendered.
#[test]
fn installed_build_depends_with_entries_renders_field() {
let status = "\
Package: gcc
Status: install ok installed
Version: 13.2
Architecture: amd64
";
let ibd = installed_build_depends_from_content(status, &["gcc"]).unwrap();
assert_eq!(ibd, "\ngcc (= 13.2)");
let input = BuildInfoInput {
source: "hello".to_string(),
binaries: vec!["hello".to_string()],
architecture: "amd64".to_string(),
version: "1.0".to_string(),
binary_only_changes: None,
build_origin: "debian".to_string(),
build_architecture: "amd64".to_string(),
build_date: "Sat, 22 Aug 2026 23:08:42 +0200".to_string(),
checksums: FileChecksums::new(),
installed_build_depends: ibd,
environment: String::new(),
};
let p = render_buildinfo(&input);
assert_eq!(p.get("Installed-Build-Depends"), Some("\ngcc (= 13.2)"));
}
#[test]
fn wrap_binary_field() {
assert_eq!(wrap_long("abc"), "abc");