oxen-cli 0.50.6

Oxen is a fast, unstructured data version control, to help version large machine learning datasets written in Rust.
pub mod add;
pub use add::WorkspaceAddCmd;

pub mod clear;
pub use clear::WorkspaceClearCmd;

pub mod create;
pub use create::WorkspaceCreateCmd;

pub mod commit;
pub use commit::WorkspaceCommitCmd;

pub mod diff;
pub use diff::WorkspaceDiffCmd;

pub mod df;
pub use df::WorkspaceDfCmd;

pub mod delete;
pub use delete::WorkspaceDeleteCmd;

pub mod download;
pub use download::WorkspaceDownloadCmd;

pub mod list;
pub use list::WorkspaceListCmd;

pub mod restore;
pub use restore::WorkspaceRestoreCmd;

pub mod rm;
pub use rm::WorkspaceRmCmd;

pub mod status;
pub use status::WorkspaceStatusCmd;

use async_trait::async_trait;
use clap::Command;

use std::collections::HashMap;

use crate::{
    cli_error::UnknownSubcommand,
    cmd::{RunCmd, Runners},
};
pub const NAME: &str = "workspace";
pub struct WorkspaceCmd;

#[async_trait]
impl RunCmd for WorkspaceCmd {
    fn name(&self) -> &str {
        NAME
    }

    fn args(&self) -> Command {
        // Setups the CLI args for the command
        let mut command = Command::new(NAME)
            .about("Manage workspaces")
            .subcommand_required(true)
            .arg_required_else_help(true);

        // These are all the subcommands for the schemas command
        // including `create`, `add`, `rm`, `commit`, and `status`
        let sub_commands = Self::get_subcommands();
        for cmd in sub_commands.values() {
            command = command.subcommand(cmd.args());
        }
        command
    }

    async fn run(&self, args: &clap::ArgMatches) -> Result<(), anyhow::Error> {
        let sub_commands = Self::get_subcommands();
        if let Some((name, sub_matches)) = args.subcommand() {
            let Some(cmd) = sub_commands.get(name) else {
                return Err(UnknownSubcommand {
                    parent: "workspace",
                    name: name.to_string(),
                })?;
            };

            // Calling await within an await is making it complain?
            tokio::task::block_in_place(|| {
                tokio::runtime::Handle::current().block_on(cmd.run(sub_matches))
            })?;
        }
        Ok(())
    }
}

impl WorkspaceCmd {
    fn get_subcommands() -> Runners {
        let commands: [Box<dyn RunCmd>; 12] = [
            Box::new(WorkspaceAddCmd),
            Box::new(WorkspaceClearCmd),
            Box::new(WorkspaceCommitCmd),
            Box::new(WorkspaceCreateCmd),
            Box::new(WorkspaceDfCmd),
            Box::new(WorkspaceDiffCmd),
            Box::new(WorkspaceDeleteCmd),
            Box::new(WorkspaceListCmd),
            Box::new(WorkspaceRmCmd),
            Box::new(WorkspaceRestoreCmd),
            Box::new(WorkspaceStatusCmd),
            Box::new(WorkspaceDownloadCmd),
        ];
        let mut runners = HashMap::new();
        for cmd in commands {
            runners.insert(cmd.name().to_string(), cmd);
        }
        runners
    }

    pub async fn run_subcommands(
        name: &str,
        sub_matches: &clap::ArgMatches,
    ) -> Result<(), anyhow::Error> {
        let sub_commands = Self::get_subcommands();
        let Some(cmd) = sub_commands.get(name) else {
            return Err(UnknownSubcommand {
                parent: "workspace",
                name: name.to_string(),
            })?;
        };

        tokio::task::block_in_place(|| {
            tokio::runtime::Handle::current().block_on(cmd.run(sub_matches))
        })?;

        Ok(())
    }
}