build: re-implement source builds natively, drop dpkg-buildpackage shell-out
Replace the 'dpkg-buildpackage -S' wrapper with a native pipeline in src/build/: - deb822 control parser/writer with dpkg-compatible multiline rendering (control.rs) - md5/sha1/sha256 checksum registry, insertion-ordered like dpkg's artifact accumulation (checksums.rs) - Debian version splitting/validation and full changelog entry parsing, including binNMU binary-only entries (metadata.rs) - build-type bitflags and rules-target/artifact-suffix mapping (buildtype.rs) - environment setup: SOURCE_DATE_EPOCH, DEB_BUILD_OPTIONS, dpkg-architecture env dump, vendor default profiles and the sanitized Environment field recorded in .buildinfo (env.rs) - debian/files registry with atomic saves (files.rs) - native .buildinfo writer, including the Installed-Build-Depends closure computed over the dpkg status database (buildinfo.rs) - native .changes writer emitting dpkg's canonical field order with legacy Files + Checksums-Sha1/Sha256 (changes.rs) - gpgme clearsigning with the transitive checksum cascade (dsc -> buildinfo -> changes), key discovery from the changelog maintainer and UNRELEASED no-sign handling (sign.rs) dpkg-source (-b/--before-build/--after-build) intentionally remains a subprocess; debian/rules execution is unchanged. Validated differentially against real dpkg-buildpackage -S -I -i -nc -d on native and 3.0 (quilt) fixture packages: .dsc byte-identical, .changes payload matches modulo machine-dependent Installed-Build-Depends and Environment content, all signatures verify with gpg, artifact ordering and UNRELEASED no-sign behavior match dpkg.
This commit is contained in:
@@ -1,82 +0,0 @@
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::changelog::parse_changelog_footer;
|
||||
use crate::utils::gpg;
|
||||
|
||||
/// Build a Debian source package (to a .dsc)
|
||||
pub fn build_source_package(cwd: Option<&Path>) -> Result<(), Box<dyn Error>> {
|
||||
let cwd = cwd.unwrap_or_else(|| Path::new("."));
|
||||
|
||||
// Parse changelog to get maintainer information from the last modification entry
|
||||
let changelog_path = cwd.join("debian/changelog");
|
||||
let (maintainer_name, maintainer_email) = parse_changelog_footer(&changelog_path)?;
|
||||
|
||||
// Check if a GPG key matching the maintainer's email exists
|
||||
let signing_key = match gpg::find_signing_key_for_email(&maintainer_email) {
|
||||
Ok(key) => key,
|
||||
Err(e) => {
|
||||
// If GPG is not available or there's an error, continue without signing
|
||||
log::warn!("Failed to check for GPG key: {}", e);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// Build command arguments
|
||||
let mut command = Command::new("dpkg-buildpackage");
|
||||
command
|
||||
.current_dir(cwd)
|
||||
.arg("-S")
|
||||
.arg("-I")
|
||||
.arg("-i")
|
||||
.arg("-nc")
|
||||
.arg("-d");
|
||||
|
||||
// If a signing key is found, use it for signing
|
||||
if let Some(key_id) = &signing_key {
|
||||
command.arg(format!("--sign-keyid={}", key_id));
|
||||
log::info!("Using GPG key {} for signing", key_id);
|
||||
} else {
|
||||
command.arg("--no-sign");
|
||||
log::info!(
|
||||
"No GPG key found for {} ({}), building without signing",
|
||||
maintainer_name,
|
||||
maintainer_email
|
||||
);
|
||||
}
|
||||
|
||||
let status = command.status().map_err(|e| {
|
||||
format!(
|
||||
"Failed to run 'dpkg-buildpackage': {}. \
|
||||
Is 'dpkg-dev' (which provides dpkg-buildpackage) installed?",
|
||||
e
|
||||
)
|
||||
})?;
|
||||
|
||||
if !status.success() {
|
||||
return Err(format!(
|
||||
"dpkg-buildpackage failed with status: {}. \
|
||||
Re-run with 'RUST_LOG=debug' for more details, or run \
|
||||
'dpkg-buildpackage -S -I -i -nc -d' manually in '{}' to see the full output.",
|
||||
status,
|
||||
cwd.display()
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
if signing_key.is_some() {
|
||||
println!("Package built and signed successfully!");
|
||||
} else {
|
||||
println!("Package built successfully (unsigned).");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
// We are not testing the build part, as for now this is just a wrapper
|
||||
// around dpkg-buildpackage.
|
||||
}
|
||||
Reference in New Issue
Block a user