use std::path::PathBuf;
use anyhow::Context;
use dialoguer::console::{style, Emoji};
use indicatif::ProgressBar;
use wasmer_package::utils::from_disk;
#[derive(clap::Parser, Debug)]
pub struct PackageUnpack {
#[clap(short = 'o', long)]
pub out_dir: PathBuf,
#[clap(long)]
pub overwrite: bool,
#[clap(long)]
pub quiet: bool,
pub package_path: PathBuf,
#[clap(short, long, default_value = "package")]
pub format: Format,
}
static PACKAGE_EMOJI: Emoji<'_, '_> = Emoji("📦 ", "");
static EXTRACTED_TO_EMOJI: Emoji<'_, '_> = Emoji("📂 ", "");
#[derive(clap::ValueEnum, Clone, Debug)]
pub enum Format {
Package,
Webc,
}
impl PackageUnpack {
pub(crate) fn execute(&self) -> Result<(), anyhow::Error> {
let pb = if self.quiet {
ProgressBar::hidden()
} else {
ProgressBar::new_spinner()
};
pb.println(format!(
"{} {}Unpacking...",
style("[1/2]").bold().dim(),
PACKAGE_EMOJI
));
let pkg = from_disk(&self.package_path).with_context(|| {
format!(
"could not open package at '{}'",
self.package_path.display()
)
})?;
let outdir = &self.out_dir;
std::fs::create_dir_all(outdir)
.with_context(|| format!("could not create output directory '{}'", outdir.display()))?;
match self.format {
Format::Package => {
wasmer_package::convert::webc_to_package_dir(&pkg, outdir)
.with_context(|| "could not extract package")?;
}
Format::Webc => {
pkg.unpack(outdir, self.overwrite)
.with_context(|| "could not extract package".to_string())?;
}
}
pb.println(format!(
"{} {}Extracted package contents to '{}'",
style("[2/2]").bold().dim(),
EXTRACTED_TO_EMOJI,
self.out_dir.display()
));
pb.finish();
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cmd_package_extract() {
let dir = tempfile::tempdir().unwrap();
let package_path = std::env::var("CARGO_MANIFEST_DIR").map(PathBuf::from).unwrap()
.parent().unwrap()
.parent().unwrap()
.join("tests/integration/cli/tests/webc/hello-0.1.0-665d2ddc-80e6-4845-85d3-4587b1693bb7.webc");
assert!(package_path.is_file());
let cmd = PackageUnpack {
out_dir: dir.path().to_owned(),
overwrite: false,
package_path,
quiet: true,
format: Format::Webc,
};
cmd.execute().unwrap();
let mut items = std::fs::read_dir(dir.path())
.unwrap()
.map(|x| {
x.unwrap()
.path()
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
})
.collect::<Vec<_>>();
items.sort();
assert_eq!(
items,
vec![
"atom".to_string(),
"manifest.json".to_string(),
"metadata".to_string(),
]
);
}
}