diff --git a/src/build.rs b/src/build.rs index 2f69660..d5889a7 100644 --- a/src/build.rs +++ b/src/build.rs @@ -19,7 +19,6 @@ pub fn build_source_package(cwd: Option<&Path>) -> Result<(), Box> { #[cfg(test)] mod tests { - use super::*; // We are not testing the build part, as for now this is just a wrapper // around dpkg-buildpackage. diff --git a/src/context/local.rs b/src/context/local.rs index 8fbe9e8..ac118b4 100644 --- a/src/context/local.rs +++ b/src/context/local.rs @@ -8,8 +8,15 @@ use std::process::Command; pub struct LocalDriver; impl ContextDriver for LocalDriver { - fn ensure_available(&self, src: &Path, _dest_root: &str) -> io::Result { - src.canonicalize() + fn ensure_available(&self, src: &Path, dest_root: &str) -> io::Result { + 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 { @@ -17,8 +24,8 @@ impl ContextDriver for LocalDriver { Ok(temp_dir.keep().to_string_lossy().to_string()) } - fn retrieve_path(&self, _src: &Path, _dest: &Path) -> io::Result<()> { - Ok(()) + fn retrieve_path(&self, src: &Path, dest: &Path) -> io::Result<()> { + self.copy_path(src, dest) } fn list_files(&self, path: &Path) -> io::Result> { diff --git a/src/deb/mod.rs b/src/deb/mod.rs index d5a53d0..c41e333 100644 --- a/src/deb/mod.rs +++ b/src/deb/mod.rs @@ -103,3 +103,45 @@ fn find_dsc_file( } 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::>(); + + 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; + } +} diff --git a/src/deb/sbuild.rs b/src/deb/sbuild.rs index 89bf9f0..8b1bacf 100644 --- a/src/deb/sbuild.rs +++ b/src/deb/sbuild.rs @@ -1,21 +1,19 @@ /// Sbuild binary package building /// Call 'sbuild' with the dsc file to build the package with unshare use crate::context; -use crate::deb::find_dsc_file; use std::error::Error; pub fn build( package: &str, - version: &str, + _version: &str, arch: &str, series: &str, build_root: &str, cross: bool, ) -> Result<(), Box> { - let dsc_path = find_dsc_file(build_root, package, version)?; - let ctx = context::current(); let mut cmd = ctx.command("sbuild"); + cmd.current_dir(format!("{}/{}", build_root, package)); cmd.arg("--chroot-mode=unshare"); if cross { @@ -28,8 +26,7 @@ pub fn build( // Add output directory argument cmd.arg(format!("--build-dir={}", build_root)); - let status = cmd.arg(dsc_path).status()?; - + let status = cmd.status()?; if !status.success() { return Err(format!("sbuild failed with status: {}", status).into()); } diff --git a/src/main.rs b/src/main.rs index 5f31ef7..cbd1f41 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,7 +57,7 @@ fn main() { .arg(arg!(-a --arch "Target architecture").required(false)) .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)) - .arg(arg!(--mode "Change build mode [sbuild, local]").required(false) + .arg(arg!(--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")), ) .subcommand( @@ -151,8 +151,8 @@ fn main() { let series = sub_matches.get_one::("series").map(|s| s.as_str()); let arch = sub_matches.get_one::("arch").map(|s| s.as_str()); let cross = sub_matches.get_one::("cross").unwrap_or(&false); - let mode = sub_matches.get_one::("mode").map(|s| s.as_str()); - let mode = match mode { + let mode: Option<&str> = sub_matches.get_one::("mode").map(|s| s.as_str()); + let mode: Option = match mode { Some("sbuild") => Some(pkh::deb::BuildMode::Sbuild), Some("local") => Some(pkh::deb::BuildMode::Local), _ => None, diff --git a/src/pull.rs b/src/pull.rs index 3cb0cff..459cda9 100644 --- a/src/pull.rs +++ b/src/pull.rs @@ -262,6 +262,35 @@ async fn fetch_orig_tarball( Ok(()) } +async fn fetch_dsc_file( + info: &PackageInfo, + cwd: Option<&Path>, + progress: ProgressCallback<'_>, +) -> Result<(), Box> { + 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( info: &PackageInfo, cwd: Option<&Path>, @@ -399,6 +428,7 @@ pub async fn pull( 0, ); } + clone_repo( url.as_str(), package, @@ -406,6 +436,7 @@ pub async fn pull( Some(&package_dir), progress, )?; + if !package_info.is_native() { if let Some(cb) = progress { cb("Fetching orig tarball...", "", 0, 0); @@ -414,12 +445,17 @@ pub async fn pull( } else { 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 { // Fallback to archive fetching if let Some(cb) = progress { 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) @@ -482,16 +518,20 @@ mod tests { // Check for orig tarball in package dir let mut found_tarball = false; + let mut found_dsc = false; for entry in std::fs::read_dir(package_dir).unwrap() { let entry = entry.unwrap(); let name = entry.file_name().to_string_lossy().to_string(); if name.contains(".orig.tar.") { found_tarball = true; - break; + } + if name.ends_with(".dsc") { + found_dsc = true; } } assert!(found_tarball, "Orig tarball not found in package dir"); + assert!(found_dsc, "DSC file not found in package dir"); } #[tokio::test]