summaryrefslogtreecommitdiff
path: root/crates/vcs_data/src/data/local/local_sheet.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2025-11-17 11:49:49 +0800
committer魏曹先生 <1992414357@qq.com>2025-11-17 11:49:49 +0800
commit7b97b52af021500d8085c875d20215e8dc0f53cc (patch)
tree9b8219363380db3330bda75e28e364154224eca8 /crates/vcs_data/src/data/local/local_sheet.rs
parente190d90594b17fb16849a13198af3f5152414e4c (diff)
feat: Add file status tracking and SHA1 hash system
- Implement SHA1 hash calculation module with async support - Add file status analysis for tracking moves, creates, and modifications - Enhance local file management with relative path handling - Update virtual file actions with improved tracking capabilities
Diffstat (limited to 'crates/vcs_data/src/data/local/local_sheet.rs')
-rw-r--r--crates/vcs_data/src/data/local/local_sheet.rs207
1 files changed, 179 insertions, 28 deletions
diff --git a/crates/vcs_data/src/data/local/local_sheet.rs b/crates/vcs_data/src/data/local/local_sheet.rs
index bfe8d01..980fa49 100644
--- a/crates/vcs_data/src/data/local/local_sheet.rs
+++ b/crates/vcs_data/src/data/local/local_sheet.rs
@@ -1,8 +1,7 @@
-use std::{collections::HashMap, io::Error, path::PathBuf};
+use std::{collections::HashMap, io::Error, path::PathBuf, time::SystemTime};
use ::serde::{Deserialize, Serialize};
use cfg_file::{ConfigFile, config::ConfigFile};
-use chrono::NaiveDate;
use string_proc::format_path::format_path;
use crate::{
@@ -10,11 +9,13 @@ use crate::{
data::{
local::LocalWorkspace,
member::MemberId,
- vault::virtual_file::{VirtualFileId, VirtualFileVersionDescription},
+ sheet::SheetName,
+ vault::virtual_file::{VirtualFileId, VirtualFileVersion, VirtualFileVersionDescription},
},
};
pub type LocalFilePathBuf = PathBuf;
+pub type LocalSheetPathBuf = PathBuf;
/// # Local Sheet
/// Local sheet information, used to record metadata of actual local files,
@@ -27,54 +28,168 @@ pub struct LocalSheet<'a> {
pub(crate) data: LocalSheetData,
}
-#[derive(Debug, Default, Serialize, Deserialize, ConfigFile)]
+#[derive(Debug, Default, Serialize, Deserialize, ConfigFile, Clone)]
#[cfg_file(path = CLIENT_FILE_LOCAL_SHEET_NOSET)] // Do not use LocalSheet::write or LocalSheet::read
pub struct LocalSheetData {
- /// Local file path to virtual file ID mapping.
+ /// Local file path to metadata mapping.
#[serde(rename = "mapping")]
- pub(crate) mapping: HashMap<LocalFilePathBuf, MappingMetaData>, // Path to VFID
+ pub(crate) mapping: HashMap<LocalFilePathBuf, LocalMappingMetadata>,
+
+ pub(crate) vfs: HashMap<VirtualFileId, LocalFilePathBuf>,
}
-#[derive(Debug, Default, Serialize, Deserialize)]
-pub struct MappingMetaData {
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct LocalMappingMetadata {
/// Hash value generated immediately after the file is downloaded to the local workspace
#[serde(rename = "hash")]
pub(crate) hash_when_updated: String,
/// Time when the file was downloaded to the local workspace
- #[serde(rename = "date", with = "naive_date_serde")]
- pub(crate) date_when_updated: NaiveDate,
+ pub(crate) time_when_updated: SystemTime,
/// Size of the file when downloaded to the local workspace
#[serde(rename = "size")]
pub(crate) size_when_updated: u64,
/// Version description when the file was downloaded to the local workspace
- #[serde(rename = "version")]
+ #[serde(rename = "version_desc")]
pub(crate) version_desc_when_updated: VirtualFileVersionDescription,
+ /// Version when the file was downloaded to the local workspace
+ #[serde(rename = "version")]
+ pub(crate) version_when_updated: VirtualFileVersion,
+
/// Virtual file ID corresponding to the local path
#[serde(rename = "id")]
pub(crate) mapping_vfid: VirtualFileId,
+
+ /// Latest modifiy check time
+ pub(crate) last_modifiy_check_time: SystemTime,
+
+ /// Latest modifiy check result
+ pub(crate) last_modifiy_check_result: bool,
+}
+
+impl LocalSheetData {
+ /// Wrap LocalSheetData into LocalSheet with workspace, member, and sheet name
+ pub fn wrap_to_local_sheet<'a>(
+ self,
+ workspace: &'a LocalWorkspace,
+ member: MemberId,
+ sheet_name: SheetName,
+ ) -> LocalSheet<'a> {
+ LocalSheet {
+ local_workspace: workspace,
+ member,
+ sheet_name,
+ data: self,
+ }
+ }
+}
+
+impl LocalMappingMetadata {
+ /// Create a new MappingMetaData instance
+ pub fn new(
+ hash_when_updated: String,
+ time_when_updated: SystemTime,
+ size_when_updated: u64,
+ version_desc_when_updated: VirtualFileVersionDescription,
+ version_when_updated: VirtualFileVersion,
+ mapping_vfid: VirtualFileId,
+ last_modifiy_check_time: SystemTime,
+ last_modifiy_check_result: bool,
+ ) -> Self {
+ Self {
+ hash_when_updated,
+ time_when_updated,
+ size_when_updated,
+ version_desc_when_updated,
+ version_when_updated,
+ mapping_vfid,
+ last_modifiy_check_time,
+ last_modifiy_check_result,
+ }
+ }
+
+ /// Getter for hash_when_updated
+ pub fn hash_when_updated(&self) -> &String {
+ &self.hash_when_updated
+ }
+
+ /// Getter for date_when_updated
+ pub fn time_when_updated(&self) -> &SystemTime {
+ &self.time_when_updated
+ }
+
+ /// Getter for size_when_updated
+ pub fn size_when_updated(&self) -> u64 {
+ self.size_when_updated
+ }
+
+ /// Getter for version_desc_when_updated
+ pub fn version_desc_when_updated(&self) -> &VirtualFileVersionDescription {
+ &self.version_desc_when_updated
+ }
+
+ /// Getter for version_when_updated
+ pub fn version_when_updated(&self) -> &VirtualFileVersion {
+ &self.version_when_updated
+ }
+
+ /// Getter for mapping_vfid
+ pub fn mapping_vfid(&self) -> &VirtualFileId {
+ &self.mapping_vfid
+ }
+
+ /// Getter for last_modifiy_check_time
+ pub fn last_modifiy_check_time(&self) -> &SystemTime {
+ &self.last_modifiy_check_time
+ }
+
+ /// Getter for last_modifiy_check_result
+ pub fn last_modifiy_check_result(&self) -> bool {
+ self.last_modifiy_check_result
+ }
+}
+
+impl Default for LocalMappingMetadata {
+ fn default() -> Self {
+ Self {
+ hash_when_updated: Default::default(),
+ time_when_updated: SystemTime::now(),
+ size_when_updated: Default::default(),
+ version_desc_when_updated: Default::default(),
+ version_when_updated: Default::default(),
+ mapping_vfid: Default::default(),
+ last_modifiy_check_time: SystemTime::now(),
+ last_modifiy_check_result: false,
+ }
+ }
}
-mod naive_date_serde {
- use chrono::NaiveDate;
+mod instant_serde {
use serde::{self, Deserialize, Deserializer, Serializer};
+ use tokio::time::Instant;
- pub fn serialize<S>(date: &NaiveDate, serializer: S) -> Result<S::Ok, S::Error>
+ pub fn serialize<S>(instant: &Instant, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- serializer.serialize_str(&date.format("%Y-%m-%d").to_string())
+ serializer.serialize_u64(instant.elapsed().as_secs())
}
- pub fn deserialize<'de, D>(deserializer: D) -> Result<NaiveDate, D::Error>
+ pub fn deserialize<'de, D>(deserializer: D) -> Result<Instant, D::Error>
where
D: Deserializer<'de>,
{
- let s = String::deserialize(deserializer)?;
- NaiveDate::parse_from_str(&s, "%Y-%m-%d").map_err(serde::de::Error::custom)
+ let secs = u64::deserialize(deserializer)?;
+ Ok(Instant::now() - std::time::Duration::from_secs(secs))
+ }
+}
+
+impl<'a> From<&'a LocalSheet<'a>> for &'a LocalSheetData {
+ fn from(sheet: &'a LocalSheet<'a>) -> Self {
+ &sheet.data
}
}
@@ -83,10 +198,12 @@ impl<'a> LocalSheet<'a> {
pub fn add_mapping(
&mut self,
path: LocalFilePathBuf,
- mapping: MappingMetaData,
+ mapping: LocalMappingMetadata,
) -> Result<(), std::io::Error> {
let path = format_path(path)?;
- if self.data.mapping.contains_key(&path) {
+ if self.data.mapping.contains_key(&path)
+ || self.data.vfs.contains_key(&mapping.mapping_vfid)
+ {
return Err(Error::new(
std::io::ErrorKind::AlreadyExists,
"Mapping already exists",
@@ -100,8 +217,8 @@ impl<'a> LocalSheet<'a> {
/// Move mapping to other path
pub fn move_mapping(
&mut self,
- from: LocalFilePathBuf,
- to: LocalFilePathBuf,
+ from: &LocalFilePathBuf,
+ to: &LocalFilePathBuf,
) -> Result<(), std::io::Error> {
let from = format_path(from)?;
let to = format_path(to)?;
@@ -124,11 +241,26 @@ impl<'a> LocalSheet<'a> {
Ok(())
}
+ /// Get immutable mapping data
+ pub fn mapping_data(
+ &self,
+ path: &LocalFilePathBuf,
+ ) -> Result<&LocalMappingMetadata, std::io::Error> {
+ let path = format_path(path)?;
+ let Some(data) = self.data.mapping.get(&path) else {
+ return Err(Error::new(
+ std::io::ErrorKind::NotFound,
+ "Path is not found.",
+ ));
+ };
+ Ok(data)
+ }
+
/// Get muttable mapping data
pub fn mapping_data_mut(
&mut self,
- path: LocalFilePathBuf,
- ) -> Result<&mut MappingMetaData, std::io::Error> {
+ path: &LocalFilePathBuf,
+ ) -> Result<&mut LocalMappingMetadata, std::io::Error> {
let path = format_path(path)?;
let Some(data) = self.data.mapping.get_mut(&path) else {
return Err(Error::new(
@@ -139,12 +271,31 @@ impl<'a> LocalSheet<'a> {
Ok(data)
}
- /// Persist the sheet to disk
- pub async fn persist(&mut self) -> Result<(), std::io::Error> {
- let _path = self
+ /// Write the sheet to disk
+ pub async fn write(&mut self) -> Result<(), std::io::Error> {
+ let path = self
.local_workspace
.local_sheet_path(&self.member, &self.sheet_name);
- LocalSheetData::write_to(&self.data, &self.sheet_name).await?;
+ self.write_to_path(path).await
+ }
+
+ /// Write the sheet to custom path
+ pub async fn write_to_path(&mut self, path: impl Into<PathBuf>) -> Result<(), std::io::Error> {
+ let path = path.into();
+
+ self.data.vfs = HashMap::new();
+ for (path, mapping) in self.data.mapping.iter() {
+ self.data
+ .vfs
+ .insert(mapping.mapping_vfid.clone(), path.clone());
+ }
+
+ LocalSheetData::write_to(&self.data, path).await?;
Ok(())
}
+
+ /// Get path by VirtualFileId
+ pub fn path_by_id(&self, vfid: &VirtualFileId) -> Option<&PathBuf> {
+ self.data.vfs.get(vfid)
+ }
}