summaryrefslogtreecommitdiff
path: root/actions/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-01-12 05:12:10 +0800
committer魏曹先生 <1992414357@qq.com>2026-01-12 05:36:40 +0800
commite3f4b8188515eeec149eec0405b51e1b57f6e7bb (patch)
treedf80e7289621c39c9d32befbe9bf85a2e129eefb /actions/src
parentdd8cbe7e863b3fec594696c15c5e009f172749f5 (diff)
Rename and reorganize remote actions modules
Diffstat (limited to 'actions/src')
-rw-r--r--actions/src/actions/sheet_actions.rs583
-rw-r--r--actions/src/actions/vault_actions.rs1
-rw-r--r--actions/src/lib.rs3
-rw-r--r--actions/src/local_actions.rs0
-rw-r--r--actions/src/registry/client_registry.rs23
-rw-r--r--actions/src/registry/server_registry.rs21
-rw-r--r--actions/src/remote_actions.rs (renamed from actions/src/actions.rs)10
-rw-r--r--actions/src/remote_actions/content_manage.rs1
-rw-r--r--actions/src/remote_actions/content_manage/track.rs (renamed from actions/src/actions/track_action.rs)10
-rw-r--r--actions/src/remote_actions/edit_right_manage.rs1
-rw-r--r--actions/src/remote_actions/edit_right_manage/change_virtual_file_edit_right.rs (renamed from actions/src/actions/user_actions.rs)2
-rw-r--r--actions/src/remote_actions/mapping_manage.rs3
-rw-r--r--actions/src/remote_actions/mapping_manage/edit_mapping.rs157
-rw-r--r--actions/src/remote_actions/mapping_manage/merge_share_mapping.rs117
-rw-r--r--actions/src/remote_actions/mapping_manage/share_mapping.rs135
-rw-r--r--actions/src/remote_actions/sheet_manage.rs2
-rw-r--r--actions/src/remote_actions/sheet_manage/drop_sheet.rs123
-rw-r--r--actions/src/remote_actions/sheet_manage/make_sheet.rs98
-rw-r--r--actions/src/remote_actions/workspace_manage.rs2
-rw-r--r--actions/src/remote_actions/workspace_manage/set_upstream_vault.rs101
-rw-r--r--actions/src/remote_actions/workspace_manage/update_to_latest_info.rs (renamed from actions/src/actions/local_actions.rs)94
21 files changed, 781 insertions, 706 deletions
diff --git a/actions/src/actions/sheet_actions.rs b/actions/src/actions/sheet_actions.rs
deleted file mode 100644
index 4c9977e..0000000
--- a/actions/src/actions/sheet_actions.rs
+++ /dev/null
@@ -1,583 +0,0 @@
-use std::{collections::HashMap, io::ErrorKind};
-
-use action_system::{action::ActionContext, macros::action_gen};
-use serde::{Deserialize, Serialize};
-use tcp_connection::error::TcpTargetError;
-use vcs_data::{
- constants::VAULT_HOST_NAME,
- data::{
- local::{
- vault_modified::sign_vault_modified,
- workspace_analyzer::{FromRelativePathBuf, ToRelativePathBuf},
- },
- sheet::SheetName,
- vault::sheet_share::{ShareMergeMode, SheetShareId},
- },
-};
-
-use crate::{
- actions::{
- auth_member, check_connection_instance, get_current_sheet_name, try_get_local_workspace,
- try_get_vault,
- },
- write_and_return,
-};
-
-#[derive(Default, Serialize, Deserialize)]
-pub enum MakeSheetActionResult {
- Success,
- SuccessRestore,
-
- // Fail
- AuthorizeFailed(String),
- SheetAlreadyExists,
- SheetCreationFailed(String),
-
- #[default]
- Unknown,
-}
-
-/// Build a sheet with context
-#[action_gen]
-pub async fn make_sheet_action(
- ctx: ActionContext,
- sheet_name: SheetName,
-) -> Result<MakeSheetActionResult, TcpTargetError> {
- let instance = check_connection_instance(&ctx)?;
-
- // Auth Member
- let (member_id, is_host_mode) = match auth_member(&ctx, instance).await {
- Ok(id) => id,
- Err(e) => return Ok(MakeSheetActionResult::AuthorizeFailed(e.to_string())),
- };
-
- if ctx.is_proc_on_remote() {
- let vault = try_get_vault(&ctx)?;
- let holder = if is_host_mode {
- VAULT_HOST_NAME.to_string()
- } else {
- member_id
- };
-
- // Check if the sheet already exists
- 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(holder.clone());
- 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, &holder).await {
- Ok(_) => {
- write_and_return!(instance, MakeSheetActionResult::Success);
- }
- Err(e) => {
- write_and_return!(
- instance,
- MakeSheetActionResult::SheetCreationFailed(e.to_string())
- );
- }
- }
- }
- }
-
- if ctx.is_proc_on_local() {
- let result = instance
- .lock()
- .await
- .read::<MakeSheetActionResult>()
- .await?;
- if matches!(result, MakeSheetActionResult::Success) {
- sign_vault_modified(true).await;
- }
- return Ok(result);
- }
-
- 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, is_host_mode) = 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 that the sheet holder is either the current user or the host
- // All sheets belong to the host
- if holder != &member_id && !is_host_mode {
- 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?;
- if matches!(result, DropSheetActionResult::Success) {
- sign_vault_modified(true).await;
- }
- return Ok(result);
- }
-
- Err(TcpTargetError::NoResult("No result.".to_string()))
-}
-
-pub type OperationArgument = (EditMappingOperations, Option<ToRelativePathBuf>);
-
-#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
-pub enum EditMappingOperations {
- Move,
- Erase,
-}
-
-#[derive(Serialize, Deserialize, Default)]
-pub enum EditMappingActionResult {
- Success,
-
- // Fail
- AuthorizeFailed(String),
- EditNotAllowed,
- MappingNotFound(FromRelativePathBuf),
- InvalidMove(InvalidMoveReason),
-
- #[default]
- Unknown,
-}
-
-#[derive(Serialize, Deserialize)]
-pub enum InvalidMoveReason {
- MoveOperationButNoTarget(FromRelativePathBuf),
- ContainsDuplicateMapping(ToRelativePathBuf),
-}
-
-#[derive(Serialize, Deserialize, Clone)]
-pub struct EditMappingActionArguments {
- pub operations: HashMap<FromRelativePathBuf, OperationArgument>,
-}
-
-/// This Action only modifies Sheet Mapping and
-/// does not interfere with the actual location of local files or Local Mapping
-#[action_gen]
-pub async fn edit_mapping_action(
- ctx: ActionContext,
- args: EditMappingActionArguments,
-) -> Result<EditMappingActionResult, TcpTargetError> {
- let instance = check_connection_instance(&ctx)?;
-
- // Auth Member
- let (member_id, is_host_mode) = match auth_member(&ctx, instance).await {
- Ok(id) => id,
- Err(e) => {
- return Ok(EditMappingActionResult::AuthorizeFailed(e.to_string()));
- }
- };
-
- // Check sheet
- let (sheet_name, is_ref_sheet) =
- get_current_sheet_name(&ctx, instance, &member_id, true).await?;
-
- // Can modify Sheet when not in reference sheet or in Host mode
- let can_modify_sheet = !is_ref_sheet || is_host_mode;
-
- if !can_modify_sheet {
- return Ok(EditMappingActionResult::EditNotAllowed);
- }
-
- if ctx.is_proc_on_remote() {
- let vault = try_get_vault(&ctx)?;
- let mut sheet = vault.sheet(&sheet_name).await?;
-
- // Precheck
- for (from_path, (operation, to_path)) in args.operations.iter() {
- // Check mapping exists
- if !sheet.mapping().contains_key(from_path) {
- write_and_return!(
- instance,
- EditMappingActionResult::MappingNotFound(from_path.clone())
- );
- }
-
- // Move check
- if operation == &EditMappingOperations::Move {
- // Check if target exists
- if let Some(to_path) = to_path {
- // Check if target is duplicate
- if sheet.mapping().contains_key(to_path) {
- write_and_return!(
- instance,
- EditMappingActionResult::InvalidMove(
- InvalidMoveReason::ContainsDuplicateMapping(to_path.clone())
- )
- );
- }
- } else {
- write_and_return!(
- instance,
- EditMappingActionResult::InvalidMove(
- InvalidMoveReason::MoveOperationButNoTarget(from_path.clone())
- )
- );
- }
- }
- }
-
- // Process
- for (from_path, (operation, to_path)) in args.operations {
- match operation {
- // During the Precheck phase, it has been ensured that:
- // 1. The mapping to be edited for the From path indeed exists
- // 2. The location of the To path is indeed empty
- // 3. In Move mode, To path can be safely unwrapped
- // Therefore, the following unwrap() calls are safe to execute
- EditMappingOperations::Move => {
- let mapping = sheet.mapping_mut().remove(&from_path).unwrap();
- let to_path = to_path.unwrap();
- sheet
- .add_mapping(to_path, mapping.id, mapping.version)
- .await?;
- }
- EditMappingOperations::Erase => {
- sheet.mapping_mut().remove(&from_path).unwrap();
- }
- }
- }
-
- // Write
- sheet.persist().await?;
-
- write_and_return!(instance, EditMappingActionResult::Success);
- }
-
- if ctx.is_proc_on_local() {
- let result = instance
- .lock()
- .await
- .read::<EditMappingActionResult>()
- .await?;
- if matches!(result, EditMappingActionResult::Success) {
- sign_vault_modified(true).await;
- }
- return Ok(result);
- }
-
- Ok(EditMappingActionResult::Success)
-}
-
-#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
-pub struct ShareMappingArguments {
- pub mappings: Vec<FromRelativePathBuf>,
- pub description: String,
- // None = current sheet,
- // Some(sheet_name) = other ref(public) sheet
- pub from_sheet: Option<SheetName>,
- pub to_sheet: SheetName,
-}
-
-#[derive(Serialize, Deserialize, Default)]
-pub enum ShareMappingActionResult {
- Success,
-
- // Fail
- AuthorizeFailed(String),
- TargetSheetNotFound(SheetName),
- TargetIsSelf,
- MappingNotFound(FromRelativePathBuf),
-
- #[default]
- Unknown,
-}
-
-#[action_gen]
-pub async fn share_mapping_action(
- ctx: ActionContext,
- args: ShareMappingArguments,
-) -> Result<ShareMappingActionResult, TcpTargetError> {
- let instance = check_connection_instance(&ctx)?;
-
- // Auth Member
- let (member_id, _is_host_mode) = match auth_member(&ctx, instance).await {
- Ok(id) => id,
- Err(e) => {
- return Ok(ShareMappingActionResult::AuthorizeFailed(e.to_string()));
- }
- };
-
- // Check sheet
- let sheet_name = args.from_sheet.unwrap_or(
- get_current_sheet_name(&ctx, instance, &member_id, true)
- .await?
- .0,
- );
-
- if ctx.is_proc_on_remote() {
- let vault = try_get_vault(&ctx)?;
- let sheet = vault.sheet(&sheet_name).await?;
-
- // Tip: Because sheet_name may specify a sheet that does not belong to the user,
- // a secondary verification is required.
-
- // Check if the sheet holder is Some and matches the member_id or is the host
- let Some(holder) = sheet.holder() else {
- // If there's no holder, the sheet cannot be shared from
- write_and_return!(
- instance,
- ShareMappingActionResult::AuthorizeFailed("Sheet has no holder".to_string())
- );
- };
-
- // Verify the holder is either the current member or the host
- if holder != &member_id && holder != VAULT_HOST_NAME {
- write_and_return!(
- instance,
- ShareMappingActionResult::AuthorizeFailed(
- "Not sheet holder or ref sheet".to_string()
- )
- );
- }
-
- let to_sheet_name = args.to_sheet;
-
- // Verify target sheet exists
- if !vault.sheet_names()?.contains(&to_sheet_name) {
- // Does not exist
- write_and_return!(
- instance,
- ShareMappingActionResult::TargetSheetNotFound(to_sheet_name.clone())
- );
- }
-
- // Verify sheet is not self
- if sheet_name == to_sheet_name {
- // Is self
- write_and_return!(instance, ShareMappingActionResult::TargetIsSelf);
- }
-
- // Verify all mappings are correct
- for mapping in args.mappings.iter() {
- if !sheet.mapping().contains_key(mapping) {
- // If any mapping is invalid, indicate failure
- write_and_return!(
- instance,
- ShareMappingActionResult::MappingNotFound(mapping.clone())
- );
- }
- }
-
- // Execute sharing logic
- sheet
- .share_mappings(&to_sheet_name, args.mappings, &member_id, args.description)
- .await?;
-
- // Sharing successful
- write_and_return!(instance, ShareMappingActionResult::Success);
- }
-
- if ctx.is_proc_on_local() {
- let result = instance
- .lock()
- .await
- .read::<ShareMappingActionResult>()
- .await?;
- return Ok(result);
- }
-
- Ok(ShareMappingActionResult::Success)
-}
-
-#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
-pub struct MergeShareMappingArguments {
- pub share_id: SheetShareId,
- pub share_merge_mode: ShareMergeMode,
-}
-
-#[derive(Serialize, Deserialize, Default)]
-pub enum MergeShareMappingActionResult {
- Success,
-
- // Fail
- HasConflicts,
- AuthorizeFailed(String),
- EditNotAllowed,
- ShareIdNotFound(SheetShareId),
- MergeFails(String),
-
- #[default]
- Unknown,
-}
-
-#[action_gen]
-pub async fn merge_share_mapping_action(
- ctx: ActionContext,
- args: MergeShareMappingArguments,
-) -> Result<MergeShareMappingActionResult, TcpTargetError> {
- let instance = check_connection_instance(&ctx)?;
-
- // Auth Member
- let (member_id, is_host_mode) = match auth_member(&ctx, instance).await {
- Ok(id) => id,
- Err(e) => {
- return Ok(MergeShareMappingActionResult::AuthorizeFailed(
- e.to_string(),
- ));
- }
- };
-
- // Check sheet
- let (sheet_name, is_ref_sheet) =
- get_current_sheet_name(&ctx, instance, &member_id, true).await?;
-
- // Can modify Sheet when not in reference sheet or in Host mode
- let can_modify_sheet = !is_ref_sheet || is_host_mode;
-
- if !can_modify_sheet {
- return Ok(MergeShareMappingActionResult::EditNotAllowed);
- }
-
- if ctx.is_proc_on_remote() {
- let vault = try_get_vault(&ctx)?;
- let share_id = args.share_id;
-
- // Get the share and sheet
- let (sheet, share) = if vault.share_file_path(&sheet_name, &share_id).exists() {
- let sheet = vault.sheet(&sheet_name).await?;
- let share = sheet.get_share(&share_id).await?;
- (sheet, share)
- } else {
- // Share does not exist
- write_and_return!(
- instance,
- MergeShareMappingActionResult::ShareIdNotFound(share_id.clone())
- );
- };
-
- // Perform the merge
- match sheet.merge_share(share, args.share_merge_mode).await {
- Ok(_) => write_and_return!(instance, MergeShareMappingActionResult::Success),
- Err(e) => match e.kind() {
- ErrorKind::AlreadyExists => {
- write_and_return!(instance, MergeShareMappingActionResult::HasConflicts);
- }
- _ => {
- write_and_return!(
- instance,
- MergeShareMappingActionResult::MergeFails(e.to_string())
- );
- }
- },
- }
- }
-
- if ctx.is_proc_on_local() {
- let result = instance
- .lock()
- .await
- .read::<MergeShareMappingActionResult>()
- .await?;
- match result {
- MergeShareMappingActionResult::Success => {
- sign_vault_modified(true).await;
- }
- _ => {}
- }
- return Ok(result);
- }
-
- Ok(MergeShareMappingActionResult::Success)
-}
diff --git a/actions/src/actions/vault_actions.rs b/actions/src/actions/vault_actions.rs
deleted file mode 100644
index 8b13789..0000000
--- a/actions/src/actions/vault_actions.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/actions/src/lib.rs b/actions/src/lib.rs
index 2f7cbe4..c1dda86 100644
--- a/actions/src/lib.rs
+++ b/actions/src/lib.rs
@@ -1,3 +1,4 @@
-pub mod actions;
pub mod connection;
+pub mod local_actions;
pub mod registry;
+pub mod remote_actions;
diff --git a/actions/src/local_actions.rs b/actions/src/local_actions.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/actions/src/local_actions.rs
diff --git a/actions/src/registry/client_registry.rs b/actions/src/registry/client_registry.rs
index 05cb7f1..c31b19a 100644
--- a/actions/src/registry/client_registry.rs
+++ b/actions/src/registry/client_registry.rs
@@ -9,18 +9,23 @@ use vcs_data::data::{
};
use crate::{
- actions::{
- local_actions::{
- register_set_upstream_vault_action, register_update_to_latest_info_action,
+ connection::protocol::RemoteActionInvoke,
+ remote_actions::{
+ content_manage::track::register_track_file_action,
+ edit_right_manage::change_virtual_file_edit_right::register_change_virtual_file_edit_right_action,
+ mapping_manage::{
+ edit_mapping::register_edit_mapping_action,
+ merge_share_mapping::register_merge_share_mapping_action,
+ share_mapping::register_share_mapping_action,
+ },
+ sheet_manage::{
+ drop_sheet::register_drop_sheet_action, make_sheet::register_make_sheet_action,
},
- sheet_actions::{
- register_drop_sheet_action, register_edit_mapping_action, register_make_sheet_action,
- register_merge_share_mapping_action, register_share_mapping_action,
+ workspace_manage::{
+ set_upstream_vault::register_set_upstream_vault_action,
+ update_to_latest_info::register_update_to_latest_info_action,
},
- track_action::register_track_file_action,
- user_actions::register_change_virtual_file_edit_right_action,
},
- connection::protocol::RemoteActionInvoke,
};
fn register_actions(pool: &mut ActionPool) {
diff --git a/actions/src/registry/server_registry.rs b/actions/src/registry/server_registry.rs
index 356e640..013cdbd 100644
--- a/actions/src/registry/server_registry.rs
+++ b/actions/src/registry/server_registry.rs
@@ -1,13 +1,20 @@
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_drop_sheet_action, register_edit_mapping_action, register_make_sheet_action,
- register_merge_share_mapping_action, register_share_mapping_action,
+use crate::remote_actions::{
+ content_manage::track::register_track_file_action,
+ edit_right_manage::change_virtual_file_edit_right::register_change_virtual_file_edit_right_action,
+ mapping_manage::{
+ edit_mapping::register_edit_mapping_action,
+ merge_share_mapping::register_merge_share_mapping_action,
+ share_mapping::register_share_mapping_action,
+ },
+ sheet_manage::{
+ drop_sheet::register_drop_sheet_action, make_sheet::register_make_sheet_action,
+ },
+ workspace_manage::{
+ set_upstream_vault::register_set_upstream_vault_action,
+ update_to_latest_info::register_update_to_latest_info_action,
},
- track_action::register_track_file_action,
- user_actions::register_change_virtual_file_edit_right_action,
};
pub fn server_action_pool() -> ActionPool {
diff --git a/actions/src/actions.rs b/actions/src/remote_actions.rs
index 3019327..33f01aa 100644
--- a/actions/src/actions.rs
+++ b/actions/src/remote_actions.rs
@@ -15,11 +15,11 @@ use vcs_data::{
},
};
-pub mod local_actions;
-pub mod sheet_actions;
-pub mod track_action;
-pub mod user_actions;
-pub mod vault_actions;
+pub mod content_manage;
+pub mod edit_right_manage;
+pub mod mapping_manage;
+pub mod sheet_manage;
+pub mod workspace_manage;
/// Check if the connection instance is valid in the given context.
/// This function is used to verify the connection instance in actions that require remote calls.
diff --git a/actions/src/remote_actions/content_manage.rs b/actions/src/remote_actions/content_manage.rs
new file mode 100644
index 0000000..aa3cb07
--- /dev/null
+++ b/actions/src/remote_actions/content_manage.rs
@@ -0,0 +1 @@
+pub mod track; \ No newline at end of file
diff --git a/actions/src/actions/track_action.rs b/actions/src/remote_actions/content_manage/track.rs
index e5f96b3..c158700 100644
--- a/actions/src/actions/track_action.rs
+++ b/actions/src/remote_actions/content_manage/track.rs
@@ -12,7 +12,7 @@ use sha1_hash::calc_sha1;
use tcp_connection::{error::TcpTargetError, instance::ConnectionInstance};
use tokio::{fs, sync::Mutex};
use vcs_data::{
- constants::CLIENT_FILE_TEMP_FILE,
+ constants::{CLIENT_FILE_TEMP_FILE, KEY_TEMP_NAME},
data::{
local::{
cached_sheet::CachedSheet, latest_file_data::LatestFileData,
@@ -29,18 +29,16 @@ use vcs_data::{
};
use crate::{
- actions::{
+ local_println,
+ remote_actions::{
auth_member, check_connection_instance, get_current_sheet_name, try_get_local_output,
try_get_local_workspace, try_get_vault,
},
- local_println,
};
pub type NextVersion = String;
pub type UpdateDescription = String;
-const TEMP_NAME: &str = "{temp_name}";
-
#[derive(Serialize, Deserialize)]
pub struct TrackFileActionArguments {
// Path need to track
@@ -842,7 +840,7 @@ async fn proc_sync_tasks_local(
// Generate a temp path
let temp_path = workspace
.local_path()
- .join(CLIENT_FILE_TEMP_FILE.replace(TEMP_NAME, &VaultUuid::new_v4().to_string()));
+ .join(CLIENT_FILE_TEMP_FILE.replace(KEY_TEMP_NAME, &VaultUuid::new_v4().to_string()));
let copy_to = workspace.local_path().join(&path);
diff --git a/actions/src/remote_actions/edit_right_manage.rs b/actions/src/remote_actions/edit_right_manage.rs
new file mode 100644
index 0000000..52305f5
--- /dev/null
+++ b/actions/src/remote_actions/edit_right_manage.rs
@@ -0,0 +1 @@
+pub mod change_virtual_file_edit_right;
diff --git a/actions/src/actions/user_actions.rs b/actions/src/remote_actions/edit_right_manage/change_virtual_file_edit_right.rs
index dc0f71a..b999e42 100644
--- a/actions/src/actions/user_actions.rs
+++ b/actions/src/remote_actions/edit_right_manage/change_virtual_file_edit_right.rs
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use tcp_connection::error::TcpTargetError;
use vcs_data::data::local::vault_modified::sign_vault_modified;
-use crate::actions::{
+use crate::remote_actions::{
auth_member, check_connection_instance, get_current_sheet_name, try_get_vault,
};
diff --git a/actions/src/remote_actions/mapping_manage.rs b/actions/src/remote_actions/mapping_manage.rs
new file mode 100644
index 0000000..624b4ab
--- /dev/null
+++ b/actions/src/remote_actions/mapping_manage.rs
@@ -0,0 +1,3 @@
+pub mod edit_mapping;
+pub mod merge_share_mapping;
+pub mod share_mapping;
diff --git a/actions/src/remote_actions/mapping_manage/edit_mapping.rs b/actions/src/remote_actions/mapping_manage/edit_mapping.rs
new file mode 100644
index 0000000..b66f568
--- /dev/null
+++ b/actions/src/remote_actions/mapping_manage/edit_mapping.rs
@@ -0,0 +1,157 @@
+use std::collections::HashMap;
+
+use action_system::{action::ActionContext, macros::action_gen};
+use serde::{Deserialize, Serialize};
+use tcp_connection::error::TcpTargetError;
+use vcs_data::data::local::{
+ vault_modified::sign_vault_modified,
+ workspace_analyzer::{FromRelativePathBuf, ToRelativePathBuf},
+};
+
+use crate::{
+ remote_actions::{
+ auth_member, check_connection_instance, get_current_sheet_name, try_get_vault,
+ },
+ write_and_return,
+};
+
+pub type OperationArgument = (EditMappingOperations, Option<ToRelativePathBuf>);
+
+#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
+pub enum EditMappingOperations {
+ Move,
+ Erase,
+}
+
+#[derive(Serialize, Deserialize, Default)]
+pub enum EditMappingActionResult {
+ Success,
+
+ // Fail
+ AuthorizeFailed(String),
+ EditNotAllowed,
+ MappingNotFound(FromRelativePathBuf),
+ InvalidMove(InvalidMoveReason),
+
+ #[default]
+ Unknown,
+}
+
+#[derive(Serialize, Deserialize)]
+pub enum InvalidMoveReason {
+ MoveOperationButNoTarget(FromRelativePathBuf),
+ ContainsDuplicateMapping(ToRelativePathBuf),
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct EditMappingActionArguments {
+ pub operations: HashMap<FromRelativePathBuf, OperationArgument>,
+}
+
+/// This Action only modifies Sheet Mapping and
+/// does not interfere with the actual location of local files or Local Mapping
+#[action_gen]
+pub async fn edit_mapping_action(
+ ctx: ActionContext,
+ args: EditMappingActionArguments,
+) -> Result<EditMappingActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ let (member_id, is_host_mode) = match auth_member(&ctx, instance).await {
+ Ok(id) => id,
+ Err(e) => {
+ return Ok(EditMappingActionResult::AuthorizeFailed(e.to_string()));
+ }
+ };
+
+ // Check sheet
+ let (sheet_name, is_ref_sheet) =
+ get_current_sheet_name(&ctx, instance, &member_id, true).await?;
+
+ // Can modify Sheet when not in reference sheet or in Host mode
+ let can_modify_sheet = !is_ref_sheet || is_host_mode;
+
+ if !can_modify_sheet {
+ return Ok(EditMappingActionResult::EditNotAllowed);
+ }
+
+ if ctx.is_proc_on_remote() {
+ let vault = try_get_vault(&ctx)?;
+ let mut sheet = vault.sheet(&sheet_name).await?;
+
+ // Precheck
+ for (from_path, (operation, to_path)) in args.operations.iter() {
+ // Check mapping exists
+ if !sheet.mapping().contains_key(from_path) {
+ write_and_return!(
+ instance,
+ EditMappingActionResult::MappingNotFound(from_path.clone())
+ );
+ }
+
+ // Move check
+ if operation == &EditMappingOperations::Move {
+ // Check if target exists
+ if let Some(to_path) = to_path {
+ // Check if target is duplicate
+ if sheet.mapping().contains_key(to_path) {
+ write_and_return!(
+ instance,
+ EditMappingActionResult::InvalidMove(
+ InvalidMoveReason::ContainsDuplicateMapping(to_path.clone())
+ )
+ );
+ }
+ } else {
+ write_and_return!(
+ instance,
+ EditMappingActionResult::InvalidMove(
+ InvalidMoveReason::MoveOperationButNoTarget(from_path.clone())
+ )
+ );
+ }
+ }
+ }
+
+ // Process
+ for (from_path, (operation, to_path)) in args.operations {
+ match operation {
+ // During the Precheck phase, it has been ensured that:
+ // 1. The mapping to be edited for the From path indeed exists
+ // 2. The location of the To path is indeed empty
+ // 3. In Move mode, To path can be safely unwrapped
+ // Therefore, the following unwrap() calls are safe to execute
+ EditMappingOperations::Move => {
+ let mapping = sheet.mapping_mut().remove(&from_path).unwrap();
+ let to_path = to_path.unwrap();
+ sheet
+ .add_mapping(to_path, mapping.id, mapping.version)
+ .await?;
+ }
+ EditMappingOperations::Erase => {
+ sheet.mapping_mut().remove(&from_path).unwrap();
+ }
+ }
+ }
+
+ // Write
+ sheet.persist().await?;
+
+ write_and_return!(instance, EditMappingActionResult::Success);
+ }
+
+ if ctx.is_proc_on_local() {
+ let result = instance
+ .lock()
+ .await
+ .read::<EditMappingActionResult>()
+ .await?;
+ if matches!(result, EditMappingActionResult::Success) {
+ sign_vault_modified(true).await;
+ }
+ return Ok(result);
+ }
+
+ Ok(EditMappingActionResult::Success)
+}
diff --git a/actions/src/remote_actions/mapping_manage/merge_share_mapping.rs b/actions/src/remote_actions/mapping_manage/merge_share_mapping.rs
new file mode 100644
index 0000000..1034029
--- /dev/null
+++ b/actions/src/remote_actions/mapping_manage/merge_share_mapping.rs
@@ -0,0 +1,117 @@
+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::{
+ local::vault_modified::sign_vault_modified,
+ vault::sheet_share::{ShareMergeMode, SheetShareId},
+};
+
+use crate::{
+ remote_actions::{
+ auth_member, check_connection_instance, get_current_sheet_name, try_get_vault,
+ },
+ write_and_return,
+};
+
+#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
+pub struct MergeShareMappingArguments {
+ pub share_id: SheetShareId,
+ pub share_merge_mode: ShareMergeMode,
+}
+
+#[derive(Serialize, Deserialize, Default)]
+pub enum MergeShareMappingActionResult {
+ Success,
+
+ // Fail
+ HasConflicts,
+ AuthorizeFailed(String),
+ EditNotAllowed,
+ ShareIdNotFound(SheetShareId),
+ MergeFails(String),
+
+ #[default]
+ Unknown,
+}
+
+#[action_gen]
+pub async fn merge_share_mapping_action(
+ ctx: ActionContext,
+ args: MergeShareMappingArguments,
+) -> Result<MergeShareMappingActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ let (member_id, is_host_mode) = match auth_member(&ctx, instance).await {
+ Ok(id) => id,
+ Err(e) => {
+ return Ok(MergeShareMappingActionResult::AuthorizeFailed(
+ e.to_string(),
+ ));
+ }
+ };
+
+ // Check sheet
+ let (sheet_name, is_ref_sheet) =
+ get_current_sheet_name(&ctx, instance, &member_id, true).await?;
+
+ // Can modify Sheet when not in reference sheet or in Host mode
+ let can_modify_sheet = !is_ref_sheet || is_host_mode;
+
+ if !can_modify_sheet {
+ return Ok(MergeShareMappingActionResult::EditNotAllowed);
+ }
+
+ if ctx.is_proc_on_remote() {
+ let vault = try_get_vault(&ctx)?;
+ let share_id = args.share_id;
+
+ // Get the share and sheet
+ let (sheet, share) = if vault.share_file_path(&sheet_name, &share_id).exists() {
+ let sheet = vault.sheet(&sheet_name).await?;
+ let share = sheet.get_share(&share_id).await?;
+ (sheet, share)
+ } else {
+ // Share does not exist
+ write_and_return!(
+ instance,
+ MergeShareMappingActionResult::ShareIdNotFound(share_id.clone())
+ );
+ };
+
+ // Perform the merge
+ match sheet.merge_share(share, args.share_merge_mode).await {
+ Ok(_) => write_and_return!(instance, MergeShareMappingActionResult::Success),
+ Err(e) => match e.kind() {
+ ErrorKind::AlreadyExists => {
+ write_and_return!(instance, MergeShareMappingActionResult::HasConflicts);
+ }
+ _ => {
+ write_and_return!(
+ instance,
+ MergeShareMappingActionResult::MergeFails(e.to_string())
+ );
+ }
+ },
+ }
+ }
+
+ if ctx.is_proc_on_local() {
+ let result = instance
+ .lock()
+ .await
+ .read::<MergeShareMappingActionResult>()
+ .await?;
+ match result {
+ MergeShareMappingActionResult::Success => {
+ sign_vault_modified(true).await;
+ }
+ _ => {}
+ }
+ return Ok(result);
+ }
+
+ Ok(MergeShareMappingActionResult::Success)
+}
diff --git a/actions/src/remote_actions/mapping_manage/share_mapping.rs b/actions/src/remote_actions/mapping_manage/share_mapping.rs
new file mode 100644
index 0000000..5c77e53
--- /dev/null
+++ b/actions/src/remote_actions/mapping_manage/share_mapping.rs
@@ -0,0 +1,135 @@
+use action_system::{action::ActionContext, macros::action_gen};
+use serde::{Deserialize, Serialize};
+use tcp_connection::error::TcpTargetError;
+use vcs_data::{
+ constants::VAULT_HOST_NAME,
+ data::{local::workspace_analyzer::FromRelativePathBuf, sheet::SheetName},
+};
+
+use crate::{
+ remote_actions::{
+ auth_member, check_connection_instance, get_current_sheet_name, try_get_vault,
+ },
+ write_and_return,
+};
+
+#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
+pub struct ShareMappingArguments {
+ pub mappings: Vec<FromRelativePathBuf>,
+ pub description: String,
+ // None = current sheet,
+ // Some(sheet_name) = other ref(public) sheet
+ pub from_sheet: Option<SheetName>,
+ pub to_sheet: SheetName,
+}
+
+#[derive(Serialize, Deserialize, Default)]
+pub enum ShareMappingActionResult {
+ Success,
+
+ // Fail
+ AuthorizeFailed(String),
+ TargetSheetNotFound(SheetName),
+ TargetIsSelf,
+ MappingNotFound(FromRelativePathBuf),
+
+ #[default]
+ Unknown,
+}
+
+#[action_gen]
+pub async fn share_mapping_action(
+ ctx: ActionContext,
+ args: ShareMappingArguments,
+) -> Result<ShareMappingActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ let (member_id, _is_host_mode) = match auth_member(&ctx, instance).await {
+ Ok(id) => id,
+ Err(e) => {
+ return Ok(ShareMappingActionResult::AuthorizeFailed(e.to_string()));
+ }
+ };
+
+ // Check sheet
+ let sheet_name = args.from_sheet.unwrap_or(
+ get_current_sheet_name(&ctx, instance, &member_id, true)
+ .await?
+ .0,
+ );
+
+ if ctx.is_proc_on_remote() {
+ let vault = try_get_vault(&ctx)?;
+ let sheet = vault.sheet(&sheet_name).await?;
+
+ // Tip: Because sheet_name may specify a sheet that does not belong to the user,
+ // a secondary verification is required.
+
+ // Check if the sheet holder is Some and matches the member_id or is the host
+ let Some(holder) = sheet.holder() else {
+ // If there's no holder, the sheet cannot be shared from
+ write_and_return!(
+ instance,
+ ShareMappingActionResult::AuthorizeFailed("Sheet has no holder".to_string())
+ );
+ };
+
+ // Verify the holder is either the current member or the host
+ if holder != &member_id && holder != VAULT_HOST_NAME {
+ write_and_return!(
+ instance,
+ ShareMappingActionResult::AuthorizeFailed(
+ "Not sheet holder or ref sheet".to_string()
+ )
+ );
+ }
+
+ let to_sheet_name = args.to_sheet;
+
+ // Verify target sheet exists
+ if !vault.sheet_names()?.contains(&to_sheet_name) {
+ // Does not exist
+ write_and_return!(
+ instance,
+ ShareMappingActionResult::TargetSheetNotFound(to_sheet_name.clone())
+ );
+ }
+
+ // Verify sheet is not self
+ if sheet_name == to_sheet_name {
+ // Is self
+ write_and_return!(instance, ShareMappingActionResult::TargetIsSelf);
+ }
+
+ // Verify all mappings are correct
+ for mapping in args.mappings.iter() {
+ if !sheet.mapping().contains_key(mapping) {
+ // If any mapping is invalid, indicate failure
+ write_and_return!(
+ instance,
+ ShareMappingActionResult::MappingNotFound(mapping.clone())
+ );
+ }
+ }
+
+ // Execute sharing logic
+ sheet
+ .share_mappings(&to_sheet_name, args.mappings, &member_id, args.description)
+ .await?;
+
+ // Sharing successful
+ write_and_return!(instance, ShareMappingActionResult::Success);
+ }
+
+ if ctx.is_proc_on_local() {
+ let result = instance
+ .lock()
+ .await
+ .read::<ShareMappingActionResult>()
+ .await?;
+ return Ok(result);
+ }
+
+ Ok(ShareMappingActionResult::Success)
+}
diff --git a/actions/src/remote_actions/sheet_manage.rs b/actions/src/remote_actions/sheet_manage.rs
new file mode 100644
index 0000000..a3a91a2
--- /dev/null
+++ b/actions/src/remote_actions/sheet_manage.rs
@@ -0,0 +1,2 @@
+pub mod drop_sheet;
+pub mod make_sheet;
diff --git a/actions/src/remote_actions/sheet_manage/drop_sheet.rs b/actions/src/remote_actions/sheet_manage/drop_sheet.rs
new file mode 100644
index 0000000..0dcd790
--- /dev/null
+++ b/actions/src/remote_actions/sheet_manage/drop_sheet.rs
@@ -0,0 +1,123 @@
+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::{local::vault_modified::sign_vault_modified, sheet::SheetName};
+
+use crate::{
+ remote_actions::{
+ auth_member, check_connection_instance, try_get_local_workspace, try_get_vault,
+ },
+ write_and_return,
+};
+
+#[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, is_host_mode) = 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 that the sheet holder is either the current user or the host
+ // All sheets belong to the host
+ if holder != &member_id && !is_host_mode {
+ 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?;
+ if matches!(result, DropSheetActionResult::Success) {
+ sign_vault_modified(true).await;
+ }
+ return Ok(result);
+ }
+
+ Err(TcpTargetError::NoResult("No result.".to_string()))
+}
diff --git a/actions/src/remote_actions/sheet_manage/make_sheet.rs b/actions/src/remote_actions/sheet_manage/make_sheet.rs
new file mode 100644
index 0000000..ac5e140
--- /dev/null
+++ b/actions/src/remote_actions/sheet_manage/make_sheet.rs
@@ -0,0 +1,98 @@
+use action_system::{action::ActionContext, macros::action_gen};
+use serde::{Deserialize, Serialize};
+use tcp_connection::error::TcpTargetError;
+use vcs_data::{
+ constants::VAULT_HOST_NAME,
+ data::{local::vault_modified::sign_vault_modified, sheet::SheetName},
+};
+
+use crate::{
+ remote_actions::{auth_member, check_connection_instance, try_get_vault},
+ write_and_return,
+};
+
+#[derive(Default, Serialize, Deserialize)]
+pub enum MakeSheetActionResult {
+ Success,
+ SuccessRestore,
+
+ // Fail
+ AuthorizeFailed(String),
+ SheetAlreadyExists,
+ SheetCreationFailed(String),
+
+ #[default]
+ Unknown,
+}
+
+/// Build a sheet with context
+#[action_gen]
+pub async fn make_sheet_action(
+ ctx: ActionContext,
+ sheet_name: SheetName,
+) -> Result<MakeSheetActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ let (member_id, is_host_mode) = match auth_member(&ctx, instance).await {
+ Ok(id) => id,
+ Err(e) => return Ok(MakeSheetActionResult::AuthorizeFailed(e.to_string())),
+ };
+
+ if ctx.is_proc_on_remote() {
+ let vault = try_get_vault(&ctx)?;
+ let holder = if is_host_mode {
+ VAULT_HOST_NAME.to_string()
+ } else {
+ member_id
+ };
+
+ // Check if the sheet already exists
+ 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(holder.clone());
+ 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, &holder).await {
+ Ok(_) => {
+ write_and_return!(instance, MakeSheetActionResult::Success);
+ }
+ Err(e) => {
+ write_and_return!(
+ instance,
+ MakeSheetActionResult::SheetCreationFailed(e.to_string())
+ );
+ }
+ }
+ }
+ }
+
+ if ctx.is_proc_on_local() {
+ let result = instance
+ .lock()
+ .await
+ .read::<MakeSheetActionResult>()
+ .await?;
+ if matches!(result, MakeSheetActionResult::Success) {
+ sign_vault_modified(true).await;
+ }
+ return Ok(result);
+ }
+
+ Err(TcpTargetError::NoResult("No result.".to_string()))
+}
diff --git a/actions/src/remote_actions/workspace_manage.rs b/actions/src/remote_actions/workspace_manage.rs
new file mode 100644
index 0000000..15f70e8
--- /dev/null
+++ b/actions/src/remote_actions/workspace_manage.rs
@@ -0,0 +1,2 @@
+pub mod set_upstream_vault;
+pub mod update_to_latest_info;
diff --git a/actions/src/remote_actions/workspace_manage/set_upstream_vault.rs b/actions/src/remote_actions/workspace_manage/set_upstream_vault.rs
new file mode 100644
index 0000000..d3201b2
--- /dev/null
+++ b/actions/src/remote_actions/workspace_manage/set_upstream_vault.rs
@@ -0,0 +1,101 @@
+use std::net::SocketAddr;
+
+use action_system::{action::ActionContext, macros::action_gen};
+use cfg_file::config::ConfigFile;
+use log::info;
+use serde::{Deserialize, Serialize};
+use tcp_connection::error::TcpTargetError;
+use vcs_data::data::{local::config::LocalConfig, vault::config::VaultUuid};
+
+use crate::remote_actions::{
+ auth_member, check_connection_instance, try_get_local_workspace, try_get_vault,
+};
+
+#[derive(Serialize, Deserialize)]
+pub enum SetUpstreamVaultActionResult {
+ // Success
+ DirectedAndStained,
+ Redirected,
+
+ // Fail
+ AlreadyStained,
+ AuthorizeFailed(String),
+ RedirectFailed(String),
+ SameUpstream,
+
+ Done,
+}
+
+#[action_gen]
+pub async fn set_upstream_vault_action(
+ ctx: ActionContext,
+ upstream: SocketAddr,
+) -> Result<SetUpstreamVaultActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ if let Err(e) = auth_member(&ctx, instance).await {
+ return Ok(SetUpstreamVaultActionResult::AuthorizeFailed(e.to_string()));
+ }
+
+ // Direct
+ if ctx.is_proc_on_remote() {
+ let vault = try_get_vault(&ctx)?;
+ instance
+ .lock()
+ .await
+ .write(*vault.config().vault_uuid())
+ .await?;
+ return Ok(SetUpstreamVaultActionResult::Done);
+ }
+
+ if ctx.is_proc_on_local() {
+ info!("Authorize successful. directing to upstream vault.");
+
+ // Read the vault UUID from the instance
+ let vault_uuid = instance.lock().await.read::<VaultUuid>().await?;
+
+ let local_workspace = try_get_local_workspace(&ctx)?;
+ let local_config = local_workspace.config();
+
+ let mut mut_local_config = local_config.lock().await;
+ if !mut_local_config.stained() {
+ // Stain the local workspace
+ mut_local_config.stain(vault_uuid);
+
+ // Set the upstream address
+ mut_local_config.set_vault_addr(upstream);
+
+ // Store the updated config
+ LocalConfig::write(&mut_local_config).await?;
+
+ info!("Workspace stained!");
+ return Ok(SetUpstreamVaultActionResult::DirectedAndStained);
+ } else {
+ // Local workspace is already stained, redirecting
+ let Some(stained_uuid) = mut_local_config.stained_uuid() else {
+ return Ok(SetUpstreamVaultActionResult::RedirectFailed(
+ "Stained uuid not found".to_string(),
+ ));
+ };
+ let local_upstream = mut_local_config.upstream_addr();
+
+ // Address changed, but same UUID.
+ if vault_uuid == stained_uuid {
+ if local_upstream != upstream {
+ // Set the upstream address
+ mut_local_config.set_vault_addr(upstream);
+
+ // Store the updated config
+ LocalConfig::write(&mut_local_config).await?;
+ return Ok(SetUpstreamVaultActionResult::Redirected);
+ } else {
+ return Ok(SetUpstreamVaultActionResult::SameUpstream);
+ }
+ }
+ return Ok(SetUpstreamVaultActionResult::AlreadyStained);
+ }
+ }
+
+ Err(TcpTargetError::NoResult("No result.".to_string()))
+}
diff --git a/actions/src/actions/local_actions.rs b/actions/src/remote_actions/workspace_manage/update_to_latest_info.rs
index 53a1ff8..695d1f0 100644
--- a/actions/src/actions/local_actions.rs
+++ b/actions/src/remote_actions/workspace_manage/update_to_latest_info.rs
@@ -1,7 +1,6 @@
use std::{
collections::{HashMap, HashSet},
io::ErrorKind,
- net::SocketAddr,
path::PathBuf,
time::SystemTime,
};
@@ -19,7 +18,6 @@ use vcs_data::{
data::{
local::{
cached_sheet::CachedSheet,
- config::LocalConfig,
latest_file_data::LatestFileData,
latest_info::{LatestInfo, SheetInfo},
vault_modified::sign_vault_modified,
@@ -27,107 +25,17 @@ use vcs_data::{
member::MemberId,
sheet::{SheetData, SheetName, SheetPathBuf},
vault::{
- config::VaultUuid,
sheet_share::{Share, SheetShareId},
virtual_file::{VirtualFileId, VirtualFileVersion, VirtualFileVersionDescription},
},
},
};
-use crate::actions::{
+use crate::remote_actions::{
auth_member, check_connection_instance, try_get_local_workspace, try_get_vault,
};
#[derive(Serialize, Deserialize)]
-pub enum SetUpstreamVaultActionResult {
- // Success
- DirectedAndStained,
- Redirected,
-
- // Fail
- AlreadyStained,
- AuthorizeFailed(String),
- RedirectFailed(String),
- SameUpstream,
-
- Done,
-}
-
-#[action_gen]
-pub async fn set_upstream_vault_action(
- ctx: ActionContext,
- upstream: SocketAddr,
-) -> Result<SetUpstreamVaultActionResult, TcpTargetError> {
- let instance = check_connection_instance(&ctx)?;
-
- // Auth Member
- if let Err(e) = auth_member(&ctx, instance).await {
- return Ok(SetUpstreamVaultActionResult::AuthorizeFailed(e.to_string()));
- }
-
- // Direct
- if ctx.is_proc_on_remote() {
- let vault = try_get_vault(&ctx)?;
- instance
- .lock()
- .await
- .write(*vault.config().vault_uuid())
- .await?;
- return Ok(SetUpstreamVaultActionResult::Done);
- }
-
- if ctx.is_proc_on_local() {
- info!("Authorize successful. directing to upstream vault.");
-
- // Read the vault UUID from the instance
- let vault_uuid = instance.lock().await.read::<VaultUuid>().await?;
-
- let local_workspace = try_get_local_workspace(&ctx)?;
- let local_config = local_workspace.config();
-
- let mut mut_local_config = local_config.lock().await;
- if !mut_local_config.stained() {
- // Stain the local workspace
- mut_local_config.stain(vault_uuid);
-
- // Set the upstream address
- mut_local_config.set_vault_addr(upstream);
-
- // Store the updated config
- LocalConfig::write(&mut_local_config).await?;
-
- info!("Workspace stained!");
- return Ok(SetUpstreamVaultActionResult::DirectedAndStained);
- } else {
- // Local workspace is already stained, redirecting
- let Some(stained_uuid) = mut_local_config.stained_uuid() else {
- return Ok(SetUpstreamVaultActionResult::RedirectFailed(
- "Stained uuid not found".to_string(),
- ));
- };
- let local_upstream = mut_local_config.upstream_addr();
-
- // Address changed, but same UUID.
- if vault_uuid == stained_uuid {
- if local_upstream != upstream {
- // Set the upstream address
- mut_local_config.set_vault_addr(upstream);
-
- // Store the updated config
- LocalConfig::write(&mut_local_config).await?;
- return Ok(SetUpstreamVaultActionResult::Redirected);
- } else {
- return Ok(SetUpstreamVaultActionResult::SameUpstream);
- }
- }
- return Ok(SetUpstreamVaultActionResult::AlreadyStained);
- }
- }
-
- Err(TcpTargetError::NoResult("No result.".to_string()))
-}
-
-#[derive(Serialize, Deserialize)]
pub enum UpdateToLatestInfoResult {
Success,