fmt, clippy

This commit is contained in:
2026-08-23 01:46:04 +02:00
parent c2e1288bc5
commit 4a8ff9ac0d
11 changed files with 108 additions and 56 deletions
+18 -5
View File
@@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet, VecDeque};
use std::path::Path;
use crate::debian::checksums::FileChecksums;
use crate::debian::control::{parse_paragraphs, write_paragraph, Paragraph};
use crate::debian::control::{Paragraph, parse_paragraphs, write_paragraph};
/// One installed package relevant for dependency resolution.
#[derive(Debug, Clone)]
@@ -52,13 +52,20 @@ impl StatusDb {
};
let arch = para.get("Architecture").unwrap_or("").to_string();
if let (Some(version), false) = (para.get("Version"), arch.is_empty()) {
db.pkgs.entry(package.to_string()).or_default().push(InstalledPkg {
db.pkgs
.entry(package.to_string())
.or_default()
.push(InstalledPkg {
version: version.to_string(),
arch: arch.clone(),
});
}
if para.get("Essential").map(|v| v.eq_ignore_ascii_case("yes")).unwrap_or(false) {
if para
.get("Essential")
.map(|v| v.eq_ignore_ascii_case("yes"))
.unwrap_or(false)
{
db.essential.push(package.to_string());
}
@@ -291,7 +298,10 @@ pub fn render_buildinfo(input: &BuildInfoInput) -> Paragraph {
}
/// Serialize and atomically write a `.buildinfo` file.
pub fn save_buildinfo(path: &Path, paragraph: &Paragraph) -> Result<(), Box<dyn std::error::Error>> {
pub fn save_buildinfo(
path: &Path,
paragraph: &Paragraph,
) -> Result<(), Box<dyn std::error::Error>> {
let tmp = path.with_extension("new");
std::fs::write(&tmp, write_paragraph(paragraph))
.map_err(|e| format!("cannot write '{}': {}", tmp.display(), e))?;
@@ -366,7 +376,10 @@ Architecture: amd64
#[test]
fn wrap_binary_field() {
assert_eq!(wrap_long("abc"), "abc");
let long = (0..500).map(|i| i.to_string()).collect::<Vec<_>>().join(" ");
let long = (0..500)
.map(|i| i.to_string())
.collect::<Vec<_>>()
.join(" ");
let wrapped = wrap_long(&long);
assert!(wrapped.contains('\n'));
for line in wrapped.lines() {
+5 -2
View File
@@ -114,7 +114,7 @@ impl BuildType {
/// The architecture suffix used in artifact file names:
/// host arch, `all` or `source`.
pub fn arch_suffix<'a>(self, host_arch: &'a str) -> &'a str {
pub fn arch_suffix(self, host_arch: &str) -> &str {
if self.has_any(ARCH_DEP) {
host_arch
} else if self.has_any(ARCH_INDEP) {
@@ -133,7 +133,10 @@ mod tests {
fn parse_options() {
assert_eq!(BuildType::from_options("full").unwrap(), FULL);
assert_eq!(BuildType::from_options("source").unwrap(), SOURCE);
assert_eq!(BuildType::from_options("source,any").unwrap(), SOURCE_ARCH_DEP);
assert_eq!(
BuildType::from_options("source,any").unwrap(),
SOURCE_ARCH_DEP
);
assert_eq!(BuildType::from_options("any,all").unwrap(), BINARY);
assert!(BuildType::from_options("bogus").is_err());
}
+6 -3
View File
@@ -5,7 +5,7 @@
use std::path::Path;
use crate::debian::checksums::FileChecksums;
use crate::debian::control::{write_paragraph, Paragraph};
use crate::debian::control::{Paragraph, write_paragraph};
use crate::debian::files::FilesList;
/// Everything needed to render a `.changes` file.
@@ -165,7 +165,10 @@ mod tests {
"verylongpkgname - short (udeb)"
);
let long_summary = "x".repeat(100);
assert_eq!(format_description("p", "deb", &long_summary).len(), 10 + 3 + 65);
assert_eq!(
format_description("p", "deb", &long_summary).len(),
10 + 3 + 65
);
}
#[test]
@@ -230,7 +233,7 @@ mod tests {
assert_eq!(
files_value,
"\n<md5> 8 utils optional pkg_1.0.dsc"
.replace("<md5>", &files_value.split_whitespace().next().unwrap_or(""))
.replace("<md5>", files_value.split_whitespace().next().unwrap_or(""))
);
}
}
+3 -6
View File
@@ -54,9 +54,7 @@ pub fn arch_env(host_arch: Option<&str>) -> Result<BTreeMap<String, String>, Str
cmd.args(["--host-arch", arch]);
}
let output = cmd
.output()
.map_err(|e| {
let output = cmd.output().map_err(|e| {
format!(
"failed to run 'dpkg-architecture': {}. Is 'dpkg-dev' installed?",
e
@@ -83,8 +81,7 @@ pub fn arch_env(host_arch: Option<&str>) -> Result<BTreeMap<String, String>, Str
/// Read the current vendor name from `/etc/dpkg/origins/default`
/// (its `Vendor:` or `Origin:` field), defaulting to `"debian"`.
pub fn current_vendor() -> String {
read_vendor_from(Path::new("/etc/dpkg/origins/default"))
.unwrap_or_else(|| "debian".to_string())
read_vendor_from(Path::new("/etc/dpkg/origins/default")).unwrap_or_else(|| "debian".to_string())
}
fn read_vendor_from(path: &Path) -> Option<String> {
@@ -289,7 +286,7 @@ mod tests {
let env = build_env(1787392800, 16, &[]);
assert_eq!(env.get("SOURCE_DATE_EPOCH").unwrap(), "1787392800");
assert_eq!(env.get("DEB_BUILD_OPTIONS").unwrap(), "parallel=16");
assert!(env.get("DEB_BUILD_PROFILES").is_none());
assert!(!env.contains_key("DEB_BUILD_PROFILES"));
let env = build_env(1, 4, &["nodoc".to_string(), "cross".to_string()]);
assert_eq!(env.get("DEB_BUILD_PROFILES").unwrap(), "nodoc,cross");
+17 -4
View File
@@ -17,7 +17,7 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use crate::debian::{
parse_paragraphs, ChecksumEntry, ControlInfo, FileChecksums, FilesEntry, FilesList,
ChecksumEntry, ControlInfo, FileChecksums, FilesEntry, FilesList, parse_paragraphs,
};
/// Options for a native source-package build.
@@ -151,7 +151,10 @@ pub fn run_source_build(
);
}
Err(e) => {
log::warn!("failed to check for GPG key: {}, building without signing", e);
log::warn!(
"failed to check for GPG key: {}, building without signing",
e
);
}
}
}
@@ -167,7 +170,12 @@ pub fn run_source_build(
// ------------------------------------------------------------------
// 5. dpkg-source lifecycle: before-build + source build
// ------------------------------------------------------------------
run_command(cwd, "dpkg-source", &["-I", "-i", "--before-build", "."], &pipeline_env)?;
run_command(
cwd,
"dpkg-source",
&["-I", "-i", "--before-build", "."],
&pipeline_env,
)?;
run_command(cwd, "dpkg-source", &["-I", "-i", "-b", "."], &pipeline_env)?;
if !dsc_path.exists() {
@@ -333,7 +341,12 @@ pub fn run_source_build(
// ------------------------------------------------------------------
// 8. dpkg-source after-build (unapplies quilt patches it applied)
// ------------------------------------------------------------------
run_command(cwd, "dpkg-source", &["-I", "-i", "--after-build", "."], &pipeline_env)?;
run_command(
cwd,
"dpkg-source",
&["-I", "-i", "--after-build", "."],
&pipeline_env,
)?;
// ------------------------------------------------------------------
// 9. Signing cascade: dsc -> buildinfo -> changes
+7 -3
View File
@@ -56,9 +56,13 @@ pub fn parse_changelog_entry(path: &Path) -> Result<ChangelogEntry, Box<dyn std:
}
};
let open = header
.find('(')
.ok_or_else(|| format!("invalid changelog header in '{}': {}", path.display(), header))?;
let open = header.find('(').ok_or_else(|| {
format!(
"invalid changelog header in '{}': {}",
path.display(),
header
)
})?;
let close = header[open..]
.find(')')
.ok_or_else(|| format!("unbalanced parenthesis in changelog header '{}'", header))?;
+21 -7
View File
@@ -90,8 +90,8 @@ pub fn parse_paragraphs(input: &str) -> Vec<Paragraph> {
// Continuation line
if line.starts_with(' ') || line.starts_with('\t') {
let content = line.strip_prefix(' ').unwrap_or(line);
if let Some(field) = &last_field {
if let Some((_, v)) = current
if let Some(field) = &last_field
&& let Some((_, v)) = current
.fields
.iter_mut()
.rev()
@@ -101,7 +101,6 @@ pub fn parse_paragraphs(input: &str) -> Vec<Paragraph> {
v.push_str(content);
continue;
}
}
// Continuation without a preceding field line: skip it (malformed)
continue;
}
@@ -174,7 +173,7 @@ mod tests {
#[test]
fn parse_multiline_and_comments() {
let input = "# a comment\nDescription: short\n long description\n" //
.to_string() //
.to_string()
+ " spanning lines\n\nPackage: x\n";
let paras = parse_paragraphs(&input);
assert_eq!(paras.len(), 2);
@@ -190,7 +189,10 @@ mod tests {
let mut p = Paragraph::new();
p.set("Description", value);
let text = write_paragraph(&p);
assert_eq!(text, "Description: short\n long description\n spanning lines\n");
assert_eq!(
text,
"Description: short\n long description\n spanning lines\n"
);
let reparsed = parse_paragraphs(&text);
assert_eq!(reparsed[0].get("Description"), Some(value));
}
@@ -228,12 +230,15 @@ impl ControlInfo {
pub fn parse(path: &Path) -> Result<ControlInfo, Box<dyn std::error::Error>> {
let content = std::fs::read_to_string(path)
.map_err(|e| format!("failed to read control file '{}': {}", path.display(), e))?;
Self::from_str(&content)
content
.parse::<ControlInfo>()
.map_err(|e| format!("invalid control file '{}': {}", path.display(), e).into())
}
/// Parse control content from a string.
pub fn from_str(content: &str) -> Result<ControlInfo, String> {
///
/// Prefer [`std::str::FromStr`] (`"...".parse::<ControlInfo>()`).
pub fn parse_content(content: &str) -> Result<ControlInfo, String> {
let paragraphs = parse_paragraphs(content);
let mut iter = paragraphs.into_iter();
let source = iter
@@ -267,9 +272,18 @@ impl ControlInfo {
}
}
impl std::str::FromStr for ControlInfo {
type Err = String;
fn from_str(content: &str) -> Result<Self, Self::Err> {
ControlInfo::parse_content(content)
}
}
#[cfg(test)]
mod control_info_tests {
use super::*;
use std::str::FromStr;
#[test]
fn control_parsing() {
+10 -3
View File
@@ -61,8 +61,11 @@ pub fn parse_filename(name: &str) -> Option<FilesEntry> {
if let Some(dot) = rest.rfind('.') {
let arch = &rest[..dot];
let ptype = &rest[dot + 1..];
let valid = |s: &str| !s.is_empty()
&& s.chars().all(|c| c.is_ascii_alphanumeric() || "-+.:~".contains(c));
let valid = |s: &str| {
!s.is_empty()
&& s.chars()
.all(|c| c.is_ascii_alphanumeric() || "-+.:~".contains(c))
};
if valid(pkg) && valid(version) && valid(arch) && valid(ptype) {
return Some(FilesEntry {
filename: name.to_string(),
@@ -128,7 +131,11 @@ impl FilesList {
return Err(format!("badly formed line in '{}': {}", path.display(), line).into());
}
let mut entry = parse_filename(tokens[0]).ok_or_else(|| {
format!("badly formed file name in '{}': {}", path.display(), tokens[0])
format!(
"badly formed file name in '{}': {}",
path.display(),
tokens[0]
)
})?;
entry.section = tokens[1].to_string();
entry.priority = tokens[2].to_string();
+2 -2
View File
@@ -15,8 +15,8 @@ pub mod control;
pub mod files;
pub mod version;
pub use changelog::{parse_changelog_entry, ChangelogEntry};
pub use changelog::{ChangelogEntry, parse_changelog_entry};
pub use checksums::{Entry as ChecksumEntry, FileChecksums};
pub use control::{parse_paragraphs, write_paragraph, ControlInfo, Paragraph};
pub use control::{ControlInfo, Paragraph, parse_paragraphs, write_paragraph};
pub use files::{FilesEntry, FilesList};
pub use version::DebianVersion;
+2 -2
View File
@@ -9,11 +9,11 @@ pub mod apt;
pub mod build;
/// Parse or edit a Debian changelog of a source package
pub mod changelog;
/// Build a Debian package into a binary (.deb)
pub mod deb;
/// Reusable Debian format primitives (control/deb822, checksums, versions,
/// changelog entries, artifact registries)
pub mod debian;
/// Build a Debian package into a binary (.deb)
pub mod deb;
/// Obtain general information about distribution, series, etc
pub mod distro_info;
/// Obtain information about one or multiple packages
+4 -6
View File
@@ -46,9 +46,7 @@ pub fn find_signing_key_for_email(
pub fn validate_key_id(keyid: &str) -> Result<(), Box<dyn Error>> {
let len = keyid.len();
if len <= 8 {
return Err(
"short OpenPGP key IDs are broken; use a key fingerprint instead".into(),
);
return Err("short OpenPGP key IDs are broken; use a key fingerprint instead".into());
} else if len <= 16 {
log::warn!(
"long OpenPGP key IDs are strongly discouraged; \
@@ -65,12 +63,12 @@ pub fn validate_key_id(keyid: &str) -> Result<(), Box<dyn Error>> {
fn find_secret_key(ctx: &mut Context, keyid: &str) -> Result<Option<gpgme::Key>, Box<dyn Error>> {
for key_result in ctx.secret_keys()? {
let key = key_result?;
if let Ok(fingerprint) = key.fingerprint() {
if fingerprint.ends_with(keyid) {
if let Ok(fingerprint) = key.fingerprint()
&& fingerprint.ends_with(keyid)
{
return Ok(Some(key));
}
}
}
Ok(None)
}