diff --git a/src/cli.rs b/src/cli.rs index 1c8d44a..629dec3 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -149,6 +149,9 @@ pub enum Command { /// Construct a CAR file bytes from a list of blocks #[cfg(feature = "ipld")] CarFromBlocks(CarFromBlocksArgs), + /// Deconstruct a CAR into its constituent blocks + #[cfg(feature = "ipld")] + CarToBlocks(CarToBlocksArgs), // ---------------- Libp2p Tools ----------------------------// /// Ping a peer @@ -285,6 +288,13 @@ pub struct CarFromBlocksArgs { pub blocks: Vec, } +#[derive(Args, Debug, Clone)] +pub struct CarToBlocksArgs { + /// Path to save the extracted blocks (default to current directory) + #[arg(default_value = ".")] + pub blocks_dir: String, +} + #[derive(Debug, Clone)] pub struct CarBlockValue { pub root: bool, diff --git a/src/ipld.rs b/src/ipld.rs index f484737..b072f30 100644 --- a/src/ipld.rs +++ b/src/ipld.rs @@ -13,8 +13,8 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use crate::{ cli::{ - CarExtractArgs, CarFromBlocksArgs, CarInspectArgs, CidFromDataArgs, CidInspectArgs, - Command, DagCborIndexArgs, + CarExtractArgs, CarFromBlocksArgs, CarInspectArgs, CarToBlocksArgs, CidFromDataArgs, + CidInspectArgs, Command, DagCborIndexArgs, }, random_cid, }; @@ -33,6 +33,7 @@ pub enum Operation { CarInspect(CarInspectArgs), CarExtract(CarExtractArgs), CarFromBlocks(CarFromBlocksArgs), + CarToBlocks(CarToBlocksArgs), } impl TryFrom for Operation { @@ -53,6 +54,7 @@ impl TryFrom for Operation { Command::CarInspect(args) => Ok(Operation::CarInspect(args)), Command::CarExtract(args) => Ok(Operation::CarExtract(args)), Command::CarFromBlocks(args) => Ok(Operation::CarFromBlocks(args)), + Command::CarToBlocks(args) => Ok(Operation::CarToBlocks(args)), _ => Err(value), } } @@ -231,6 +233,13 @@ pub async fn run( stdout.write_all(&car).await?; } + Operation::CarToBlocks(args) => { + let mut reader = CarReader::new(stdin).await?; + while let Some((cid, data)) = reader.next_block().await? { + let path = format!("{}/{}", args.blocks_dir, cid); + tokio::fs::write(path, data).await?; + } + } }; Ok(()) }