From 54ec3d6d2b016054430f02650a2c0b85e8ef2f7e Mon Sep 17 00:00:00 2001 From: Valentin Haudiquet Date: Thu, 22 Jan 2026 00:05:19 +0100 Subject: [PATCH] pull: allow applying diff.gz from archive download --- src/pull.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/src/pull.rs b/src/pull.rs index 12049dd..fee4edb 100644 --- a/src/pull.rs +++ b/src/pull.rs @@ -431,6 +431,43 @@ async fn fetch_archive_sources( } } } + + // Extract and apply .diff.gz if present (old packages) + if file.name.ends_with(".diff.gz") { + let diff_gz_path = package_dir.join(&file.name); + let source_dir = package_dir.join(&info.stanza.package); + + // Create the .diff file path by replacing .gz with empty string + let diff_path = diff_gz_path.with_extension(""); + + // Decompress the .diff.gz file directly to .diff + let input_file = File::open(&diff_gz_path)?; + let mut decoder = GzDecoder::new(input_file); + let mut output_file = File::create(&diff_path)?; + + std::io::copy(&mut decoder, &mut output_file)?; + + // Use relative path for the diff file (it's in the parent directory) + let relative_diff_path = format!("../{}", diff_path.file_name().unwrap().to_string_lossy()); + + // Apply the patch using the patch command with relative path + let output = Command::new("patch") + .current_dir(&source_dir) + .arg("-p1") + .arg("--input") + .arg(&relative_diff_path) + .output()?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("Failed to apply patch: {}\n{}", diff_path.display(), stderr).into()); + } + + debug!("Successfully applied patch: {}", diff_path.display()); + + // Clean up the extracted .diff file + std::fs::remove_file(&diff_path)?; + } } Ok(()) @@ -533,7 +570,12 @@ pub async fn pull( mod tests { use super::*; - async fn test_pull_package_end_to_end(package: &str, series: Option<&str>, dist: Option<&str>) { + async fn test_pull_package_end_to_end( + package: &str, + series: Option<&str>, + dist: Option<&str>, + archive: Option, + ) { // This test verifies that 'pkh pull' clones the repo and fetches the tarball. // For determinism, we require for tests that either a distro or series is specified, @@ -548,7 +590,9 @@ mod tests { let info = crate::package_info::lookup(package, None, series, "", dist, None) .await .unwrap(); - pull(&info, Some(cwd), None, false).await.unwrap(); + pull(&info, Some(cwd), None, archive.unwrap_or(false)) + .await + .unwrap(); let package_dir = cwd.join(package); assert!(package_dir.exists()); @@ -608,33 +652,39 @@ mod tests { #[tokio::test] async fn test_pull_hello_ubuntu_end_to_end() { - test_pull_package_end_to_end("hello", Some("noble"), None).await; + test_pull_package_end_to_end("hello", Some("noble"), None, None).await; } #[tokio::test] async fn test_pull_hello_debian_end_to_end() { - test_pull_package_end_to_end("hello", Some("bookworm"), None).await; + test_pull_package_end_to_end("hello", Some("bookworm"), None, None).await; + } + + /// Specific test for a package using a .diff.gz, instead of .debian and .orig + #[tokio::test] + async fn test_pull_linux_riscv_ubuntu_end_to_end() { + test_pull_package_end_to_end("linux-riscv", Some("noble"), None, Some(true)).await; } #[tokio::test] async fn test_pull_2048_universe_ubuntu_end_to_end() { - test_pull_package_end_to_end("2048", Some("noble"), None).await; + test_pull_package_end_to_end("2048", Some("noble"), None, None).await; } #[tokio::test] async fn test_pull_1oom_contrib_debian_end_to_end() { - test_pull_package_end_to_end("1oom", Some("trixie"), None).await; + test_pull_package_end_to_end("1oom", Some("trixie"), None, None).await; } #[tokio::test] async fn test_pull_agg_svn_fallback_ok() { - test_pull_package_end_to_end("agg", Some("trixie"), None).await; + test_pull_package_end_to_end("agg", Some("trixie"), None, None).await; } #[tokio::test] async fn test_pull_hello_debian_latest_end_to_end() { - test_pull_package_end_to_end("hello", None, Some("debian")).await; + test_pull_package_end_to_end("hello", None, Some("debian"), None).await; } #[tokio::test] async fn test_pull_hello_ubuntu_latest_end_to_end() { - test_pull_package_end_to_end("hello", None, Some("ubuntu")).await; + test_pull_package_end_to_end("hello", None, Some("ubuntu"), None).await; } }