deb: retrieve only the artifacts produced by the build, not globbed files
build_binary_package_impl copied the whole parent directory into the build root (ensure_available) and then retrieved every *.deb / *.changes / *.buildinfo it found there. That surfaced stale files already sitting next to the package tree in the "Built in Ns:" summary. Now local::build returns the exact set of artifacts produced by this build — the binary packages registered in debian/files plus the generated .buildinfo/.changes from generate_binary_metadata — and build_binary_package_impl retrieves that list instead of globbing the build root. Only files genuinely produced by the current build are printed.
This commit is contained in:
+52
-14
@@ -7,7 +7,7 @@ use crate::ui::logfmt::QuiltClassifier;
|
||||
use log::warn;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::apt;
|
||||
@@ -38,7 +38,7 @@ pub async fn build(
|
||||
ctx: Arc<Context>,
|
||||
ui: Option<Arc<DebUi>>,
|
||||
jobs: Option<usize>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
) -> Result<Vec<PathBuf>, Box<dyn Error>> {
|
||||
let sink: Option<Arc<dyn LineSink>> = ui.as_ref().map(|u| u.sink());
|
||||
|
||||
// Environment
|
||||
@@ -334,15 +334,60 @@ pub async fn build(
|
||||
);
|
||||
}
|
||||
|
||||
// Collect the exact set of artifacts produced by this build so the caller
|
||||
// retrieves only those: the binary packages registered in debian/files
|
||||
// (the contract between dh_builddeb/dpkg-gencontrol and the artifact
|
||||
// generators) plus the .buildinfo/.changes generated below. This avoids
|
||||
// globbing the build root, which would also surface stale files copied
|
||||
// alongside the package tree.
|
||||
let mut artifacts = collect_binary_artifacts(&ctx, package_dir_str, build_root)?;
|
||||
|
||||
// Generate the upload metadata (.buildinfo + .changes) natively, the
|
||||
// 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) {
|
||||
warn!("failed to generate .buildinfo/.changes: {}", e);
|
||||
match generate_upload_metadata(package_dir_str, build_root, arch, cross, &env, &ctx) {
|
||||
Ok((buildinfo, changes)) => {
|
||||
log::info!(
|
||||
"generated upload metadata: {} and {}",
|
||||
buildinfo.display(),
|
||||
changes.display()
|
||||
);
|
||||
artifacts.push(buildinfo);
|
||||
artifacts.push(changes);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("failed to generate .buildinfo/.changes: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(artifacts)
|
||||
}
|
||||
|
||||
/// Collect the binary artifacts (.deb/.udeb) registered by the build in
|
||||
/// `debian/files`, returning their paths inside the build context
|
||||
/// (`<build_root>/<filename>`). `debian/files` is the canonical record of
|
||||
/// which binary packages `debian/rules binary` produced, so we retrieve
|
||||
/// exactly those instead of globbing the build root (which would also pick
|
||||
/// up stale files copied alongside the package tree).
|
||||
fn collect_binary_artifacts(
|
||||
ctx: &Arc<Context>,
|
||||
package_dir: &str,
|
||||
build_root: &str,
|
||||
) -> Result<Vec<PathBuf>, Box<dyn Error>> {
|
||||
let files_content = ctx
|
||||
.read_file(&Path::new(package_dir).join("debian/files"))
|
||||
.unwrap_or_default();
|
||||
let files_list = crate::debian::FilesList::parse(&files_content)
|
||||
.map_err(|e| format!("invalid debian/files in {package_dir}: {e}"))?;
|
||||
let upload_dir = Path::new(build_root);
|
||||
let mut artifacts = Vec::new();
|
||||
for entry in files_list.iter() {
|
||||
if matches!(entry.package_type.as_deref(), Some("deb") | Some("udeb")) {
|
||||
artifacts.push(upload_dir.join(&entry.filename));
|
||||
}
|
||||
}
|
||||
Ok(artifacts)
|
||||
}
|
||||
|
||||
/// Generate `.buildinfo` and `.changes` for the finished binary build,
|
||||
@@ -354,9 +399,7 @@ fn generate_upload_metadata(
|
||||
cross: bool,
|
||||
env: &HashMap<String, String>,
|
||||
ctx: &Arc<Context>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
use std::path::Path;
|
||||
|
||||
) -> Result<(PathBuf, PathBuf), Box<dyn Error>> {
|
||||
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)?;
|
||||
@@ -414,12 +457,7 @@ fn generate_upload_metadata(
|
||||
Path::new(build_root),
|
||||
&opts,
|
||||
)?;
|
||||
log::info!(
|
||||
"generated upload metadata: {} and {}",
|
||||
buildinfo.display(),
|
||||
changes.display()
|
||||
);
|
||||
Ok(())
|
||||
Ok((buildinfo, changes))
|
||||
}
|
||||
|
||||
/// Apply quilt patches before building, if the package provides a
|
||||
|
||||
+19
-23
@@ -17,10 +17,13 @@ pub enum BuildMode {
|
||||
|
||||
/// Build package in 'cwd' to a .deb
|
||||
///
|
||||
/// Returns the list of produced .deb files retrieved locally. When `ui` is
|
||||
/// Returns the list of produced artifacts (.deb files plus the upload
|
||||
/// metadata `.buildinfo`/`.changes`) retrieved locally, identified from
|
||||
/// `debian/files` and the native metadata generation rather than by
|
||||
/// globbing the build root (which would surface stale files). When `ui` is
|
||||
/// set, a live view (status bar + rolling log pane) is displayed and all
|
||||
/// subprocess output is captured through it; on failure the widget is cleared
|
||||
/// and a summary of captured errors is printed.
|
||||
/// subprocess output is captured through it; on failure the widget is
|
||||
/// cleared and a summary of captured errors is printed.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn build_binary_package(
|
||||
arch: Option<&str>,
|
||||
@@ -148,8 +151,11 @@ async fn build_binary_package_impl(
|
||||
.ok_or("Cannot find parent directory name")?;
|
||||
let build_root = format!("{}/{}", build_root, parent_dir_name.to_str().unwrap());
|
||||
|
||||
// Run the build using target build mode
|
||||
match mode {
|
||||
// Run the build using target build mode. It returns the exact set of
|
||||
// artifacts produced by this build (binary packages registered in
|
||||
// debian/files plus the generated .buildinfo/.changes), as paths
|
||||
// inside the build context.
|
||||
let remote_files: Vec<PathBuf> = match mode {
|
||||
BuildMode::Local => {
|
||||
local::build(
|
||||
&package,
|
||||
@@ -167,30 +173,20 @@ async fn build_binary_package_impl(
|
||||
)
|
||||
.await?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Retrieve produced artifacts (.deb files plus the upload metadata
|
||||
// (.buildinfo/.changes) generated natively after the build)
|
||||
// Retrieve the produced artifacts (binary packages plus the upload
|
||||
// metadata) to the parent directory.
|
||||
if let Some(u) = ui {
|
||||
u.phase(Phase::RetrievingArtifacts);
|
||||
}
|
||||
let remote_files = build_ctx.list_files(Path::new(&build_root))?;
|
||||
let deb_files: Vec<PathBuf> = remote_files
|
||||
.into_iter()
|
||||
.filter(|f| {
|
||||
f.extension().is_some_and(|ext| {
|
||||
matches!(
|
||||
ext.to_str(),
|
||||
Some("deb") | Some("buildinfo") | Some("changes")
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let total_debs = deb_files.len();
|
||||
let total_debs = remote_files.len();
|
||||
|
||||
let mut artifacts = Vec::with_capacity(total_debs);
|
||||
for (idx, remote_file) in deb_files.iter().enumerate() {
|
||||
let file_name = remote_file.file_name().ok_or("Invalid remote filename")?;
|
||||
for (idx, remote_file) in remote_files.iter().enumerate() {
|
||||
let file_name = remote_file
|
||||
.file_name()
|
||||
.ok_or("Invalid remote filename")?;
|
||||
let local_dest = parent_dir.join(file_name);
|
||||
build_ctx.retrieve_path(remote_file, &local_dest)?;
|
||||
artifacts.push(local_dest);
|
||||
|
||||
Reference in New Issue
Block a user