ocilot 0.2.0

cli and library for interacting with OCI registries
Documentation
use clap::Parser;
use ocilot::{
    error,
    layer::Layer,
    models::MediaType,
    repository::Repository,
    uri::{Reference, Uri},
};
use snafu::ensure;

use super::context::Ctx;

#[derive(Parser, Debug)]
#[command(version, about = "Commands to delete objects in a registry", long_about = None)]
pub struct Delete {
    #[clap(subcommand)]
    command: DeleteCommands,
}

#[derive(Parser, Debug)]
pub enum DeleteCommands {
    Blob(DeleteBlob),
    Tag(DeleteTag),
}

impl Delete {
    pub async fn run(&self, _ctx: &Ctx) -> Result<(), error::Error> {
        match &self.command {
            DeleteCommands::Blob(cmd) => cmd.run().await,
            DeleteCommands::Tag(cmd) => cmd.run().await,
        }
    }
}

#[derive(Parser, Debug)]
#[command(version, about = "Delete tag in a repo", long_about = None)]
pub struct DeleteTag {
    url: String,
    #[arg(short, long)]
    insecure: bool,
}

impl DeleteTag {
    pub async fn run(&self) -> Result<(), error::Error> {
        let mut uri = Uri::new(self.url.as_str()).await?;
        uri.set_secure(!self.insecure);
        let repository = Repository::new(uri.registry(), uri.repository());
        match uri.reference() {
            Reference::Digest { .. } => error::DeleteTagDigestSnafu {}.fail(),
            Reference::Tag(tag) => repository.delete_tag(tag.as_str()).await,
        }
    }
}

#[derive(Parser, Debug)]
#[command(version, about = "Delete a blob in a repo", long_about = None)]
pub struct DeleteBlob {
    url: String,
    #[arg(short, long)]
    insecure: bool,
}

impl DeleteBlob {
    pub async fn run(&self) -> Result<(), error::Error> {
        let mut uri = Uri::new(self.url.as_str()).await?;
        uri.set_secure(!self.insecure);
        ensure!(
            matches!(uri.reference(), Reference::Digest { .. }),
            error::DeleteBlobNoDigestSnafu {}
        );
        let digest = uri.reference().to_string();
        let layer = Layer::builder()
            .media_type(MediaType::Manifest)
            .digest(digest)
            .size(0_usize)
            .build();
        layer.delete(&uri).await
    }
}