quilt-rs 0.5.7

Rust library for accessing Quilt data packages.
Documentation
use clap::{Parser, Subcommand};
use std::path::Path;

mod browse;
mod install;
mod list;
mod model;
mod output;
mod package;
mod uninstall;

use model::Model;
use output::print;

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Args {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Browse remote manifest
    Browse {
        #[arg(value_name = "PKG_URI")]
        uri: String,
    },
    /// Install package locally
    Install {
        /// Source URI for the package.
        /// Ex. quilt+s3://bucket#package=foo/bar
        #[arg(value_name = "PKG_URI")]
        uri: String,
        /// Path to local domain. Should be absolute path when installing paths
        #[arg(short, long)]
        domain: String,
        /// Namespace for the package, ex. foo/bar.
        #[arg(short, long)]
        namespace: Option<String>,
        /// Logical key relative to the root of the package to be installed locally.
        /// You can provide multiple paths.
        #[arg(short, long)]
        path: Option<Vec<String>>,
    },
    /// List installed packages
    List {
        /// Path to local domain
        #[arg(short, long)]
        domain: String,
    },
    /// Create and install manifest to S3
    Package {
        /// Source URI for the package.
        /// Ex. s3://bucket/s3/prefix
        #[arg(value_name = "S3_URI")]
        uri: String,
        /// quilt+s3 URI for new package
        #[arg(short, long, value_name = "PKG_URI")]
        target: String,
    },
    /// Uninstall package from local domain
    Uninstall {
        /// Namespace of the package to uninstall.
        /// Ex. foo/bar
        #[arg(short, long)]
        namespace: String,
        /// Path to local domain
        #[arg(short, long)]
        domain: String,
    },
}

pub async fn init() -> Result<(), std::io::Error> {
    let args = Args::parse();

    match args.command {
        Commands::Browse { uri } => {
            let (m, temp_dir) = Model::from_temp_dir()?;
            let args = browse::Input { uri };
            tracing::info!("Browsing {:?} using {:?}", args, temp_dir);
            print(browse::command(m, args).await);
            Ok(())
        }
        Commands::Install {
            path,
            domain,
            namespace,
            uri,
        } => {
            let root = Path::new(&domain).to_path_buf();
            let m = Model::from(root);
            let args = install::Input {
                namespace,
                paths: path,
                uri,
            };
            tracing::info!("Installing {:?}", args);
            print(install::command(m, args).await);
            Ok(())
        }
        Commands::List { domain } => {
            // TODO: validate domain exists
            let root = Path::new(&domain).to_path_buf();
            let m = Model::from(root);
            tracing::info!("Listing installed packages");
            print(list::command(m).await);
            Ok(())
        }
        Commands::Package { uri, target } => {
            let (m, temp_dir) = Model::from_temp_dir()?;
            let args = package::Input { target, uri };
            tracing::info!("Packaging {:?} using {:?}", args, temp_dir);
            print(package::command(m, args).await);
            Ok(())
        }
        Commands::Uninstall { domain, namespace } => {
            // TODO: validate domain exists
            let root = Path::new(&domain).to_path_buf();
            let m = Model::from(root);
            let args = uninstall::Input { namespace };
            tracing::info!("Uninstalling {:?}", args);
            print(uninstall::command(m, args).await);
            Ok(())
        }
    }
}

#[derive(thiserror::Error, Debug)]
enum Error {
    #[error("quilt_rs error: {0}")]
    Quilt(quilt_rs::Error),
}

impl From<quilt_rs::Error> for Error {
    fn from(err: quilt_rs::Error) -> Error {
        Error::Quilt(err)
    }
}