use std::{fs::File, path::PathBuf};
use bytes::Buf;
use clap::{Parser, Subcommand, ValueEnum};
use shared_buffer::OwnedBuffer;
use webc::migration::are_semantically_equivalent;
#[derive(Debug, PartialEq, Eq, Clone, ValueEnum)]
enum TargetVersion {
V2,
V3,
}
#[derive(Parser)]
#[clap(name = "webc", about = "Client to work with webc files")]
struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Migrate(Migrate),
Validate(Validate),
Compare(Compare),
}
#[derive(Parser)]
struct Migrate {
#[clap(value_parser)]
input: PathBuf,
#[clap(short, long, value_parser)]
output: PathBuf,
#[clap(long, value_enum)]
target: TargetVersion,
}
impl Migrate {
fn run(&self) -> Result<(), anyhow::Error> {
println!(
"Migrating '{}' to '{}' targeting version '{:?}'",
self.input.display(),
self.output.display(),
self.target
);
let webc = OwnedBuffer::from_bytes(std::fs::read(self.input.as_path())?);
let version = webc::detect(webc.clone().reader())?;
if (version == webc::Version::V2 && self.target == TargetVersion::V2)
|| (version == webc::Version::V3 && self.target == TargetVersion::V3)
{
println!("Input file is already {:?}", self.target);
return Ok(());
}
let webc = match self.target {
TargetVersion::V2 => webc::migration::v3_to_v2(webc)?,
TargetVersion::V3 => webc::migration::v2_to_v3(webc)?,
};
std::fs::write(self.output.as_path(), webc)?;
Ok(())
}
}
#[derive(Parser)]
struct Validate {
#[clap(value_parser)]
input: PathBuf,
}
impl Validate {
fn run(&self) -> Result<(), anyhow::Error> {
println!("Validating '{}'...", self.input.display());
webc::Container::from_disk(&self.input)?.validate()?;
Ok(())
}
}
#[derive(Parser)]
struct Compare {
#[clap(value_parser)]
v2: PathBuf,
#[clap(value_parser)]
v3: PathBuf,
}
impl Compare {
fn run(&self) -> Result<(), anyhow::Error> {
let webc_v2 = {
let file = File::open(&self.v2)?;
OwnedBuffer::from_file(&file)?
};
let webc_v3 = {
let file = File::open(&self.v3)?;
OwnedBuffer::from_file(&file)?
};
are_semantically_equivalent(webc_v2, webc_v3)?;
Ok(())
}
}
fn main() -> Result<(), anyhow::Error> {
let cli = Cli::parse();
match cli.command {
Commands::Migrate(migrate) => migrate.run()?,
Commands::Validate(validate) => validate.run()?,
Commands::Compare(compare) => compare.run()?,
}
Ok(())
}