diff --git a/iroh/src/commands.rs b/iroh/src/commands.rs index e852627ea9..7dafc4805d 100644 --- a/iroh/src/commands.rs +++ b/iroh/src/commands.rs @@ -199,7 +199,8 @@ pub enum FullCommands { /// DERP region of the provider #[clap(long)] region: Option, - /// Directory in which to save the file(s), defaults to writing to STDOUT + /// Directory in which to save the file(s). When passed `STDOUT` will be written to stdout, + /// otherwise the content will be stored in the provided path. /// /// If the directory exists and contains a partial download, the download will /// be resumed. @@ -207,7 +208,7 @@ pub enum FullCommands { /// Otherwise, all files in the collection will be overwritten. Other files /// in the directory will be left untouched. #[clap(long, short)] - out: Option, + out: OutputTarget, #[clap(conflicts_with_all = &["hash", "peer", "addrs", "token"])] /// Ticket containing everything to retrieve the data from a provider. #[clap(long)] @@ -224,6 +225,27 @@ pub enum FullCommands { }, } +/// Where the data should be stored. +#[derive(Debug, Clone, derive_more::Display, PartialEq, Eq)] +pub enum OutputTarget { + /// Writes to stdout + #[display("STDOUT")] + Stdout, + /// Writes to the provided path + #[display("{}", _0.display())] + Path(PathBuf), +} + +impl From for OutputTarget { + fn from(s: String) -> Self { + if s == "STDOUT" { + return OutputTarget::Stdout; + } + + OutputTarget::Path(s.into()) + } +} + impl FullCommands { pub async fn run( self, @@ -1132,4 +1154,17 @@ mod tests { BlobSource::Path("hello/world".into()), ); } + + #[test] + fn test_output_target() { + assert_eq!( + OutputTarget::from(OutputTarget::Stdout.to_string()), + OutputTarget::Stdout + ); + + assert_eq!( + OutputTarget::from(OutputTarget::Path("hello/world".into()).to_string()), + OutputTarget::Path("hello/world".into()), + ); + } } diff --git a/iroh/src/commands/get.rs b/iroh/src/commands/get.rs index 67d8766bba..e44e0a0f67 100644 --- a/iroh/src/commands/get.rs +++ b/iroh/src/commands/get.rs @@ -26,6 +26,8 @@ use iroh_net::derp::DerpMode; use crate::commands::show_download_progress; +use super::OutputTarget; + #[derive(Debug)] pub struct GetInteractive { pub rt: iroh_bytes::util::runtime::Handle, @@ -99,11 +101,10 @@ impl GetInteractive { Ok(()) } - pub async fn get_interactive(self, out_dir: Option) -> Result<()> { - if let Some(out_dir) = out_dir { - self.get_to_dir(out_dir).await - } else { - self.get_to_stdout().await + pub async fn get_interactive(self, out_dir: OutputTarget) -> Result<()> { + match out_dir { + OutputTarget::Path(dir) => self.get_to_dir(dir).await, + OutputTarget::Stdout => self.get_to_stdout().await, } } diff --git a/iroh/tests/cli.rs b/iroh/tests/cli.rs index c14f4f2ddd..60e615562d 100644 --- a/iroh/tests/cli.rs +++ b/iroh/tests/cli.rs @@ -633,7 +633,7 @@ fn make_get_cmd(iroh_data_dir: &Path, ticket: &str, out: Option) -> duc ["get", "--ticket", ticket, "--out", out.to_str().unwrap()], ) } else { - cmd(iroh_bin(), ["get", "--ticket", ticket]) + cmd(iroh_bin(), ["get", "--ticket", ticket, "--out", "STDOUT"]) } .env_remove("RUST_LOG") .env("IROH_DATA_DIR", iroh_data_dir) @@ -694,12 +694,12 @@ fn test_provide_get_loop_single( hash: Hash, ) -> Result<()> { let out = match output { - Output::Stdout => None, + Output::Stdout => "STDOUT".to_string(), Output::Path => { let dir = testdir!(); - Some(dir.join("out")) + dir.join("out").display().to_string() } - Output::Custom(out) => Some(out), + Output::Custom(ref out) => out.display().to_string(), }; let num_blobs = if path.is_dir() { @@ -733,10 +733,9 @@ fn test_provide_get_loop_single( args.push("--addrs"); args.push(addr); } - if let Some(ref out) = out { - args.push("--out"); - args.push(out.to_str().unwrap()); - } + args.push("--out"); + args.push(&out); + args.push("--region"); args.push(®ion); let hash_str = hash.to_string(); @@ -757,12 +756,12 @@ fn test_provide_get_loop_single( // test output let expect_content = std::fs::read(path)?; - match out { - None => { + match output { + Output::Stdout => { assert!(!get_output.stdout.is_empty()); assert_eq!(expect_content, get_output.stdout); } - Some(out) => { + _ => { let content = std::fs::read(out)?; assert_eq!(expect_content, content); }