summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-02-27 06:43:17 +0800
committer魏曹先生 <1992414357@qq.com>2026-02-27 06:43:17 +0800
commit7404a0e1b324ded78f6d579b4da2dcbafe5f72ca (patch)
tree3a5bbe87ec8e9b86e97f708907b725c002a2ba4e /src
parent84b004a421000c776f1009687562a47533d6cff7 (diff)
Add storage build and write commands
Diffstat (limited to 'src')
-rw-r--r--src/cmds/arg/storage_build.rs12
-rw-r--r--src/cmds/arg/storage_write.rs33
-rw-r--r--src/cmds/cmd/storage_build.rs70
-rw-r--r--src/cmds/cmd/storage_write.rs110
-rw-r--r--src/cmds/in/storage_rw.rs11
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>,
+}