diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-03-11 22:52:25 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-03-11 22:52:25 +0800 |
| commit | 085bce616f68eb6c1586f7a7e1089b5f4cdd0155 (patch) | |
| tree | 5782ae03692754845958ef06b92c56805ddd7bbc /systems/workspace/src | |
| parent | 55c7ea778be2f3ce44d88440607ac8d4117e31d2 (diff) | |
Add vault and workspace systems with config management
Diffstat (limited to 'systems/workspace/src')
| -rw-r--r-- | systems/workspace/src/func.rs | 45 | ||||
| -rw-r--r-- | systems/workspace/src/lib.rs | 2 | ||||
| -rw-r--r-- | systems/workspace/src/workspace.rs | 38 | ||||
| -rw-r--r-- | systems/workspace/src/workspace/config.rs | 121 | ||||
| -rw-r--r-- | systems/workspace/src/workspace/error.rs | 40 | ||||
| -rw-r--r-- | systems/workspace/src/workspace/manager.rs | 38 |
6 files changed, 284 insertions, 0 deletions
diff --git a/systems/workspace/src/func.rs b/systems/workspace/src/func.rs new file mode 100644 index 0000000..4a1e57d --- /dev/null +++ b/systems/workspace/src/func.rs @@ -0,0 +1,45 @@ +use std::{env::current_dir, path::PathBuf}; + +use asset_system::asset::Handle; +use framework::space::Space; + +use crate::workspace::{ + Workspace, config::WorkspaceConfig, error::WorkspaceOperationError, manager::WorkspaceManager, +}; + +/// Create a workspace at the current location +pub async fn create_workspace_here() -> Result<(), WorkspaceOperationError> { + create_workspace(current_dir()?).await +} + +/// Create a workspace at the specified location +pub async fn create_workspace(path: impl Into<PathBuf>) -> Result<(), WorkspaceOperationError> { + let path = path.into(); + let mut space = Space::new(Workspace); + space.set_current_dir(path)?; + space.init_here().await?; + + Ok(()) +} + +#[allow(unused)] +/// Get a handle to the workspace configuration file and edit its content +pub async fn operate_workspace_config<F>( + workspace_path: impl Into<PathBuf>, + operate: F, +) -> Result<(), WorkspaceOperationError> +where + F: AsyncFn(Handle<WorkspaceConfig>), +{ + // Get the workspace manager and set the context to the given workspace path + let mut mgr = WorkspaceManager::new(); + mgr.get_space_mut().set_current_dir(workspace_path.into())?; + + // Obtain the read-only asset of the workspace configuration file, + // lock it to get a writable handle, and pass it to the function for execution + let config = mgr.workspace_config()?; + let handle = config.get_handle().await?; + operate(handle).await; + + Ok(()) +} diff --git a/systems/workspace/src/lib.rs b/systems/workspace/src/lib.rs new file mode 100644 index 0000000..9fd4ec8 --- /dev/null +++ b/systems/workspace/src/lib.rs @@ -0,0 +1,2 @@ +pub mod func; +pub mod workspace; diff --git a/systems/workspace/src/workspace.rs b/systems/workspace/src/workspace.rs new file mode 100644 index 0000000..6310146 --- /dev/null +++ b/systems/workspace/src/workspace.rs @@ -0,0 +1,38 @@ +use asset_system::rw::RWData; +use constants::workspace::{dirs::workspace_dir_workspace, files::workspace_file_config}; +use framework::{SpaceRootTest, space::SpaceRoot}; +use tokio::fs::create_dir_all; + +use crate::workspace::config::WorkspaceConfig; + +pub mod config; +pub mod error; +pub mod manager; + +#[derive(Default, SpaceRootTest)] +pub struct Workspace; + +impl SpaceRoot for Workspace { + fn get_pattern() -> framework::space::SpaceRootFindPattern { + framework::space::SpaceRootFindPattern::IncludeDotDir(workspace_dir_workspace().into()) + } + + async fn create_space( + path: &std::path::Path, + ) -> Result<(), framework::space::error::SpaceError> { + let workspace_root = path.join(workspace_dir_workspace()); + let workspace_toml = path.join(workspace_file_config()); + + // Create workspace directory + create_dir_all(workspace_root) + .await + .map_err(framework::space::error::SpaceError::from)?; + + // Create configuration file + WorkspaceConfig::write(WorkspaceConfig::default(), &workspace_toml) + .await + .map_err(|e| framework::space::error::SpaceError::Other(e.to_string()))?; + + Ok(()) + } +} diff --git a/systems/workspace/src/workspace/config.rs b/systems/workspace/src/workspace/config.rs new file mode 100644 index 0000000..278ec08 --- /dev/null +++ b/systems/workspace/src/workspace/config.rs @@ -0,0 +1,121 @@ +use std::{io::Error, path::PathBuf}; + +use asset_system::{ + RWDataTest, + error::{DataReadError, DataWriteError}, + rw::RWData, +}; +use config_system::rw::{read_config, write_config}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, RWDataTest)] +pub struct WorkspaceConfig { + /// Upstream address, pointing to the upstream Vault + #[serde(rename = "upstream")] + upstream: String, + + /// Vault Uuid, used to ensure consistency between upstream and local + #[serde(rename = "uuid")] + uuid: Option<String>, + + /// Account name used by self, + /// upstream Vault uses this parameter for identity verification + #[serde(rename = "account")] + use_accout: Option<String>, +} + +impl WorkspaceConfig { + /// Returns a reference to the upstream address. + pub fn upstream(&self) -> &String { + &self.upstream + } + + /// Sets the upstream address. + pub fn set_upstream(&mut self, upstream: String) { + self.upstream = upstream + } + + /// Returns a new instance with the given upstream address. + pub fn with_upstream(mut self, upstream: String) -> Self { + self.upstream = upstream; + self + } + + /// Returns a reference to the vault UUID, if any. + pub fn uuid(&self) -> Option<&String> { + self.uuid.as_ref() + } + + /// Sets the vault UUID. + pub fn set_uuid(&mut self, uuid: String) { + self.uuid = Some(uuid) + } + + /// Returns a new instance with the given vault UUID. + pub fn with_uuid(mut self, uuid: String) -> Self { + self.uuid = Some(uuid); + self + } + + /// Clears the vault UUID. + pub fn erase_uuid(&mut self) { + self.uuid = None; + } + + /// Returns a reference to the account name, if any. + pub fn account(&self) -> Option<&String> { + self.use_accout.as_ref() + } + + /// Sets the account name. + pub fn set_account(&mut self, account: String) { + self.use_accout = Some(account) + } + + /// Returns a new instance with the given account name. + pub fn with_account(mut self, account: String) -> Self { + self.use_accout = Some(account); + self + } + + /// Clears the account name. + pub fn erase_account(&mut self) { + self.use_accout = None; + } +} + +impl RWData<WorkspaceConfig> for WorkspaceConfig { + type DataType = WorkspaceConfig; + + async fn read(path: &PathBuf) -> Result<Self::DataType, DataReadError> { + let read_config = read_config(path).await; + match read_config { + Ok(config) => Ok(config), + Err(e) => Err(DataReadError::IoError(Error::new( + std::io::ErrorKind::Other, + e, + ))), + } + } + + async fn write(data: Self::DataType, path: &PathBuf) -> Result<(), DataWriteError> { + let write_config = write_config(path, &data).await; + match write_config { + Ok(_) => Ok(()), + Err(e) => { + return Err(DataWriteError::IoError(Error::new( + std::io::ErrorKind::Other, + e, + ))); + } + } + } + + fn test_data() -> Self::DataType { + WorkspaceConfig::default() + } + + fn verify_data(data_a: Self::DataType, data_b: Self::DataType) -> bool { + &data_a == &data_b + } +} diff --git a/systems/workspace/src/workspace/error.rs b/systems/workspace/src/workspace/error.rs new file mode 100644 index 0000000..495558b --- /dev/null +++ b/systems/workspace/src/workspace/error.rs @@ -0,0 +1,40 @@ +use asset_system::error::{DataApplyError, DataReadError, DataWriteError, HandleLockError}; +use framework::space::error::SpaceError; + +#[derive(thiserror::Error, Debug)] +pub enum WorkspaceOperationError { + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + + #[error("{0}")] + Other(String), + + #[error("Configuration not found")] + ConfigNotFound, + + #[error("Workspace not found")] + WorkspaceNotFound, + + #[error("Handle lock error: {0}")] + HandleLock(#[from] HandleLockError), + + #[error("Data read error: {0}")] + DataRead(#[from] DataReadError), + + #[error("Data write error: {0}")] + DataWrite(#[from] DataWriteError), + + #[error("Data apply error: {0}")] + DataApply(#[from] DataApplyError), +} + +impl From<SpaceError> for WorkspaceOperationError { + fn from(value: SpaceError) -> Self { + match value { + SpaceError::SpaceNotFound => WorkspaceOperationError::WorkspaceNotFound, + SpaceError::Io(error) => WorkspaceOperationError::Io(error), + SpaceError::Other(e) => Self::Other(e), + _ => Self::Other(value.to_string()), + } + } +} diff --git a/systems/workspace/src/workspace/manager.rs b/systems/workspace/src/workspace/manager.rs new file mode 100644 index 0000000..9e319a1 --- /dev/null +++ b/systems/workspace/src/workspace/manager.rs @@ -0,0 +1,38 @@ +use crate::workspace::{Workspace, config::WorkspaceConfig, error::WorkspaceOperationError}; +use asset_system::asset::ReadOnlyAsset; +use constants::workspace::files::workspace_file_config; +use framework::space::Space; + +pub struct WorkspaceManager { + space: Space<Workspace>, +} + +impl WorkspaceManager { + pub fn new() -> Self { + WorkspaceManager { + space: Space::new(Workspace), + } + } + + /// Get an immutable reference to the internal Space + pub fn get_space(&self) -> &Space<Workspace> { + &self.space + } + + /// Get a mutable reference to the internal Space + pub fn get_space_mut(&mut self) -> &mut Space<Workspace> { + &mut self.space + } + + /// Get a read-only instance of the workspace configuration file + pub fn workspace_config( + &self, + ) -> Result<ReadOnlyAsset<WorkspaceConfig>, WorkspaceOperationError> { + let config_path = self.space.local_path(workspace_file_config())?; + if !config_path.exists() { + return Err(WorkspaceOperationError::ConfigNotFound); + } + let asset = ReadOnlyAsset::from(config_path); + Ok(asset) + } +} |
