diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-02-27 06:43:17 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-02-27 06:43:17 +0800 |
| commit | 7404a0e1b324ded78f6d579b4da2dcbafe5f72ca (patch) | |
| tree | 3a5bbe87ec8e9b86e97f708907b725c002a2ba4e /src | |
| parent | 84b004a421000c776f1009687562a47533d6cff7 (diff) | |
Add storage build and write commands
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmds/arg/storage_build.rs | 12 | ||||
| -rw-r--r-- | src/cmds/arg/storage_write.rs | 33 | ||||
| -rw-r--r-- | src/cmds/cmd/storage_build.rs | 70 | ||||
| -rw-r--r-- | src/cmds/cmd/storage_write.rs | 110 | ||||
| -rw-r--r-- | src/cmds/in/storage_rw.rs | 11 |
5 files changed, 236 insertions, 0 deletions
diff --git a/src/cmds/arg/storage_build.rs b/src/cmds/arg/storage_build.rs new file mode 100644 index 0000000..5d57b97 --- /dev/null +++ b/src/cmds/arg/storage_build.rs @@ -0,0 +1,12 @@ +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Parser, Debug)] +pub struct JVStorageBuildArgument { + pub index_file: PathBuf, + pub storage: PathBuf, + + #[arg(short = 'o', long = "output")] + pub output_file: Option<PathBuf>, +} diff --git a/src/cmds/arg/storage_write.rs b/src/cmds/arg/storage_write.rs new file mode 100644 index 0000000..e00dfdf --- /dev/null +++ b/src/cmds/arg/storage_write.rs @@ -0,0 +1,33 @@ +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Parser, Debug)] +pub struct JVStorageWriteArgument { + pub file: PathBuf, + pub storage: PathBuf, + + #[arg(short = 'o', long = "output")] + pub output_index: Option<PathBuf>, + + #[arg(long = "line")] + pub line_chunking: bool, + + #[arg(long = "cdc", default_value_t = 0)] + pub cdc_chunking: u32, + + #[arg(long = "fixed", default_value_t = 0)] + pub fixed_chunking: u32, + + #[arg(long)] + pub b: bool, + + #[arg(long)] + pub kb: bool, // default chunk size unit + + #[arg(long)] + pub mb: bool, + + #[arg(long)] + pub gb: bool, +} diff --git a/src/cmds/cmd/storage_build.rs b/src/cmds/cmd/storage_build.rs new file mode 100644 index 0000000..8e4d39c --- /dev/null +++ b/src/cmds/cmd/storage_build.rs @@ -0,0 +1,70 @@ +use crate::{ + cmd_output, + cmds::{ + arg::storage_build::JVStorageBuildArgument, collect::empty::JVEmptyCollect, + r#in::storage_rw::JVStorageRWInput, out::none::JVNoneOutput, + }, + systems::cmd::{ + cmd_system::JVCommandContext, + errors::{CmdExecuteError, CmdPrepareError}, + }, +}; +use cli_utils::display::md; +use cmd_system_macros::exec; +use just_enough_vcs::system::storage_system::{error::StorageIOError, store::build_file}; +use rust_i18n::t; +use std::any::TypeId; + +pub struct JVStorageBuildCommand; +type Cmd = JVStorageBuildCommand; +type Arg = JVStorageBuildArgument; +type In = JVStorageRWInput; +type Collect = JVEmptyCollect; + +fn help_str() -> String { + todo!() +} + +async fn prepare(args: &Arg, _ctx: &JVCommandContext) -> Result<In, CmdPrepareError> { + let output_file = match &args.output_file { + Some(v) => v.clone(), + None => args.index_file.clone().with_extension("unknown"), + }; + + let (input, storage, output) = just_enough_vcs::system::storage_system::store::precheck( + args.index_file.clone(), + args.storage.clone(), + output_file, + ) + .await?; + + Ok(JVStorageRWInput { + input, + storage, + output, + chunking_policy: None, + }) +} + +async fn collect(_args: &Arg, _ctx: &JVCommandContext) -> Result<Collect, CmdPrepareError> { + Ok(Collect {}) +} + +#[exec] +async fn exec( + input: In, + _collect: Collect, +) -> Result<(Box<dyn std::any::Any + Send + 'static>, TypeId), CmdExecuteError> { + build_file(input.input, input.storage, input.output) + .await + .map_err(|e| match e { + StorageIOError::IOErr(error) => CmdExecuteError::Io(error), + StorageIOError::HashTooShort => { + CmdExecuteError::Error(md(t!("storage_write.hash_too_short")).to_string()) + } + })?; + + cmd_output!(JVNoneOutput => JVNoneOutput {}) +} + +crate::command_template!(); diff --git a/src/cmds/cmd/storage_write.rs b/src/cmds/cmd/storage_write.rs new file mode 100644 index 0000000..8c864a8 --- /dev/null +++ b/src/cmds/cmd/storage_write.rs @@ -0,0 +1,110 @@ +use crate::{ + cmd_output, + cmds::{ + arg::storage_write::JVStorageWriteArgument, collect::empty::JVEmptyCollect, + r#in::storage_rw::JVStorageRWInput, out::none::JVNoneOutput, + }, + systems::cmd::{ + cmd_system::JVCommandContext, + errors::{CmdExecuteError, CmdPrepareError}, + }, +}; +use cli_utils::display::md; +use cmd_system_macros::exec; +use just_enough_vcs::system::{ + constants::vault::values::vault_value_index_file_suffix, + storage_system::{ + error::StorageIOError, + store::{ChunkingPolicy, StorageConfig, write_file}, + }, +}; +use rust_i18n::t; +use std::any::TypeId; + +pub struct JVStorageWriteCommand; +type Cmd = JVStorageWriteCommand; +type Arg = JVStorageWriteArgument; +type In = JVStorageRWInput; +type Collect = JVEmptyCollect; + +fn help_str() -> String { + todo!() +} + +async fn prepare(args: &Arg, _ctx: &JVCommandContext) -> Result<In, CmdPrepareError> { + let output_path = match &args.output_index { + Some(v) => v.clone(), + None => args + .file + .clone() + .with_extension(vault_value_index_file_suffix()), + }; + + // Default to using kb as the unit + let scale = if args.gb { + 1024 * 1024 * 1024 + } else if args.mb { + 1024 * 1024 + } else if args.b { + 1 + } else { + 1024 + }; + + let (input, storage, output) = just_enough_vcs::system::storage_system::store::precheck( + args.file.clone(), + args.storage.clone(), + output_path, + ) + .await?; + + let chunking_policy: ChunkingPolicy = if args.cdc_chunking > 0 { + ChunkingPolicy::Cdc(args.cdc_chunking * scale) + } else if args.fixed_chunking > 0 { + ChunkingPolicy::FixedSize(args.fixed_chunking * scale) + } else if args.line_chunking { + ChunkingPolicy::Line + } else { + return Err(CmdPrepareError::Error(md(t!( + "storage_write.unknown_chunking_policy" + )))); + }; + + Ok(JVStorageRWInput { + input, + storage, + output, + chunking_policy: Some(chunking_policy), + }) +} + +async fn collect(_args: &Arg, _ctx: &JVCommandContext) -> Result<Collect, CmdPrepareError> { + Ok(JVEmptyCollect {}) +} + +#[exec] +async fn exec( + input: In, + _collect: Collect, +) -> Result<(Box<dyn std::any::Any + Send + 'static>, TypeId), CmdExecuteError> { + // There is no chance to return None in the Prepare phase, so unwrap is safe here + let chunking_policy = input.chunking_policy.unwrap(); + + write_file( + input.input, + input.storage, + input.output, + &StorageConfig { chunking_policy }, + ) + .await + .map_err(|e| match e { + StorageIOError::IOErr(error) => CmdExecuteError::Io(error), + StorageIOError::HashTooShort => { + CmdExecuteError::Error(md(t!("storage_write.hash_too_short")).to_string()) + } + })?; + + cmd_output!(JVNoneOutput => JVNoneOutput {}) +} + +crate::command_template!(); diff --git a/src/cmds/in/storage_rw.rs b/src/cmds/in/storage_rw.rs new file mode 100644 index 0000000..596c1f9 --- /dev/null +++ b/src/cmds/in/storage_rw.rs @@ -0,0 +1,11 @@ +use std::path::PathBuf; + +use just_enough_vcs::system::storage_system::store::ChunkingPolicy; + +pub struct JVStorageRWInput { + pub input: PathBuf, + pub storage: PathBuf, + pub output: PathBuf, + + pub chunking_policy: Option<ChunkingPolicy>, +} |
