xtask: Allow to run VM integration tests without dpkg

Debian packages are just nested archives, where the outer one is ar
and the inner one is lzma2 tarball. Use Rust crates to unpack them.

Co-authored-by: Tamir Duberstein <tamird@gmail.com>
pull/1367/merge
Michal R 4 days ago
parent 03e8487177
commit a7cfc694bd

@ -62,6 +62,7 @@ rust-version = "1.85.0"
# them to do that, but in the meantime we need to be careful. # them to do that, but in the meantime we need to be careful.
[workspace.dependencies] [workspace.dependencies]
anyhow = { version = "1", default-features = false } anyhow = { version = "1", default-features = false }
ar = { version = "0.9", default-features = false }
assert_matches = { version = "1.5.0", default-features = false } assert_matches = { version = "1.5.0", default-features = false }
base64 = { version = "0.22.1", default-features = false } base64 = { version = "0.22.1", default-features = false }
bindgen = { version = "0.72", default-features = false } bindgen = { version = "0.72", default-features = false }

@ -15,6 +15,7 @@ workspace = true
[dependencies] [dependencies]
anyhow = { workspace = true, features = ["std"] } anyhow = { workspace = true, features = ["std"] }
ar = { workspace = true }
aya-tool = { path = "../aya-tool", version = "0.1.0", default-features = false } aya-tool = { path = "../aya-tool", version = "0.1.0", default-features = false }
cargo_metadata = { workspace = true } cargo_metadata = { workspace = true }
clap = { workspace = true, features = ["derive"] } clap = { workspace = true, features = ["derive"] }
@ -30,3 +31,4 @@ syn = { workspace = true }
tar = { workspace = true } tar = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }
walkdir = { workspace = true } walkdir = { workspace = true }
xz2 = { workspace = true }

@ -1,7 +1,7 @@
use std::{ use std::{
ffi::{OsStr, OsString}, ffi::{OsStr, OsString},
fmt::Write as _, fmt::Write as _,
fs::{self, OpenOptions}, fs::{self, File, OpenOptions},
io::{BufRead as _, BufReader, Write as _}, io::{BufRead as _, BufReader, Write as _},
ops::Deref as _, ops::Deref as _,
path::{self, Path, PathBuf}, path::{self, Path, PathBuf},
@ -300,29 +300,37 @@ pub(crate) fn run(opts: Options) -> Result<()> {
fs::create_dir_all(&archive_dir) fs::create_dir_all(&archive_dir)
.with_context(|| format!("failed to create {}", archive_dir.display()))?; .with_context(|| format!("failed to create {}", archive_dir.display()))?;
let mut dpkg = Command::new("dpkg-deb"); let archive_reader = File::open(archive).with_context(|| {
dpkg.arg("--fsys-tarfile") format!("failed to open the deb package {}", archive.display())
.arg(archive)
.stdout(Stdio::piped());
let mut dpkg_child = dpkg
.spawn()
.with_context(|| format!("failed to spawn {dpkg:?}"))?;
let Child { stdout, .. } = &mut dpkg_child;
let stdout = stdout.take().unwrap();
let mut archive_reader = tar::Archive::new(stdout);
archive_reader.unpack(&archive_dir).with_context(|| {
format!(
"failed to unpack archive {} to {}",
archive.display(),
archive_dir.display()
)
})?; })?;
let status = dpkg_child let mut archive_reader = ar::Archive::new(archive_reader);
.wait() // `ar` entries are borrowed from the reader, so the reader
.with_context(|| format!("failed to wait for {dpkg:?}"))?; // cannot implement `Iterator` (because `Iterator::Item` is not
if !status.success() { // a GAT).
bail!("{dpkg:?} exited with {status}"); //
// https://github.com/mdsteele/rust-ar/issues/15
let mut entries = 0;
while let Some(entry) = archive_reader.next_entry() {
let entry = entry.with_context(|| {
format!(
"failed to read an entry of the deb package {}",
archive.display()
)
})?;
if entry.header().identifier() == b"data.tar.xz" {
let entry_reader = xz2::read::XzDecoder::new(entry);
let mut entry_reader = tar::Archive::new(entry_reader);
entry_reader.unpack(&archive_dir).with_context(|| {
format!(
"failed to unpack archive {} to {}",
archive.display(),
archive_dir.display()
)
})?;
entries += 1;
}
} }
assert_eq!(entries, 1);
let mut kernel_images = Vec::new(); let mut kernel_images = Vec::new();
let mut configs = Vec::new(); let mut configs = Vec::new();

Loading…
Cancel
Save