summaryrefslogtreecommitdiff
path: root/rola-bucket
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-18 02:47:32 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-18 02:47:32 +0800
commit0b8e6e7d18abb94bd99553dc1d2b0ba5d4f265ea (patch)
tree97a7c3430d56bfcb885cbfff0b011362671dd474 /rola-bucket
parentebd46942c3fcc7939e5567a797a55198148301ea (diff)
refactor: extract shared utilities and add space-system crate
Extract rola-vcs/internal_macros into shared utils crates (shared_constants, shared_macros, space-system) and implement the Bucket enum with async space management
Diffstat (limited to 'rola-bucket')
-rw-r--r--rola-bucket/Cargo.toml5
-rw-r--r--rola-bucket/src/bucket.rs135
-rw-r--r--rola-bucket/src/bucket/init.rs1
-rw-r--r--rola-bucket/src/bucket/space.rs22
-rw-r--r--rola-bucket/src/lib.rs3
5 files changed, 166 insertions, 0 deletions
diff --git a/rola-bucket/Cargo.toml b/rola-bucket/Cargo.toml
index 001ec11..07c555e 100644
--- a/rola-bucket/Cargo.toml
+++ b/rola-bucket/Cargo.toml
@@ -6,6 +6,11 @@ authors.workspace = true
license.workspace = true
[dependencies]
+shared_constants.workspace = true
shared_functions.workspace = true
shared_macros.workspace = true
+
+space-system.workspace = true
+
thiserror.workspace = true
+tokio.workspace = true
diff --git a/rola-bucket/src/bucket.rs b/rola-bucket/src/bucket.rs
index e69de29..b70afd8 100644
--- a/rola-bucket/src/bucket.rs
+++ b/rola-bucket/src/bucket.rs
@@ -0,0 +1,135 @@
+use crate::AsyncBucketTransferProtocol;
+
+#[cfg(test)]
+use crate::LocalFileSystemProtocol;
+use space_system::SpaceRootTest;
+
+mod init;
+// pub use init::*;
+
+mod space;
+
+/// Represents the state of a bucket in the transfer protocol.
+///
+/// # Variants
+///
+/// * `Uninit` - The bucket has not been initialized. This is the default state.
+/// **Warning:** Most mutation methods (e.g., `set_extra_info`, `remove_extra_info`) will **panic**
+/// when called on an `Uninit` bucket. Always ensure the bucket is in a `Local` or `Remote` state
+/// before attempting to modify its `extra_info`.
+///
+/// * `Local` - The bucket is on the local side of the transfer, with optional extra information.
+///
+/// * `Remote` - The bucket is on the remote side of the transfer, with optional extra information.
+#[derive(Default, Clone, SpaceRootTest)]
+#[space_root_test_generic(LocalFileSystemProtocol)]
+pub enum Bucket<Protocol>
+where
+ Protocol: AsyncBucketTransferProtocol + Send + Sync,
+{
+ #[default]
+ Uninit,
+
+ Local {
+ extra_info: Option<Protocol::ExtraInfo>,
+ },
+ Remote {
+ extra_info: Option<Protocol::ExtraInfo>,
+ },
+}
+
+impl<Protocol: AsyncBucketTransferProtocol + Send + Sync> Bucket<Protocol> {
+ /// Creates a new `Bucket::Local`
+ pub fn new_local() -> Self {
+ Self::Local { extra_info: None }
+ }
+
+ /// Creates a new `Bucket::Local` with extra information.
+ pub fn local_with_extra_info(extra_info: Protocol::ExtraInfo) -> Self {
+ Self::Local {
+ extra_info: Some(extra_info),
+ }
+ }
+
+ /// Creates a new `Bucket::Remote`
+ pub fn new_remote() -> Self {
+ Self::Remote { extra_info: None }
+ }
+
+ /// Creates a new `Bucket::Remote` with extra information.
+ pub fn remote_with_extra_info(extra_info: Protocol::ExtraInfo) -> Self {
+ Self::Remote {
+ extra_info: Some(extra_info),
+ }
+ }
+
+ /// Returns a mutable reference to the extra_info field regardless of variant.
+ fn extra_info_mut(&mut self) -> &mut Option<Protocol::ExtraInfo> {
+ match self {
+ Self::Local { extra_info } | Self::Remote { extra_info } => extra_info,
+ Self::Uninit => panic!("Cannot access extra_info on an Uninit bucket"),
+ }
+ }
+
+ /// Sets extra info on an existing bucket, returning the previous value if any.
+ pub fn set_extra_info(
+ &mut self,
+ extra_info: Protocol::ExtraInfo,
+ ) -> Option<Protocol::ExtraInfo> {
+ self.extra_info_mut().replace(extra_info)
+ }
+
+ /// Removes extra info from the bucket, returning it if present.
+ pub fn remove_extra_info(&mut self) -> Option<Protocol::ExtraInfo> {
+ self.extra_info_mut().take()
+ }
+
+ /// Checks if the bucket has extra information.
+ pub fn has_extra_info(&self) -> bool {
+ match self {
+ Self::Local { extra_info } | Self::Remote { extra_info } => extra_info.is_some(),
+ Self::Uninit => false,
+ }
+ }
+
+ /// Gets a reference to the extra info, if present.
+ pub fn extra_info(&self) -> Option<&Protocol::ExtraInfo> {
+ match self {
+ Self::Local { extra_info } | Self::Remote { extra_info } => extra_info.as_ref(),
+ Self::Uninit => None,
+ }
+ }
+
+ /// Returns true if this is a local bucket.
+ pub fn is_local(&self) -> bool {
+ matches!(self, Self::Local { .. })
+ }
+
+ /// Returns true if this is a remote bucket.
+ pub fn is_remote(&self) -> bool {
+ matches!(self, Self::Remote { .. })
+ }
+
+ /// Returns true if this bucket is uninitialized.
+ pub fn is_uninit(&self) -> bool {
+ matches!(self, Self::Uninit)
+ }
+
+ /// Converts the bucket to a Remote variant, keeping extra_info if present.
+ pub fn force_to_remote(self) -> Self {
+ let extra_info = match self {
+ Self::Local { extra_info } | Self::Remote { extra_info } => extra_info,
+ Self::Uninit => None,
+ };
+ Self::Remote { extra_info }
+ }
+
+ /// Converts the bucket to a Local variant, keeping extra_info if present.
+ pub fn force_to_local(self) -> Self {
+ let extra_info = match self {
+ Self::Local { extra_info } | Self::Remote { extra_info } => extra_info,
+ Self::Uninit => None,
+ };
+ Self::Local { extra_info }
+ }
+}
diff --git a/rola-bucket/src/bucket/init.rs b/rola-bucket/src/bucket/init.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/rola-bucket/src/bucket/init.rs
@@ -0,0 +1 @@
+
diff --git a/rola-bucket/src/bucket/space.rs b/rola-bucket/src/bucket/space.rs
new file mode 100644
index 0000000..9559b1d
--- /dev/null
+++ b/rola-bucket/src/bucket/space.rs
@@ -0,0 +1,22 @@
+use shared_constants::common::DRAFT_META_DIR;
+use space_system::{SpaceError, SpaceRoot, SpaceRootFindPattern};
+use tokio::fs::create_dir_all;
+
+use crate::{AsyncBucketTransferProtocol, Bucket};
+
+impl<Protocol: AsyncBucketTransferProtocol + Send + Sync> SpaceRoot for Bucket<Protocol> {
+ fn get_pattern() -> SpaceRootFindPattern {
+ SpaceRootFindPattern::IncludeDotDir(DRAFT_META_DIR.into())
+ }
+
+ async fn create_space(path: &std::path::Path) -> Result<(), space_system::SpaceError> {
+ let draft_meta_dir = path.join(DRAFT_META_DIR);
+
+ // Create workspace directory
+ create_dir_all(&draft_meta_dir)
+ .await
+ .map_err(SpaceError::from)?;
+
+ Ok(())
+ }
+}
diff --git a/rola-bucket/src/lib.rs b/rola-bucket/src/lib.rs
index c45452c..1f3470f 100644
--- a/rola-bucket/src/lib.rs
+++ b/rola-bucket/src/lib.rs
@@ -12,5 +12,8 @@
//!
//! This module does **not** implement any **specific transport method**; it only implements the workflow for file storage and retrieval.
+mod bucket;
+pub use bucket::*;
+
mod protocol;
pub use protocol::*;