diff --git a/CHANGELOG.md b/CHANGELOG.md index 76b4e6e..fd3ebba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `--personal-fork` flag to `repo announce` command - by Awiteb - Log to stderr and a file - by Awiteb - Accept patches from stdin in `patch send` command - by Awiteb +- Write patches to the stdout in `patch fetch` command - by Awiteb ### Breaking Change diff --git a/docs/patch/fetch.md b/docs/patch/fetch.md index 467a455..63a5432 100644 --- a/docs/patch/fetch.md +++ b/docs/patch/fetch.md @@ -13,9 +13,19 @@ Arguments: Options: --repo Repository addresses - -o, --output Output directory for the patches. Default to the current directory + -o, --output Directory for saving patches. Defaults to the current directory. Use `-` for stdout output ``` Fetches patches using their original patch ID. All fetched patches will be saved to the specified output directory (current directory by default). You can then apply or merge these patches into your branch as needed. + +You can also write patches to stdout for direct application with tools like +`git-am`. For instance, to fetch and apply patches use: + +```bash +n34 patch fetch -o '-' | git am --empty=drop +``` + +The `--empty=drop` option ensures empty commits, such as cover letters, are +omitted. diff --git a/src/cli/commands/patch/fetch.rs b/src/cli/commands/patch/fetch.rs index e141ea7..e9cf8be 100644 --- a/src/cli/commands/patch/fetch.rs +++ b/src/cli/commands/patch/fetch.rs @@ -14,11 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{ - fs, - path::{Path, PathBuf}, - str::FromStr, -}; +use std::{fs, ops::Deref, path::PathBuf, str::FromStr}; use clap::Args; use nostr::{ @@ -55,7 +51,8 @@ pub struct FetchArgs { value_delimiter = ',' )] naddrs: Option>, - /// Output directory for the patches. Default to the current directory + /// Directory for saving patches. Defaults to the current directory. Use `-` + /// for stdout output. #[arg(short, long, value_name = "PATH")] output: Option, /// The patch id to fetch it @@ -73,6 +70,10 @@ impl CommandRunner for FetchArgs { let relays = options.relays.clone().flat_relays(&options.config.sets)?; let client = NostrClient::init(&options, &relays).await; let output_path = self.output.unwrap_or_default(); + let (is_stdout, is_current_dir) = { + let str_path = output_path.to_string_lossy(); + (str_path.deref() == "-", str_path.deref().is_empty()) + }; client .add_relays( @@ -129,13 +130,29 @@ impl CommandRunner for FetchArgs { patches.sort_unstable_by_key(|p| p.0.clone()); patches.dedup_by_key(|p| p.0.clone()); - if output_path.as_path() != Path::new("") && !output_path.exists() { + if !is_stdout && !is_current_dir && !output_path.exists() { fs::create_dir_all(&output_path)?; } - for (patch_path, patch) in patches { - tracing::info!("Writeing `{}` in `{}`", patch.subject, patch_path.display()); - fs::write(patch_path, patch.inner)?; + if is_stdout { + tracing::info!( + "Writeing {} patch{} to the stdout", + patches.len(), + if patches.len() >= 2 { "es" } else { "" } + ); + println!( + "{}", + patches + .into_iter() + .map(|(_, patch)| patch.inner) + .collect::>() + .join("\n") + ); + } else { + for (patch_path, patch) in patches { + tracing::info!("Writeing `{}` in `{}`", patch.subject, patch_path.display()); + fs::write(patch_path, patch.inner)?; + } } Ok(())