pull: fetch every component tarball of multi-orig packages
Sources listed with "3.0 (quilt)" extra components (node-jest, php-*, ...) carry one tarball per bundled module next to the main orig, named <package>_<uver>.orig-<component>.tar.<ext>. fetch_orig_tarball picked the single file matching ".orig.tar." — which cannot even match the component naming — so a git pull only fetched the main orig. The later dpkg-source -b quilt verification then failed with "can't find file to patch" on the first patch touching a component directory. Select the files with the existing build::changes::is_orig_tarball helper (mirroring dpkg's \.orig(-.+)?\.tar\. strip pattern) and fetch all of them, pristine-tar checkout first with a checksummed archive download fallback, per tarball. The end-to-end test now asserts every stanza-listed orig lands in the package dir instead of just any *.orig.tar.* file, and gains a node-jest (trixie, 24 components) regression case. Verified live: pkh pull node-jest -d debian fetches all 15 origs of the sid ds7 repack, and dpkg-source -b builds the debian.tar.xz and dsc without touching the series.
This commit is contained in:
+66
-42
@@ -452,50 +452,57 @@ async fn fetch_orig_tarball(
|
|||||||
Path::new(&info.stanza.package).to_path_buf()
|
Path::new(&info.stanza.package).to_path_buf()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find the orig tarball in the file list
|
// Upstream tarballs in the file list: the main orig tarball plus, for
|
||||||
// Usually ends with .orig.tar.gz or .orig.tar.xz
|
// multi-orig ("3.0 (quilt)" extra-component) sources, one component
|
||||||
let orig_file = info
|
// tarball per bundled module (`*.orig-<component>.tar.<ext>`). dpkg-source
|
||||||
|
// unpacks all of them side by side, so a git pull must fetch them all.
|
||||||
|
let orig_files: Vec<_> = info
|
||||||
.stanza
|
.stanza
|
||||||
.files
|
.files
|
||||||
.iter()
|
.iter()
|
||||||
.find(|f| f.name.contains(".orig.tar."))
|
.filter(|f| crate::build::changes::is_orig_tarball(&f.name))
|
||||||
.ok_or_else(|| {
|
.collect();
|
||||||
format!(
|
if orig_files.is_empty() {
|
||||||
"Could not find orig tarball in file list for package '{}'. \
|
return Err(format!(
|
||||||
Available files: {:?}",
|
"Could not find orig tarball in file list for package '{}'. \
|
||||||
info.stanza.package,
|
Available files: {:?}",
|
||||||
info.stanza
|
info.stanza.package,
|
||||||
.files
|
info.stanza
|
||||||
.iter()
|
.files
|
||||||
.map(|f| &f.name)
|
.iter()
|
||||||
.collect::<Vec<_>>()
|
.map(|f| &f.name)
|
||||||
)
|
.collect::<Vec<_>>()
|
||||||
})?;
|
)
|
||||||
let filename = &orig_file.name;
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Try executing pristine-tar
|
// 1. Try executing pristine-tar
|
||||||
|
|
||||||
// Setup pristine-tar branch if needed (by tracking remote branch)
|
// Setup pristine-tar branch if needed (by tracking remote branch)
|
||||||
let _ = setup_pristine_tar_branch(&package_dir, info.dist.as_str());
|
let _ = setup_pristine_tar_branch(&package_dir, info.dist.as_str());
|
||||||
|
|
||||||
if let Err(e) = checkout_pristine_tar(&package_dir, filename.as_str()) {
|
for orig_file in orig_files {
|
||||||
debug!(
|
let filename = &orig_file.name;
|
||||||
"pristine-tar failed: {}. Falling back to archive download.",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. Fallback to archive download
|
if let Err(e) = checkout_pristine_tar(&package_dir, filename.as_str()) {
|
||||||
// We download to the parent directory of the package repo (which is standard for build tools)
|
debug!(
|
||||||
// or the current directory if cwd is None (which effectively is the parent of the package dir)
|
"pristine-tar failed: {}. Falling back to archive download.",
|
||||||
let target_dir = cwd.unwrap_or_else(|| Path::new("."));
|
e
|
||||||
download_file_checksum(
|
);
|
||||||
format!("{}/{}", info.archive_url, filename).as_str(),
|
|
||||||
&orig_file.checksum,
|
// 2. Fallback to archive download
|
||||||
orig_file.checksum_algo,
|
// We download to the parent directory of the package repo (which is standard for build tools)
|
||||||
target_dir,
|
// or the current directory if cwd is None (which effectively is the parent of the package dir)
|
||||||
progress,
|
let target_dir = cwd.unwrap_or_else(|| Path::new("."));
|
||||||
)
|
download_file_checksum(
|
||||||
.await?;
|
format!("{}/{}", info.archive_url, filename).as_str(),
|
||||||
|
&orig_file.checksum,
|
||||||
|
orig_file.checksum_algo,
|
||||||
|
target_dir,
|
||||||
|
progress,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -844,23 +851,29 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for orig tarball in package dir (only for non-native packages)
|
// Check for the orig tarballs in the package dir (only for non-native
|
||||||
let mut found_tarball = false;
|
// packages): every orig listed in the stanza must be present, including
|
||||||
|
// the component tarballs of multi-orig packages (dpkg-source needs them
|
||||||
|
// all to unpack the merged upstream tree)
|
||||||
let mut found_dsc = 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.") {
|
|
||||||
found_tarball = true;
|
|
||||||
}
|
|
||||||
if name.ends_with(".dsc") {
|
if name.ends_with(".dsc") {
|
||||||
found_dsc = true;
|
found_dsc = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only check for orig tarball if the package is not native
|
|
||||||
if !info.is_native() {
|
if !info.is_native() {
|
||||||
assert!(found_tarball, "Orig tarball not found in package dir");
|
for file in &info.stanza.files {
|
||||||
|
if crate::build::changes::is_orig_tarball(&file.name) {
|
||||||
|
assert!(
|
||||||
|
package_dir.join(&file.name).exists(),
|
||||||
|
"Orig tarball '{}' not found in package dir",
|
||||||
|
file.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert!(found_dsc, "DSC file not found in package dir");
|
assert!(found_dsc, "DSC file not found in package dir");
|
||||||
}
|
}
|
||||||
@@ -914,6 +927,17 @@ mod tests {
|
|||||||
test_pull_package_end_to_end("paraview", Some("noble"), None, None).await;
|
test_pull_package_end_to_end("paraview", Some("noble"), None, None).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Multi-orig ("3.0 (quilt)" extra component) regression test: node-jest
|
||||||
|
/// ships its bundled modules as separate `*.orig-<component>.tar.xz`
|
||||||
|
/// tarballs next to the main orig. The git pull path must fetch every
|
||||||
|
/// component, or the later `dpkg-source -b` quilt verification fails
|
||||||
|
/// with "can't find file to patch" on the first patch touching a
|
||||||
|
/// component directory.
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_pull_node_jest_debian_end_to_end() {
|
||||||
|
test_pull_package_end_to_end("node-jest", Some("trixie"), None, None).await;
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a minimal uncompressed ustar archive from (name, data) entries.
|
/// Build a minimal uncompressed ustar archive from (name, data) entries.
|
||||||
///
|
///
|
||||||
/// Raw header blocks are crafted instead of using `tar::Builder` because
|
/// Raw header blocks are crafted instead of using `tar::Builder` because
|
||||||
|
|||||||
Reference in New Issue
Block a user