webc 6.0.0-alpha2

WebContainer implementation for wapm.io
Documentation
use std::error::Error;
use std::path::PathBuf;

use bytes::Buf;
use clap::{Parser, Subcommand, ValueEnum};

use shared_buffer::OwnedBuffer;

#[derive(Debug, PartialEq, Eq, Clone, ValueEnum)]
enum TargetVersion {
    V2,
    V3,
}

/// Main CLI entry point
#[derive(Parser)]
#[clap(name = "webc", about = "Client to work with webc files")]
struct Cli {
    #[clap(subcommand)]
    command: Commands,
}

/// Subcommands for the CLI
#[derive(Subcommand)]
enum Commands {
    Migrate(Migrate),
}

/// Migrates webc from one format to another
#[derive(Parser)]
struct Migrate {
    /// Input file to migrate
    #[clap(value_parser)]
    input: PathBuf,

    /// Output file to write the results to
    #[clap(short, long, value_parser)]
    output: PathBuf,

    /// Target version to migrate to
    #[clap(long, value_enum)]
    target: TargetVersion,
}

impl Migrate {
    fn run(&self) -> Result<(), Box<dyn 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(())
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    let cli = Cli::parse();

    match cli.command {
        Commands::Migrate(migrate) => migrate.run()?,
    }

    Ok(())
}