pull: keep self-prefixed multi-orig components in place
A component tarball whose entries already carry the addon prefix
('www/...' in sqlite3's 'sqlite3_3.53.4.orig-www.tar.xz') extracts
to its end state, but the wrapper detection named it a wrapper and
unwrap_into then cleared the addon target - destroying the component
just extracted into it - and unwrapped the emptied directory into
itself: no 'www' at all, and the deb failed at dh_installdocs over
the missing 'www/*' docs.
dpkg-source unpacks a component into '<root>/<addon>': when the
tarball's own layout already is that, the extraction is the end
state; leave it alone.
This commit is contained in:
+45
-5
@@ -167,19 +167,24 @@ fn component_addon(name: &str) -> Option<&str> {
|
||||
/// `dir/<addon>` for a multi-orig component, replacing any pre-existing
|
||||
/// addon directory.
|
||||
fn unwrap_into(dir: &Path, wrapper: &Path, addon: Option<&str>) -> Result<(), Box<dyn Error>> {
|
||||
let target = match addon {
|
||||
match addon {
|
||||
// dpkg-source unpacks a component into '<root>/<addon>': a tarball
|
||||
// whose entries already carry that prefix ('www/...' in
|
||||
// 'sqlite3_3.53.4.orig-www.tar.xz') extracts to its end state, and
|
||||
// unwrapping it would clear the target and move the cleared
|
||||
// directory into itself.
|
||||
Some(addon) if wrapper.file_name().is_some_and(|name| name == addon) => Ok(()),
|
||||
Some(addon) => {
|
||||
let target = dir.join(addon);
|
||||
if target.is_dir() {
|
||||
std::fs::remove_dir_all(&target)?;
|
||||
}
|
||||
std::fs::create_dir_all(&target)?;
|
||||
target
|
||||
}
|
||||
None => dir.to_path_buf(),
|
||||
};
|
||||
unwrap_wrapper(&target, wrapper)
|
||||
}
|
||||
None => unwrap_wrapper(dir, wrapper),
|
||||
}
|
||||
}
|
||||
|
||||
/// Move the contents of an archive's wrapper directory up into `dir` itself.
|
||||
///
|
||||
@@ -1450,6 +1455,41 @@ mod tests {
|
||||
assert!(!tree.join("dovecot-pigeonhole-2.4.5").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unwrap_component_already_prefixed_with_addon() {
|
||||
// Regression: a component tarball whose entries already carry the
|
||||
// addon prefix ('www/...' in 'sqlite3_3.53.4.orig-www.tar.xz')
|
||||
// extracts to its end state. It used to be treated as a wrapper of
|
||||
// the same name as the addon: unwrap_into cleared the target —
|
||||
// destroying the component just extracted into it — and unwrapped
|
||||
// the emptied directory into itself, leaving no 'www' at all.
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let tar_path = temp_dir.path().join("pkg_1.0.orig-www.tar.gz");
|
||||
std::fs::write(
|
||||
&tar_path,
|
||||
build_tar(&[("www/README", b"docs"), ("www/img/x", b"img")]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let tree = temp_dir.path().join("tree");
|
||||
let extracted = extract_tar_archive(&tar_path, &tree, None, |f| f).unwrap();
|
||||
unwrap_into(
|
||||
&tree,
|
||||
&extracted.wrapper.unwrap(),
|
||||
component_addon("pkg_1.0.orig-www.tar.gz"),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(tree.join("www/README")).unwrap(),
|
||||
"docs"
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(tree.join("www/img/x")).unwrap(),
|
||||
"img"
|
||||
);
|
||||
}
|
||||
|
||||
/// A minimal ustar archive of `pkg-1.0/{Makefile,doc/readme}`,
|
||||
/// bz2-compressed.
|
||||
const BZ2_TAR_WRAPPED: &[u8] = &[
|
||||
|
||||
Reference in New Issue
Block a user