diff options
| -rw-r--r-- | crates/vcs_actions/src/actions/local_actions.rs | 72 | ||||
| -rw-r--r-- | crates/vcs_data/src/data/local/file_status.rs | 50 |
2 files changed, 72 insertions, 50 deletions
diff --git a/crates/vcs_actions/src/actions/local_actions.rs b/crates/vcs_actions/src/actions/local_actions.rs index d10c317..f48cf6c 100644 --- a/crates/vcs_actions/src/actions/local_actions.rs +++ b/crates/vcs_actions/src/actions/local_actions.rs @@ -6,17 +6,22 @@ use log::info; use serde::{Deserialize, Serialize}; use tcp_connection::error::TcpTargetError; use tokio::time::Instant; -use vcs_data::data::{ - local::{ - cached_sheet::CachedSheet, - config::LocalConfig, - latest_info::{LatestInfo, SheetInfo}, - local_sheet::LocalSheetData, - member_held::MemberHeld, +use vcs_data::{ + constants::{CLIENT_PATH_CACHED_SHEET, CLIENT_PATH_LOCAL_SHEET}, + data::{ + local::{ + cached_sheet::CachedSheet, + config::LocalConfig, + latest_file_data::LatestFileData, + latest_info::{LatestInfo, SheetInfo}, + }, + member::MemberId, + sheet::{SheetData, SheetName}, + vault::{ + config::VaultUuid, + virtual_file::{VirtualFileId, VirtualFileVersion}, + }, }, - member::MemberId, - sheet::{SheetData, SheetName}, - vault::{config::VaultUuid, virtual_file::VirtualFileId}, }; use crate::actions::{ @@ -236,6 +241,11 @@ pub async fn update_to_latest_info_action( if len < 1 { // Don't return here, continue to next section + // But we need to consume the false marker from the server + if ctx.is_proc_on_local() { + let mut mut_instance = instance.lock().await; + let _: bool = mut_instance.read_msgpack().await?; + } } else { // Send data to local if ctx.is_proc_on_remote() { @@ -336,21 +346,21 @@ pub async fn update_to_latest_info_action( .await?; // Receive information and write to local - let result: HashMap<VirtualFileId, Option<MemberId>> = + let result: HashMap<VirtualFileId, (Option<MemberId>, VirtualFileVersion)> = mut_instance.read_large_msgpack(1024u16).await?; // Read configuration file - let path = MemberHeld::held_file_path(&member_id)?; - let mut member_held = match MemberHeld::read_from(&path).await { + let path = LatestFileData::data_path(&member_id)?; + let mut latest_file_data = match LatestFileData::read_from(&path).await { Ok(r) => r, - Err(_) => MemberHeld::default(), + Err(_) => LatestFileData::default(), }; // Write the received information - member_held.update_held_status(result); + latest_file_data.update_info(result); // Write - MemberHeld::write_to(&member_held, &path).await?; + LatestFileData::write_to(&latest_file_data, &path).await?; } if ctx.is_proc_on_remote() { @@ -362,7 +372,8 @@ pub async fn update_to_latest_info_action( mut_instance.read_large_msgpack(1024u16).await?; // Organize the information - let mut result: HashMap<VirtualFileId, Option<MemberId>> = HashMap::new(); + let mut result: HashMap<VirtualFileId, (Option<MemberId>, VirtualFileVersion)> = + HashMap::new(); for id in holder_wants_know { let Ok(meta) = vault.virtual_file_meta(&id).await else { continue; @@ -370,9 +381,9 @@ pub async fn update_to_latest_info_action( result.insert( id, if meta.hold_member().is_empty() { - None + (None, "".to_string()) } else { - Some(meta.hold_member().to_string()) + (Some(meta.hold_member().to_string()), meta.version_latest()) }, ); } @@ -385,25 +396,24 @@ pub async fn update_to_latest_info_action( // Sync cached sheet to local sheet if ctx.is_proc_on_local() { let workspace = try_get_local_workspace(&ctx)?; - let local_sheet_paths = - extract_sheet_names_from_paths(workspace.local_sheet_paths().await?)?; + let cached_sheet_path = workspace.local_path().join(CLIENT_PATH_CACHED_SHEET); + let local_sheet_path = workspace.local_path().join(CLIENT_PATH_LOCAL_SHEET); + if !local_sheet_path.exists() || !cached_sheet_path.exists() { + // No need to sync + return Ok(UpdateToLatestInfoResult::Success); + } + let cached_sheet_paths = extract_sheet_names_from_paths(CachedSheet::cached_sheet_paths().await?)?; - // Match cached sheets and local heets, and sync content + // Match cached sheets and local sheets, and sync content for (cached_sheet_name, _cached_sheet_path) in cached_sheet_paths { - // Get local sheet path by cached_sheet_name - let Some(local_sheet_path) = local_sheet_paths.get(&cached_sheet_name) else { - continue; - }; - // Read cached sheet and local sheet let cached_sheet = CachedSheet::cached_sheet_data(&cached_sheet_name).await?; - let Ok(local_sheet_data) = LocalSheetData::read_from(local_sheet_path).await else { + let Ok(mut local_sheet) = workspace.local_sheet(&member_id, &cached_sheet_name).await + else { continue; }; - let mut local_sheet = - local_sheet_data.wrap_to_local_sheet(&workspace, "".to_string(), "".to_string()); // Read cached id mapping let Some(cached_sheet_id_mapping) = cached_sheet.id_mapping() else { @@ -437,7 +447,7 @@ pub async fn update_to_latest_info_action( }, _ => {} } - local_sheet.write_to_path(&local_sheet_path).await? + local_sheet.write().await?; } } } diff --git a/crates/vcs_data/src/data/local/file_status.rs b/crates/vcs_data/src/data/local/file_status.rs index c37c21b..8b1c17f 100644 --- a/crates/vcs_data/src/data/local/file_status.rs +++ b/crates/vcs_data/src/data/local/file_status.rs @@ -55,9 +55,9 @@ impl<'a> AnalyzeResult<'a> { // Current member, sheet let (member, sheet_name) = { - let lock = workspace.config.lock().await; - let member = lock.current_account(); - let Some(sheet) = lock.sheet_in_use().clone() else { + let mut_workspace = workspace.config.lock().await; + let member = mut_workspace.current_account(); + let Some(sheet) = mut_workspace.sheet_in_use().clone() else { return Err(Error::new(std::io::ErrorKind::NotFound, "Sheet not found")); }; (member, sheet) @@ -119,8 +119,14 @@ impl<'a> AnalyzeResult<'a> { local_sheet, cached_sheet_data, }; - Self::analyze_moved(&mut result, &file_relative_paths, &analyze_ctx).await?; - Self::analyze_modified(&mut result, &file_relative_paths, &mut analyze_ctx).await?; + Self::analyze_moved(&mut result, &file_relative_paths, &analyze_ctx, &workspace).await?; + Self::analyze_modified( + &mut result, + &file_relative_paths, + &mut analyze_ctx, + &workspace, + ) + .await?; Ok(result) } @@ -131,6 +137,7 @@ impl<'a> AnalyzeResult<'a> { result: &mut AnalyzeResult<'_>, file_relative_paths: &HashSet<PathBuf>, analyze_ctx: &AnalyzeContext<'a>, + workspace: &LocalWorkspace, ) -> Result<(), std::io::Error> { let local_sheet_paths: HashSet<&PathBuf> = match &analyze_ctx.local_sheet { Some(local_sheet) => local_sheet.data.mapping.keys().collect(), @@ -138,20 +145,23 @@ impl<'a> AnalyzeResult<'a> { }; let file_relative_paths_ref: HashSet<&PathBuf> = file_relative_paths.iter().collect(); - // 在本地表存在但实际不存在的文件,为丢失 + // Files that exist in the local sheet but not in reality are considered lost let mut lost_files: HashSet<&PathBuf> = local_sheet_paths .difference(&file_relative_paths_ref) .cloned() .collect(); - // 在本地表不存在但实际存在的文件,记录为新建 + // Files that exist in reality but not in the local sheet are recorded as newly created let mut new_files: HashSet<&PathBuf> = file_relative_paths_ref .difference(&local_sheet_paths) .cloned() .collect(); - // 计算新增的文件 Hash - let new_files_for_hash: Vec<PathBuf> = new_files.iter().map(|p| (*p).clone()).collect(); + // Calculate hashes for new files + let new_files_for_hash: Vec<PathBuf> = new_files + .iter() + .map(|p| workspace.local_path.join(p)) + .collect(); let file_hashes: HashSet<(PathBuf, String)> = match calc_sha1_multi::<PathBuf, Vec<PathBuf>>(new_files_for_hash, 8192).await { Ok(hash) => hash, @@ -161,7 +171,7 @@ impl<'a> AnalyzeResult<'a> { .map(|r| (r.file_path.clone(), r.hash.to_string())) .collect(); - // 建立丢失文件的 Hash 映射表 + // Build hash mapping table for lost files let mut lost_files_hash_mapping: HashMap<String, FromRelativePathBuf> = match &analyze_ctx.local_sheet { Some(local_sheet) => lost_files @@ -175,28 +185,28 @@ impl<'a> AnalyzeResult<'a> { None => HashMap::new(), }; - // 如果这些 Hash 能对应缺失文件的 Hash,那么这对新增和丢失项将被合并为移动项 + // If these hashes correspond to the hashes of missing files, then this pair of new and lost items will be merged into moved items let mut moved_files: HashSet<(FromRelativePathBuf, ToRelativePathBuf)> = HashSet::new(); for (new_path, new_hash) in file_hashes { - // 如果新的 Hash 值命中映射,则添加移动项 + // If the new hash value hits the mapping, add a moved item if let Some(lost_path) = lost_files_hash_mapping.remove(&new_hash) { - // 移除该新增项和丢失项 + // Remove this new item and lost item lost_files.remove(&lost_path); new_files.remove(&new_path); - // 建立移动项 + // Create moved item moved_files.insert((lost_path.clone(), new_path)); } } - // 进入模糊匹配,将其他未匹配的可能移动项进行匹配 - // 如果 新增 和 缺失 数量总和能被 2 整除,则说明还存在文件被移动的可能,考虑尝试模糊匹配 + // Enter fuzzy matching to match other potentially moved items that haven't been matched + // If the total number of new and lost files is divisible by 2, it indicates there might still be files that have been moved, consider trying fuzzy matching if new_files.len() + lost_files.len() % 2 == 0 { - // 尝试模糊匹配 + // Try fuzzy matching // ... } - // 将结果收集,并设置结果 + // Collect results and set the result result.created = new_files.iter().map(|p| (*p).clone()).collect(); result.lost = lost_files.iter().map(|p| (*p).clone()).collect(); result.moved = moved_files @@ -224,6 +234,7 @@ impl<'a> AnalyzeResult<'a> { result: &mut AnalyzeResult<'_>, file_relative_paths: &HashSet<PathBuf>, analyze_ctx: &mut AnalyzeContext<'a>, + workspace: &LocalWorkspace, ) -> Result<(), std::io::Error> { let local_sheet = &mut analyze_ctx.local_sheet.as_mut().unwrap(); let local_path = local_sheet.local_workspace.local_path().clone(); @@ -244,7 +255,8 @@ impl<'a> AnalyzeResult<'a> { } // Calculate hash - let hash_calc = match sha1_hash::calc_sha1(path, 2048).await { + let hash_calc = match sha1_hash::calc_sha1(workspace.local_path.join(path), 2048).await + { Ok(hash) => hash, Err(e) => return Err(Error::new(std::io::ErrorKind::Other, e)), }; |
