use async_trait::async_trait;
use clap::{Arg, Command, arg};
use std::collections::HashMap;
use liboxen::model::LocalRepository;
use liboxen::repositories;
use crate::cli_error::UnknownSubcommand;
use crate::cmd::{RunCmd, Runners};
pub const NAME: &str = "schemas";
pub mod add;
pub use add::SchemasAddCmd;
pub mod list;
pub use list::SchemasListCmd;
pub mod rm;
pub use rm::SchemasRmCmd;
pub mod show;
pub use show::SchemasShowCmd;
pub struct SchemasCmd;
#[async_trait]
impl RunCmd for SchemasCmd {
fn name(&self) -> &str {
NAME
}
fn args(&self) -> Command {
let mut command = Command::new(NAME)
.about("Manage schemas that are created from committing tabular data")
.arg(arg!([SCHEMA_REF] "Name, hash, or path of the schema you want to view in more detail."))
.arg(
Arg::new("staged")
.long("staged")
.help("Show the staged schema")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("flatten")
.long("flatten")
.help("Print the schema in a flattened format")
.action(clap::ArgAction::SetTrue),
)
;
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: "schemas",
name: name.to_string(),
})?;
};
tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(cmd.run(sub_matches))
})?;
} else if let Some(schema_ref) = args.get_one::<String>("SCHEMA_REF") {
let repository = LocalRepository::from_current_dir()?;
let staged = args.get_flag("staged");
let verbose = !args.get_flag("flatten"); let val =
repositories::data_frames::schemas::show(&repository, schema_ref, staged, verbose)?;
println!("{val}");
} else {
let Some(cmd) = sub_commands.get("list") else {
return Err(UnknownSubcommand {
parent: "schemas",
name: "list".to_string(),
})?;
};
tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(cmd.run(args))
})?;
}
Ok(())
}
}
impl SchemasCmd {
fn get_subcommands(&self) -> Runners {
let commands: [Box<dyn RunCmd>; 4] = [
Box::new(SchemasAddCmd),
Box::new(SchemasListCmd),
Box::new(SchemasRmCmd),
Box::new(SchemasShowCmd),
];
let mut runners = HashMap::new();
for cmd in commands {
runners.insert(cmd.name().to_string(), cmd);
}
runners
}
}