ocilot 0.2.0

cli and library for interacting with OCI registries
Documentation
use clap::{Parser, ValueEnum};
use ocilot::index::Index;
use ocilot::uri::Uri;
use ocilot::{Result, error};
use snafu::{OptionExt, ResultExt};
use std::path::PathBuf;

use super::context::Ctx;

/// Pull remote images and store locally as an archive.
#[derive(Parser, Debug)]
#[command(version, about = "Pull remote images by reference and store their contents locally as an archive", long_about = None)]
pub struct Pull {
    url: String,
    output: PathBuf,
    #[arg(short, long)]
    insecure: bool,
    #[arg(short, long)]
    platform: Option<String>,
    #[arg(short, long)]
    format: Format,
}

/// Output archive format.
#[derive(Default, PartialEq, Eq, Debug, Clone, ValueEnum)]
enum Format {
    #[default]
    Tarball,
    Oci,
}

impl Pull {
    pub async fn run(&self, ctx: &mut Ctx) -> Result<()> {
        let mut uri = Uri::new(self.url.as_str()).await?;
        uri.set_secure(!self.insecure);
        let index = Index::fetch(&uri).await?;
        let platform = self.platform.clone().map(|x| x.parse()).transpose()?;

        let output = tokio::fs::File::create(&self.output)
            .await
            .context(error::FileSnafu)?;
        let progress = ctx.progress();
        match self.format {
            Format::Tarball => {
                let image = index
                    .fetch_image(&uri, platform.clone())
                    .await?
                    .context(error::ImageNotFoundSnafu { uri: uri.clone() })?;
                image.to_tarball(&uri, output, progress).await?
            }
            Format::Oci => index.to_oci(&uri, platform, output, progress).await?,
        }

        Ok(())
    }
}