diff --git a/src/build/binary.rs b/src/build/binary.rs index 1e313c2..ee5f77d 100644 --- a/src/build/binary.rs +++ b/src/build/binary.rs @@ -15,7 +15,7 @@ use std::sync::Arc; use crate::context::Context; use crate::debian::{ - parse_changelog_entry_from_str, ChecksumEntry, ControlInfo, FileChecksums, FilesList, + ChecksumEntry, ControlInfo, FileChecksums, FilesList, parse_changelog_entry_from_str, }; /// Digests of one artifact. @@ -80,16 +80,12 @@ pub fn generate_binary_metadata( // ------------------------------------------------------------------ let artifact_names: Vec = files_list .iter() - .filter(|e| { - matches!(e.package_type.as_deref(), Some("deb") | Some("udeb")) - }) + .filter(|e| matches!(e.package_type.as_deref(), Some("deb") | Some("udeb"))) .map(|e| e.filename.clone()) .collect(); if artifact_names.is_empty() { - return Err( - "binary build with no binary artifacts found; cannot distribute".into(), - ); + return Err("binary build with no binary artifacts found; cannot distribute".into()); } let mut hashes = hashes_in_context(ctx, upload_dir, &artifact_names)?; @@ -98,9 +94,9 @@ pub fn generate_binary_metadata( let mut arch_values: Vec = Vec::new(); let mut arch_seen = std::collections::HashSet::new(); for name in &artifact_names { - let entry_hashes = hashes.remove(name).ok_or_else(|| { - format!("artifact '{name}' listed in debian/files but not found") - })?; + let entry_hashes = hashes + .remove(name) + .ok_or_else(|| format!("artifact '{name}' listed in debian/files but not found"))?; checksums.insert_entry( name, ChecksumEntry { @@ -112,9 +108,10 @@ pub fn generate_binary_metadata( ); // Architecture accumulation in encounter order (dpkg-genchanges). if let Some(file_entry) = files_list.get(name) - && let Some(arch) = file_entry.arch.as_ref().or_else(|| { - file_entry.attrs.get("architecture") - }) + && let Some(arch) = file_entry + .arch + .as_ref() + .or_else(|| file_entry.attrs.get("architecture")) && arch_seen.insert(arch.clone()) { arch_values.push(arch.clone()); @@ -129,19 +126,15 @@ pub fn generate_binary_metadata( let mut binary_only_changes = None; if entry.binary_only - && let Ok(prev_entry) = - crate::debian::changelog::parse_previous_version_from_str(&ctx.read_file( - &package_dir.join("debian/changelog"), - )?) + && let Ok(prev_entry) = crate::debian::changelog::parse_previous_version_from_str( + &ctx.read_file(&package_dir.join("debian/changelog"))?, + ) && let Some(prev) = prev_entry { source_display = format!("{} ({})", entry.source, prev); binary_only_changes = Some(format!( "{}\n\n -- {} <{}> {}", - entry.changes_field, - entry.maintainer_name, - entry.maintainer_email, - entry.date_raw + entry.changes_field, entry.maintainer_name, entry.maintainer_email, entry.date_raw )); let prev_version = crate::debian::DebianVersion::parse(&prev)?; let dsc_name = format!("{}_{}.dsc", entry.source, prev_version.no_epoch()); @@ -210,10 +203,7 @@ pub fn generate_binary_metadata( control.source.get("Build-Depends-Indep").unwrap_or(""), ]; let installed_build_depends = - crate::build::buildinfo::installed_build_depends_from_content( - &status_content, - &bd_fields, - )?; + crate::build::buildinfo::installed_build_depends_from_content(&status_content, &bd_fields)?; // ------------------------------------------------------------------ // .buildinfo generation, then registration in debian/files @@ -226,14 +216,9 @@ pub fn generate_binary_metadata( let mut buildinfo_arch_values = arch_values.clone(); buildinfo_arch_values.sort(); - let buildinfo_name = format!( - "{}_{}_{}.buildinfo", - entry.source, - sversion, - opts.host_arch - ); - let buildinfo_doc = crate::build::buildinfo::render_buildinfo( - &crate::build::buildinfo::BuildInfoInput { + let buildinfo_name = format!("{}_{}_{}.buildinfo", entry.source, sversion, opts.host_arch); + let buildinfo_doc = + crate::build::buildinfo::render_buildinfo(&crate::build::buildinfo::BuildInfoInput { source: source_display.clone(), binaries: binaries.clone(), architecture: buildinfo_arch_values.join(" "), @@ -245,10 +230,12 @@ pub fn generate_binary_metadata( checksums: checksums.clone(), installed_build_depends, environment, - }, - ); + }); let buildinfo_path = upload_dir.join(&buildinfo_name); - ctx.write_file(&buildinfo_path, &crate::debian::control::write_paragraph(&buildinfo_doc))?; + ctx.write_file( + &buildinfo_path, + &crate::debian::control::write_paragraph(&buildinfo_doc), + )?; // Register the .buildinfo in debian/files, like dpkg-genbuildinfo does, // so the .changes distributes it. @@ -257,17 +244,11 @@ pub fn generate_binary_metadata( control.section(), control.priority(), )); - ctx.write_file( - &package_dir.join("debian/files"), - &files_list.render(), - )?; + ctx.write_file(&package_dir.join("debian/files"), &files_list.render())?; // Hash the freshly written .buildinfo inside the context. - let buildinfo_hashes = hashes_in_context( - ctx, - upload_dir, - std::slice::from_ref(&buildinfo_name), - )?; + let buildinfo_hashes = + hashes_in_context(ctx, upload_dir, std::slice::from_ref(&buildinfo_name))?; if let Some(h) = buildinfo_hashes.get(&buildinfo_name) { checksums.insert_entry( &buildinfo_name, @@ -303,7 +284,10 @@ pub fn generate_binary_metadata( files_list, }); let changes_path = upload_dir.join(&changes_name); - ctx.write_file(&changes_path, &crate::debian::control::write_paragraph(&changes_doc))?; + ctx.write_file( + &changes_path, + &crate::debian::control::write_paragraph(&changes_doc), + )?; Ok((buildinfo_path, changes_path)) } @@ -321,10 +305,7 @@ fn pipeline_environment(opts: &BinaryMetadataOptions) -> BTreeMap Result> { let content = std::fs::read_to_string(status_path) .map_err(|e| format!("cannot read status file '{}': {}", status_path.display(), e))?; - installed_build_depends_from_content(&content, build_depends_fields) - .map_err(|e| e.into()) + installed_build_depends_from_content(&content, build_depends_fields).map_err(|e| e.into()) } /// Compute the `Installed-Build-Depends` value from the textual content of a diff --git a/src/build/mod.rs b/src/build/mod.rs index 86a92b8..574ceb2 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -219,7 +219,9 @@ pub fn run_source_build( let report = crate::debian::deps::check_build_depends(&ctrl, &check_opts)?; if !report.is_ok() { eprintln!("{}", report.message()); - return Err(Box::new(crate::debian::deps::UnmetBuildDependencies(report))); + return Err(Box::new(crate::debian::deps::UnmetBuildDependencies( + report, + ))); } } @@ -892,7 +894,9 @@ mod differential_tests { if let Some(a) = arch { cmd.args(["-a", a]); } - let output = cmd.output().expect("run dpkg-architecture (is dpkg-dev installed?)"); + let output = cmd + .output() + .expect("run dpkg-architecture (is dpkg-dev installed?)"); assert!( output.status.success(), "dpkg-architecture -f {arch:?} failed: {}", @@ -907,7 +911,10 @@ mod differential_tests { let ours = crate::debian::arch::arch_env(arch) .unwrap_or_else(|e| panic!("native arch_env({arch:?}) failed: {e}")); - assert_eq!(ours, expected, "arch_env({arch:?}) differs from dpkg-architecture"); + assert_eq!( + ours, expected, + "arch_env({arch:?}) differs from dpkg-architecture" + ); } /// Every architecture known to the local dpkg must produce an identical @@ -993,12 +1000,16 @@ mod differential_tests { ignore_builtin: true, admindir: admindir.clone(), }; - let control_info = crate::debian::ControlInfo::parse_content(control).expect("parse control"); + let control_info = + crate::debian::ControlInfo::parse_content(control).expect("parse control"); let report = crate::debian::deps::check_build_depends(&control_info, &opts) .expect("native parse failure"); let ours_exit = if report.is_ok() { 0 } else { 1 }; - assert_eq!(ours_exit, real_exit, "exit status mismatch for {control:?} {args:?}"); + assert_eq!( + ours_exit, real_exit, + "exit status mismatch for {control:?} {args:?}" + ); assert_eq!( report.message(), real_msg, @@ -1083,7 +1094,11 @@ Provides: virtual-thing (= 2.0), plain-virtual diff_checkbuilddeps_case(&control_ab, STATUS, &["-B", "-P", "cross"]); // Combined unmet + conflict reporting in one run. - case("missing-one, libc6 (>> 999)", "libfoo-dev", &["-P", "cross"]); + case( + "missing-one, libc6 (>> 999)", + "libfoo-dev", + &["-P", "cross"], + ); } /// Differential check of [`crate::debian::version`] against real @@ -1094,10 +1109,10 @@ Provides: virtual-thing (= 2.0), plain-virtual let vectors = crate::debian::version::test_vectors::COMPARE; assert!(!vectors.is_empty()); for (a, b, expected) in vectors { - let va = crate::debian::DebianVersion::parse(a) - .unwrap_or_else(|e| panic!("parse {a}: {e}")); - let vb = crate::debian::DebianVersion::parse(b) - .unwrap_or_else(|e| panic!("parse {b}: {e}")); + let va = + crate::debian::DebianVersion::parse(a).unwrap_or_else(|e| panic!("parse {a}: {e}")); + let vb = + crate::debian::DebianVersion::parse(b).unwrap_or_else(|e| panic!("parse {b}: {e}")); let ours = match va.cmp(&vb) { std::cmp::Ordering::Less => -1, std::cmp::Ordering::Equal => 0, @@ -1151,8 +1166,7 @@ Provides: virtual-thing (= 2.0), plain-virtual let tree = root.join(NAME); fs::write(tree.join("debian/control"), &control).expect("write control"); fs::write(tree.join("debian/changelog"), &changelog).expect("write changelog"); - fs::write(tree.join("debian/source/format"), "3.0 (native)\n") - .expect("write format"); + fs::write(tree.join("debian/source/format"), "3.0 (native)\n").expect("write format"); fs::write(tree.join("debian/rules"), &rules).expect("write rules"); #[cfg(unix)] { @@ -1192,7 +1206,10 @@ Provides: virtual-thing (= 2.0), plain-virtual let parallel = env::num_parallel(); let build_env_vars: Vec<(String, String)> = [ ("LANG".to_string(), "C".to_string()), - ("DEB_BUILD_OPTIONS".to_string(), format!("parallel={parallel}")), + ( + "DEB_BUILD_OPTIONS".to_string(), + format!("parallel={parallel}"), + ), ("SOURCE_DATE_EPOCH".to_string(), entry.timestamp.to_string()), ] .into_iter() diff --git a/src/deb/local.rs b/src/deb/local.rs index a9caaf6..93b6e15 100644 --- a/src/deb/local.rs +++ b/src/deb/local.rs @@ -232,10 +232,7 @@ pub async fn build( match ctx.read_file(&package_dir.join("debian/changelog")) { Ok(content) => { if let Ok(entry) = crate::debian::parse_changelog_entry_from_str(&content) { - env.insert( - "SOURCE_DATE_EPOCH".to_string(), - entry.timestamp.to_string(), - ); + env.insert("SOURCE_DATE_EPOCH".to_string(), entry.timestamp.to_string()); } } Err(e) => log::debug!("cannot read changelog for SOURCE_DATE_EPOCH: {}", e), @@ -336,9 +333,7 @@ pub async fn build( // equivalent of dpkg-genbuildinfo -b + dpkg-genchanges -b, consuming // debian/files produced by the build. Failures are logged but do not // discard the produced binaries. - if let Err(e) = - generate_upload_metadata(package_dir_str, build_root, arch, cross, &env, &ctx) - { + if let Err(e) = generate_upload_metadata(package_dir_str, build_root, arch, cross, &env, &ctx) { warn!("failed to generate .buildinfo/.changes: {}", e); } @@ -359,8 +354,7 @@ fn generate_upload_metadata( let changelog_path = Path::new(package_dir).join("debian/changelog"); let changelog_content = ctx.read_file(&changelog_path)?; - let entry = - crate::debian::parse_changelog_entry_from_str(&changelog_content)?; + let entry = crate::debian::parse_changelog_entry_from_str(&changelog_content)?; // Build architecture: the machine inside the build context. let build_arch = ctx @@ -395,10 +389,7 @@ fn generate_upload_metadata( }) .unwrap_or_else(crate::build::env::current_vendor); - let profiles = crate::build::env::resolve_build_profiles( - &[], - &vendor, - ); + let profiles = crate::build::env::resolve_build_profiles(&[], &vendor); let source_date_epoch = env .get("SOURCE_DATE_EPOCH") .and_then(|v| v.parse::().ok()) diff --git a/src/deb/mod.rs b/src/deb/mod.rs index 2cf440b..6f97cb1 100644 --- a/src/deb/mod.rs +++ b/src/deb/mod.rs @@ -174,8 +174,12 @@ async fn build_binary_package_impl( let deb_files: Vec = remote_files .into_iter() .filter(|f| { - f.extension() - .is_some_and(|ext| matches!(ext.to_str(), Some("deb") | Some("buildinfo") | Some("changes"))) + f.extension().is_some_and(|ext| { + matches!( + ext.to_str(), + Some("deb") | Some("buildinfo") | Some("changes") + ) + }) }) .collect(); let total_debs = deb_files.len(); diff --git a/src/debian/arch.rs b/src/debian/arch.rs index 2e7ab9c..9d47e1e 100644 --- a/src/debian/arch.rs +++ b/src/debian/arch.rs @@ -99,65 +99,349 @@ struct OsEntry { // Factual data from dpkg `data/cputable` (columns: debian name, GNU name, // config.guess regex, bits, endianness). static CPU_TABLE: &[CpuEntry] = &[ - CpuEntry { name: "alpha", gnu: "alpha", guess: "alpha.*", bits: 64, endian: Endian::Little }, - CpuEntry { name: "amd64", gnu: "x86_64", guess: "(amd64|x86_64)", bits: 64, endian: Endian::Little }, - CpuEntry { name: "arc", gnu: "arc", guess: "arc", bits: 32, endian: Endian::Little }, - CpuEntry { name: "armeb", gnu: "armeb", guess: "arm.*b", bits: 32, endian: Endian::Big }, - CpuEntry { name: "arm", gnu: "arm", guess: "arm.*", bits: 32, endian: Endian::Little }, - CpuEntry { name: "arm64", gnu: "aarch64", guess: "aarch64", bits: 64, endian: Endian::Little }, - CpuEntry { name: "hppa", gnu: "hppa", guess: "hppa.*", bits: 32, endian: Endian::Big }, - CpuEntry { name: "loong64", gnu: "loongarch64", guess: "loongarch64", bits: 64, endian: Endian::Little }, - CpuEntry { name: "i386", gnu: "i686", guess: "(i[34567]86|pentium)", bits: 32, endian: Endian::Little }, - CpuEntry { name: "ia64", gnu: "ia64", guess: "ia64", bits: 64, endian: Endian::Little }, - CpuEntry { name: "m68k", gnu: "m68k", guess: "m68k", bits: 32, endian: Endian::Big }, - CpuEntry { name: "mips", gnu: "mips", guess: "mips(eb)?", bits: 32, endian: Endian::Big }, - CpuEntry { name: "mipsel", gnu: "mipsel", guess: "mipsel", bits: 32, endian: Endian::Little }, - CpuEntry { name: "mipsr6", gnu: "mipsisa32r6", guess: "mipsisa32r6", bits: 32, endian: Endian::Big }, - CpuEntry { name: "mipsr6el", gnu: "mipsisa32r6el", guess: "mipsisa32r6el", bits: 32, endian: Endian::Little }, - CpuEntry { name: "mips64", gnu: "mips64", guess: "mips64", bits: 64, endian: Endian::Big }, - CpuEntry { name: "mips64el", gnu: "mips64el", guess: "mips64el", bits: 64, endian: Endian::Little }, - CpuEntry { name: "mips64r6", gnu: "mipsisa64r6", guess: "mipsisa64r6", bits: 64, endian: Endian::Big }, - CpuEntry { name: "mips64r6el", gnu: "mipsisa64r6el", guess: "mipsisa64r6el", bits: 64, endian: Endian::Little }, - CpuEntry { name: "nios2", gnu: "nios2", guess: "nios2", bits: 32, endian: Endian::Little }, - CpuEntry { name: "or1k", gnu: "or1k", guess: "or1k", bits: 32, endian: Endian::Big }, - CpuEntry { name: "powerpc", gnu: "powerpc", guess: "(powerpc|ppc)", bits: 32, endian: Endian::Big }, - CpuEntry { name: "powerpcel", gnu: "powerpcle", guess: "powerpcle", bits: 32, endian: Endian::Little }, - CpuEntry { name: "ppc64", gnu: "powerpc64", guess: "(powerpc|ppc)64", bits: 64, endian: Endian::Big }, - CpuEntry { name: "ppc64el", gnu: "powerpc64le", guess: "powerpc64le", bits: 64, endian: Endian::Little }, - CpuEntry { name: "riscv64", gnu: "riscv64", guess: "riscv64", bits: 64, endian: Endian::Little }, - CpuEntry { name: "s390", gnu: "s390", guess: "s390", bits: 32, endian: Endian::Big }, - CpuEntry { name: "s390x", gnu: "s390x", guess: "s390x", bits: 64, endian: Endian::Big }, - CpuEntry { name: "sh3", gnu: "sh3", guess: "sh3", bits: 32, endian: Endian::Little }, - CpuEntry { name: "sh3eb", gnu: "sh3eb", guess: "sh3eb", bits: 32, endian: Endian::Big }, - CpuEntry { name: "sh4", gnu: "sh4", guess: "sh4", bits: 32, endian: Endian::Little }, - CpuEntry { name: "sh4eb", gnu: "sh4eb", guess: "sh4eb", bits: 32, endian: Endian::Big }, - CpuEntry { name: "sparc", gnu: "sparc", guess: "sparc", bits: 32, endian: Endian::Big }, - CpuEntry { name: "sparc64", gnu: "sparc64", guess: "sparc(64|v9)", bits: 64, endian: Endian::Big }, + CpuEntry { + name: "alpha", + gnu: "alpha", + guess: "alpha.*", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "amd64", + gnu: "x86_64", + guess: "(amd64|x86_64)", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "arc", + gnu: "arc", + guess: "arc", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "armeb", + gnu: "armeb", + guess: "arm.*b", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "arm", + gnu: "arm", + guess: "arm.*", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "arm64", + gnu: "aarch64", + guess: "aarch64", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "hppa", + gnu: "hppa", + guess: "hppa.*", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "loong64", + gnu: "loongarch64", + guess: "loongarch64", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "i386", + gnu: "i686", + guess: "(i[34567]86|pentium)", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "ia64", + gnu: "ia64", + guess: "ia64", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "m68k", + gnu: "m68k", + guess: "m68k", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "mips", + gnu: "mips", + guess: "mips(eb)?", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "mipsel", + gnu: "mipsel", + guess: "mipsel", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "mipsr6", + gnu: "mipsisa32r6", + guess: "mipsisa32r6", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "mipsr6el", + gnu: "mipsisa32r6el", + guess: "mipsisa32r6el", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "mips64", + gnu: "mips64", + guess: "mips64", + bits: 64, + endian: Endian::Big, + }, + CpuEntry { + name: "mips64el", + gnu: "mips64el", + guess: "mips64el", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "mips64r6", + gnu: "mipsisa64r6", + guess: "mipsisa64r6", + bits: 64, + endian: Endian::Big, + }, + CpuEntry { + name: "mips64r6el", + gnu: "mipsisa64r6el", + guess: "mipsisa64r6el", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "nios2", + gnu: "nios2", + guess: "nios2", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "or1k", + gnu: "or1k", + guess: "or1k", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "powerpc", + gnu: "powerpc", + guess: "(powerpc|ppc)", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "powerpcel", + gnu: "powerpcle", + guess: "powerpcle", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "ppc64", + gnu: "powerpc64", + guess: "(powerpc|ppc)64", + bits: 64, + endian: Endian::Big, + }, + CpuEntry { + name: "ppc64el", + gnu: "powerpc64le", + guess: "powerpc64le", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "riscv64", + gnu: "riscv64", + guess: "riscv64", + bits: 64, + endian: Endian::Little, + }, + CpuEntry { + name: "s390", + gnu: "s390", + guess: "s390", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "s390x", + gnu: "s390x", + guess: "s390x", + bits: 64, + endian: Endian::Big, + }, + CpuEntry { + name: "sh3", + gnu: "sh3", + guess: "sh3", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "sh3eb", + gnu: "sh3eb", + guess: "sh3eb", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "sh4", + gnu: "sh4", + guess: "sh4", + bits: 32, + endian: Endian::Little, + }, + CpuEntry { + name: "sh4eb", + gnu: "sh4eb", + guess: "sh4eb", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "sparc", + gnu: "sparc", + guess: "sparc", + bits: 32, + endian: Endian::Big, + }, + CpuEntry { + name: "sparc64", + gnu: "sparc64", + guess: "sparc(64|v9)", + bits: 64, + endian: Endian::Big, + }, ]; // Factual data from dpkg `data/ostable` (columns: debian `abi-libc-os`, // GNU system name, config.guess regex). static OS_TABLE: &[OsEntry] = &[ - OsEntry { tuple: "eabi-uclibc-linux", gnu: "linux-uclibceabi", guess: "linux[^-]*-uclibceabi" }, - OsEntry { tuple: "base-uclibc-linux", gnu: "linux-uclibc", guess: "linux[^-]*-uclibc" }, - OsEntry { tuple: "eabihf-musl-linux", gnu: "linux-musleabihf", guess: "linux[^-]*-musleabihf" }, - OsEntry { tuple: "base-musl-linux", gnu: "linux-musl", guess: "linux[^-]*-musl" }, - OsEntry { tuple: "eabihf-gnu-linux", gnu: "linux-gnueabihf", guess: "linux[^-]*-gnueabihf" }, - OsEntry { tuple: "eabi-gnu-linux", gnu: "linux-gnueabi", guess: "linux[^-]*-gnueabi" }, - OsEntry { tuple: "abin32-gnu-linux", gnu: "linux-gnuabin32", guess: "linux[^-]*-gnuabin32" }, - OsEntry { tuple: "abi64-gnu-linux", gnu: "linux-gnuabi64", guess: "linux[^-]*-gnuabi64" }, - OsEntry { tuple: "spe-gnu-linux", gnu: "linux-gnuspe", guess: "linux[^-]*-gnuspe" }, - OsEntry { tuple: "x32-gnu-linux", gnu: "linux-gnux32", guess: "linux[^-]*-gnux32" }, - OsEntry { tuple: "base-gnu-linux", gnu: "linux-gnu", guess: "linux[^-]*(-gnu.*)?" }, - OsEntry { tuple: "base-gnu-hurd", gnu: "gnu", guess: "gnu[^-]*" }, - OsEntry { tuple: "base-bsd-darwin", gnu: "darwin", guess: "darwin[^-]*" }, - OsEntry { tuple: "base-bsd-dragonflybsd", gnu: "dragonflybsd", guess: "dragonfly[^-]*" }, - OsEntry { tuple: "base-bsd-freebsd", gnu: "freebsd", guess: "freebsd[^-]*" }, - OsEntry { tuple: "base-bsd-netbsd", gnu: "netbsd", guess: "netbsd[^-]*" }, - OsEntry { tuple: "base-bsd-openbsd", gnu: "openbsd", guess: "openbsd[^-]*" }, - OsEntry { tuple: "base-sysv-aix", gnu: "aix", guess: "aix[^-]*" }, - OsEntry { tuple: "base-sysv-solaris", gnu: "solaris", guess: "solaris[^-]*" }, - OsEntry { tuple: "base-tos-mint", gnu: "mint", guess: "mint[^-]*" }, + OsEntry { + tuple: "eabi-uclibc-linux", + gnu: "linux-uclibceabi", + guess: "linux[^-]*-uclibceabi", + }, + OsEntry { + tuple: "base-uclibc-linux", + gnu: "linux-uclibc", + guess: "linux[^-]*-uclibc", + }, + OsEntry { + tuple: "eabihf-musl-linux", + gnu: "linux-musleabihf", + guess: "linux[^-]*-musleabihf", + }, + OsEntry { + tuple: "base-musl-linux", + gnu: "linux-musl", + guess: "linux[^-]*-musl", + }, + OsEntry { + tuple: "eabihf-gnu-linux", + gnu: "linux-gnueabihf", + guess: "linux[^-]*-gnueabihf", + }, + OsEntry { + tuple: "eabi-gnu-linux", + gnu: "linux-gnueabi", + guess: "linux[^-]*-gnueabi", + }, + OsEntry { + tuple: "abin32-gnu-linux", + gnu: "linux-gnuabin32", + guess: "linux[^-]*-gnuabin32", + }, + OsEntry { + tuple: "abi64-gnu-linux", + gnu: "linux-gnuabi64", + guess: "linux[^-]*-gnuabi64", + }, + OsEntry { + tuple: "spe-gnu-linux", + gnu: "linux-gnuspe", + guess: "linux[^-]*-gnuspe", + }, + OsEntry { + tuple: "x32-gnu-linux", + gnu: "linux-gnux32", + guess: "linux[^-]*-gnux32", + }, + OsEntry { + tuple: "base-gnu-linux", + gnu: "linux-gnu", + guess: "linux[^-]*(-gnu.*)?", + }, + OsEntry { + tuple: "base-gnu-hurd", + gnu: "gnu", + guess: "gnu[^-]*", + }, + OsEntry { + tuple: "base-bsd-darwin", + gnu: "darwin", + guess: "darwin[^-]*", + }, + OsEntry { + tuple: "base-bsd-dragonflybsd", + gnu: "dragonflybsd", + guess: "dragonfly[^-]*", + }, + OsEntry { + tuple: "base-bsd-freebsd", + gnu: "freebsd", + guess: "freebsd[^-]*", + }, + OsEntry { + tuple: "base-bsd-netbsd", + gnu: "netbsd", + guess: "netbsd[^-]*", + }, + OsEntry { + tuple: "base-bsd-openbsd", + gnu: "openbsd", + guess: "openbsd[^-]*", + }, + OsEntry { + tuple: "base-sysv-aix", + gnu: "aix", + guess: "aix[^-]*", + }, + OsEntry { + tuple: "base-sysv-solaris", + gnu: "solaris", + guess: "solaris[^-]*", + }, + OsEntry { + tuple: "base-tos-mint", + gnu: "mint", + guess: "mint[^-]*", + }, ]; // Factual data from dpkg `data/tupletable`: bidirectional mapping between a @@ -347,15 +631,20 @@ pub fn is(real: &str, alias: &str) -> bool { let (Some(r), Some(a)) = (debarch_to_debtuple(real), wildcard_to_debtuple(alias)) else { return false; }; - [a.abi.as_str(), a.libc.as_str(), a.os.as_str(), a.cpu.as_str()] - .iter() - .zip([ - r.abi.as_str(), - r.libc.as_str(), - r.os.as_str(), - r.cpu.as_str(), - ]) - .all(|(alias_part, real_part)| *alias_part == "any" || *alias_part == real_part) + [ + a.abi.as_str(), + a.libc.as_str(), + a.os.as_str(), + a.cpu.as_str(), + ] + .iter() + .zip([ + r.abi.as_str(), + r.libc.as_str(), + r.os.as_str(), + r.cpu.as_str(), + ]) + .all(|(alias_part, real_part)| *alias_part == "any" || *alias_part == real_part) } /// Evaluate whether a Debian architecture name is an architecture wildcard. @@ -557,8 +846,8 @@ pub fn arch_env(host_arch: Option<&str>) -> Result, Str env.insert(format!("DEB_{role}_ARCH_BITS"), bits.to_string()); env.insert(format!("DEB_{role}_ARCH_ENDIAN"), endian.to_string()); - let multi = multiarch(&arch) - .ok_or_else(|| format!("unknown Debian architecture '{arch}'"))?; + let multi = + multiarch(&arch).ok_or_else(|| format!("unknown Debian architecture '{arch}'"))?; env.insert(format!("DEB_{role}_MULTIARCH"), multi); let gnu_type = debarch_to_gnutriplet(&arch) @@ -617,14 +906,8 @@ mod tests { Some("i686-linux-gnu") ); assert_eq!(multiarch("i386").as_deref(), Some("i386-linux-gnu")); - assert_eq!( - multiarch("amd64").as_deref(), - Some("x86_64-linux-gnu") - ); - assert_eq!( - multiarch("arm64").as_deref(), - Some("aarch64-linux-gnu") - ); + assert_eq!(multiarch("amd64").as_deref(), Some("x86_64-linux-gnu")); + assert_eq!(multiarch("arm64").as_deref(), Some("aarch64-linux-gnu")); } #[test] @@ -690,7 +973,15 @@ mod tests { #[test] fn known_arches() { let arches = valid_arches(); - for expected in ["amd64", "armhf", "armel", "i386", "riscv64", "x32", "hurd-i386"] { + for expected in [ + "amd64", + "armhf", + "armel", + "i386", + "riscv64", + "x32", + "hurd-i386", + ] { assert!(arches.iter().any(|a| a == expected), "missing {expected}"); } } @@ -722,7 +1013,10 @@ mod tests { assert_ne!(env.get("DEB_BUILD_ARCH").unwrap(), "armhf"); assert_eq!(env.get("DEB_HOST_ARCH").unwrap(), "armhf"); assert_eq!(env.get("DEB_HOST_GNU_TYPE").unwrap(), "arm-linux-gnueabihf"); - assert_eq!(env.get("DEB_HOST_MULTIARCH").unwrap(), "arm-linux-gnueabihf"); + assert_eq!( + env.get("DEB_HOST_MULTIARCH").unwrap(), + "arm-linux-gnueabihf" + ); assert_eq!(env.get("DEB_TARGET_ARCH").unwrap(), "armhf"); } diff --git a/src/debian/changelog.rs b/src/debian/changelog.rs index c2d9c50..0859621 100644 --- a/src/debian/changelog.rs +++ b/src/debian/changelog.rs @@ -68,9 +68,9 @@ pub fn parse_changelog_entry_from_str( } }; - let open = header.find('(').ok_or_else(|| { - format!("invalid changelog header in '{origin}': {header}") - })?; + let open = header + .find('(') + .ok_or_else(|| format!("invalid changelog header in '{origin}': {header}"))?; let close = header[open..] .find(')') .ok_or_else(|| format!("unbalanced parenthesis in changelog header '{}'", header))?; @@ -150,9 +150,7 @@ pub fn parse_changelog_entry_from_str( let date_raw = trailer_body[gt + 1..].trim().to_string(); let timestamp = DateTime::parse_from_rfc2822(&date_raw) - .map_err(|e| { - format!("cannot parse changelog date '{date_raw}' in '{origin}': {e}") - })? + .map_err(|e| format!("cannot parse changelog date '{date_raw}' in '{origin}': {e}"))? .timestamp(); // Changes field value (leading `\n` marks it as a pre-wrapped multiline diff --git a/src/debian/deps.rs b/src/debian/deps.rs index ce24b06..481c3a4 100644 --- a/src/debian/deps.rs +++ b/src/debian/deps.rs @@ -18,7 +18,7 @@ use regex::Regex; use crate::debian::arch; use crate::debian::control::ControlInfo; -use crate::debian::version::{compare as version_cmp, DebianVersion}; +use crate::debian::version::{DebianVersion, compare as version_cmp}; /// Version relation operator between a package and a version. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -145,11 +145,11 @@ fn dep_regex() -> &'static Regex { static REGEX: OnceLock = OnceLock::new(); REGEX.get_or_init(|| { Regex::new(concat!( - r"^(\s*)([a-zA-Z0-9][a-zA-Z0-9+.\-]*)", // package name - r"(?::([a-zA-Z0-9][a-zA-Z0-9\-]*))?", // optional :arch qualifier + r"^(\s*)([a-zA-Z0-9][a-zA-Z0-9+.\-]*)", // package name + r"(?::([a-zA-Z0-9][a-zA-Z0-9\-]*))?", // optional :arch qualifier r"(\s*\(\s*(<<|<=|=|>=|>>|[<>])\s*([^\)\s]+)\s*\))?", // optional version - r"(\s*\[\s*([^\]]+?)\s*\])?", // optional [arch list] - r"((?:\s*<\s*[^>]+?\s*>)+)?(\s*)$", // optional + r"(\s*\[\s*([^\]]+?)\s*\])?", // optional [arch list] + r"((?:\s*<\s*[^>]+?\s*>)+)?(\s*)$", // optional )) .expect("valid dependency regex") }) @@ -291,11 +291,7 @@ impl Deps { Self::parse_inner(input, opts, false) } - fn parse_inner( - input: &str, - opts: &ParseOpts, - reduce_arch_only: bool, - ) -> Result { + fn parse_inner(input: &str, opts: &ParseOpts, reduce_arch_only: bool) -> Result { if opts.host_arch.is_empty() || arch::is_invalid(&opts.host_arch, true) { return Err(format!("invalid host_arch {}", opts.host_arch)); } @@ -336,9 +332,7 @@ impl Deps { continue; } if opts.union && alternatives.len() > 1 { - return Err( - "an union dependency can only contain simple dependencies".to_string(), - ); + return Err("an union dependency can only contain simple dependencies".to_string()); } clauses.push(alternatives); } @@ -369,8 +363,7 @@ impl Deps { self.clauses .iter() .map(|alts| { - alts - .iter() + alts.iter() .map(PkgRelation::output) .collect::>() .join(" | ") @@ -1145,7 +1138,10 @@ Provides: old-virtual (= 0.5) // Real packages. assert_eq!(facts.evaluate_relation(&o("mypackage")), Some(true)); - assert_eq!(facts.evaluate_relation(&o("mypackage (>= 1.3)")), Some(true)); + assert_eq!( + facts.evaluate_relation(&o("mypackage (>= 1.3)")), + Some(true) + ); assert_eq!( facts.evaluate_relation(&o("mypackage (>> 1.3.4-1)")), Some(false) @@ -1157,7 +1153,10 @@ Provides: old-virtual (= 0.5) facts.evaluate_relation(&o("pkg-ma-foreign:somearch")), Some(true) ); - assert_eq!(facts.evaluate_relation(&o("pkg-ma-allowed:any")), Some(true)); + assert_eq!( + facts.evaluate_relation(&o("pkg-ma-allowed:any")), + Some(true) + ); assert_eq!(facts.evaluate_relation(&o("pkg-ma-allowed")), Some(false)); assert_eq!(facts.evaluate_relation(&o("pkg-ma-foreign2")), Some(true)); diff --git a/src/debian/files.rs b/src/debian/files.rs index c4abb85..a587712 100644 --- a/src/debian/files.rs +++ b/src/debian/files.rs @@ -121,8 +121,7 @@ impl FilesList { return Err(format!("cannot read '{}': {}", path.display(), e).into()); } }; - FilesList::parse(&content) - .map_err(|e| format!("in '{}': {}", path.display(), e).into()) + FilesList::parse(&content).map_err(|e| format!("in '{}': {}", path.display(), e).into()) } /// Parse a `debian/files` registry from its textual content diff --git a/src/debian/version.rs b/src/debian/version.rs index 192a984..578bf1a 100644 --- a/src/debian/version.rs +++ b/src/debian/version.rs @@ -102,7 +102,8 @@ impl DebianVersion { /// - digit chunks compare numerically (leading zeroes are irrelevant; an /// empty digit chunk counts as `0`, so a missing revision equals `0`). pub fn compare(a: &DebianVersion, b: &DebianVersion) -> std::cmp::Ordering { - a.epoch.unwrap_or(0) + a.epoch + .unwrap_or(0) .cmp(&b.epoch.unwrap_or(0)) .then_with(|| verrevcmp(a.upstream.as_bytes(), b.upstream.as_bytes())) .then_with(|| { @@ -137,8 +138,7 @@ fn verrevcmp(mut a: &[u8], mut b: &[u8]) -> std::cmp::Ordering { // Non-digit chunks: compare by character weight. A chunk boundary // (end of string or start of a digit run) weighs 0, which sorts // after `~` (-1) and before every real character. - while (!a.is_empty() && !a[0].is_ascii_digit()) - || (!b.is_empty() && !b[0].is_ascii_digit()) + while (!a.is_empty() && !a[0].is_ascii_digit()) || (!b.is_empty() && !b[0].is_ascii_digit()) { let ac = if !a.is_empty() && !a[0].is_ascii_digit() { char_order(a[0]) @@ -276,7 +276,14 @@ pub(crate) mod test_vectors { ], ), ( - &["4", "5.0abc", "0.0alpha0", "10.100.1", "0~999.999zeta", "1.0"], + &[ + "4", + "5.0abc", + "0.0alpha0", + "10.100.1", + "0~999.999zeta", + "1.0", + ], &[ "0~999.999zeta", "0.0alpha0", @@ -334,10 +341,8 @@ mod tests { #[test] fn comparison_dpkg_vectors() { for (a, b, expected) in test_vectors::COMPARE { - let va = - DebianVersion::parse(a).unwrap_or_else(|e| panic!("parse {a}: {e}")); - let vb = - DebianVersion::parse(b).unwrap_or_else(|e| panic!("parse {b}: {e}")); + let va = DebianVersion::parse(a).unwrap_or_else(|e| panic!("parse {a}: {e}")); + let vb = DebianVersion::parse(b).unwrap_or_else(|e| panic!("parse {b}: {e}")); assert_eq!( cmp_sign(&va, &vb), *expected,