exp: cross #6

This commit is contained in:
2025-12-22 23:08:44 +01:00
parent 63389f0bad
commit 3ecfe6dda2
6 changed files with 101 additions and 16 deletions

View File

@@ -19,7 +19,6 @@ pub fn build_source_package(cwd: Option<&Path>) -> Result<(), Box<dyn Error>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
// We are not testing the build part, as for now this is just a wrapper // We are not testing the build part, as for now this is just a wrapper
// around dpkg-buildpackage. // around dpkg-buildpackage.

View File

@@ -8,8 +8,15 @@ use std::process::Command;
pub struct LocalDriver; pub struct LocalDriver;
impl ContextDriver for LocalDriver { impl ContextDriver for LocalDriver {
fn ensure_available(&self, src: &Path, _dest_root: &str) -> io::Result<PathBuf> { fn ensure_available(&self, src: &Path, dest_root: &str) -> io::Result<PathBuf> {
src.canonicalize() let dest_root_path = Path::new(dest_root);
let dest = dest_root_path.join(src.file_name().unwrap_or(src.as_os_str()));
if src != dest {
// Copy src inside dest_root
self.copy_path(src, &dest)?;
}
dest.canonicalize()
} }
fn create_temp_dir(&self) -> io::Result<String> { fn create_temp_dir(&self) -> io::Result<String> {
@@ -17,8 +24,8 @@ impl ContextDriver for LocalDriver {
Ok(temp_dir.keep().to_string_lossy().to_string()) Ok(temp_dir.keep().to_string_lossy().to_string())
} }
fn retrieve_path(&self, _src: &Path, _dest: &Path) -> io::Result<()> { fn retrieve_path(&self, src: &Path, dest: &Path) -> io::Result<()> {
Ok(()) self.copy_path(src, dest)
} }
fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>> { fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>> {

View File

@@ -103,3 +103,45 @@ fn find_dsc_file(
} }
Ok(dsc_path) Ok(dsc_path)
} }
#[cfg(test)]
mod tests {
async fn test_build_end_to_end(package: &str, series: &str, arch: Option<&str>, cross: bool) {
let temp_dir = tempfile::tempdir().unwrap();
let cwd = temp_dir.path();
crate::pull::pull(
package,
"",
Some(series),
"",
"",
Some("ubuntu"),
Some(cwd),
None,
)
.await
.expect("Cannot pull package");
// Change directory to the package directory
let cwd = cwd.join(package).join(package);
crate::deb::build_binary_package(arch, Some(series), Some(&cwd), cross, None)
.expect("Cannot build binary package (deb)");
// Check that the .deb files are present
let parent_dir = cwd.parent().expect("Cannot find parent directory");
let deb_files = std::fs::read_dir(parent_dir)
.expect("Cannot read build directory")
.filter_map(|entry| entry.ok())
.filter(|entry| entry.path().extension().is_some_and(|ext| ext == "deb"))
.collect::<Vec<_>>();
assert!(!deb_files.is_empty(), "No .deb files found after build");
}
#[tokio::test]
async fn test_deb_hello_ubuntu_end_to_end() {
test_build_end_to_end("hello", "noble", None, false).await;
}
}

View File

@@ -1,21 +1,19 @@
/// Sbuild binary package building /// Sbuild binary package building
/// Call 'sbuild' with the dsc file to build the package with unshare /// Call 'sbuild' with the dsc file to build the package with unshare
use crate::context; use crate::context;
use crate::deb::find_dsc_file;
use std::error::Error; use std::error::Error;
pub fn build( pub fn build(
package: &str, package: &str,
version: &str, _version: &str,
arch: &str, arch: &str,
series: &str, series: &str,
build_root: &str, build_root: &str,
cross: bool, cross: bool,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let dsc_path = find_dsc_file(build_root, package, version)?;
let ctx = context::current(); let ctx = context::current();
let mut cmd = ctx.command("sbuild"); let mut cmd = ctx.command("sbuild");
cmd.current_dir(format!("{}/{}", build_root, package));
cmd.arg("--chroot-mode=unshare"); cmd.arg("--chroot-mode=unshare");
if cross { if cross {
@@ -28,8 +26,7 @@ pub fn build(
// Add output directory argument // Add output directory argument
cmd.arg(format!("--build-dir={}", build_root)); cmd.arg(format!("--build-dir={}", build_root));
let status = cmd.arg(dsc_path).status()?; let status = cmd.status()?;
if !status.success() { if !status.success() {
return Err(format!("sbuild failed with status: {}", status).into()); return Err(format!("sbuild failed with status: {}", status).into());
} }

View File

@@ -57,7 +57,7 @@ fn main() {
.arg(arg!(-a --arch <arch> "Target architecture").required(false)) .arg(arg!(-a --arch <arch> "Target architecture").required(false))
.arg(arg!(--cross "Cross-compile for target architecture (instead of qemu-binfmt)") .arg(arg!(--cross "Cross-compile for target architecture (instead of qemu-binfmt)")
.long_help("Cross-compile for target architecture (instead of using qemu-binfmt)\nNote that most packages cannot be cross-compiled").required(false)) .long_help("Cross-compile for target architecture (instead of using qemu-binfmt)\nNote that most packages cannot be cross-compiled").required(false))
.arg(arg!(--mode "Change build mode [sbuild, local]").required(false) .arg(arg!(--mode <mode> "Change build mode [sbuild, local]").required(false)
.long_help("Change build mode [sbuild, local]\nDefault will chose depending on other parameters, don't provide if unsure")), .long_help("Change build mode [sbuild, local]\nDefault will chose depending on other parameters, don't provide if unsure")),
) )
.subcommand( .subcommand(
@@ -151,8 +151,8 @@ fn main() {
let series = sub_matches.get_one::<String>("series").map(|s| s.as_str()); let series = sub_matches.get_one::<String>("series").map(|s| s.as_str());
let arch = sub_matches.get_one::<String>("arch").map(|s| s.as_str()); let arch = sub_matches.get_one::<String>("arch").map(|s| s.as_str());
let cross = sub_matches.get_one::<bool>("cross").unwrap_or(&false); let cross = sub_matches.get_one::<bool>("cross").unwrap_or(&false);
let mode = sub_matches.get_one::<String>("mode").map(|s| s.as_str()); let mode: Option<&str> = sub_matches.get_one::<String>("mode").map(|s| s.as_str());
let mode = match mode { let mode: Option<pkh::deb::BuildMode> = match mode {
Some("sbuild") => Some(pkh::deb::BuildMode::Sbuild), Some("sbuild") => Some(pkh::deb::BuildMode::Sbuild),
Some("local") => Some(pkh::deb::BuildMode::Local), Some("local") => Some(pkh::deb::BuildMode::Local),
_ => None, _ => None,

View File

@@ -262,6 +262,35 @@ async fn fetch_orig_tarball(
Ok(()) Ok(())
} }
async fn fetch_dsc_file(
info: &PackageInfo,
cwd: Option<&Path>,
progress: ProgressCallback<'_>,
) -> Result<(), Box<dyn Error>> {
let target_dir = cwd.unwrap_or_else(|| Path::new("."));
// Find the dsc file in the file list
let dsc_file = info
.stanza
.files
.iter()
.find(|f| f.name.ends_with(".dsc"))
.ok_or("Could not find .dsc file in package info")?;
let filename = &dsc_file.name;
debug!("Fetching dsc file: {}", filename);
download_file_checksum(
format!("{}/{}", &info.archive_url, filename).as_str(),
&dsc_file.sha256,
target_dir,
progress,
)
.await?;
Ok(())
}
async fn fetch_archive_sources( async fn fetch_archive_sources(
info: &PackageInfo, info: &PackageInfo,
cwd: Option<&Path>, cwd: Option<&Path>,
@@ -399,6 +428,7 @@ pub async fn pull(
0, 0,
); );
} }
clone_repo( clone_repo(
url.as_str(), url.as_str(),
package, package,
@@ -406,6 +436,7 @@ pub async fn pull(
Some(&package_dir), Some(&package_dir),
progress, progress,
)?; )?;
if !package_info.is_native() { if !package_info.is_native() {
if let Some(cb) = progress { if let Some(cb) = progress {
cb("Fetching orig tarball...", "", 0, 0); cb("Fetching orig tarball...", "", 0, 0);
@@ -414,12 +445,17 @@ pub async fn pull(
} else { } else {
debug!("Native package, skipping orig tarball fetch."); debug!("Native package, skipping orig tarball fetch.");
} }
if let Some(cb) = progress {
cb("Fetching dsc file...", "", 0, 0);
}
fetch_dsc_file(&package_info, Some(&package_dir), progress).await?;
} else { } else {
// Fallback to archive fetching // Fallback to archive fetching
if let Some(cb) = progress { if let Some(cb) = progress {
cb("Downloading from archive...", "", 0, 0); cb("Downloading from archive...", "", 0, 0);
} }
fetch_archive_sources(&package_info, Some(cwd.unwrap_or(Path::new("."))), progress).await?; fetch_archive_sources(&package_info, Some(&package_dir), progress).await?;
} }
Ok(package_info) Ok(package_info)
@@ -482,16 +518,20 @@ mod tests {
// Check for orig tarball in package dir // Check for orig tarball in package dir
let mut found_tarball = false; let mut found_tarball = false;
let mut found_dsc = false;
for entry in std::fs::read_dir(package_dir).unwrap() { for entry in std::fs::read_dir(package_dir).unwrap() {
let entry = entry.unwrap(); let entry = entry.unwrap();
let name = entry.file_name().to_string_lossy().to_string(); let name = entry.file_name().to_string_lossy().to_string();
if name.contains(".orig.tar.") { if name.contains(".orig.tar.") {
found_tarball = true; found_tarball = true;
break; }
if name.ends_with(".dsc") {
found_dsc = true;
} }
} }
assert!(found_tarball, "Orig tarball not found in package dir"); assert!(found_tarball, "Orig tarball not found in package dir");
assert!(found_dsc, "DSC file not found in package dir");
} }
#[tokio::test] #[tokio::test]