diff --git a/rfs/src/config.rs b/rfs/src/config.rs index 648578d..62eaf4d 100644 --- a/rfs/src/config.rs +++ b/rfs/src/config.rs @@ -1,27 +1,53 @@ use crate::{ fungi::{meta::Tag, Reader, Result, Writer}, - store::Store, + store::{self, Store}, }; -/// configure FL with the provided tags/stores and print the result tags/stores -pub async fn config( - writer: Writer, - reader: Reader, - store: S, - tags: Vec<(String, String)>, - stores: Vec, - replace: bool, -) -> Result<()> { - if !tags.is_empty() && replace { - writer.delete_tags().await?; +pub async fn tag_list(reader: Reader) -> Result<()> { + let tags = reader.tags().await?; + if !tags.is_empty() { + println!("tags:"); } - if !stores.is_empty() && replace { - writer.delete_routes().await?; + for (key, value) in tags { + println!("\t{}={}", key, value); } + Ok(()) +} + +pub async fn tag_add(writer: Writer, tags: Vec<(String, String)>) -> Result<()> { for (key, value) in tags { writer.tag(Tag::Custom(key.as_str()), value).await?; } + Ok(()) +} + +pub async fn tag_delete(writer: Writer, keys: Vec, all: bool) -> Result<()> { + if all { + writer.delete_tags().await?; + return Ok(()); + } + for key in keys { + writer.delete_tag(Tag::Custom(key.as_str())).await?; + } + Ok(()) +} +pub async fn store_list(reader: Reader) -> Result<()> { + let routes = reader.routes().await?; + if !routes.is_empty() { + println!("routes:") + } + for route in routes { + println!( + "\trange:[{}-{}] store:{}", + route.start, route.end, route.url + ); + } + Ok(()) +} + +pub async fn store_add(writer: Writer, stores: Vec) -> Result<()> { + let store = store::parse_router(stores.as_slice()).await?; for route in store.routes() { writer .route( @@ -31,22 +57,16 @@ pub async fn config( ) .await?; } + Ok(()) +} - let tags = reader.tags().await?; - if !tags.is_empty() { - println!("tags:"); - } - for (key, value) in tags { - println!("\t{}={}", key, value); - } - - let routes = reader.routes().await?; - if !routes.is_empty() { - println!("routes:") +pub async fn store_delete(writer: Writer, stores: Vec, all: bool) -> Result<()> { + if all { + writer.delete_routes().await?; + return Ok(()); } - for route in routes { - println!("\trange:[{}-{}] store:{}", route.start, route.end, route.url); + for store in stores { + writer.delete_route(store).await?; } - Ok(()) } diff --git a/rfs/src/fungi/meta.rs b/rfs/src/fungi/meta.rs index 25113c4..bc251cf 100644 --- a/rfs/src/fungi/meta.rs +++ b/rfs/src/fungi/meta.rs @@ -426,6 +426,22 @@ impl Writer { .await?; Ok(()) } + pub async fn delete_tag(&self, tag: Tag<'_>) -> Result<()> { + sqlx::query("delete from tag where key = ?;") + .bind(tag.key()) + .execute(&self.pool) + .await?; + Ok(()) + } + + pub async fn delete_route>(&self, url: U) -> Result<()> { + sqlx::query("delete from route where url = ?;") + .bind(url.as_ref()) + .execute(&self.pool) + .await?; + Ok(()) + } + pub async fn delete_tags(&self) -> Result<()> { sqlx::query("delete from tag;").execute(&self.pool).await?; Ok(()) diff --git a/rfs/src/lib.rs b/rfs/src/lib.rs index 68453ab..77f8e30 100644 --- a/rfs/src/lib.rs +++ b/rfs/src/lib.rs @@ -9,8 +9,7 @@ mod pack; pub use pack::pack; mod unpack; pub use unpack::unpack; -mod config; -pub use config::config; +pub mod config; const PARALLEL_UPLOAD: usize = 10; // number of files we can upload in parallel diff --git a/rfs/src/main.rs b/rfs/src/main.rs index 9c8e9fc..a605f7d 100644 --- a/rfs/src/main.rs +++ b/rfs/src/main.rs @@ -8,9 +8,9 @@ use std::io::Read; use anyhow::{Context, Result}; use clap::{ArgAction, Args, Parser, Subcommand}; -use rfs::cache; use rfs::fungi; use rfs::store::{self, Router, Stores}; +use rfs::{cache, config}; mod fs; /// mount flists @@ -103,18 +103,64 @@ struct ConfigOptions { #[clap(short, long)] meta: String, + #[command(subcommand)] + command: ConfigCommands, +} + +#[derive(Subcommand, Debug)] +enum ConfigCommands { + #[command(subcommand)] + Tag(TagOperation), + #[command(subcommand)] + Store(StoreOperation), +} + +#[derive(Subcommand, Debug)] +enum TagOperation { + List, + Add(TagAddOptions), + Delete(TagDeleteOptions), +} + +#[derive(Args, Debug)] +struct TagAddOptions { /// pair of key-values separated with '=' #[clap(short, long, value_parser = parse_key_val::, number_of_values = 1)] tag: Vec<(String, String)>, +} - /// store url in the format [xx-xx=]. the range xx-xx is optional and used for +#[derive(Args, Debug)] +struct TagDeleteOptions { + /// key to remove + #[clap(short, long, action=ArgAction::Append)] + key: Vec, + /// remove all tags + #[clap(short, long, default_value_t = false)] + all: bool, +} + +#[derive(Subcommand, Debug)] +enum StoreOperation { + List, + Add(StoreAddOptions), + Delete(StoreDeleteOptions), +} + +#[derive(Args, Debug)] +struct StoreAddOptions { /// sharding. the URL is per store type, please check docs for more information #[clap(short, long, action=ArgAction::Append)] store: Vec, +} - /// replace the current metadata with the provided ones - #[clap(long, default_value_t = true, action=ArgAction::Set)] - replace: bool, +#[derive(Args, Debug)] +struct StoreDeleteOptions { + /// store to remove + #[clap(short, long, action=ArgAction::Append)] + store: Vec, + /// remove all stores + #[clap(short, long, default_value_t = false)] + all: bool, } /// Parse a single key-value pair @@ -291,9 +337,22 @@ fn config(opts: ConfigOptions) -> Result<()> { .await .context("failed to initialize metadata database")?; - let store = store::parse_router(opts.store.as_slice()).await?; - - rfs::config(writer, reader, store, opts.tag, opts.store, opts.replace).await?; + match opts.command { + ConfigCommands::Tag(opts) => match opts { + TagOperation::List => config::tag_list(reader).await?, + TagOperation::Add(opts) => config::tag_add(writer, opts.tag).await?, + TagOperation::Delete(opts) => { + config::tag_delete(writer, opts.key, opts.all).await? + } + }, + ConfigCommands::Store(opts) => match opts { + StoreOperation::List => config::store_list(reader).await?, + StoreOperation::Add(opts) => config::store_add(writer, opts.store).await?, + StoreOperation::Delete(opts) => { + config::store_delete(writer, opts.store, opts.all).await? + } + }, + } Ok(()) })