use std::io::Write;
use std::path::Path;
use serde::Serialize;
use void_core::cid;
use void_core::store::{FsStore, ObjectStoreExt};
use crate::context::{open_repo, void_err_to_cli};
use crate::output::{run_command, CliError, CliOptions};
pub struct ReadShardFileArgs {
pub shard_cid: String,
pub path: String,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ReadShardFileOutput {
pub shard_cid: String,
pub path: String,
pub size: usize,
}
pub fn run(cwd: &Path, args: ReadShardFileArgs, opts: &CliOptions) -> Result<(), CliError> {
run_command("debug read-shard-file", opts, |ctx| {
let repo = open_repo(cwd)?;
let vault = repo.vault();
let objects_dir = repo.void_dir().join("objects");
let store = FsStore::new(objects_dir)
.map_err(|e| CliError::internal(format!("failed to open store: {}", e)))?;
ctx.progress(format!("Loading shard {}...", &args.shard_cid));
let shard_cid = cid::parse(&args.shard_cid)
.map_err(|e| CliError::invalid_args(format!("invalid CID: {}", e)))?;
let shard_blob: void_core::crypto::EncryptedShard = store.get_blob(&shard_cid).map_err(void_err_to_cli)?;
let decrypted = vault.unseal_shard(&shard_blob)
.map_err(|e| CliError::internal(format!("failed to decrypt shard: {}", e)))?;
let size = decrypted.len();
if !ctx.use_json() {
ctx.info(format!(
"Shard body: {} bytes (compressed, opaque block)",
size
));
ctx.info("File index is in TreeManifest, not shard. Use `void debug read-shard` for size info.".to_string());
std::io::stdout()
.flush()
.map_err(|e| CliError::internal(format!("failed to flush output: {}", e)))?;
}
Ok(ReadShardFileOutput {
shard_cid: args.shard_cid,
path: args.path,
size,
})
})
}