diff options
| -rw-r--r-- | src/bin/ngit/cli.rs | 2 | ||||
| -rw-r--r-- | src/bin/ngit/sub_commands/create.rs | 30 | ||||
| -rw-r--r-- | src/lib/client.rs | 20 | ||||
| -rw-r--r-- | src/lib/login/fresh.rs | 17 | ||||
| -rw-r--r-- | src/lib/login/user.rs | 2 | ||||
| -rw-r--r-- | tests/ngit_init.rs | 140 | ||||
| -rw-r--r-- | tests/ngit_send.rs | 167 |
7 files changed, 315 insertions, 63 deletions
diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index d2246d7..47f4b27 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs | |||
| @@ -53,7 +53,7 @@ ngit settings are managed through the git config. | |||
| 53 | Currently the only settings not reachable through standard commands relate to default hardcoded relays: | 53 | Currently the only settings not reachable through standard commands relate to default hardcoded relays: |
| 54 | 54 | ||
| 55 | - nostr.grasp-default-set - only used during `ngit init` | 55 | - nostr.grasp-default-set - only used during `ngit init` |
| 56 | - nostr.relay-default-set - must have at least 1 value, all events send to repo relays, user write and default relays | 56 | - nostr.relay-default-set - used for profile discovery and account bootstrapping |
| 57 | - nostr.relay-blaster-set - only used for repo announcement events | 57 | - nostr.relay-blaster-set - only used for repo announcement events |
| 58 | - nostr.relay-signer-fallback-set | 58 | - nostr.relay-signer-fallback-set |
| 59 | 59 | ||
diff --git a/src/bin/ngit/sub_commands/create.rs b/src/bin/ngit/sub_commands/create.rs index e0d89b5..1c2b8db 100644 --- a/src/bin/ngit/sub_commands/create.rs +++ b/src/bin/ngit/sub_commands/create.rs | |||
| @@ -16,6 +16,11 @@ pub struct SubCommandArgs { | |||
| 16 | #[arg(long, required = true)] | 16 | #[arg(long, required = true)] |
| 17 | pub name: String, | 17 | pub name: String, |
| 18 | 18 | ||
| 19 | /// Relay URLs for the new account's relay list (can be specified multiple | ||
| 20 | /// times). Defaults to the relay-default-set if not provided. | ||
| 21 | #[arg(long = "relay", value_parser, num_args = 1)] | ||
| 22 | pub relays: Vec<String>, | ||
| 23 | |||
| 19 | /// Don't publish metadata to relays (offline mode) | 24 | /// Don't publish metadata to relays (offline mode) |
| 20 | #[arg(long)] | 25 | #[arg(long)] |
| 21 | pub offline: bool, | 26 | pub offline: bool, |
| @@ -28,20 +33,31 @@ pub struct SubCommandArgs { | |||
| 28 | pub async fn launch(_cli: &Cli, args: &SubCommandArgs) -> Result<()> { | 33 | pub async fn launch(_cli: &Cli, args: &SubCommandArgs) -> Result<()> { |
| 29 | let git_repo = Repo::discover().ok(); | 34 | let git_repo = Repo::discover().ok(); |
| 30 | 35 | ||
| 36 | let params = Params::with_git_config_relay_defaults(&git_repo.as_ref()); | ||
| 37 | |||
| 38 | let relay_urls = if args.relays.is_empty() { | ||
| 39 | params.relay_default_set.clone() | ||
| 40 | } else { | ||
| 41 | args.relays.clone() | ||
| 42 | }; | ||
| 43 | |||
| 31 | let client = if args.offline { | 44 | let client = if args.offline { |
| 32 | None | 45 | None |
| 33 | } else { | 46 | } else { |
| 34 | Some(Client::new(Params::with_git_config_relay_defaults( | 47 | Some(Client::new(params)) |
| 35 | &git_repo.as_ref(), | ||
| 36 | ))) | ||
| 37 | }; | 48 | }; |
| 38 | 49 | ||
| 39 | let publish = !args.offline; | 50 | let publish = !args.offline; |
| 40 | 51 | ||
| 41 | let (_signer, public_key, _signer_info, keys) = | 52 | let (_signer, public_key, _signer_info, keys) = signup_non_interactive( |
| 42 | signup_non_interactive(args.name.clone(), client.as_ref(), args.local, publish) | 53 | args.name.clone(), |
| 43 | .await | 54 | client.as_ref(), |
| 44 | .context("failed to create account")?; | 55 | args.local, |
| 56 | publish, | ||
| 57 | relay_urls, | ||
| 58 | ) | ||
| 59 | .await | ||
| 60 | .context("failed to create account")?; | ||
| 45 | 61 | ||
| 46 | // Display the generated nsec prominently | 62 | // Display the generated nsec prominently |
| 47 | println!("\nā Account created successfully!"); | 63 | println!("\nā Account created successfully!"); |
diff --git a/src/lib/client.rs b/src/lib/client.rs index 9c49653..89fcaf7 100644 --- a/src/lib/client.rs +++ b/src/lib/client.rs | |||
| @@ -1577,7 +1577,14 @@ async fn create_relays_request( | |||
| 1577 | }; | 1577 | }; |
| 1578 | 1578 | ||
| 1579 | let relays = { | 1579 | let relays = { |
| 1580 | let mut relays = fallback_relays; | 1580 | // Only use fallback relays for bootstrapping (no repo context). |
| 1581 | // When we have a repo coordinate, rely on repo relays and coordinate | ||
| 1582 | // hint relays instead of always merging in the default set. | ||
| 1583 | let mut relays = if trusted_maintainer_coordinate.is_none() { | ||
| 1584 | fallback_relays | ||
| 1585 | } else { | ||
| 1586 | HashSet::new() | ||
| 1587 | }; | ||
| 1581 | if let Some(repo_ref) = &repo_ref { | 1588 | if let Some(repo_ref) = &repo_ref { |
| 1582 | for r in repo_ref.relays.clone() { | 1589 | for r in repo_ref.relays.clone() { |
| 1583 | relays.insert(r); | 1590 | relays.insert(r); |
| @@ -1588,6 +1595,8 @@ async fn create_relays_request( | |||
| 1588 | relays.insert(r.clone()); | 1595 | relays.insert(r.clone()); |
| 1589 | } | 1596 | } |
| 1590 | } | 1597 | } |
| 1598 | // When bootstrapping with no repo context and no coordinate hints, | ||
| 1599 | // we need at least the fallback relays to discover the user profile. | ||
| 1591 | relays | 1600 | relays |
| 1592 | }; | 1601 | }; |
| 1593 | 1602 | ||
| @@ -2238,8 +2247,15 @@ pub async fn send_events( | |||
| 2238 | animate: bool, | 2247 | animate: bool, |
| 2239 | silent: bool, | 2248 | silent: bool, |
| 2240 | ) -> Result<()> { | 2249 | ) -> Result<()> { |
| 2250 | // Only include default relays as fallback when there are no repo relays | ||
| 2251 | // (bootstrapping case, e.g. new account signup). When repo relays exist, | ||
| 2252 | // trust the repo and user relay configuration. | ||
| 2241 | let fallback = [ | 2253 | let fallback = [ |
| 2242 | client.get_relay_default_set().clone(), | 2254 | if repo_read_relays.is_empty() && my_write_relays.is_empty() { |
| 2255 | client.get_relay_default_set().clone() | ||
| 2256 | } else { | ||
| 2257 | vec![] | ||
| 2258 | }, | ||
| 2243 | if events.iter().any(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) { | 2259 | if events.iter().any(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) { |
| 2244 | client.get_blaster_relays().clone() | 2260 | client.get_blaster_relays().clone() |
| 2245 | } else { | 2261 | } else { |
diff --git a/src/lib/login/fresh.rs b/src/lib/login/fresh.rs index 886b0e4..8e49085 100644 --- a/src/lib/login/fresh.rs +++ b/src/lib/login/fresh.rs | |||
| @@ -715,6 +715,7 @@ pub async fn signup_non_interactive( | |||
| 715 | #[cfg(not(test))] client: Option<&Client>, | 715 | #[cfg(not(test))] client: Option<&Client>, |
| 716 | save_local: bool, | 716 | save_local: bool, |
| 717 | publish: bool, | 717 | publish: bool, |
| 718 | relay_urls: Vec<String>, | ||
| 718 | ) -> Result<(Arc<dyn NostrSigner>, PublicKey, SignerInfo, Keys)> { | 719 | ) -> Result<(Arc<dyn NostrSigner>, PublicKey, SignerInfo, Keys)> { |
| 719 | // Generate new keypair | 720 | // Generate new keypair |
| 720 | let keys = nostr::Keys::generate(); | 721 | let keys = nostr::Keys::generate(); |
| @@ -783,10 +784,9 @@ pub async fn signup_non_interactive( | |||
| 783 | if let Some(client) = client { | 784 | if let Some(client) = client { |
| 784 | let profile = EventBuilder::metadata(&Metadata::new().name(name)).sign_with_keys(&keys)?; | 785 | let profile = EventBuilder::metadata(&Metadata::new().name(name)).sign_with_keys(&keys)?; |
| 785 | let relay_list = EventBuilder::relay_list( | 786 | let relay_list = EventBuilder::relay_list( |
| 786 | client | 787 | relay_urls |
| 787 | .get_relay_default_set() | ||
| 788 | .iter() | 788 | .iter() |
| 789 | .map(|s| (RelayUrl::parse(s).unwrap(), None)), | 789 | .filter_map(|s| RelayUrl::parse(s).ok().map(|url| (url, None))), |
| 790 | ) | 790 | ) |
| 791 | .sign_with_keys(&keys)?; | 791 | .sign_with_keys(&keys)?; |
| 792 | 792 | ||
| @@ -799,7 +799,7 @@ pub async fn signup_non_interactive( | |||
| 799 | client, | 799 | client, |
| 800 | git_repo_path, | 800 | git_repo_path, |
| 801 | vec![profile, relay_list], | 801 | vec![profile, relay_list], |
| 802 | client.get_relay_default_set().clone(), | 802 | relay_urls, |
| 803 | vec![], | 803 | vec![], |
| 804 | true, | 804 | true, |
| 805 | false, | 805 | false, |
| @@ -848,12 +848,19 @@ async fn signup( | |||
| 848 | } | 848 | } |
| 849 | } | 849 | } |
| 850 | 850 | ||
| 851 | // Call the non-interactive function | 851 | // Call the non-interactive function, using relay_default_set as the |
| 852 | // relay list for interactive signup | ||
| 853 | let relay_urls = if let Some(c) = client { | ||
| 854 | c.get_relay_default_set().clone() | ||
| 855 | } else { | ||
| 856 | vec![] | ||
| 857 | }; | ||
| 852 | let (signer, public_key, signer_info, _keys) = signup_non_interactive( | 858 | let (signer, public_key, signer_info, _keys) = signup_non_interactive( |
| 853 | name.clone(), | 859 | name.clone(), |
| 854 | client, | 860 | client, |
| 855 | false, // save_local = false (will be saved globally by caller) | 861 | false, // save_local = false (will be saved globally by caller) |
| 856 | true, // publish = true (always publish in interactive mode) | 862 | true, // publish = true (always publish in interactive mode) |
| 863 | relay_urls, | ||
| 857 | ) | 864 | ) |
| 858 | .await?; | 865 | .await?; |
| 859 | 866 | ||
diff --git a/src/lib/login/user.rs b/src/lib/login/user.rs index 0b702ef..b273363 100644 --- a/src/lib/login/user.rs +++ b/src/lib/login/user.rs | |||
| @@ -113,6 +113,8 @@ pub async fn get_user_details( | |||
| 113 | } | 113 | } |
| 114 | Ok(user_ref) | 114 | Ok(user_ref) |
| 115 | } else { | 115 | } else { |
| 116 | // No cached profile found. Fall back to fetching from default relays | ||
| 117 | // (bootstrapping). | ||
| 116 | let empty = UserRef { | 118 | let empty = UserRef { |
| 117 | public_key: public_key.to_owned(), | 119 | public_key: public_key.to_owned(), |
| 118 | metadata: extract_user_metadata(public_key, &[])?, | 120 | metadata: extract_user_metadata(public_key, &[])?, |
diff --git a/tests/ngit_init.rs b/tests/ngit_init.rs index 5483315..f70bc2e 100644 --- a/tests/ngit_init.rs +++ b/tests/ngit_init.rs | |||
| @@ -337,7 +337,21 @@ mod state_b_coordinate_only { | |||
| 337 | ), | 337 | ), |
| 338 | Relay::new(8052, None, None), | 338 | Relay::new(8052, None, None), |
| 339 | Relay::new(8053, None, None), | 339 | Relay::new(8053, None, None), |
| 340 | Relay::new(8055, None, None), | 340 | Relay::new( |
| 341 | 8055, | ||
| 342 | None, | ||
| 343 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 344 | relay.respond_events( | ||
| 345 | client_id, | ||
| 346 | &subscription_id, | ||
| 347 | &vec![ | ||
| 348 | generate_test_key_1_metadata_event("fred"), | ||
| 349 | generate_test_key_1_relay_list_event(), | ||
| 350 | ], | ||
| 351 | )?; | ||
| 352 | Ok(()) | ||
| 353 | }), | ||
| 354 | ), | ||
| 341 | Relay::new(8056, None, None), | 355 | Relay::new(8056, None, None), |
| 342 | ); | 356 | ); |
| 343 | 357 | ||
| @@ -420,7 +434,21 @@ mod state_b_coordinate_only { | |||
| 420 | ), | 434 | ), |
| 421 | Relay::new(8052, None, None), | 435 | Relay::new(8052, None, None), |
| 422 | Relay::new(8053, None, None), | 436 | Relay::new(8053, None, None), |
| 423 | Relay::new(8055, None, None), | 437 | Relay::new( |
| 438 | 8055, | ||
| 439 | None, | ||
| 440 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 441 | relay.respond_events( | ||
| 442 | client_id, | ||
| 443 | &subscription_id, | ||
| 444 | &vec![ | ||
| 445 | generate_test_key_1_metadata_event("fred"), | ||
| 446 | generate_test_key_1_relay_list_event(), | ||
| 447 | ], | ||
| 448 | )?; | ||
| 449 | Ok(()) | ||
| 450 | }), | ||
| 451 | ), | ||
| 424 | Relay::new(8056, None, None), | 452 | Relay::new(8056, None, None), |
| 425 | ); | 453 | ); |
| 426 | 454 | ||
| @@ -537,7 +565,22 @@ mod state_c_my_announcement { | |||
| 537 | ), | 565 | ), |
| 538 | Relay::new(8052, None, None), | 566 | Relay::new(8052, None, None), |
| 539 | Relay::new(8053, None, None), | 567 | Relay::new(8053, None, None), |
| 540 | Relay::new(8055, None, None), | 568 | Relay::new( |
| 569 | 8055, | ||
| 570 | None, | ||
| 571 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 572 | relay.respond_events( | ||
| 573 | client_id, | ||
| 574 | &subscription_id, | ||
| 575 | &vec![ | ||
| 576 | generate_test_key_1_metadata_event("fred"), | ||
| 577 | generate_test_key_1_relay_list_event(), | ||
| 578 | generate_repo_ref_event(), | ||
| 579 | ], | ||
| 580 | )?; | ||
| 581 | Ok(()) | ||
| 582 | }), | ||
| 583 | ), | ||
| 541 | Relay::new(8056, None, None), | 584 | Relay::new(8056, None, None), |
| 542 | ); | 585 | ); |
| 543 | 586 | ||
| @@ -595,7 +638,22 @@ mod state_c_my_announcement { | |||
| 595 | ), | 638 | ), |
| 596 | Relay::new(8052, None, None), | 639 | Relay::new(8052, None, None), |
| 597 | Relay::new(8053, None, None), | 640 | Relay::new(8053, None, None), |
| 598 | Relay::new(8055, None, None), | 641 | Relay::new( |
| 642 | 8055, | ||
| 643 | None, | ||
| 644 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 645 | relay.respond_events( | ||
| 646 | client_id, | ||
| 647 | &subscription_id, | ||
| 648 | &vec![ | ||
| 649 | generate_test_key_1_metadata_event("fred"), | ||
| 650 | generate_test_key_1_relay_list_event(), | ||
| 651 | generate_repo_ref_event(), | ||
| 652 | ], | ||
| 653 | )?; | ||
| 654 | Ok(()) | ||
| 655 | }), | ||
| 656 | ), | ||
| 599 | Relay::new(8056, None, None), | 657 | Relay::new(8056, None, None), |
| 600 | ); | 658 | ); |
| 601 | 659 | ||
| @@ -657,7 +715,22 @@ mod state_c_my_announcement { | |||
| 657 | ), | 715 | ), |
| 658 | Relay::new(8052, None, None), | 716 | Relay::new(8052, None, None), |
| 659 | Relay::new(8053, None, None), | 717 | Relay::new(8053, None, None), |
| 660 | Relay::new(8055, None, None), | 718 | Relay::new( |
| 719 | 8055, | ||
| 720 | None, | ||
| 721 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 722 | relay.respond_events( | ||
| 723 | client_id, | ||
| 724 | &subscription_id, | ||
| 725 | &vec![ | ||
| 726 | generate_test_key_1_metadata_event("fred"), | ||
| 727 | generate_test_key_1_relay_list_event(), | ||
| 728 | generate_repo_ref_event(), | ||
| 729 | ], | ||
| 730 | )?; | ||
| 731 | Ok(()) | ||
| 732 | }), | ||
| 733 | ), | ||
| 661 | Relay::new(8056, None, None), | 734 | Relay::new(8056, None, None), |
| 662 | ); | 735 | ); |
| 663 | 736 | ||
| @@ -836,7 +909,24 @@ mod state_d_co_maintainer { | |||
| 836 | ), | 909 | ), |
| 837 | Relay::new(8052, None, None), | 910 | Relay::new(8052, None, None), |
| 838 | Relay::new(8053, None, None), | 911 | Relay::new(8053, None, None), |
| 839 | Relay::new(8055, None, None), | 912 | Relay::new( |
| 913 | 8055, | ||
| 914 | None, | ||
| 915 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 916 | relay.respond_events( | ||
| 917 | client_id, | ||
| 918 | &subscription_id, | ||
| 919 | &vec![ | ||
| 920 | generate_test_key_1_metadata_event("fred"), | ||
| 921 | generate_test_key_1_relay_list_event(), | ||
| 922 | generate_test_key_2_metadata_event("carole"), | ||
| 923 | generate_test_key_2_relay_list_event(), | ||
| 924 | generate_repo_ref_event_as_key_2_listing_key_1(), | ||
| 925 | ], | ||
| 926 | )?; | ||
| 927 | Ok(()) | ||
| 928 | }), | ||
| 929 | ), | ||
| 840 | Relay::new(8056, None, None), | 930 | Relay::new(8056, None, None), |
| 841 | ); | 931 | ); |
| 842 | 932 | ||
| @@ -1021,7 +1111,24 @@ mod state_e_not_listed { | |||
| 1021 | ), | 1111 | ), |
| 1022 | Relay::new(8052, None, None), | 1112 | Relay::new(8052, None, None), |
| 1023 | Relay::new(8053, None, None), | 1113 | Relay::new(8053, None, None), |
| 1024 | Relay::new(8055, None, None), | 1114 | Relay::new( |
| 1115 | 8055, | ||
| 1116 | None, | ||
| 1117 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 1118 | relay.respond_events( | ||
| 1119 | client_id, | ||
| 1120 | &subscription_id, | ||
| 1121 | &vec![ | ||
| 1122 | generate_test_key_1_metadata_event("fred"), | ||
| 1123 | generate_test_key_1_relay_list_event(), | ||
| 1124 | generate_test_key_2_metadata_event("carole"), | ||
| 1125 | generate_test_key_2_relay_list_event(), | ||
| 1126 | generate_repo_ref_event_as_key_2_not_listing_key_1(), | ||
| 1127 | ], | ||
| 1128 | )?; | ||
| 1129 | Ok(()) | ||
| 1130 | }), | ||
| 1131 | ), | ||
| 1025 | Relay::new(8056, None, None), | 1132 | Relay::new(8056, None, None), |
| 1026 | ); | 1133 | ); |
| 1027 | 1134 | ||
| @@ -1104,7 +1211,24 @@ mod state_e_not_listed { | |||
| 1104 | ), | 1211 | ), |
| 1105 | Relay::new(8052, None, None), | 1212 | Relay::new(8052, None, None), |
| 1106 | Relay::new(8053, None, None), | 1213 | Relay::new(8053, None, None), |
| 1107 | Relay::new(8055, None, None), | 1214 | Relay::new( |
| 1215 | 8055, | ||
| 1216 | None, | ||
| 1217 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 1218 | relay.respond_events( | ||
| 1219 | client_id, | ||
| 1220 | &subscription_id, | ||
| 1221 | &vec![ | ||
| 1222 | generate_test_key_1_metadata_event("fred"), | ||
| 1223 | generate_test_key_1_relay_list_event(), | ||
| 1224 | generate_test_key_2_metadata_event("carole"), | ||
| 1225 | generate_test_key_2_relay_list_event(), | ||
| 1226 | generate_repo_ref_event_as_key_2_not_listing_key_1(), | ||
| 1227 | ], | ||
| 1228 | )?; | ||
| 1229 | Ok(()) | ||
| 1230 | }), | ||
| 1231 | ), | ||
| 1108 | Relay::new(8056, None, None), | 1232 | Relay::new(8056, None, None), |
| 1109 | ); | 1233 | ); |
| 1110 | 1234 | ||
diff --git a/tests/ngit_send.rs b/tests/ngit_send.rs index 7946aef..7170f84 100644 --- a/tests/ngit_send.rs +++ b/tests/ngit_send.rs | |||
| @@ -56,6 +56,29 @@ mod when_commits_behind_ask_to_proceed { | |||
| 56 | )) | 56 | )) |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | fn create_relay_55() -> Result<Relay<'static>> { | ||
| 60 | Ok(Relay::new( | ||
| 61 | 8055, | ||
| 62 | None, | ||
| 63 | Some(&|relay, client_id, subscription_id, _| -> Result<()> { | ||
| 64 | relay.respond_events( | ||
| 65 | client_id, | ||
| 66 | &subscription_id, | ||
| 67 | &vec![ | ||
| 68 | generate_repo_ref_event(), | ||
| 69 | generate_test_key_1_metadata_event("fred"), | ||
| 70 | generate_test_key_1_relay_list_event(), | ||
| 71 | ], | ||
| 72 | )?; | ||
| 73 | Ok(()) | ||
| 74 | }), | ||
| 75 | )) | ||
| 76 | } | ||
| 77 | |||
| 78 | fn create_relay_56() -> Result<Relay<'static>> { | ||
| 79 | Ok(Relay::new(8056, None, None)) | ||
| 80 | } | ||
| 81 | |||
| 59 | fn expect_confirm_prompt(p: &'_ mut CliTester) -> Result<CliTesterConfirmPrompt<'_>> { | 82 | fn expect_confirm_prompt(p: &'_ mut CliTester) -> Result<CliTesterConfirmPrompt<'_>> { |
| 60 | p.expect("fetching updates...\r\n")?; | 83 | p.expect("fetching updates...\r\n")?; |
| 61 | p.expect_eventually("\r\n")?; // may be 'no updates' or some updates | 84 | p.expect_eventually("\r\n")?; // may be 'no updates' or some updates |
| @@ -73,17 +96,25 @@ mod when_commits_behind_ask_to_proceed { | |||
| 73 | async fn asked_with_default_no() -> Result<()> { | 96 | async fn asked_with_default_no() -> Result<()> { |
| 74 | let test_repo = prep_test_repo()?; | 97 | let test_repo = prep_test_repo()?; |
| 75 | let mut r51 = create_relay_51()?; | 98 | let mut r51 = create_relay_51()?; |
| 99 | let mut r55 = create_relay_55()?; | ||
| 100 | let mut r56 = create_relay_56()?; | ||
| 76 | // // check relay had the right number of events | 101 | // // check relay had the right number of events |
| 77 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 102 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { |
| 78 | let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); | 103 | let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); |
| 79 | expect_confirm_prompt(&mut p)?; | 104 | expect_confirm_prompt(&mut p)?; |
| 80 | p.exit()?; | 105 | p.exit()?; |
| 81 | relay::shutdown_relay(8051)?; | 106 | for p in [51, 55, 56] { |
| 107 | relay::shutdown_relay(8000 + p)?; | ||
| 108 | } | ||
| 82 | Ok(()) | 109 | Ok(()) |
| 83 | }); | 110 | }); |
| 84 | 111 | ||
| 85 | // launch relay | 112 | // launch relay |
| 86 | r51.listen_until_close().await?; | 113 | let _ = join!( |
| 114 | r51.listen_until_close(), | ||
| 115 | r55.listen_until_close(), | ||
| 116 | r56.listen_until_close(), | ||
| 117 | ); | ||
| 87 | cli_tester_handle.join().unwrap()?; | 118 | cli_tester_handle.join().unwrap()?; |
| 88 | Ok(()) | 119 | Ok(()) |
| 89 | } | 120 | } |
| @@ -93,16 +124,24 @@ mod when_commits_behind_ask_to_proceed { | |||
| 93 | async fn when_response_is_false_aborts() -> Result<()> { | 124 | async fn when_response_is_false_aborts() -> Result<()> { |
| 94 | let test_repo = prep_test_repo()?; | 125 | let test_repo = prep_test_repo()?; |
| 95 | let mut r51 = create_relay_51()?; | 126 | let mut r51 = create_relay_51()?; |
| 127 | let mut r55 = create_relay_55()?; | ||
| 128 | let mut r56 = create_relay_56()?; | ||
| 96 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 129 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { |
| 97 | let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); | 130 | let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); |
| 98 | expect_confirm_prompt(&mut p)?.succeeds_with(Some(false))?; | 131 | expect_confirm_prompt(&mut p)?.succeeds_with(Some(false))?; |
| 99 | p.expect_end_with("Error: aborting so commits can be rebased\r\n")?; | 132 | p.expect_end_with("Error: aborting so commits can be rebased\r\n")?; |
| 100 | relay::shutdown_relay(8051)?; | 133 | for p in [51, 55, 56] { |
| 134 | relay::shutdown_relay(8000 + p)?; | ||
| 135 | } | ||
| 101 | Ok(()) | 136 | Ok(()) |
| 102 | }); | 137 | }); |
| 103 | 138 | ||
| 104 | // launch relay | 139 | // launch relay |
| 105 | r51.listen_until_close().await?; | 140 | let _ = join!( |
| 141 | r51.listen_until_close(), | ||
| 142 | r55.listen_until_close(), | ||
| 143 | r56.listen_until_close(), | ||
| 144 | ); | ||
| 106 | cli_tester_handle.join().unwrap()?; | 145 | cli_tester_handle.join().unwrap()?; |
| 107 | Ok(()) | 146 | Ok(()) |
| 108 | } | 147 | } |
| @@ -112,17 +151,25 @@ mod when_commits_behind_ask_to_proceed { | |||
| 112 | async fn when_response_is_true_proceeds() -> Result<()> { | 151 | async fn when_response_is_true_proceeds() -> Result<()> { |
| 113 | let test_repo = prep_test_repo()?; | 152 | let test_repo = prep_test_repo()?; |
| 114 | let mut r51 = create_relay_51()?; | 153 | let mut r51 = create_relay_51()?; |
| 154 | let mut r55 = create_relay_55()?; | ||
| 155 | let mut r56 = create_relay_56()?; | ||
| 115 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 156 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { |
| 116 | let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); | 157 | let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); |
| 117 | expect_confirm_prompt(&mut p)?.succeeds_with(Some(true))?; | 158 | expect_confirm_prompt(&mut p)?.succeeds_with(Some(true))?; |
| 118 | p.expect("? include cover letter")?; | 159 | p.expect("? include cover letter")?; |
| 119 | p.exit()?; | 160 | p.exit()?; |
| 120 | relay::shutdown_relay(8051)?; | 161 | for p in [51, 55, 56] { |
| 162 | relay::shutdown_relay(8000 + p)?; | ||
| 163 | } | ||
| 121 | Ok(()) | 164 | Ok(()) |
| 122 | }); | 165 | }); |
| 123 | 166 | ||
| 124 | // launch relay | 167 | // launch relay |
| 125 | r51.listen_until_close().await?; | 168 | let _ = join!( |
| 169 | r51.listen_until_close(), | ||
| 170 | r55.listen_until_close(), | ||
| 171 | r56.listen_until_close(), | ||
| 172 | ); | ||
| 126 | cli_tester_handle.join().unwrap()?; | 173 | cli_tester_handle.join().unwrap()?; |
| 127 | Ok(()) | 174 | Ok(()) |
| 128 | } | 175 | } |
| @@ -245,7 +292,11 @@ async fn prep_run_create_proposal( | |||
| 245 | relay.respond_events( | 292 | relay.respond_events( |
| 246 | client_id, | 293 | client_id, |
| 247 | &subscription_id, | 294 | &subscription_id, |
| 248 | &vec![generate_repo_ref_event()], | 295 | &vec![ |
| 296 | generate_repo_ref_event(), | ||
| 297 | generate_test_key_1_metadata_event("fred"), | ||
| 298 | generate_test_key_1_relay_list_event(), | ||
| 299 | ], | ||
| 249 | )?; | 300 | )?; |
| 250 | Ok(()) | 301 | Ok(()) |
| 251 | }), | 302 | }), |
| @@ -319,13 +370,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 319 | 370 | ||
| 320 | #[tokio::test] | 371 | #[tokio::test] |
| 321 | #[serial] | 372 | #[serial] |
| 322 | async fn only_1_cover_letter_event_sent_to_fallback_relays() -> Result<()> { | 373 | async fn no_events_sent_to_fallback_relays() -> Result<()> { |
| 323 | let (r51, r52, _, _, _) = prep_run_create_proposal(true).await?; | 374 | let (r51, r52, _, _, _) = prep_run_create_proposal(true).await?; |
| 375 | // Fallback relays should not receive events when repo relays exist | ||
| 324 | for relay in [&r51, &r52] { | 376 | for relay in [&r51, &r52] { |
| 325 | assert_eq!( | 377 | assert_eq!(relay.events.len(), 0); |
| 326 | relay.events.iter().filter(|e| is_cover_letter(e)).count(), | ||
| 327 | 1, | ||
| 328 | ); | ||
| 329 | } | 378 | } |
| 330 | Ok(()) | 379 | Ok(()) |
| 331 | } | 380 | } |
| @@ -333,8 +382,9 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 333 | #[tokio::test] | 382 | #[tokio::test] |
| 334 | #[serial] | 383 | #[serial] |
| 335 | async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> { | 384 | async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> { |
| 336 | let (r51, r52, r53, r55, r56) = prep_run_create_proposal(true).await?; | 385 | let (_, _, r53, r55, r56) = prep_run_create_proposal(true).await?; |
| 337 | for relay in [&r51, &r52, &r53, &r55, &r56] { | 386 | // Only user and repo relays should receive patches, not fallback relays |
| 387 | for relay in [&r53, &r55, &r56] { | ||
| 338 | assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,); | 388 | assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,); |
| 339 | } | 389 | } |
| 340 | Ok(()) | 390 | Ok(()) |
| @@ -832,7 +882,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 832 | relay.respond_events( | 882 | relay.respond_events( |
| 833 | client_id, | 883 | client_id, |
| 834 | &subscription_id, | 884 | &subscription_id, |
| 835 | &vec![generate_repo_ref_event()], | 885 | &vec![ |
| 886 | generate_repo_ref_event(), | ||
| 887 | generate_test_key_1_metadata_event("fred"), | ||
| 888 | generate_test_key_1_relay_list_event(), | ||
| 889 | ], | ||
| 836 | )?; | 890 | )?; |
| 837 | Ok(()) | 891 | Ok(()) |
| 838 | }), | 892 | }), |
| @@ -848,10 +902,8 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 848 | &mut p, | 902 | &mut p, |
| 849 | vec![ | 903 | vec![ |
| 850 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), | 904 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), |
| 851 | (" [my-relay] ws://localhost:8053", true, ""), | ||
| 852 | (" [repo-relay] ws://localhost:8056", true, ""), | 905 | (" [repo-relay] ws://localhost:8056", true, ""), |
| 853 | (" [default] ws://localhost:8051", true, ""), | 906 | (" [my-relay] ws://localhost:8053", true, ""), |
| 854 | (" [default] ws://localhost:8052", true, ""), | ||
| 855 | ], | 907 | ], |
| 856 | 3, | 908 | 3, |
| 857 | )?; | 909 | )?; |
| @@ -912,7 +964,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 912 | relay.respond_events( | 964 | relay.respond_events( |
| 913 | client_id, | 965 | client_id, |
| 914 | &subscription_id, | 966 | &subscription_id, |
| 915 | &vec![generate_repo_ref_event()], | 967 | &vec![ |
| 968 | generate_repo_ref_event(), | ||
| 969 | generate_test_key_1_metadata_event("fred"), | ||
| 970 | generate_test_key_1_relay_list_event(), | ||
| 971 | ], | ||
| 916 | )?; | 972 | )?; |
| 917 | Ok(()) | 973 | Ok(()) |
| 918 | }), | 974 | }), |
| @@ -986,7 +1042,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 986 | relay.respond_events( | 1042 | relay.respond_events( |
| 987 | client_id, | 1043 | client_id, |
| 988 | &subscription_id, | 1044 | &subscription_id, |
| 989 | &vec![generate_repo_ref_event()], | 1045 | &vec![ |
| 1046 | generate_repo_ref_event(), | ||
| 1047 | generate_test_key_1_metadata_event("fred"), | ||
| 1048 | generate_test_key_1_relay_list_event(), | ||
| 1049 | ], | ||
| 990 | )?; | 1050 | )?; |
| 991 | Ok(()) | 1051 | Ok(()) |
| 992 | }), | 1052 | }), |
| @@ -1009,14 +1069,12 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_ | |||
| 1009 | &mut p, | 1069 | &mut p, |
| 1010 | vec![ | 1070 | vec![ |
| 1011 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), | 1071 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), |
| 1012 | (" [my-relay] ws://localhost:8053", true, ""), | ||
| 1013 | ( | 1072 | ( |
| 1014 | " [repo-relay] ws://localhost:8056", | 1073 | " [repo-relay] ws://localhost:8056", |
| 1015 | false, | 1074 | false, |
| 1016 | "error: Payment Required", | 1075 | "error: Payment Required", |
| 1017 | ), | 1076 | ), |
| 1018 | (" [default] ws://localhost:8051", true, ""), | 1077 | (" [my-relay] ws://localhost:8053", true, ""), |
| 1019 | (" [default] ws://localhost:8052", true, ""), | ||
| 1020 | ], | 1078 | ], |
| 1021 | 3, | 1079 | 3, |
| 1022 | )?; | 1080 | )?; |
| @@ -1080,7 +1138,11 @@ mod when_no_cover_letter_flag_set_with_range_of_head_2_sends_2_patches_without_c | |||
| 1080 | relay.respond_events( | 1138 | relay.respond_events( |
| 1081 | client_id, | 1139 | client_id, |
| 1082 | &subscription_id, | 1140 | &subscription_id, |
| 1083 | &vec![generate_repo_ref_event()], | 1141 | &vec![ |
| 1142 | generate_repo_ref_event(), | ||
| 1143 | generate_test_key_1_metadata_event("fred"), | ||
| 1144 | generate_test_key_1_relay_list_event(), | ||
| 1145 | ], | ||
| 1084 | )?; | 1146 | )?; |
| 1085 | Ok(()) | 1147 | Ok(()) |
| 1086 | }), | 1148 | }), |
| @@ -1097,10 +1159,8 @@ mod when_no_cover_letter_flag_set_with_range_of_head_2_sends_2_patches_without_c | |||
| 1097 | &mut p, | 1159 | &mut p, |
| 1098 | vec![ | 1160 | vec![ |
| 1099 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), | 1161 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), |
| 1100 | (" [my-relay] ws://localhost:8053", true, ""), | ||
| 1101 | (" [repo-relay] ws://localhost:8056", true, ""), | 1162 | (" [repo-relay] ws://localhost:8056", true, ""), |
| 1102 | (" [default] ws://localhost:8051", true, ""), | 1163 | (" [my-relay] ws://localhost:8053", true, ""), |
| 1103 | (" [default] ws://localhost:8052", true, ""), | ||
| 1104 | ], | 1164 | ], |
| 1105 | 2, | 1165 | 2, |
| 1106 | )?; | 1166 | )?; |
| @@ -1303,7 +1363,11 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main { | |||
| 1303 | relay.respond_events( | 1363 | relay.respond_events( |
| 1304 | client_id, | 1364 | client_id, |
| 1305 | &subscription_id, | 1365 | &subscription_id, |
| 1306 | &vec![generate_repo_ref_event()], | 1366 | &vec![ |
| 1367 | generate_repo_ref_event(), | ||
| 1368 | generate_test_key_1_metadata_event("fred"), | ||
| 1369 | generate_test_key_1_relay_list_event(), | ||
| 1370 | ], | ||
| 1307 | )?; | 1371 | )?; |
| 1308 | Ok(()) | 1372 | Ok(()) |
| 1309 | }), | 1373 | }), |
| @@ -1366,7 +1430,11 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main { | |||
| 1366 | relay.respond_events( | 1430 | relay.respond_events( |
| 1367 | client_id, | 1431 | client_id, |
| 1368 | &subscription_id, | 1432 | &subscription_id, |
| 1369 | &vec![generate_repo_ref_event()], | 1433 | &vec![ |
| 1434 | generate_repo_ref_event(), | ||
| 1435 | generate_test_key_1_metadata_event("fred"), | ||
| 1436 | generate_test_key_1_relay_list_event(), | ||
| 1437 | ], | ||
| 1370 | )?; | 1438 | )?; |
| 1371 | Ok(()) | 1439 | Ok(()) |
| 1372 | }), | 1440 | }), |
| @@ -1382,10 +1450,8 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main { | |||
| 1382 | &mut p, | 1450 | &mut p, |
| 1383 | vec![ | 1451 | vec![ |
| 1384 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), | 1452 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), |
| 1385 | (" [my-relay] ws://localhost:8053", true, ""), | ||
| 1386 | (" [repo-relay] ws://localhost:8056", true, ""), | 1453 | (" [repo-relay] ws://localhost:8056", true, ""), |
| 1387 | (" [default] ws://localhost:8051", true, ""), | 1454 | (" [my-relay] ws://localhost:8053", true, ""), |
| 1388 | (" [default] ws://localhost:8052", true, ""), | ||
| 1389 | ], | 1455 | ], |
| 1390 | 2, | 1456 | 2, |
| 1391 | )?; | 1457 | )?; |
| @@ -1504,7 +1570,12 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let | |||
| 1504 | relay.respond_events( | 1570 | relay.respond_events( |
| 1505 | client_id, | 1571 | client_id, |
| 1506 | &subscription_id, | 1572 | &subscription_id, |
| 1507 | &vec![generate_repo_ref_event(), get_pretend_proposal_root_event()], | 1573 | &vec![ |
| 1574 | generate_repo_ref_event(), | ||
| 1575 | get_pretend_proposal_root_event(), | ||
| 1576 | generate_test_key_1_metadata_event("fred"), | ||
| 1577 | generate_test_key_1_relay_list_event(), | ||
| 1578 | ], | ||
| 1508 | )?; | 1579 | )?; |
| 1509 | Ok(()) | 1580 | Ok(()) |
| 1510 | }), | 1581 | }), |
| @@ -1567,7 +1638,12 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let | |||
| 1567 | relay.respond_events( | 1638 | relay.respond_events( |
| 1568 | client_id, | 1639 | client_id, |
| 1569 | &subscription_id, | 1640 | &subscription_id, |
| 1570 | &vec![generate_repo_ref_event(), get_pretend_proposal_root_event()], | 1641 | &vec![ |
| 1642 | generate_repo_ref_event(), | ||
| 1643 | get_pretend_proposal_root_event(), | ||
| 1644 | generate_test_key_1_metadata_event("fred"), | ||
| 1645 | generate_test_key_1_relay_list_event(), | ||
| 1646 | ], | ||
| 1571 | )?; | 1647 | )?; |
| 1572 | Ok(()) | 1648 | Ok(()) |
| 1573 | }), | 1649 | }), |
| @@ -1583,10 +1659,8 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let | |||
| 1583 | &mut p, | 1659 | &mut p, |
| 1584 | vec![ | 1660 | vec![ |
| 1585 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), | 1661 | (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), |
| 1586 | (" [my-relay] ws://localhost:8053", true, ""), | ||
| 1587 | (" [repo-relay] ws://localhost:8056", true, ""), | 1662 | (" [repo-relay] ws://localhost:8056", true, ""), |
| 1588 | (" [default] ws://localhost:8051", true, ""), | 1663 | (" [my-relay] ws://localhost:8053", true, ""), |
| 1589 | (" [default] ws://localhost:8052", true, ""), | ||
| 1590 | ], | 1664 | ], |
| 1591 | 3, | 1665 | 3, |
| 1592 | )?; | 1666 | )?; |
| @@ -1765,7 +1839,12 @@ mod in_reply_to_mentions_issue { | |||
| 1765 | relay.respond_events( | 1839 | relay.respond_events( |
| 1766 | client_id, | 1840 | client_id, |
| 1767 | &subscription_id, | 1841 | &subscription_id, |
| 1768 | &vec![generate_repo_ref_event(), get_pretend_issue_event()], | 1842 | &vec![ |
| 1843 | generate_repo_ref_event(), | ||
| 1844 | get_pretend_issue_event(), | ||
| 1845 | generate_test_key_1_metadata_event("fred"), | ||
| 1846 | generate_test_key_1_relay_list_event(), | ||
| 1847 | ], | ||
| 1769 | )?; | 1848 | )?; |
| 1770 | Ok(()) | 1849 | Ok(()) |
| 1771 | }), | 1850 | }), |
| @@ -1885,7 +1964,11 @@ mod in_reply_to_mentions_npub_and_nprofile_which_get_mentioned_in_proposal_root | |||
| 1885 | relay.respond_events( | 1964 | relay.respond_events( |
| 1886 | client_id, | 1965 | client_id, |
| 1887 | &subscription_id, | 1966 | &subscription_id, |
| 1888 | &vec![generate_repo_ref_event()], | 1967 | &vec![ |
| 1968 | generate_repo_ref_event(), | ||
| 1969 | generate_test_key_1_metadata_event("fred"), | ||
| 1970 | generate_test_key_1_relay_list_event(), | ||
| 1971 | ], | ||
| 1889 | )?; | 1972 | )?; |
| 1890 | Ok(()) | 1973 | Ok(()) |
| 1891 | }), | 1974 | }), |
| @@ -2037,7 +2120,11 @@ mod non_interactive_validation { | |||
| 2037 | relay.respond_events( | 2120 | relay.respond_events( |
| 2038 | client_id, | 2121 | client_id, |
| 2039 | &subscription_id, | 2122 | &subscription_id, |
| 2040 | &vec![generate_repo_ref_event()], | 2123 | &vec![ |
| 2124 | generate_repo_ref_event(), | ||
| 2125 | generate_test_key_1_metadata_event("fred"), | ||
| 2126 | generate_test_key_1_relay_list_event(), | ||
| 2127 | ], | ||
| 2041 | )?; | 2128 | )?; |
| 2042 | Ok(()) | 2129 | Ok(()) |
| 2043 | }), | 2130 | }), |