summaryrefslogtreecommitdiff
path: root/rola-cli/src/bucket_mgr
diff options
context:
space:
mode:
Diffstat (limited to 'rola-cli/src/bucket_mgr')
-rw-r--r--rola-cli/src/bucket_mgr/bind.rs262
-rw-r--r--rola-cli/src/bucket_mgr/creation.rs27
2 files changed, 277 insertions, 12 deletions
diff --git a/rola-cli/src/bucket_mgr/bind.rs b/rola-cli/src/bucket_mgr/bind.rs
new file mode 100644
index 0000000..48186a2
--- /dev/null
+++ b/rola-cli/src/bucket_mgr/bind.rs
@@ -0,0 +1,262 @@
+use colored::Colorize;
+use mingling::{
+ Groupped, LazyRes,
+ macros::{chain, dispatcher_clap, pack, pack_err, r_println, renderer},
+ res::ResExitCode,
+};
+use rorolala::bucket::{self, bind::BucketBind};
+use serde::Serialize;
+use shared_functions::info;
+
+use crate::{
+ Next,
+ bucket_mgr::ResultEnumBucketOperation::Set,
+ error::{ErrorRequireOverwrite, ErrorSpace},
+ locale::I18nBucketManager,
+ output::display::markdown,
+ res::{bucket::ResBucketWithoutProtocol, overwrite::ResOverwrite},
+};
+
+pub const EC_BUCKET_BIND_INDEX_NOT_PROVIDED: i32 = 251;
+pub const EC_BUCKET_BIND_INDEX_NOT_FOUND: i32 = 252;
+
+#[derive(Default, clap::Parser, Serialize, Groupped)]
+#[dispatcher_clap("bucket.bind", CMDBucketBind)]
+pub struct EntryBucketBind {
+ index: Option<u8>,
+
+ #[arg(long, conflicts_with_all = ["set"])]
+ remove: bool,
+
+ #[arg(long, conflicts_with_all = ["remove"])]
+ set: Option<String>,
+}
+
+pack!(StateBucketBindListAll = ());
+pack!(StateBucketBindListSpecified = u8);
+pack!(StateBucketBindRemove = u8);
+pack!(StateBucketBindSet = (u8, String)); // idx, url
+
+#[derive(Default, Serialize, Groupped)]
+pub struct ResultAllBucketBind {
+ bind_list: Vec<BucketBind>,
+}
+
+#[derive(Default, Serialize, Groupped)]
+pub struct ResultOneBucketBind {
+ index: u8,
+ url: String,
+}
+
+#[derive(Default, Serialize, Groupped)]
+pub struct ResultBucketOperated {
+ pub operation: ResultEnumBucketOperation,
+ pub index: u8,
+ pub url: Option<String>,
+}
+
+#[derive(Default, Serialize)]
+pub enum ResultEnumBucketOperation {
+ #[serde(rename = "none")]
+ #[default]
+ None,
+ #[serde(rename = "set_bind")]
+ Set,
+ #[serde(rename = "remove_bind")]
+ Remove,
+}
+
+pack_err!(ErrorBucketBindIndexNotProvided);
+pack_err!(ErrorBucketBindIndexNotFound = u8);
+
+// Chains
+
+#[chain]
+pub fn handle_bucket_bind(args: EntryBucketBind) -> Next {
+ match args.index {
+ Some(op_idx) => {
+ if let Some(url) = args.set {
+ // bind idx --set url
+ return StateBucketBindSet::new((op_idx, url)).to_chain();
+ } else if args.remove {
+ // bind idx --remove
+ return StateBucketBindRemove::new(op_idx).to_chain();
+ } else {
+ // bind idx
+ return StateBucketBindListSpecified::new(op_idx).to_chain();
+ }
+ }
+ None => {
+ if !args.remove && args.set.is_none() {
+ // bind
+ return StateBucketBindListAll::new(()).to_chain();
+ } else {
+ // index not provided
+ // bind --set url
+ // or
+ // bind --remove
+ return ErrorBucketBindIndexNotProvided::default().to_render();
+ }
+ }
+ }
+}
+
+#[chain]
+pub fn handle_state_bucket_bind_set(
+ set: StateBucketBindSet,
+ bucket: &mut LazyRes<ResBucketWithoutProtocol>,
+ overwrite: &ResOverwrite,
+) -> Next {
+ let (index, url) = set.inner;
+ let bucket_space_ref = &bucket.get_ref().space;
+
+ let exist = match bucket::bind::check_bucket_bind_exists(bucket_space_ref, index) {
+ Ok(exists) => exists,
+ Err(e) => return ErrorSpace::from(e).to_chain(),
+ };
+
+ // When the bind already exists but overwrite is not specified
+ // Dispatch to ErrorRequireOverwrite
+ if exist && !overwrite.overwrite {
+ return ErrorRequireOverwrite::default().to_render();
+ }
+
+ if let Err(space_error) =
+ bucket::bind::write_bucket_bind(bucket_space_ref, index, url.clone().as_str())
+ {
+ ErrorSpace::from(space_error).to_chain();
+ }
+
+ ResultBucketOperated {
+ operation: Set,
+ index,
+ url: Some(url),
+ }
+ .to_render()
+}
+
+#[chain]
+pub fn handle_state_bucket_bind_remove(
+ remove: StateBucketBindRemove,
+ bucket: &mut LazyRes<ResBucketWithoutProtocol>,
+) -> Next {
+ let index = remove.inner;
+ let bucket_space_ref = &bucket.get_ref().space;
+
+ if let Err(space_error) = bucket::bind::remove_bucket_bind(bucket_space_ref, index) {
+ return ErrorSpace::from(space_error).to_chain();
+ }
+
+ ResultBucketOperated {
+ operation: ResultEnumBucketOperation::Remove,
+ index,
+ url: None,
+ }
+ .to_render()
+}
+
+#[chain]
+pub fn handle_state_bucket_bind_list_specified(
+ index: StateBucketBindListSpecified,
+ bucket: &mut LazyRes<ResBucketWithoutProtocol>,
+) -> Next {
+ let index = index.inner;
+ let bucket_space_ref = &bucket.get_ref().space;
+ let bind_info = match bucket::bind::read_bucket_bind(bucket_space_ref, index) {
+ Err(e) => return ErrorSpace::from(e).to_chain(),
+ Ok(None) => return ErrorBucketBindIndexNotFound::new(index).to_render(),
+ Ok(Some(r)) => r,
+ };
+
+ ResultOneBucketBind {
+ index: bind_info.get_index(),
+ url: bind_info.get_url().to_string(),
+ }
+ .to_render()
+}
+
+#[chain]
+pub fn handle_state_bucket_bind_list_all(
+ _p: StateBucketBindListAll,
+ bucket: &mut LazyRes<ResBucketWithoutProtocol>,
+) -> Next {
+ let bucket_space_ref = &bucket.get_ref().space;
+ info!("Reading all bucket binds from space");
+ let bind_list = match bucket::bind::read_bucket_binds(bucket_space_ref) {
+ Err(e) => return ErrorSpace::from(e).to_chain(),
+ Ok(r) => r,
+ };
+ info!("Read {} bucket binds", bind_list.len());
+ ResultAllBucketBind { bind_list }.to_render()
+}
+
+// Result Renderers
+
+#[renderer]
+pub fn render_result_one_bucket_bind(result: ResultOneBucketBind) {
+ r_println!("BIND_{} => \"{}\"", result.index, result.url.trim().bold());
+}
+
+#[renderer]
+pub fn render_result_all_bucket_bind(result: ResultAllBucketBind) {
+ let list: Vec<String> = result
+ .bind_list
+ .iter()
+ .map(|b| {
+ format!(
+ "BIND_{} => \"{}\"",
+ b.get_index(),
+ b.get_url().trim().bold()
+ )
+ })
+ .collect();
+ for item in list {
+ r_println!("{}", item);
+ }
+}
+
+#[renderer]
+pub fn render_result_bucket_operated(result: ResultBucketOperated) {
+ let index = result.index;
+ let url = result.url.unwrap_or("".to_string());
+ match result.operation {
+ ResultEnumBucketOperation::Set => {
+ r_println!(
+ "{} BIND_{} => \"{}\"",
+ "+++".bold().bright_green(),
+ index,
+ url.bold().trim()
+ )
+ }
+ ResultEnumBucketOperation::Remove => {
+ r_println!("{} BIND_{}", "---".bold().bright_red(), index)
+ }
+ _ => {}
+ }
+}
+
+// Error Renderers
+
+#[renderer]
+pub fn render_error_bucket_bind_index_not_provided(
+ _err: ErrorBucketBindIndexNotProvided,
+ ec: &mut ResExitCode,
+) {
+ r_println!(
+ "{}",
+ markdown(I18nBucketManager::error_bind_index_not_provided().trim())
+ );
+ ec.exit_code = EC_BUCKET_BIND_INDEX_NOT_PROVIDED;
+}
+
+#[renderer]
+pub fn render_error_bucket_bind_index_not_found(
+ err: ErrorBucketBindIndexNotFound,
+ ec: &mut ResExitCode,
+) {
+ r_println!(
+ "{}",
+ markdown(I18nBucketManager::error_bind_index_not_found(err.info.to_string()).trim())
+ );
+ ec.exit_code = EC_BUCKET_BIND_INDEX_NOT_FOUND;
+}
diff --git a/rola-cli/src/bucket_mgr/creation.rs b/rola-cli/src/bucket_mgr/creation.rs
index c363773..2394228 100644
--- a/rola-cli/src/bucket_mgr/creation.rs
+++ b/rola-cli/src/bucket_mgr/creation.rs
@@ -1,16 +1,16 @@
use std::{fs::create_dir_all, path::PathBuf};
use mingling::{
- macros::{chain, dispatcher, pack, r_println, renderer, route},
+ Groupped,
+ macros::{chain, dispatcher, pack, pack_err, r_println, renderer, route},
parser::AsPicker,
res::ResExitCode,
};
use rorolala::bucket::{Bucket, NoProtocol};
+use serde::Serialize;
use space_system::{Space, SpaceError, SpaceRoot, find_space_root_with};
-use crate::{
- Next, error::ErrorIo, locale::I18nBucketManager, res::current_dir::ResCurrentDir, tkr,
-};
+use crate::{Next, error::ErrorIo, locale::I18nBucketManager, res::current_dir::ResCurrentDir};
pub const EC_BUCKET_CREATE_DIR_NOT_EMPTY: i32 = 2400;
pub const EC_BUCKET_PATH_NOT_PROVIDED: i32 = 2401;
@@ -23,12 +23,15 @@ dispatcher!("bucket.create");
pack!(StateBucketCreationPrecheck = PathBuf);
pack!(StateBucketCreation = PathBuf);
-pack!(ResultBucketCreated = PathBuf);
+#[derive(Debug, Groupped, Serialize)]
+pub struct ResultBucketCreated {
+ bucket_path: PathBuf,
+}
-pack!(ErrorDirectoryNotEmpty = PathBuf);
-pack!(ErrorBucketPathNotProvided = ());
-pack!(ErrorBucketPathNotDirectory = PathBuf);
-pack!(ErrorBucketPathNested = PathBuf);
+pack_err!(ErrorDirectoryNotEmpty = PathBuf);
+pack_err!(ErrorBucketPathNotProvided = ());
+pack_err!(ErrorBucketPathNotDirectory = PathBuf);
+pack_err!(ErrorBucketPathNested = PathBuf);
#[chain]
pub fn handle_bucket_init(_args: EntryBucketInit, cwd: &mut ResCurrentDir) -> Next {
@@ -86,16 +89,16 @@ pub fn handle_state_bucket_creation(create: StateBucketCreation) -> Next {
// Initialize the Space and capture any SpaceError::Io
let path_to_init = path.clone();
- if let Err(SpaceError::Io(error)) = tkr! { bucket_space.init(path_to_init).await } {
+ if let Err(SpaceError::Io(error)) = bucket_space.init(path_to_init) {
return ErrorIo::from(error).to_render();
}
- ResultBucketCreated::new(path).to_render()
+ ResultBucketCreated { bucket_path: path }.to_render()
}
#[renderer]
pub fn render_result_bucket_created(result: ResultBucketCreated) {
- let path = result.inner.to_string_lossy();
+ let path = result.bucket_path.to_string_lossy();
r_println!("{}", I18nBucketManager::created(path));
}