feat: write patches to the stdout in patch fetch command

Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
Awiteb
2025-09-24 15:45:11 +00:00
parent ee17c21dbb
commit d2adff7882
3 changed files with 39 additions and 11 deletions

View File

@@ -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 - Add `--personal-fork` flag to `repo announce` command - by Awiteb
- Log to stderr and a file - by Awiteb - Log to stderr and a file - by Awiteb
- Accept patches from stdin in `patch send` command - 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 ### Breaking Change

View File

@@ -13,9 +13,19 @@ Arguments:
Options: Options:
--repo <NADDR-NIP05-OR-SET> Repository addresses --repo <NADDR-NIP05-OR-SET> Repository addresses
-o, --output <PATH> Output directory for the patches. Default to the current directory -o, --output <PATH> 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 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 to the specified output directory (current directory by default). You can then
apply or merge these patches into your branch as needed. 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 '-' <note1...> | git am --empty=drop
```
The `--empty=drop` option ensures empty commits, such as cover letters, are
omitted.

View File

@@ -14,11 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://gnu.org/licenses/gpl-3.0.html>. // along with this program. If not, see <https://gnu.org/licenses/gpl-3.0.html>.
use std::{ use std::{fs, ops::Deref, path::PathBuf, str::FromStr};
fs,
path::{Path, PathBuf},
str::FromStr,
};
use clap::Args; use clap::Args;
use nostr::{ use nostr::{
@@ -55,7 +51,8 @@ pub struct FetchArgs {
value_delimiter = ',' value_delimiter = ','
)] )]
naddrs: Option<Vec<NaddrOrSet>>, naddrs: Option<Vec<NaddrOrSet>>,
/// 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")] #[arg(short, long, value_name = "PATH")]
output: Option<PathBuf>, output: Option<PathBuf>,
/// The patch id to fetch it /// 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 relays = options.relays.clone().flat_relays(&options.config.sets)?;
let client = NostrClient::init(&options, &relays).await; let client = NostrClient::init(&options, &relays).await;
let output_path = self.output.unwrap_or_default(); 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 client
.add_relays( .add_relays(
@@ -129,14 +130,30 @@ impl CommandRunner for FetchArgs {
patches.sort_unstable_by_key(|p| p.0.clone()); patches.sort_unstable_by_key(|p| p.0.clone());
patches.dedup_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)?; fs::create_dir_all(&output_path)?;
} }
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::<Vec<String>>()
.join("\n")
);
} else {
for (patch_path, patch) in patches { for (patch_path, patch) in patches {
tracing::info!("Writeing `{}` in `{}`", patch.subject, patch_path.display()); tracing::info!("Writeing `{}` in `{}`", patch.subject, patch_path.display());
fs::write(patch_path, patch.inner)?; fs::write(patch_path, patch.inner)?;
} }
}
Ok(()) Ok(())
} }