summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/vcs_actions/src/actions.rs9
-rw-r--r--crates/vcs_actions/src/actions/sheet_actions.rs156
-rw-r--r--crates/vcs_actions/src/registry/client_registry.rs3
-rw-r--r--crates/vcs_actions/src/registry/server_registry.rs3
-rw-r--r--crates/vcs_data/src/constants.rs2
-rw-r--r--crates/vcs_data/src/data/local/config.rs23
-rw-r--r--crates/vcs_data/src/data/sheet.rs10
7 files changed, 178 insertions, 28 deletions
diff --git a/crates/vcs_actions/src/actions.rs b/crates/vcs_actions/src/actions.rs
index 795d2b0..51186fb 100644
--- a/crates/vcs_actions/src/actions.rs
+++ b/crates/vcs_actions/src/actions.rs
@@ -116,3 +116,12 @@ pub async fn auth_member(
Err(TcpTargetError::NoResult("Auth failed.".to_string()))
}
+
+/// The macro to write and return a result.
+#[macro_export]
+macro_rules! write_and_return {
+ ($instance:expr, $result:expr) => {{
+ $instance.lock().await.write($result).await?;
+ return Ok($result);
+ }};
+}
diff --git a/crates/vcs_actions/src/actions/sheet_actions.rs b/crates/vcs_actions/src/actions/sheet_actions.rs
index b6ea51d..b4e07a7 100644
--- a/crates/vcs_actions/src/actions/sheet_actions.rs
+++ b/crates/vcs_actions/src/actions/sheet_actions.rs
@@ -1,13 +1,19 @@
+use std::io::ErrorKind;
+
use action_system::{action::ActionContext, macros::action_gen};
use serde::{Deserialize, Serialize};
use tcp_connection::error::TcpTargetError;
use vcs_data::data::sheet::SheetName;
-use crate::actions::{auth_member, check_connection_instance, try_get_vault};
+use crate::{
+ actions::{auth_member, check_connection_instance, try_get_local_workspace, try_get_vault},
+ write_and_return,
+};
#[derive(Default, Serialize, Deserialize)]
pub enum MakeSheetActionResult {
Success,
+ SuccessRestore,
// Fail
AuthorizeFailed(String),
@@ -36,31 +42,35 @@ pub async fn make_sheet_action(
let vault = try_get_vault(&ctx)?;
// Check if the sheet already exists
- if vault.sheet(&sheet_name).await.is_ok() {
- instance
- .lock()
- .await
- .write(MakeSheetActionResult::SheetAlreadyExists)
- .await?;
- return Ok(MakeSheetActionResult::SheetAlreadyExists);
+ if let Ok(mut sheet) = vault.sheet(&sheet_name).await {
+ // If the sheet has no holder, assign it to the current member (restore operation)
+ if sheet.holder().is_none() {
+ sheet.set_holder(member_id);
+ match sheet.persist().await {
+ Ok(_) => {
+ write_and_return!(instance, MakeSheetActionResult::SuccessRestore);
+ }
+ Err(e) => {
+ write_and_return!(
+ instance,
+ MakeSheetActionResult::SheetCreationFailed(e.to_string())
+ );
+ }
+ }
+ } else {
+ write_and_return!(instance, MakeSheetActionResult::SheetAlreadyExists);
+ }
} else {
// Create the sheet
match vault.create_sheet(&sheet_name, &member_id).await {
Ok(_) => {
- instance
- .lock()
- .await
- .write(MakeSheetActionResult::Success)
- .await?;
- return Ok(MakeSheetActionResult::Success);
+ write_and_return!(instance, MakeSheetActionResult::Success);
}
Err(e) => {
- instance
- .lock()
- .await
- .write(MakeSheetActionResult::SheetCreationFailed(e.to_string()))
- .await?;
- return Ok(MakeSheetActionResult::SheetCreationFailed(e.to_string()));
+ write_and_return!(
+ instance,
+ MakeSheetActionResult::SheetCreationFailed(e.to_string())
+ );
}
}
}
@@ -77,3 +87,109 @@ pub async fn make_sheet_action(
Err(TcpTargetError::NoResult("No result.".to_string()))
}
+
+#[derive(Default, Serialize, Deserialize)]
+pub enum DropSheetActionResult {
+ Success,
+
+ // Fail
+ SheetInUse,
+ AuthorizeFailed(String),
+ SheetNotExists,
+ SheetDropFailed(String),
+ NoHolder,
+ NotOwner,
+
+ #[default]
+ Unknown,
+}
+
+#[action_gen]
+pub async fn drop_sheet_action(
+ ctx: ActionContext,
+ sheet_name: SheetName,
+) -> Result<DropSheetActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ let member_id = match auth_member(&ctx, instance).await {
+ Ok(id) => id,
+ Err(e) => {
+ return Ok(DropSheetActionResult::AuthorizeFailed(e.to_string()));
+ }
+ };
+
+ // Check sheet in use on local
+ if ctx.is_proc_on_local() {
+ let local_workspace = try_get_local_workspace(&ctx)?;
+ if let Some(sheet) = local_workspace.config().lock().await.sheet_in_use() {
+ if sheet == &sheet_name {
+ instance.lock().await.write(false).await?;
+ return Ok(DropSheetActionResult::SheetInUse);
+ }
+ instance.lock().await.write(true).await?;
+ } else {
+ instance.lock().await.write(true).await?;
+ }
+ }
+
+ if ctx.is_proc_on_remote() {
+ // Check if client sheet is in use
+ let sheet_in_use = instance.lock().await.read::<bool>().await?;
+ if !sheet_in_use {
+ return Ok(DropSheetActionResult::SheetInUse);
+ }
+
+ let vault = try_get_vault(&ctx)?;
+
+ // Check if the sheet exists
+ let mut sheet = match vault.sheet(&sheet_name).await {
+ Ok(sheet) => sheet,
+ Err(e) => {
+ if e.kind() == ErrorKind::NotFound {
+ write_and_return!(instance, DropSheetActionResult::SheetNotExists);
+ } else {
+ write_and_return!(
+ instance,
+ DropSheetActionResult::SheetDropFailed(e.to_string())
+ );
+ }
+ }
+ };
+
+ // Get the sheet's holder
+ let Some(holder) = sheet.holder() else {
+ write_and_return!(instance, DropSheetActionResult::NoHolder);
+ };
+
+ // Verify the sheet's holder
+ if holder != &member_id {
+ write_and_return!(instance, DropSheetActionResult::NotOwner);
+ }
+
+ // Drop the sheet
+ sheet.forget_holder();
+ match sheet.persist().await {
+ Ok(_) => {
+ write_and_return!(instance, DropSheetActionResult::Success);
+ }
+ Err(e) => {
+ write_and_return!(
+ instance,
+ DropSheetActionResult::SheetDropFailed(e.to_string())
+ );
+ }
+ }
+ }
+
+ if ctx.is_proc_on_local() {
+ let result = instance
+ .lock()
+ .await
+ .read::<DropSheetActionResult>()
+ .await?;
+ return Ok(result);
+ }
+
+ Err(TcpTargetError::NoResult("No result.".to_string()))
+}
diff --git a/crates/vcs_actions/src/registry/client_registry.rs b/crates/vcs_actions/src/registry/client_registry.rs
index a0b87a6..95c0939 100644
--- a/crates/vcs_actions/src/registry/client_registry.rs
+++ b/crates/vcs_actions/src/registry/client_registry.rs
@@ -13,7 +13,7 @@ use crate::{
local_actions::{
register_set_upstream_vault_action, register_update_to_latest_info_action,
},
- sheet_actions::register_make_sheet_action,
+ sheet_actions::{register_drop_sheet_action, register_make_sheet_action},
},
connection::protocol::RemoteActionInvoke,
};
@@ -27,6 +27,7 @@ fn register_actions(pool: &mut ActionPool) {
// Sheet Actions
register_make_sheet_action(pool);
+ register_drop_sheet_action(pool);
}
pub fn client_action_pool() -> ActionPool {
diff --git a/crates/vcs_actions/src/registry/server_registry.rs b/crates/vcs_actions/src/registry/server_registry.rs
index eade391..b99d697 100644
--- a/crates/vcs_actions/src/registry/server_registry.rs
+++ b/crates/vcs_actions/src/registry/server_registry.rs
@@ -2,7 +2,7 @@ use action_system::action_pool::ActionPool;
use crate::actions::{
local_actions::{register_set_upstream_vault_action, register_update_to_latest_info_action},
- sheet_actions::register_make_sheet_action,
+ sheet_actions::{register_drop_sheet_action, register_make_sheet_action},
};
pub fn server_action_pool() -> ActionPool {
@@ -14,6 +14,7 @@ pub fn server_action_pool() -> ActionPool {
// Sheet Actions
register_make_sheet_action(&mut pool);
+ register_drop_sheet_action(&mut pool);
pool
}
diff --git a/crates/vcs_data/src/constants.rs b/crates/vcs_data/src/constants.rs
index 1d17927..55662e7 100644
--- a/crates/vcs_data/src/constants.rs
+++ b/crates/vcs_data/src/constants.rs
@@ -54,7 +54,7 @@ pub const CLIENT_FILE_LATEST_INFO: &str = "./.jv/latest.json";
pub const CLIENT_FILE_SHEET_COPY: &str = "./.jv/sheets/{sheet_name}.copy.json";
// Client - Local Draft
-pub const CLIENT_PATH_LOCAL_DRAFT: &str = "./.jv/drafts/{sheet_name}/";
+pub const CLIENT_PATH_LOCAL_DRAFT: &str = "./.jv/drafts/{account}_{sheet_name}/";
// Client - Other
pub const CLIENT_FILE_IGNOREFILES: &str = "IGNORE_RULES.toml";
diff --git a/crates/vcs_data/src/data/local/config.rs b/crates/vcs_data/src/data/local/config.rs
index 3dc5248..fa3b607 100644
--- a/crates/vcs_data/src/data/local/config.rs
+++ b/crates/vcs_data/src/data/local/config.rs
@@ -1,6 +1,7 @@
use cfg_file::ConfigFile;
use cfg_file::config::ConfigFile;
use serde::{Deserialize, Serialize};
+use std::io::Error;
use std::net::SocketAddr;
use std::path::Path;
use std::path::PathBuf;
@@ -17,6 +18,7 @@ use crate::data::member::MemberId;
use crate::data::sheet::SheetName;
use crate::data::vault::config::VaultUuid;
+const ACCOUNT: &str = "{account}";
const SHEET_NAME: &str = "{sheet_name}";
#[derive(Serialize, Deserialize, ConfigFile)]
@@ -68,8 +70,15 @@ impl LocalConfig {
}
/// Set the currently used account
- pub fn set_current_account(&mut self, account: MemberId) {
+ pub fn set_current_account(&mut self, account: MemberId) -> Result<(), std::io::Error> {
+ if self.sheet_in_use().is_some() {
+ return Err(Error::new(
+ std::io::ErrorKind::DirectoryNotEmpty,
+ "Please exit the current sheet before switching accounts",
+ ));
+ }
self.using_account = account;
+ Ok(())
}
/// Set the currently used sheet
@@ -107,7 +116,7 @@ impl LocalConfig {
self.check_local_path_empty(&local_path).await?;
// Get the draft folder path
- let draft_folder = self.draft_folder(&sheet, &local_path);
+ let draft_folder = self.draft_folder(&self.using_account, &sheet, &local_path);
if draft_folder.exists() {
// Exists
@@ -135,7 +144,7 @@ impl LocalConfig {
let sheet_name = self.sheet_in_use().as_ref().unwrap().clone();
// Get the draft folder path
- let draft_folder = self.draft_folder(&sheet_name, &local_path);
+ let draft_folder = self.draft_folder(&self.using_account, &sheet_name, &local_path);
// Create the draft folder if it doesn't exist
if !draft_folder.exists() {
@@ -312,11 +321,15 @@ impl LocalConfig {
/// Get draft folder
pub fn draft_folder(
&self,
+ account: &MemberId,
sheet_name: &SheetName,
local_workspace_path: impl Into<PathBuf>,
) -> PathBuf {
+ let account_str = snake_case!(account.as_str());
let sheet_name_str = snake_case!(sheet_name.as_str());
- let draft_path = CLIENT_PATH_LOCAL_DRAFT.replace(SHEET_NAME, &sheet_name_str);
+ let draft_path = CLIENT_PATH_LOCAL_DRAFT
+ .replace(ACCOUNT, &account_str)
+ .replace(SHEET_NAME, &sheet_name_str);
local_workspace_path.into().join(draft_path)
}
@@ -330,7 +343,7 @@ impl LocalConfig {
return None;
};
- Some(self.draft_folder(sheet_name, current_dir))
+ Some(self.draft_folder(&self.using_account, sheet_name, current_dir))
}
}
diff --git a/crates/vcs_data/src/data/sheet.rs b/crates/vcs_data/src/data/sheet.rs
index ce450a6..69dc27d 100644
--- a/crates/vcs_data/src/data/sheet.rs
+++ b/crates/vcs_data/src/data/sheet.rs
@@ -89,6 +89,16 @@ impl<'a> Sheet<'a> {
&self.data.mapping
}
+ /// Forget the holder of this sheet
+ pub fn forget_holder(&mut self) {
+ self.data.holder = None;
+ }
+
+ /// Set the holder of this sheet
+ pub fn set_holder(&mut self, holder: MemberId) {
+ self.data.holder = Some(holder);
+ }
+
/// Add an input package to the sheet
pub fn add_input(&mut self, input_package: InputPackage) -> Result<(), std::io::Error> {
if self.data.inputs.iter().any(|input| input == &input_package) {