upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-08-04 08:12:51 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2025-08-04 08:12:51 +0100
commit3d04fb224b68187a67b9db0a37f662b5c5382f1e (patch)
treeb23fc7bc77d4918c74811862bc110daa55e08f38
parent056c400c5eb6cd8b105f38eea43922f71b0204dc (diff)
refactor: abstract pr event generation & ref push
so that we can use it in `ngit send`
-rw-r--r--src/bin/git_remote_nostr/push.rs206
1 files changed, 115 insertions, 91 deletions
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index 38b6fc4..3478608 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -452,101 +452,28 @@ async fn generate_patches_or_pr_event_or_pr_updates(
452 term: &Term, 452 term: &Term,
453) -> Result<Vec<Event>> { 453) -> Result<Vec<Event>> {
454 let mut events: Vec<Event> = vec![]; 454 let mut events: Vec<Event> = vec![];
455 let use_pr = root_proposal.is_some_and(|proposal| proposal.kind.eq(&KIND_PULL_REQUEST)) 455 let parent_is_pr = root_proposal.is_some_and(|proposal| proposal.kind.eq(&KIND_PULL_REQUEST));
456 || git_repo.are_commits_too_big_for_patches(ahead); 456 let use_pr = parent_is_pr || git_repo.are_commits_too_big_for_patches(ahead);
457 457
458 if use_pr { 458 if use_pr {
459 let repo_grasps = repo_ref.grasp_servers(); 459 for event in push_refs_and_generate_pr_or_pr_update_event(
460 let repo_grasp_clone_urls = repo_ref 460 git_repo,
461 .git_server 461 repo_ref,
462 .iter() 462 ahead.first().context("no commits to push")?,
463 .filter(|s| is_grasp_server(s, &repo_grasps)); 463 user_ref,
464 464 root_proposal,
465 let mut unsigned_pr_event: Option<UnsignedEvent> = None; 465 signer,
466 let mut failed_clone_urls = vec![]; 466 term,
467 for clone_url in repo_grasp_clone_urls { 467 )
468 let mut draft_pr_event = if let Some(ref unsigned_pr_event) = unsigned_pr_event { 468 .await.context(
469 unsigned_pr_event.clone() 469 if parent_is_pr {
470 } else { 470 "couldn't generate PR update event"
471 generate_unsigned_pr_or_update_event(
472 git_repo,
473 repo_ref,
474 &user_ref.public_key,
475 root_proposal,
476 ahead.first().context("no commits to push")?,
477 &[clone_url],
478 &[],
479 )?
480 };
481
482 let refspec = format!(
483 "{}:refs/nostr/{}",
484 ahead.first().unwrap(),
485 draft_pr_event.id()
486 );
487
488 if let Err(error) = push_to_remote_url(git_repo, clone_url, &[refspec], term) {
489 failed_clone_urls.push(clone_url);
490 term.write_line(
491 format!(
492 "push: error sending commit data to {}: {error}",
493 normalize_grasp_server_url(clone_url)?
494 )
495 .as_str(),
496 )?;
497 } else { 471 } else {
498 term.write_line( 472 "a commit in your proposal is too big for a nostr patch so we tried to create it as a nostr PR instead. Unfortunately this failed."
499 format!(
500 "push: commit data sent to {}",
501 normalize_grasp_server_url(clone_url)?
502 )
503 .as_str(),
504 )?;
505 unsigned_pr_event = Some(draft_pr_event);
506 } 473 }
507 } 474 )?
508 if unsigned_pr_event.is_none() { 475 {
509 bail!( 476 events.push(event);
510 "a commit in your proposal is too big for a nostr patch. The repository doesnt list a grasp server which would otherwise be used to submit your proposal as nostr Pull Request. Soon ngit will support pushing your changes to a different git / grasp git server."
511 );
512
513 // TODO get grasp_default_set servers that aren't in repo_grasps
514 // cycle through until one succeeds TODO create
515 // personal-fork announcement with grasp servers and
516 // push, after a few seconds push ref/nostr/eventid. if
517 // one success break out of for loop and continue
518 }
519 if let Some(unsigned_pr_event) = unsigned_pr_event {
520 let pr_event = sign_draft_event(
521 unsigned_pr_event,
522 signer,
523 if root_proposal.is_some_and(|proposal| proposal.kind.eq(&Kind::GitPatch)) {
524 "Pull Request Replacing Original Patch"
525 } else if root_proposal.is_some() {
526 "Pull Request Update"
527 } else {
528 "Pull Request"
529 }
530 .to_string(),
531 )
532 .await?;
533 events.push(pr_event);
534 if root_proposal.is_some_and(|proposal| proposal.kind.eq(&Kind::GitPatch)) {
535 events.push(
536 create_close_status_for_original_patch(
537 signer,
538 repo_ref,
539 root_proposal.unwrap(),
540 )
541 .await?,
542 );
543 }
544 } else {
545 bail!(
546 "a commit in your proposal is too big for a nostr patch. tried to use submit as a nostr Pull Request but could not find a grasp server that would accept your changes"
547 );
548 // TODO suggest `ngit send` where user could specify their own clone
549 // url to push to once that feature is added
550 } 477 }
551 } else { 478 } else {
552 for patch in generate_cover_letter_and_patch_events( 479 for patch in generate_cover_letter_and_patch_events(
@@ -567,6 +494,103 @@ async fn generate_patches_or_pr_event_or_pr_updates(
567 Ok(events) 494 Ok(events)
568} 495}
569 496
497async fn push_refs_and_generate_pr_or_pr_update_event(
498 git_repo: &Repo,
499 repo_ref: &RepoRef,
500 tip: &Sha1Hash,
501 user_ref: &UserRef,
502 root_proposal: Option<&Event>,
503 signer: &Arc<dyn NostrSigner>,
504 term: &Term,
505) -> Result<Vec<Event>> {
506 let mut events: Vec<Event> = vec![];
507 let repo_grasps = repo_ref.grasp_servers();
508 let repo_grasp_clone_urls = repo_ref
509 .git_server
510 .iter()
511 .filter(|s| is_grasp_server(s, &repo_grasps));
512
513 let mut unsigned_pr_event: Option<UnsignedEvent> = None;
514 let mut failed_clone_urls = vec![];
515 for clone_url in repo_grasp_clone_urls {
516 let mut draft_pr_event = if let Some(ref unsigned_pr_event) = unsigned_pr_event {
517 unsigned_pr_event.clone()
518 } else {
519 generate_unsigned_pr_or_update_event(
520 git_repo,
521 repo_ref,
522 &user_ref.public_key,
523 root_proposal,
524 tip,
525 &[clone_url],
526 &[],
527 )?
528 };
529
530 let refspec = format!("{}:refs/nostr/{}", tip, draft_pr_event.id());
531
532 if let Err(error) = push_to_remote_url(git_repo, clone_url, &[refspec], term) {
533 failed_clone_urls.push(clone_url);
534 term.write_line(
535 format!(
536 "push: error sending commit data to {}: {error}",
537 normalize_grasp_server_url(clone_url)?
538 )
539 .as_str(),
540 )?;
541 } else {
542 term.write_line(
543 format!(
544 "push: commit data sent to {}",
545 normalize_grasp_server_url(clone_url)?
546 )
547 .as_str(),
548 )?;
549 unsigned_pr_event = Some(draft_pr_event);
550 }
551 }
552 if unsigned_pr_event.is_none() {
553 bail!(
554 "The repository doesnt list a grasp server which would otherwise be used to submit your proposal as nostr Pull Request. Soon ngit will support pushing your changes to a different git / grasp git server."
555 );
556
557 // TODO get grasp_default_set servers that aren't in repo_grasps
558 // cycle through until one succeeds TODO create
559 // personal-fork announcement with grasp servers and
560 // push, after a few seconds push ref/nostr/eventid. if
561 // one success break out of for loop and continue
562 }
563 if let Some(unsigned_pr_event) = unsigned_pr_event {
564 let pr_event = sign_draft_event(
565 unsigned_pr_event,
566 signer,
567 if root_proposal.is_some_and(|proposal| proposal.kind.eq(&Kind::GitPatch)) {
568 "Pull Request Replacing Original Patch"
569 } else if root_proposal.is_some() {
570 "Pull Request Update"
571 } else {
572 "Pull Request"
573 }
574 .to_string(),
575 )
576 .await?;
577 events.push(pr_event);
578 if root_proposal.is_some_and(|proposal| proposal.kind.eq(&Kind::GitPatch)) {
579 events.push(
580 create_close_status_for_original_patch(signer, repo_ref, root_proposal.unwrap())
581 .await?,
582 );
583 }
584 } else {
585 bail!(
586 "a commit in your proposal is too big for a nostr patch. tried to use submit as a nostr Pull Request but could not find a grasp server that would accept your changes"
587 );
588 // TODO suggest `ngit send` where user could specify their own clone
589 // url to push to once that feature is added
590 }
591 Ok(events)
592}
593
570type HashMapUrlRefspecs = HashMap<String, Vec<String>>; 594type HashMapUrlRefspecs = HashMap<String, Vec<String>>;
571 595
572#[allow(clippy::too_many_lines)] 596#[allow(clippy::too_many_lines)]