Skip to content

Commit

Permalink
Use subcommands for metadata operations
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelrahmanElawady committed Jul 23, 2024
1 parent 9c31d4b commit feacee0
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 37 deletions.
76 changes: 48 additions & 28 deletions rfs/src/config.rs
Original file line number Diff line number Diff line change
@@ -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<S: Store>(
writer: Writer,
reader: Reader,
store: S,
tags: Vec<(String, String)>,
stores: Vec<String>,
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<String>, 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<String>) -> Result<()> {
let store = store::parse_router(stores.as_slice()).await?;
for route in store.routes() {
writer
.route(
Expand All @@ -31,22 +57,16 @@ pub async fn config<S: Store>(
)
.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<String>, 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(())
}
16 changes: 16 additions & 0 deletions rfs/src/fungi/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<U: AsRef<str>>(&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(())
Expand Down
3 changes: 1 addition & 2 deletions rfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
74 changes: 67 additions & 7 deletions rfs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -103,18 +103,65 @@ 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::<String, String>, number_of_values = 1)]
tag: Vec<(String, String)>,
}

#[derive(Args, Debug)]
struct TagDeleteOptions {
/// key to remove
#[clap(short, long, action=ArgAction::Append)]
key: Vec<String>,
/// 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 {
/// store url in the format [xx-xx=]<url>. the range xx-xx is optional and used for
/// sharding. the URL is per store type, please check docs for more information
#[clap(short, long, action=ArgAction::Append)]
store: Vec<String>,
}

/// 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<String>,
/// remove all stores
#[clap(short, long, default_value_t = false)]
all: bool,
}

/// Parse a single key-value pair
Expand Down Expand Up @@ -291,9 +338,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(())
})
Expand Down

0 comments on commit feacee0

Please sign in to comment.