upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/sub_commands
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-02-21 15:01:11 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2024-02-21 15:01:11 +0000
commitea5aa6993d4c906c1703563ddc304c324c4ae079 (patch)
tree061ef2f644b099661c0b0b5c74a88ab8f6d549c6 /src/sub_commands
parent125ead4bb64d9e4a76266aabe5e826fc23551edc (diff)
feat(send): in-reply-to arg for revised proposal
send a revised version of a proposal using the new in-replyto argument suppliments existing 'root' tag with 'root-revision' e 'reply' tag to the original proposal
Diffstat (limited to 'src/sub_commands')
-rw-r--r--src/sub_commands/push.rs1
-rw-r--r--src/sub_commands/send.rs96
2 files changed, 88 insertions, 9 deletions
diff --git a/src/sub_commands/push.rs b/src/sub_commands/push.rs
index 2500e9f..73bdb38 100644
--- a/src/sub_commands/push.rs
+++ b/src/sub_commands/push.rs
@@ -119,6 +119,7 @@ pub async fn launch(cli_args: &Cli) -> Result<()> {
119 patch_events.last().map(nostr::Event::id), 119 patch_events.last().map(nostr::Event::id),
120 None, 120 None,
121 None, 121 None,
122 &None,
122 ) 123 )
123 .context("cannot make patch event from commit")?, 124 .context("cannot make patch event from commit")?,
124 ); 125 );
diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs
index 105f87a..c9c81ee 100644
--- a/src/sub_commands/send.rs
+++ b/src/sub_commands/send.rs
@@ -1,9 +1,12 @@
1use std::time::Duration; 1use std::{str::FromStr, time::Duration};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use futures::future::join_all; 4use futures::future::join_all;
5use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; 5use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
6use nostr::{prelude::sha1::Hash as Sha1Hash, EventBuilder, Marker, Tag, TagKind}; 6use nostr::{
7 nips::nip19::Nip19, prelude::sha1::Hash as Sha1Hash, EventBuilder, FromBech32, Marker, Tag,
8 TagKind, UncheckedUrl,
9};
7 10
8use super::list::tag_value; 11use super::list::tag_value;
9#[cfg(not(test))] 12#[cfg(not(test))]
@@ -25,6 +28,10 @@ pub struct SubCommandArgs {
25 /// starting commit (commits since in current branch) or commit range, like 28 /// starting commit (commits since in current branch) or commit range, like
26 /// in `git format-patch` 29 /// in `git format-patch`
27 starting_commit: String, 30 starting_commit: String,
31 #[clap(long)]
32 /// nevent or event id of an existing proposal for which this is a new
33 /// version
34 in_reply_to: Option<String>,
28 /// optional cover letter title 35 /// optional cover letter title
29 #[clap(short, long)] 36 #[clap(short, long)]
30 title: Option<String>, 37 title: Option<String>,
@@ -161,6 +168,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
161 &commits, 168 &commits,
162 &keys, 169 &keys,
163 &repo_ref, 170 &repo_ref,
171 &args.in_reply_to,
164 )?; 172 )?;
165 173
166 println!( 174 println!(
@@ -390,6 +398,7 @@ pub fn generate_cover_letter_and_patch_events(
390 commits: &Vec<Sha1Hash>, 398 commits: &Vec<Sha1Hash>,
391 keys: &nostr::Keys, 399 keys: &nostr::Keys,
392 repo_ref: &RepoRef, 400 repo_ref: &RepoRef,
401 in_reply_to: &Option<String>,
393) -> Result<Vec<nostr::Event>> { 402) -> Result<Vec<nostr::Event>> {
394 let root_commit = git_repo 403 let root_commit = git_repo
395 .get_root_commit() 404 .get_root_commit()
@@ -418,8 +427,19 @@ pub fn generate_cover_letter_and_patch_events(
418 }, 427 },
419 Tag::Reference(format!("{root_commit}")), 428 Tag::Reference(format!("{root_commit}")),
420 Tag::Hashtag("cover-letter".to_string()), 429 Tag::Hashtag("cover-letter".to_string()),
421 Tag::Hashtag("root".to_string()),
422 ], 430 ],
431 if let Some(event_ref) = in_reply_to.clone() {
432 vec![
433 Tag::Hashtag("root".to_string()),
434 Tag::Hashtag("revision-root".to_string()),
435 // TODO check if id is for a root proposal (perhaps its for an issue?)
436 e_tag_from_nip19(&event_ref,"proposal",nostr::Marker::Reply)?,
437 ]
438 } else {
439 vec![
440 Tag::Hashtag("root".to_string()),
441 ]
442 },
423 // this is not strictly needed but makes for prettier branch names 443 // this is not strictly needed but makes for prettier branch names
424 // eventually a prefix will be needed of the event id to stop 2 proposals with the same name colliding 444 // eventually a prefix will be needed of the event id to stop 2 proposals with the same name colliding
425 // a change like this, or the removal of this tag will require the actual branch name to be tracked 445 // a change like this, or the removal of this tag will require the actual branch name to be tracked
@@ -466,6 +486,7 @@ pub fn generate_cover_letter_and_patch_events(
466 } else { 486 } else {
467 None 487 None
468 }, 488 },
489 in_reply_to,
469 ) 490 )
470 .context("failed to generate patch event")?, 491 .context("failed to generate patch event")?,
471 ); 492 );
@@ -473,6 +494,51 @@ pub fn generate_cover_letter_and_patch_events(
473 Ok(events) 494 Ok(events)
474} 495}
475 496
497fn e_tag_from_nip19(
498 reference: &str,
499 reference_name: &str,
500 marker: nostr::Marker,
501) -> Result<nostr::Tag> {
502 let mut bech32 = reference.to_string();
503 loop {
504 if bech32.is_empty() {
505 bech32 = Interactor::default().input(
506 PromptInputParms::default().with_prompt(&format!("{reference_name} nevent")),
507 )?;
508 }
509
510 if let Ok(nip19) = Nip19::from_bech32(bech32.clone()) {
511 match nip19 {
512 Nip19::Event(n) => {
513 break Ok(nostr::Tag::Event {
514 event_id: n.event_id,
515 relay_url: n.relays.first().map(UncheckedUrl::new),
516 marker: Some(marker),
517 });
518 }
519 Nip19::EventId(id) => {
520 break Ok(nostr::Tag::Event {
521 event_id: id,
522 relay_url: None,
523 marker: Some(marker),
524 });
525 }
526 _ => {}
527 }
528 }
529 if let Ok(id) = nostr::EventId::from_str(&bech32) {
530 break Ok(nostr::Tag::Event {
531 event_id: id,
532 relay_url: None,
533 marker: Some(marker),
534 });
535 }
536 println!("not a valid {reference_name} event reference");
537
538 bech32 = String::new();
539 }
540}
541
476pub struct CoverLetter { 542pub struct CoverLetter {
477 pub title: String, 543 pub title: String,
478 pub description: String, 544 pub description: String,
@@ -565,6 +631,7 @@ pub fn generate_patch_event(
565 parent_patch_event_id: Option<nostr::EventId>, 631 parent_patch_event_id: Option<nostr::EventId>,
566 series_count: Option<(u64, u64)>, 632 series_count: Option<(u64, u64)>,
567 branch_name: Option<String>, 633 branch_name: Option<String>,
634 in_reply_to: &Option<String>,
568) -> Result<nostr::Event> { 635) -> Result<nostr::Event> {
569 let commit_parent = git_repo 636 let commit_parent = git_repo
570 .get_commit_parent(commit) 637 .get_commit_parent(commit)
@@ -592,16 +659,27 @@ pub fn generate_patch_event(
592 // code that makes it into the main branch, assuming 659 // code that makes it into the main branch, assuming
593 // the commit id is correct 660 // the commit id is correct
594 Tag::Reference(commit.to_string()), 661 Tag::Reference(commit.to_string()),
662 ],
595 663
596 if let Some(thread_event_id) = thread_event_id { Tag::Event { 664 if let Some(thread_event_id) = thread_event_id {
665 vec![Tag::Event {
597 event_id: thread_event_id, 666 event_id: thread_event_id,
598 relay_url: relay_hint.clone(), 667 relay_url: relay_hint.clone(),
599 marker: Some(Marker::Root), 668 marker: Some(Marker::Root),
600 } } 669 }]
601 else { 670 } else if let Some(event_ref) = in_reply_to.clone() {
602 Tag::Hashtag("root".to_string()) 671 vec![
603 }, 672 Tag::Hashtag("root".to_string()),
604 ], 673 Tag::Hashtag("revision-root".to_string()),
674 // TODO check if id is for a root proposal (perhaps its for an issue?)
675 e_tag_from_nip19(&event_ref,"proposal",nostr::Marker::Reply)?,
676 ]
677 } else {
678 vec![
679 Tag::Hashtag("root".to_string()),
680 ]
681 },
682
605 if let Some(id) = parent_patch_event_id { 683 if let Some(id) = parent_patch_event_id {
606 vec![Tag::Event { 684 vec![Tag::Event {
607 event_id: id, 685 event_id: id,