upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.nix2
-rw-r--r--rustfmt.toml2
-rw-r--r--src/bin/git_remote_nostr/fetch.rs10
-rw-r--r--src/bin/git_remote_nostr/list.rs6
-rw-r--r--src/bin/git_remote_nostr/main.rs6
-rw-r--r--src/bin/git_remote_nostr/push.rs62
-rw-r--r--src/bin/git_remote_nostr/utils.rs17
-rw-r--r--src/bin/ngit/cli.rs2
-rw-r--r--src/bin/ngit/sub_commands/export_keys.rs2
-rw-r--r--src/bin/ngit/sub_commands/init.rs12
-rw-r--r--src/bin/ngit/sub_commands/list.rs19
-rw-r--r--src/bin/ngit/sub_commands/login.rs4
-rw-r--r--src/bin/ngit/sub_commands/logout.rs2
-rw-r--r--src/bin/ngit/sub_commands/send.rs17
-rw-r--r--src/lib/cli_interactor.rs2
-rw-r--r--src/lib/client.rs140
-rw-r--r--src/lib/git/identify_ahead_behind.rs8
-rw-r--r--src/lib/git/mod.rs87
-rw-r--r--src/lib/git/nostr_url.rs136
-rw-r--r--src/lib/git_events.rs22
-rw-r--r--src/lib/login/existing.rs8
-rw-r--r--src/lib/login/fresh.rs10
-rw-r--r--src/lib/login/mod.rs14
-rw-r--r--src/lib/login/user.rs4
-rw-r--r--src/lib/mod.rs2
-rw-r--r--src/lib/repo_ref.rs46
-rw-r--r--test_utils/src/lib.rs203
-rw-r--r--test_utils/src/relay.rs2
-rw-r--r--tests/git_remote_nostr/main.rs2
-rw-r--r--tests/git_remote_nostr/push.rs30
-rw-r--r--tests/ngit_init.rs36
-rw-r--r--tests/ngit_list.rs488
-rw-r--r--tests/ngit_login.rs352
-rw-r--r--tests/ngit_send.rs246
34 files changed, 830 insertions, 1171 deletions
diff --git a/flake.nix b/flake.nix
index 096727d..a642221 100644
--- a/flake.nix
+++ b/flake.nix
@@ -23,7 +23,7 @@
23 # ideally this wouldn't be pinned to a specific nightly version but 23 # ideally this wouldn't be pinned to a specific nightly version but
24 # selectLatestNightlyWith isn't support with mixed toolchains 24 # selectLatestNightlyWith isn't support with mixed toolchains
25 # https://github.com/oxalica/rust-overlay/issues/136 25 # https://github.com/oxalica/rust-overlay/issues/136
26 (lib.hiPrio rust-bin.nightly."2024-09-17".rustfmt) 26 (lib.hiPrio rust-bin.nightly."2024-12-15".rustfmt)
27 # (rust-bin.stable.latest.override { extensions = [ "rust-analyzer" ]; }) 27 # (rust-bin.stable.latest.override { extensions = [ "rust-analyzer" ]; })
28 rust-bin.stable.latest.default 28 rust-bin.stable.latest.default
29 ]; 29 ];
diff --git a/rustfmt.toml b/rustfmt.toml
index bcf7279..0869bdf 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,5 +1,5 @@
1unstable_features = true 1unstable_features = true
2version = "Two" 2style_edition = "2024"
3 3
4# Imports 4# Imports
5imports_granularity = "Crate" 5imports_granularity = "Crate"
diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs
index 458c6d8..7012955 100644
--- a/src/bin/git_remote_nostr/fetch.rs
+++ b/src/bin/git_remote_nostr/fetch.rs
@@ -6,15 +6,15 @@ use std::{
6 time::Instant, 6 time::Instant,
7}; 7};
8 8
9use anyhow::{anyhow, bail, Context, Result}; 9use anyhow::{Context, Result, anyhow, bail};
10use auth_git2::GitAuthenticator; 10use auth_git2::GitAuthenticator;
11use git2::{Progress, Repository}; 11use git2::{Progress, Repository};
12use ngit::{ 12use ngit::{
13 cli_interactor::count_lines_per_msg_vec, 13 cli_interactor::count_lines_per_msg_vec,
14 git::{ 14 git::{
15 Repo, RepoActions,
15 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol}, 16 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol},
16 utils::check_ssh_keys, 17 utils::check_ssh_keys,
17 Repo, RepoActions,
18 }, 18 },
19 git_events::tag_value, 19 git_events::tag_value,
20 login::get_curent_user, 20 login::get_curent_user,
@@ -24,9 +24,9 @@ use nostr::nips::nip19;
24use nostr_sdk::{Event, ToBech32}; 24use nostr_sdk::{Event, ToBech32};
25 25
26use crate::utils::{ 26use crate::utils::{
27 fetch_or_list_error_is_not_authentication_failure, find_proposal_and_patches_by_branch_name, 27 Direction, fetch_or_list_error_is_not_authentication_failure,
28 get_oids_from_fetch_batch, get_open_proposals, get_read_protocols_to_try, join_with_and, 28 find_proposal_and_patches_by_branch_name, get_oids_from_fetch_batch, get_open_proposals,
29 set_protocol_preference, Direction, 29 get_read_protocols_to_try, join_with_and, set_protocol_preference,
30}; 30};
31 31
32pub async fn run_fetch( 32pub async fn run_fetch(
diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs
index 9171544..bba15aa 100644
--- a/src/bin/git_remote_nostr/list.rs
+++ b/src/bin/git_remote_nostr/list.rs
@@ -1,7 +1,7 @@
1use core::str; 1use core::str;
2use std::collections::HashMap; 2use std::collections::HashMap;
3 3
4use anyhow::{anyhow, Context, Result}; 4use anyhow::{Context, Result, anyhow};
5use auth_git2::GitAuthenticator; 5use auth_git2::GitAuthenticator;
6use client::get_state_from_cache; 6use client::get_state_from_cache;
7use git::RepoActions; 7use git::RepoActions;
@@ -22,9 +22,9 @@ use crate::{
22 fetch::{fetch_from_git_server, make_commits_for_proposal}, 22 fetch::{fetch_from_git_server, make_commits_for_proposal},
23 git::Repo, 23 git::Repo,
24 utils::{ 24 utils::{
25 fetch_or_list_error_is_not_authentication_failure, get_open_proposals, 25 Direction, fetch_or_list_error_is_not_authentication_failure, get_open_proposals,
26 get_read_protocols_to_try, get_short_git_server_name, join_with_and, 26 get_read_protocols_to_try, get_short_git_server_name, join_with_and,
27 set_protocol_preference, Direction, 27 set_protocol_preference,
28 }, 28 },
29}; 29};
30 30
diff --git a/src/bin/git_remote_nostr/main.rs b/src/bin/git_remote_nostr/main.rs
index 1a21341..e6f7af3 100644
--- a/src/bin/git_remote_nostr/main.rs
+++ b/src/bin/git_remote_nostr/main.rs
@@ -11,9 +11,9 @@ use std::{
11 path::{Path, PathBuf}, 11 path::{Path, PathBuf},
12}; 12};
13 13
14use anyhow::{bail, Context, Result}; 14use anyhow::{Context, Result, bail};
15use client::{consolidate_fetch_reports, get_repo_ref_from_cache, Connect}; 15use client::{Connect, consolidate_fetch_reports, get_repo_ref_from_cache};
16use git::{nostr_url::NostrUrlDecoded, RepoActions}; 16use git::{RepoActions, nostr_url::NostrUrlDecoded};
17use ngit::{client, git, login::existing::load_existing_login}; 17use ngit::{client, git, login::existing::load_existing_login};
18use nostr::nips::nip01::Coordinate; 18use nostr::nips::nip01::Coordinate;
19use utils::read_line; 19use utils::read_line;
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index f2ac169..e8e1587 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -6,17 +6,17 @@ use std::{
6 time::Instant, 6 time::Instant,
7}; 7};
8 8
9use anyhow::{anyhow, bail, Context, Result}; 9use anyhow::{Context, Result, anyhow, bail};
10use auth_git2::GitAuthenticator; 10use auth_git2::GitAuthenticator;
11use client::{ 11use client::{
12 get_events_from_local_cache, get_state_from_cache, send_events, sign_event, STATE_KIND, 12 STATE_KIND, get_events_from_local_cache, get_state_from_cache, send_events, sign_event,
13}; 13};
14use console::Term; 14use console::Term;
15use git::{sha1_to_oid, RepoActions}; 15use git::{RepoActions, sha1_to_oid};
16use git2::{Oid, Repository};
17use git_events::{ 16use git_events::{
18 generate_cover_letter_and_patch_events, generate_patch_event, get_commit_id_from_patch, 17 generate_cover_letter_and_patch_events, generate_patch_event, get_commit_id_from_patch,
19}; 18};
19use git2::{Oid, Repository};
20use ngit::{ 20use ngit::{
21 cli_interactor::count_lines_per_msg_vec, 21 cli_interactor::count_lines_per_msg_vec,
22 client::{self, get_event_from_cache_by_id}, 22 client::{self, get_event_from_cache_by_id},
@@ -32,8 +32,8 @@ use ngit::{
32}; 32};
33use nostr::nips::nip10::Marker; 33use nostr::nips::nip10::Marker;
34use nostr_sdk::{ 34use nostr_sdk::{
35 hashes::sha1::Hash as Sha1Hash, Event, EventBuilder, EventId, Kind, NostrSigner, PublicKey, 35 Event, EventBuilder, EventId, Kind, NostrSigner, PublicKey, RelayUrl, Tag,
36 RelayUrl, Tag, 36 hashes::sha1::Hash as Sha1Hash,
37}; 37};
38use repo_ref::RepoRef; 38use repo_ref::RepoRef;
39use repo_state::RepoState; 39use repo_state::RepoState;
@@ -43,9 +43,10 @@ use crate::{
43 git::Repo, 43 git::Repo,
44 list::list_from_remotes, 44 list::list_from_remotes,
45 utils::{ 45 utils::{
46 find_proposal_and_patches_by_branch_name, get_all_proposals, get_remote_name_by_url, 46 Direction, find_proposal_and_patches_by_branch_name, get_all_proposals,
47 get_short_git_server_name, get_write_protocols_to_try, join_with_and, 47 get_remote_name_by_url, get_short_git_server_name, get_write_protocols_to_try,
48 push_error_is_not_authentication_failure, read_line, set_protocol_preference, Direction, 48 join_with_and, push_error_is_not_authentication_failure, read_line,
49 set_protocol_preference,
49 }, 50 },
50}; 51};
51 52
@@ -1023,13 +1024,10 @@ async fn get_merged_status_events(
1023 let (ahead, _) = 1024 let (ahead, _) =
1024 git_repo.get_commits_ahead_behind(&tip_of_remote_branch, &tip_of_pushed_branch)?; 1025 git_repo.get_commits_ahead_behind(&tip_of_remote_branch, &tip_of_pushed_branch)?;
1025 1026
1026 let commit_events = get_events_from_local_cache( 1027 let commit_events = get_events_from_local_cache(git_repo.get_path()?, vec![
1027 git_repo.get_path()?, 1028 nostr::Filter::default().kind(nostr::Kind::GitPatch),
1028 vec![ 1029 // TODO: limit by repo_ref
1029 nostr::Filter::default().kind(nostr::Kind::GitPatch), 1030 ])
1030 // TODO: limit by repo_ref
1031 ],
1032 )
1033 .await?; 1031 .await?;
1034 1032
1035 let merged_proposals_info = 1033 let merged_proposals_info =
@@ -1106,12 +1104,9 @@ async fn get_merged_proposals_info(
1106 proposals.entry(proposal_id).or_default(); 1104 proposals.entry(proposal_id).or_default();
1107 // ignore revisions without all the merged commits 1105 // ignore revisions without all the merged commits
1108 if entry_revision_id == &revision_id { 1106 if entry_revision_id == &revision_id {
1109 merged_patches.insert( 1107 merged_patches.insert(*commit_hash, MergedPRCommitType::PatchCommit {
1110 *commit_hash, 1108 event_id: patch_event.id,
1111 MergedPRCommitType::PatchCommit { 1109 });
1112 event_id: patch_event.id,
1113 },
1114 );
1115 } 1110 }
1116 } 1111 }
1117 } 1112 }
@@ -1136,12 +1131,9 @@ async fn get_merged_proposals_info(
1136 proposals.entry(proposal_id).or_default(); 1131 proposals.entry(proposal_id).or_default();
1137 // ignore revisions without all the applied commits 1132 // ignore revisions without all the applied commits
1138 if entry_revision_id == &revision_id { 1133 if entry_revision_id == &revision_id {
1139 merged_patches.insert( 1134 merged_patches.insert(*commit_hash, MergedPRCommitType::PatchApplied {
1140 *commit_hash, 1135 event_id: patch_event.id,
1141 MergedPRCommitType::PatchApplied { 1136 });
1142 event_id: patch_event.id,
1143 },
1144 );
1145 } 1137 }
1146 } 1138 }
1147 } 1139 }
@@ -1379,10 +1371,9 @@ async fn get_proposal_and_revision_root_from_patch(
1379 .clone(), 1371 .clone(),
1380 )?; 1372 )?;
1381 1373
1382 get_events_from_local_cache( 1374 get_events_from_local_cache(git_repo.get_path()?, vec![
1383 git_repo.get_path()?, 1375 nostr::Filter::default().id(proposal_or_revision_id),
1384 vec![nostr::Filter::default().id(proposal_or_revision_id)], 1376 ])
1385 )
1386 .await? 1377 .await?
1387 .first() 1378 .first()
1388 .unwrap() 1379 .unwrap()
@@ -1538,10 +1529,9 @@ impl BuildRepoState for RepoState {
1538 ) -> Result<RepoState> { 1529 ) -> Result<RepoState> {
1539 let mut tags = vec![Tag::identifier(identifier.clone())]; 1530 let mut tags = vec![Tag::identifier(identifier.clone())];
1540 for (name, value) in &state { 1531 for (name, value) in &state {
1541 tags.push(Tag::custom( 1532 tags.push(Tag::custom(nostr_sdk::TagKind::Custom(name.into()), vec![
1542 nostr_sdk::TagKind::Custom(name.into()), 1533 value.clone(),
1543 vec![value.clone()], 1534 ]));
1544 ));
1545 } 1535 }
1546 let event = sign_event(EventBuilder::new(STATE_KIND, "").tags(tags), signer).await?; 1536 let event = sign_event(EventBuilder::new(STATE_KIND, "").tags(tags), signer).await?;
1547 Ok(RepoState { 1537 Ok(RepoState {
diff --git a/src/bin/git_remote_nostr/utils.rs b/src/bin/git_remote_nostr/utils.rs
index 8e89652..15ebb10 100644
--- a/src/bin/git_remote_nostr/utils.rs
+++ b/src/bin/git_remote_nostr/utils.rs
@@ -6,7 +6,7 @@ use std::{
6 str::FromStr, 6 str::FromStr,
7}; 7};
8 8
9use anyhow::{bail, Context, Result}; 9use anyhow::{Context, Result, bail};
10use git2::Repository; 10use git2::Repository;
11use ngit::{ 11use ngit::{
12 client::{ 12 client::{
@@ -14,8 +14,8 @@ use ngit::{
14 get_proposals_and_revisions_from_cache, 14 get_proposals_and_revisions_from_cache,
15 }, 15 },
16 git::{ 16 git::{
17 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol},
18 Repo, RepoActions, 17 Repo, RepoActions,
18 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol},
19 }, 19 },
20 git_events::{ 20 git_events::{
21 event_is_revision_root, get_most_recent_patch_with_ancestors, 21 event_is_revision_root, get_most_recent_patch_with_ancestors,
@@ -108,14 +108,11 @@ pub async fn get_open_proposals(
108 .collect(); 108 .collect();
109 109
110 let statuses: Vec<nostr::Event> = { 110 let statuses: Vec<nostr::Event> = {
111 let mut statuses = get_events_from_local_cache( 111 let mut statuses = get_events_from_local_cache(git_repo_path, vec![
112 git_repo_path, 112 nostr::Filter::default()
113 vec![ 113 .kinds(status_kinds().clone())
114 nostr::Filter::default() 114 .events(proposals.iter().map(|e| e.id)),
115 .kinds(status_kinds().clone()) 115 ])
116 .events(proposals.iter().map(|e| e.id)),
117 ],
118 )
119 .await?; 116 .await?;
120 statuses.sort_by_key(|e| e.created_at); 117 statuses.sort_by_key(|e| e.created_at);
121 statuses.reverse(); 118 statuses.reverse();
diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs
index 1737a9f..60bc5d2 100644
--- a/src/bin/ngit/cli.rs
+++ b/src/bin/ngit/cli.rs
@@ -1,4 +1,4 @@
1use anyhow::{bail, Result}; 1use anyhow::{Result, bail};
2use clap::{Parser, Subcommand}; 2use clap::{Parser, Subcommand};
3use ngit::login::SignerInfo; 3use ngit::login::SignerInfo;
4 4
diff --git a/src/bin/ngit/sub_commands/export_keys.rs b/src/bin/ngit/sub_commands/export_keys.rs
index 54a716f..45b1b89 100644
--- a/src/bin/ngit/sub_commands/export_keys.rs
+++ b/src/bin/ngit/sub_commands/export_keys.rs
@@ -2,9 +2,9 @@ use anyhow::{Context, Result};
2use ngit::{ 2use ngit::{
3 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms}, 3 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms},
4 login::{ 4 login::{
5 SignerInfo, SignerInfoSource,
5 existing::{get_signer_info, load_existing_login}, 6 existing::{get_signer_info, load_existing_login},
6 fresh::generate_qr, 7 fresh::generate_qr,
7 SignerInfo, SignerInfoSource,
8 }, 8 },
9}; 9};
10 10
diff --git a/src/bin/ngit/sub_commands/init.rs b/src/bin/ngit/sub_commands/init.rs
index 0894f41..80e182b 100644
--- a/src/bin/ngit/sub_commands/init.rs
+++ b/src/bin/ngit/sub_commands/init.rs
@@ -3,18 +3,18 @@ use std::collections::HashMap;
3use anyhow::{Context, Result}; 3use anyhow::{Context, Result};
4use console::Style; 4use console::Style;
5use ngit::{cli_interactor::PromptConfirmParms, git::nostr_url::NostrUrlDecoded}; 5use ngit::{cli_interactor::PromptConfirmParms, git::nostr_url::NostrUrlDecoded};
6use nostr::{nips::nip01::Coordinate, FromBech32, PublicKey, ToBech32}; 6use nostr::{FromBech32, PublicKey, ToBech32, nips::nip01::Coordinate};
7use nostr_sdk::{Kind, RelayUrl}; 7use nostr_sdk::{Kind, RelayUrl};
8 8
9use crate::{ 9use crate::{
10 cli::{extract_signer_cli_arguments, Cli}, 10 cli::{Cli, extract_signer_cli_arguments},
11 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, 11 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms},
12 client::{fetching_with_report, get_repo_ref_from_cache, send_events, Client, Connect}, 12 client::{Client, Connect, fetching_with_report, get_repo_ref_from_cache, send_events},
13 git::{nostr_url::convert_clone_url_to_https, Repo, RepoActions}, 13 git::{Repo, RepoActions, nostr_url::convert_clone_url_to_https},
14 login, 14 login,
15 repo_ref::{ 15 repo_ref::{
16 extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml, 16 RepoRef, extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml,
17 try_and_get_repo_coordinates_when_remote_unknown, RepoRef, 17 try_and_get_repo_coordinates_when_remote_unknown,
18 }, 18 },
19}; 19};
20 20
diff --git a/src/bin/ngit/sub_commands/list.rs b/src/bin/ngit/sub_commands/list.rs
index ee015ef..9b84c1b 100644
--- a/src/bin/ngit/sub_commands/list.rs
+++ b/src/bin/ngit/sub_commands/list.rs
@@ -1,6 +1,6 @@
1use std::{io::Write, ops::Add}; 1use std::{io::Write, ops::Add};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{Context, Result, bail};
4use ngit::{ 4use ngit::{
5 client::{get_all_proposal_patch_events_from_cache, get_proposals_and_revisions_from_cache}, 5 client::{get_all_proposal_patch_events_from_cache, get_proposals_and_revisions_from_cache},
6 git_events::{ 6 git_events::{
@@ -12,9 +12,9 @@ use nostr_sdk::Kind;
12use crate::{ 12use crate::{
13 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms}, 13 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms},
14 client::{ 14 client::{
15 fetching_with_report, get_events_from_local_cache, get_repo_ref_from_cache, Client, Connect, 15 Client, Connect, fetching_with_report, get_events_from_local_cache, get_repo_ref_from_cache,
16 }, 16 },
17 git::{str_to_sha1, Repo, RepoActions}, 17 git::{Repo, RepoActions, str_to_sha1},
18 git_events::{ 18 git_events::{
19 commit_msg_from_patch_oneliner, event_is_revision_root, event_to_cover_letter, 19 commit_msg_from_patch_oneliner, event_is_revision_root, event_to_cover_letter,
20 patch_supports_commit_ids, 20 patch_supports_commit_ids,
@@ -47,14 +47,11 @@ pub async fn launch() -> Result<()> {
47 } 47 }
48 48
49 let statuses: Vec<nostr::Event> = { 49 let statuses: Vec<nostr::Event> = {
50 let mut statuses = get_events_from_local_cache( 50 let mut statuses = get_events_from_local_cache(git_repo_path, vec![
51 git_repo_path, 51 nostr::Filter::default()
52 vec![ 52 .kinds(status_kinds().clone())
53 nostr::Filter::default() 53 .events(proposals_and_revisions.iter().map(|e| e.id)),
54 .kinds(status_kinds().clone()) 54 ])
55 .events(proposals_and_revisions.iter().map(|e| e.id)),
56 ],
57 )
58 .await?; 55 .await?;
59 statuses.sort_by_key(|e| e.created_at); 56 statuses.sort_by_key(|e| e.created_at);
60 statuses.reverse(); 57 statuses.reverse();
diff --git a/src/bin/ngit/sub_commands/login.rs b/src/bin/ngit/sub_commands/login.rs
index ccbdf01..06236ec 100644
--- a/src/bin/ngit/sub_commands/login.rs
+++ b/src/bin/ngit/sub_commands/login.rs
@@ -3,11 +3,11 @@ use clap;
3use ngit::{ 3use ngit::{
4 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms}, 4 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms},
5 git::{get_git_config_item, remove_git_config_item}, 5 git::{get_git_config_item, remove_git_config_item},
6 login::{existing::load_existing_login, SignerInfoSource}, 6 login::{SignerInfoSource, existing::load_existing_login},
7}; 7};
8 8
9use crate::{ 9use crate::{
10 cli::{extract_signer_cli_arguments, Cli}, 10 cli::{Cli, extract_signer_cli_arguments},
11 client::{Client, Connect}, 11 client::{Client, Connect},
12 git::Repo, 12 git::Repo,
13 login::fresh::fresh_login_or_signup, 13 login::fresh::fresh_login_or_signup,
diff --git a/src/bin/ngit/sub_commands/logout.rs b/src/bin/ngit/sub_commands/logout.rs
index f3f9620..2df96c8 100644
--- a/src/bin/ngit/sub_commands/logout.rs
+++ b/src/bin/ngit/sub_commands/logout.rs
@@ -1,7 +1,7 @@
1use anyhow::{Context, Result}; 1use anyhow::{Context, Result};
2use ngit::{ 2use ngit::{
3 git::remove_git_config_item, 3 git::remove_git_config_item,
4 login::{existing::load_existing_login, SignerInfoSource}, 4 login::{SignerInfoSource, existing::load_existing_login},
5}; 5};
6 6
7use crate::{ 7use crate::{
diff --git a/src/bin/ngit/sub_commands/send.rs b/src/bin/ngit/sub_commands/send.rs
index c6c75c9..7c898bc 100644
--- a/src/bin/ngit/sub_commands/send.rs
+++ b/src/bin/ngit/sub_commands/send.rs
@@ -1,23 +1,23 @@
1use std::path::Path; 1use std::path::Path;
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{Context, Result, bail};
4use console::Style; 4use console::Style;
5use ngit::{client::send_events, git_events::generate_cover_letter_and_patch_events}; 5use ngit::{client::send_events, git_events::generate_cover_letter_and_patch_events};
6use nostr::{ 6use nostr::{
7 nips::{nip10::Marker, nip19::Nip19Event},
8 ToBech32, 7 ToBech32,
8 nips::{nip10::Marker, nip19::Nip19Event},
9}; 9};
10use nostr_sdk::hashes::sha1::Hash as Sha1Hash; 10use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
11 11
12use crate::{ 12use crate::{
13 cli::{extract_signer_cli_arguments, Cli}, 13 cli::{Cli, extract_signer_cli_arguments},
14 cli_interactor::{ 14 cli_interactor::{
15 Interactor, InteractorPrompt, PromptConfirmParms, PromptInputParms, PromptMultiChoiceParms, 15 Interactor, InteractorPrompt, PromptConfirmParms, PromptInputParms, PromptMultiChoiceParms,
16 }, 16 },
17 client::{ 17 client::{
18 fetching_with_report, get_events_from_local_cache, get_repo_ref_from_cache, Client, Connect, 18 Client, Connect, fetching_with_report, get_events_from_local_cache, get_repo_ref_from_cache,
19 }, 19 },
20 git::{identify_ahead_behind, Repo, RepoActions}, 20 git::{Repo, RepoActions, identify_ahead_behind},
21 git_events::{event_is_patch_set_root, event_tag_from_nip19_or_hex}, 21 git_events::{event_is_patch_set_root, event_tag_from_nip19_or_hex},
22 login, 22 login,
23 repo_ref::get_repo_coordinates_when_remote_unknown, 23 repo_ref::get_repo_coordinates_when_remote_unknown,
@@ -369,10 +369,9 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to(
369 public_key: _, 369 public_key: _,
370 uppercase: false, 370 uppercase: false,
371 }) => { 371 }) => {
372 let events = get_events_from_local_cache( 372 let events = get_events_from_local_cache(git_repo_path, vec![
373 git_repo_path, 373 nostr::Filter::new().id(*event_id),
374 vec![nostr::Filter::new().id(*event_id)], 374 ])
375 )
376 .await?; 375 .await?;
377 376
378 if let Some(first) = events.iter().find(|e| e.id.eq(event_id)) { 377 if let Some(first) = events.iter().find(|e| e.id.eq(event_id)) {
diff --git a/src/lib/cli_interactor.rs b/src/lib/cli_interactor.rs
index 50a0f0c..1b74101 100644
--- a/src/lib/cli_interactor.rs
+++ b/src/lib/cli_interactor.rs
@@ -1,5 +1,5 @@
1use anyhow::{Context, Result}; 1use anyhow::{Context, Result};
2use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password}; 2use dialoguer::{Confirm, Input, Password, theme::ColorfulTheme};
3use indicatif::TermLike; 3use indicatif::TermLike;
4#[cfg(test)] 4#[cfg(test)]
5use mockall::*; 5use mockall::*;
diff --git a/src/lib/client.rs b/src/lib/client.rs
index 32f5bd7..59ec583 100644
--- a/src/lib/client.rs
+++ b/src/lib/client.rs
@@ -19,7 +19,7 @@ use std::{
19 time::Duration, 19 time::Duration,
20}; 20};
21 21
22use anyhow::{bail, Context, Result}; 22use anyhow::{Context, Result, bail};
23use async_trait::async_trait; 23use async_trait::async_trait;
24use console::Style; 24use console::Style;
25use futures::{ 25use futures::{
@@ -29,12 +29,12 @@ use futures::{
29use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressState, ProgressStyle}; 29use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressState, ProgressStyle};
30#[cfg(test)] 30#[cfg(test)]
31use mockall::*; 31use mockall::*;
32use nostr::{nips::nip01::Coordinate, signer::SignerBackend, Event}; 32use nostr::{Event, nips::nip01::Coordinate, signer::SignerBackend};
33use nostr_database::NostrEventsDatabase; 33use nostr_database::NostrEventsDatabase;
34use nostr_lmdb::NostrLMDB; 34use nostr_lmdb::NostrLMDB;
35use nostr_sdk::{ 35use nostr_sdk::{
36 prelude::RelayLimits, EventBuilder, EventId, Kind, NostrSigner, Options, PublicKey, RelayUrl, 36 EventBuilder, EventId, Kind, NostrSigner, Options, PublicKey, RelayUrl, SingleLetterTag,
37 SingleLetterTag, Timestamp, 37 Timestamp, prelude::RelayLimits,
38}; 38};
39 39
40use crate::{ 40use crate::{
@@ -894,18 +894,16 @@ pub async fn get_state_from_cache(
894) -> Result<RepoState> { 894) -> Result<RepoState> {
895 if let Some(git_repo_path) = git_repo_path { 895 if let Some(git_repo_path) = git_repo_path {
896 RepoState::try_from( 896 RepoState::try_from(
897 get_events_from_local_cache( 897 get_events_from_local_cache(git_repo_path, vec![get_filter_state_events(
898 git_repo_path, 898 &repo_ref.coordinates(),
899 vec![get_filter_state_events(&repo_ref.coordinates())], 899 )])
900 )
901 .await?, 900 .await?,
902 ) 901 )
903 } else { 902 } else {
904 RepoState::try_from( 903 RepoState::try_from(
905 get_event_from_global_cache( 904 get_event_from_global_cache(git_repo_path, vec![get_filter_state_events(
906 git_repo_path, 905 &repo_ref.coordinates(),
907 vec![get_filter_state_events(&repo_ref.coordinates())], 906 )])
908 )
909 .await?, 907 .await?,
910 ) 908 )
911 } 909 }
@@ -975,20 +973,17 @@ async fn create_relays_request(
975 } 973 }
976 974
977 if let Some(git_repo_path) = git_repo_path { 975 if let Some(git_repo_path) = git_repo_path {
978 for event in &get_events_from_local_cache( 976 for event in &get_events_from_local_cache(git_repo_path, vec![
979 git_repo_path, 977 nostr::Filter::default()
980 vec![ 978 .kinds(vec![Kind::GitPatch])
981 nostr::Filter::default() 979 .custom_tag(
982 .kinds(vec![Kind::GitPatch]) 980 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
983 .custom_tag( 981 repo_coordinates_without_relays
984 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 982 .iter()
985 repo_coordinates_without_relays 983 .map(std::string::ToString::to_string)
986 .iter() 984 .collect::<Vec<String>>(),
987 .map(std::string::ToString::to_string) 985 ),
988 .collect::<Vec<String>>(), 986 ])
989 ),
990 ],
991 )
992 .await? 987 .await?
993 { 988 {
994 if event_is_patch_set_root(event) || event_is_revision_root(event) { 989 if event_is_patch_set_root(event) || event_is_revision_root(event) {
@@ -998,11 +993,11 @@ async fn create_relays_request(
998 } 993 }
999 } 994 }
1000 995
1001 let profile_events = get_event_from_global_cache( 996 let profile_events =
1002 git_repo_path, 997 get_event_from_global_cache(git_repo_path, vec![get_filter_contributor_profiles(
1003 vec![get_filter_contributor_profiles(contributors.clone())], 998 contributors.clone(),
1004 ) 999 )])
1005 .await?; 1000 .await?;
1006 for c in &contributors { 1001 for c in &contributors {
1007 if let Some(event) = profile_events 1002 if let Some(event) = profile_events
1008 .iter() 1003 .iter()
@@ -1564,20 +1559,17 @@ pub async fn get_proposals_and_revisions_from_cache(
1564 git_repo_path: &Path, 1559 git_repo_path: &Path,
1565 repo_coordinates: HashSet<Coordinate>, 1560 repo_coordinates: HashSet<Coordinate>,
1566) -> Result<Vec<nostr::Event>> { 1561) -> Result<Vec<nostr::Event>> {
1567 let mut proposals = get_events_from_local_cache( 1562 let mut proposals = get_events_from_local_cache(git_repo_path, vec![
1568 git_repo_path, 1563 nostr::Filter::default()
1569 vec![ 1564 .kind(nostr::Kind::GitPatch)
1570 nostr::Filter::default() 1565 .custom_tag(
1571 .kind(nostr::Kind::GitPatch) 1566 nostr::SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
1572 .custom_tag( 1567 repo_coordinates
1573 nostr::SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 1568 .iter()
1574 repo_coordinates 1569 .map(std::string::ToString::to_string)
1575 .iter() 1570 .collect::<Vec<String>>(),
1576 .map(std::string::ToString::to_string) 1571 ),
1577 .collect::<Vec<String>>(), 1572 ])
1578 ),
1579 ],
1580 )
1581 .await? 1573 .await?
1582 .iter() 1574 .iter()
1583 .filter(|e| event_is_patch_set_root(e)) 1575 .filter(|e| event_is_patch_set_root(e))
@@ -1593,29 +1585,23 @@ pub async fn get_all_proposal_patch_events_from_cache(
1593 repo_ref: &RepoRef, 1585 repo_ref: &RepoRef,
1594 proposal_id: &nostr::EventId, 1586 proposal_id: &nostr::EventId,
1595) -> Result<Vec<nostr::Event>> { 1587) -> Result<Vec<nostr::Event>> {
1596 let mut commit_events = get_events_from_local_cache( 1588 let mut commit_events = get_events_from_local_cache(git_repo_path, vec![
1597 git_repo_path, 1589 nostr::Filter::default()
1598 vec![ 1590 .kind(nostr::Kind::GitPatch)
1599 nostr::Filter::default() 1591 .event(*proposal_id),
1600 .kind(nostr::Kind::GitPatch) 1592 nostr::Filter::default()
1601 .event(*proposal_id), 1593 .kind(nostr::Kind::GitPatch)
1602 nostr::Filter::default() 1594 .id(*proposal_id),
1603 .kind(nostr::Kind::GitPatch) 1595 ])
1604 .id(*proposal_id),
1605 ],
1606 )
1607 .await?; 1596 .await?;
1608 1597
1609 let permissioned_users: HashSet<PublicKey> = [ 1598 let permissioned_users: HashSet<PublicKey> = [repo_ref.maintainers.clone(), vec![
1610 repo_ref.maintainers.clone(), 1599 commit_events
1611 vec![ 1600 .iter()
1612 commit_events 1601 .find(|e| e.id.eq(proposal_id))
1613 .iter() 1602 .context("proposal not in cache")?
1614 .find(|e| e.id.eq(proposal_id)) 1603 .pubkey,
1615 .context("proposal not in cache")? 1604 ]]
1616 .pubkey,
1617 ],
1618 ]
1619 .concat() 1605 .concat()
1620 .iter() 1606 .iter()
1621 .copied() 1607 .copied()
@@ -1629,15 +1615,12 @@ pub async fn get_all_proposal_patch_events_from_cache(
1629 .collect(); 1615 .collect();
1630 1616
1631 if !revision_roots.is_empty() { 1617 if !revision_roots.is_empty() {
1632 for event in get_events_from_local_cache( 1618 for event in get_events_from_local_cache(git_repo_path, vec![
1633 git_repo_path, 1619 nostr::Filter::default()
1634 vec![ 1620 .kind(nostr::Kind::GitPatch)
1635 nostr::Filter::default() 1621 .events(revision_roots)
1636 .kind(nostr::Kind::GitPatch) 1622 .authors(permissioned_users.clone()),
1637 .events(revision_roots) 1623 ])
1638 .authors(permissioned_users.clone()),
1639 ],
1640 )
1641 .await? 1624 .await?
1642 { 1625 {
1643 commit_events.push(event); 1626 commit_events.push(event);
@@ -1652,10 +1635,9 @@ pub async fn get_all_proposal_patch_events_from_cache(
1652} 1635}
1653 1636
1654pub async fn get_event_from_cache_by_id(git_repo: &Repo, event_id: &EventId) -> Result<Event> { 1637pub async fn get_event_from_cache_by_id(git_repo: &Repo, event_id: &EventId) -> Result<Event> {
1655 Ok(get_events_from_local_cache( 1638 Ok(get_events_from_local_cache(git_repo.get_path()?, vec![
1656 git_repo.get_path()?, 1639 nostr::Filter::default().id(*event_id),
1657 vec![nostr::Filter::default().id(*event_id)], 1640 ])
1658 )
1659 .await? 1641 .await?
1660 .first() 1642 .first()
1661 .context("failed to find event in cache")? 1643 .context("failed to find event in cache")?
diff --git a/src/lib/git/identify_ahead_behind.rs b/src/lib/git/identify_ahead_behind.rs
index d736522..baea687 100644
--- a/src/lib/git/identify_ahead_behind.rs
+++ b/src/lib/git/identify_ahead_behind.rs
@@ -184,10 +184,10 @@ mod tests {
184 identify_ahead_behind(&git_repo, &Some("feature".to_string()), &None)?; 184 identify_ahead_behind(&git_repo, &Some("feature".to_string()), &None)?;
185 185
186 assert_eq!(from_branch, "feature"); 186 assert_eq!(from_branch, "feature");
187 assert_eq!( 187 assert_eq!(ahead, vec![
188 ahead, 188 oid_to_sha1(&feature_oid),
189 vec![oid_to_sha1(&feature_oid), oid_to_sha1(&dev_oid_first)] 189 oid_to_sha1(&dev_oid_first)
190 ); 190 ]);
191 assert_eq!(to_branch, "main"); 191 assert_eq!(to_branch, "main");
192 assert_eq!(behind, vec![]); 192 assert_eq!(behind, vec![]);
193 193
diff --git a/src/lib/git/mod.rs b/src/lib/git/mod.rs
index 7a7ad5d..2b78f38 100644
--- a/src/lib/git/mod.rs
+++ b/src/lib/git/mod.rs
@@ -3,12 +3,12 @@ use std::{
3 path::{Path, PathBuf}, 3 path::{Path, PathBuf},
4}; 4};
5 5
6use anyhow::{bail, Context, Result}; 6use anyhow::{Context, Result, bail};
7use git2::{DiffOptions, Oid, Revwalk}; 7use git2::{DiffOptions, Oid, Revwalk};
8pub use identify_ahead_behind::identify_ahead_behind; 8pub use identify_ahead_behind::identify_ahead_behind;
9use nostr_sdk::{ 9use nostr_sdk::{
10 hashes::{sha1::Hash as Sha1Hash, Hash},
11 Tags, 10 Tags,
11 hashes::{Hash, sha1::Hash as Sha1Hash},
12}; 12};
13 13
14use crate::git_events::{get_commit_id_from_patch, tag_value}; 14use crate::git_events::{get_commit_id_from_patch, tag_value};
@@ -1493,10 +1493,10 @@ mod tests {
1493 &oid_to_sha1(&feature_oid), 1493 &oid_to_sha1(&feature_oid),
1494 )?; 1494 )?;
1495 assert_eq!(ahead, vec![]); 1495 assert_eq!(ahead, vec![]);
1496 assert_eq!( 1496 assert_eq!(behind, vec![
1497 behind, 1497 oid_to_sha1(&behind_2_oid),
1498 vec![oid_to_sha1(&behind_2_oid), oid_to_sha1(&behind_1_oid),], 1498 oid_to_sha1(&behind_1_oid),
1499 ); 1499 ],);
1500 Ok(()) 1500 Ok(())
1501 } 1501 }
1502 1502
@@ -1518,10 +1518,10 @@ mod tests {
1518 &oid_to_sha1(&main_oid), 1518 &oid_to_sha1(&main_oid),
1519 &oid_to_sha1(&ahead_2_oid), 1519 &oid_to_sha1(&ahead_2_oid),
1520 )?; 1520 )?;
1521 assert_eq!( 1521 assert_eq!(ahead, vec![
1522 ahead, 1522 oid_to_sha1(&ahead_2_oid),
1523 vec![oid_to_sha1(&ahead_2_oid), oid_to_sha1(&ahead_1_oid),], 1523 oid_to_sha1(&ahead_1_oid),
1524 ); 1524 ],);
1525 assert_eq!(behind, vec![]); 1525 assert_eq!(behind, vec![]);
1526 Ok(()) 1526 Ok(())
1527 } 1527 }
@@ -1550,14 +1550,14 @@ mod tests {
1550 &oid_to_sha1(&behind_2_oid), 1550 &oid_to_sha1(&behind_2_oid),
1551 &oid_to_sha1(&ahead_2_oid), 1551 &oid_to_sha1(&ahead_2_oid),
1552 )?; 1552 )?;
1553 assert_eq!( 1553 assert_eq!(ahead, vec![
1554 ahead, 1554 oid_to_sha1(&ahead_2_oid),
1555 vec![oid_to_sha1(&ahead_2_oid), oid_to_sha1(&ahead_1_oid)], 1555 oid_to_sha1(&ahead_1_oid)
1556 ); 1556 ],);
1557 assert_eq!( 1557 assert_eq!(behind, vec![
1558 behind, 1558 oid_to_sha1(&behind_2_oid),
1559 vec![oid_to_sha1(&behind_2_oid), oid_to_sha1(&behind_1_oid)], 1559 oid_to_sha1(&behind_1_oid)
1560 ); 1560 ],);
1561 Ok(()) 1561 Ok(())
1562 } 1562 }
1563 } 1563 }
@@ -2212,10 +2212,9 @@ mod tests {
2212 test_repo.populate_with_test_branch()?; 2212 test_repo.populate_with_test_branch()?;
2213 test_repo.checkout("main")?; 2213 test_repo.checkout("main")?;
2214 2214
2215 assert_eq!( 2215 assert_eq!(git_repo.parse_starting_commits("HEAD~1")?, vec![
2216 git_repo.parse_starting_commits("HEAD~1")?, 2216 str_to_sha1("431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?
2217 vec![str_to_sha1("431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?], 2217 ],);
2218 );
2219 Ok(()) 2218 Ok(())
2220 } 2219 }
2221 2220
@@ -2225,10 +2224,9 @@ mod tests {
2225 let git_repo = Repo::from_path(&test_repo.dir)?; 2224 let git_repo = Repo::from_path(&test_repo.dir)?;
2226 test_repo.populate_with_test_branch()?; 2225 test_repo.populate_with_test_branch()?;
2227 2226
2228 assert_eq!( 2227 assert_eq!(git_repo.parse_starting_commits("HEAD~1")?, vec![
2229 git_repo.parse_starting_commits("HEAD~1")?, 2228 str_to_sha1("82ff2bcc9aa94d1bd8faee723d4c8cc190d6061c")?
2230 vec![str_to_sha1("82ff2bcc9aa94d1bd8faee723d4c8cc190d6061c")?], 2229 ],);
2231 );
2232 Ok(()) 2230 Ok(())
2233 } 2231 }
2234 } 2232 }
@@ -2242,13 +2240,10 @@ mod tests {
2242 test_repo.populate_with_test_branch()?; 2240 test_repo.populate_with_test_branch()?;
2243 test_repo.checkout("main")?; 2241 test_repo.checkout("main")?;
2244 2242
2245 assert_eq!( 2243 assert_eq!(git_repo.parse_starting_commits("HEAD~2")?, vec![
2246 git_repo.parse_starting_commits("HEAD~2")?, 2244 str_to_sha1("431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?,
2247 vec![ 2245 str_to_sha1("af474d8d271490e5c635aad337abdc050034b16a")?,
2248 str_to_sha1("431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?, 2246 ],);
2249 str_to_sha1("af474d8d271490e5c635aad337abdc050034b16a")?,
2250 ],
2251 );
2252 Ok(()) 2247 Ok(())
2253 } 2248 }
2254 } 2249 }
@@ -2261,14 +2256,11 @@ mod tests {
2261 let git_repo = Repo::from_path(&test_repo.dir)?; 2256 let git_repo = Repo::from_path(&test_repo.dir)?;
2262 test_repo.populate_with_test_branch()?; 2257 test_repo.populate_with_test_branch()?;
2263 2258
2264 assert_eq!( 2259 assert_eq!(git_repo.parse_starting_commits("HEAD~3")?, vec![
2265 git_repo.parse_starting_commits("HEAD~3")?, 2260 str_to_sha1("82ff2bcc9aa94d1bd8faee723d4c8cc190d6061c")?,
2266 vec![ 2261 str_to_sha1("a23e6b05aaeb7d1471b4a838b51f337d5644eeb0")?,
2267 str_to_sha1("82ff2bcc9aa94d1bd8faee723d4c8cc190d6061c")?, 2262 str_to_sha1("7ab82116068982671a8111f27dc10599172334b2")?,
2268 str_to_sha1("a23e6b05aaeb7d1471b4a838b51f337d5644eeb0")?, 2263 ],);
2269 str_to_sha1("7ab82116068982671a8111f27dc10599172334b2")?,
2270 ],
2271 );
2272 Ok(()) 2264 Ok(())
2273 } 2265 }
2274 } 2266 }
@@ -2282,14 +2274,11 @@ mod tests {
2282 test_repo.populate_with_test_branch()?; 2274 test_repo.populate_with_test_branch()?;
2283 test_repo.checkout("main")?; 2275 test_repo.checkout("main")?;
2284 2276
2285 assert_eq!( 2277 assert_eq!(git_repo.parse_starting_commits("af474d8..a23e6b0")?, vec![
2286 git_repo.parse_starting_commits("af474d8..a23e6b0")?, 2278 str_to_sha1("a23e6b05aaeb7d1471b4a838b51f337d5644eeb0")?,
2287 vec![ 2279 str_to_sha1("7ab82116068982671a8111f27dc10599172334b2")?,
2288 str_to_sha1("a23e6b05aaeb7d1471b4a838b51f337d5644eeb0")?, 2280 str_to_sha1("431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?,
2289 str_to_sha1("7ab82116068982671a8111f27dc10599172334b2")?, 2281 ],);
2290 str_to_sha1("431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?,
2291 ],
2292 );
2293 Ok(()) 2282 Ok(())
2294 } 2283 }
2295 } 2284 }
diff --git a/src/lib/git/nostr_url.rs b/src/lib/git/nostr_url.rs
index 4fbc786..6b38a93 100644
--- a/src/lib/git/nostr_url.rs
+++ b/src/lib/git/nostr_url.rs
@@ -1,11 +1,11 @@
1use core::fmt; 1use core::fmt;
2use std::{collections::HashMap, str::FromStr}; 2use std::{collections::HashMap, str::FromStr};
3 3
4use anyhow::{anyhow, bail, Context, Error, Result}; 4use anyhow::{Context, Error, Result, anyhow, bail};
5use nostr::nips::{nip01::Coordinate, nip05}; 5use nostr::nips::{nip01::Coordinate, nip05};
6use nostr_sdk::{PublicKey, RelayUrl, ToBech32, Url}; 6use nostr_sdk::{PublicKey, RelayUrl, ToBech32, Url};
7 7
8use super::{get_git_config_item, save_git_config_item, Repo}; 8use super::{Repo, get_git_config_item, save_git_config_item};
9 9
10#[derive(Debug, PartialEq, Default, Clone)] 10#[derive(Debug, PartialEq, Default, Clone)]
11pub enum ServerProtocol { 11pub enum ServerProtocol {
@@ -961,24 +961,21 @@ mod tests {
961 #[test] 961 #[test]
962 fn standard() -> Result<()> { 962 fn standard() -> Result<()> {
963 assert_eq!( 963 assert_eq!(
964 format!( 964 format!("{}", NostrUrlDecoded {
965 "{}", 965 original_string: String::new(),
966 NostrUrlDecoded { 966 coordinate: Coordinate {
967 original_string: String::new(), 967 identifier: "ngit".to_string(),
968 coordinate: Coordinate { 968 public_key: PublicKey::parse(
969 identifier: "ngit".to_string(), 969 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
970 public_key: PublicKey::parse( 970 )
971 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 971 .unwrap(),
972 ) 972 kind: nostr_sdk::Kind::GitRepoAnnouncement,
973 .unwrap(), 973 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()],
974 kind: nostr_sdk::Kind::GitRepoAnnouncement, 974 },
975 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], 975 protocol: None,
976 }, 976 user: None,
977 protocol: None, 977 nip05: None,
978 user: None, 978 }),
979 nip05: None,
980 }
981 ),
982 "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit", 979 "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit",
983 ); 980 );
984 Ok(()) 981 Ok(())
@@ -987,24 +984,21 @@ mod tests {
987 #[test] 984 #[test]
988 fn no_relay() -> Result<()> { 985 fn no_relay() -> Result<()> {
989 assert_eq!( 986 assert_eq!(
990 format!( 987 format!("{}", NostrUrlDecoded {
991 "{}", 988 original_string: String::new(),
992 NostrUrlDecoded { 989 coordinate: Coordinate {
993 original_string: String::new(), 990 identifier: "ngit".to_string(),
994 coordinate: Coordinate { 991 public_key: PublicKey::parse(
995 identifier: "ngit".to_string(), 992 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
996 public_key: PublicKey::parse( 993 )
997 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 994 .unwrap(),
998 ) 995 kind: nostr_sdk::Kind::GitRepoAnnouncement,
999 .unwrap(), 996 relays: vec![],
1000 kind: nostr_sdk::Kind::GitRepoAnnouncement, 997 },
1001 relays: vec![], 998 protocol: None,
1002 }, 999 user: None,
1003 protocol: None, 1000 nip05: None,
1004 user: None, 1001 }),
1005 nip05: None,
1006 }
1007 ),
1008 "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit", 1002 "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit",
1009 ); 1003 );
1010 Ok(()) 1004 Ok(())
@@ -1013,24 +1007,21 @@ mod tests {
1013 #[test] 1007 #[test]
1014 fn with_protocol() -> Result<()> { 1008 fn with_protocol() -> Result<()> {
1015 assert_eq!( 1009 assert_eq!(
1016 format!( 1010 format!("{}", NostrUrlDecoded {
1017 "{}", 1011 original_string: String::new(),
1018 NostrUrlDecoded { 1012 coordinate: Coordinate {
1019 original_string: String::new(), 1013 identifier: "ngit".to_string(),
1020 coordinate: Coordinate { 1014 public_key: PublicKey::parse(
1021 identifier: "ngit".to_string(), 1015 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
1022 public_key: PublicKey::parse( 1016 )
1023 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 1017 .unwrap(),
1024 ) 1018 kind: nostr_sdk::Kind::GitRepoAnnouncement,
1025 .unwrap(), 1019 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()],
1026 kind: nostr_sdk::Kind::GitRepoAnnouncement, 1020 },
1027 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], 1021 protocol: Some(ServerProtocol::Ssh),
1028 }, 1022 user: None,
1029 protocol: Some(ServerProtocol::Ssh), 1023 nip05: None,
1030 user: None, 1024 }),
1031 nip05: None,
1032 }
1033 ),
1034 "nostr://ssh/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit", 1025 "nostr://ssh/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit",
1035 ); 1026 );
1036 Ok(()) 1027 Ok(())
@@ -1039,24 +1030,21 @@ mod tests {
1039 #[test] 1030 #[test]
1040 fn with_protocol_and_user() -> Result<()> { 1031 fn with_protocol_and_user() -> Result<()> {
1041 assert_eq!( 1032 assert_eq!(
1042 format!( 1033 format!("{}", NostrUrlDecoded {
1043 "{}", 1034 original_string: String::new(),
1044 NostrUrlDecoded { 1035 coordinate: Coordinate {
1045 original_string: String::new(), 1036 identifier: "ngit".to_string(),
1046 coordinate: Coordinate { 1037 public_key: PublicKey::parse(
1047 identifier: "ngit".to_string(), 1038 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr",
1048 public_key: PublicKey::parse( 1039 )
1049 "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", 1040 .unwrap(),
1050 ) 1041 kind: nostr_sdk::Kind::GitRepoAnnouncement,
1051 .unwrap(), 1042 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()],
1052 kind: nostr_sdk::Kind::GitRepoAnnouncement, 1043 },
1053 relays: vec![RelayUrl::parse("wss://nos.lol").unwrap()], 1044 protocol: Some(ServerProtocol::Ssh),
1054 }, 1045 user: Some("bla".to_string()),
1055 protocol: Some(ServerProtocol::Ssh), 1046 nip05: None,
1056 user: Some("bla".to_string()), 1047 }),
1057 nip05: None,
1058 }
1059 ),
1060 "nostr://bla@ssh/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit", 1048 "nostr://bla@ssh/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit",
1061 ); 1049 );
1062 Ok(()) 1050 Ok(())
diff --git a/src/lib/git_events.rs b/src/lib/git_events.rs
index d8564ae..af469d3 100644
--- a/src/lib/git_events.rs
+++ b/src/lib/git_events.rs
@@ -1,10 +1,10 @@
1use std::{str::FromStr, sync::Arc}; 1use std::{str::FromStr, sync::Arc};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{Context, Result, bail};
4use nostr::nips::{nip01::Coordinate, nip10::Marker, nip19::Nip19}; 4use nostr::nips::{nip01::Coordinate, nip10::Marker, nip19::Nip19};
5use nostr_sdk::{ 5use nostr_sdk::{
6 hashes::sha1::Hash as Sha1Hash, Event, EventBuilder, EventId, FromBech32, Kind, NostrSigner, 6 Event, EventBuilder, EventId, FromBech32, Kind, NostrSigner, PublicKey, RelayUrl, Tag, TagKind,
7 PublicKey, RelayUrl, Tag, TagKind, TagStandard, 7 TagStandard, hashes::sha1::Hash as Sha1Hash,
8}; 8};
9 9
10use crate::{ 10use crate::{
@@ -131,15 +131,14 @@ pub async fn generate_patch_event(
131 // code that makes it into the main branch, assuming 131 // code that makes it into the main branch, assuming
132 // the commit id is correct 132 // the commit id is correct
133 Tag::from_standardized(TagStandard::Reference(commit.to_string())), 133 Tag::from_standardized(TagStandard::Reference(commit.to_string())),
134 Tag::custom( 134 Tag::custom(TagKind::Custom(std::borrow::Cow::Borrowed("alt")), vec![
135 TagKind::Custom(std::borrow::Cow::Borrowed("alt")), 135 format!(
136 vec![format!(
137 "git patch: {}", 136 "git patch: {}",
138 git_repo 137 git_repo
139 .get_commit_message_summary(commit) 138 .get_commit_message_summary(commit)
140 .unwrap_or_default() 139 .unwrap_or_default()
141 )], 140 ),
142 ), 141 ]),
143 ], 142 ],
144 if let Some(thread_event_id) = thread_event_id { 143 if let Some(thread_event_id) = thread_event_id {
145 vec![Tag::from_standardized(nostr_sdk::TagStandard::Event { 144 vec![Tag::from_standardized(nostr_sdk::TagStandard::Event {
@@ -203,10 +202,9 @@ pub async fn generate_patch_event(
203 .collect(), 202 .collect(),
204 vec![ 203 vec![
205 // a fallback is now in place to extract this from the patch 204 // a fallback is now in place to extract this from the patch
206 Tag::custom( 205 Tag::custom(TagKind::Custom(std::borrow::Cow::Borrowed("commit")), vec![
207 TagKind::Custom(std::borrow::Cow::Borrowed("commit")), 206 commit.to_string(),
208 vec![commit.to_string()], 207 ]),
209 ),
210 // this is required as patches cannot be relied upon to include the 'base 208 // this is required as patches cannot be relied upon to include the 'base
211 // commit' 209 // commit'
212 Tag::custom( 210 Tag::custom(
diff --git a/src/lib/login/existing.rs b/src/lib/login/existing.rs
index 4606c22..efe187e 100644
--- a/src/lib/login/existing.rs
+++ b/src/lib/login/existing.rs
@@ -1,15 +1,15 @@
1use std::{str::FromStr, sync::Arc, time::Duration}; 1use std::{str::FromStr, sync::Arc, time::Duration};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{Context, Result, bail};
4use nostr::nips::nip46::NostrConnectURI; 4use nostr::nips::nip46::NostrConnectURI;
5use nostr_connect::client::NostrConnect; 5use nostr_connect::client::NostrConnect;
6use nostr_sdk::{NostrSigner, PublicKey}; 6use nostr_sdk::{NostrSigner, PublicKey};
7 7
8use super::{ 8use super::{
9 SignerInfo, SignerInfoSource,
9 key_encryption::decrypt_key, 10 key_encryption::decrypt_key,
10 print_logged_in_as, 11 print_logged_in_as,
11 user::{get_user_details, UserRef}, 12 user::{UserRef, get_user_details},
12 SignerInfo, SignerInfoSource,
13}; 13};
14#[cfg(not(test))] 14#[cfg(not(test))]
15use crate::client::Client; 15use crate::client::Client;
@@ -18,7 +18,7 @@ use crate::client::MockConnect;
18use crate::{ 18use crate::{
19 cli_interactor::{Interactor, InteractorPrompt, PromptPasswordParms}, 19 cli_interactor::{Interactor, InteractorPrompt, PromptPasswordParms},
20 client::fetch_public_key, 20 client::fetch_public_key,
21 git::{get_git_config_item, Repo, RepoActions}, 21 git::{Repo, RepoActions, get_git_config_item},
22}; 22};
23 23
24/// load signer from git config and UserProfile from cache or relays 24/// load signer from git config and UserProfile from cache or relays
diff --git a/src/lib/login/fresh.rs b/src/lib/login/fresh.rs
index 7cdbde8..635c0b3 100644
--- a/src/lib/login/fresh.rs
+++ b/src/lib/login/fresh.rs
@@ -1,6 +1,6 @@
1use std::{str::FromStr, sync::Arc, time::Duration}; 1use std::{str::FromStr, sync::Arc, time::Duration};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{Context, Result, bail};
4use console::Style; 4use console::Style;
5use dialoguer::theme::{ColorfulTheme, Theme}; 5use dialoguer::theme::{ColorfulTheme, Theme};
6use nostr::nips::{nip05, nip46::NostrConnectURI}; 6use nostr::nips::{nip05, nip46::NostrConnectURI};
@@ -10,11 +10,11 @@ use qrcode::QrCode;
10use tokio::{signal, sync::Mutex}; 10use tokio::{signal, sync::Mutex};
11 11
12use super::{ 12use super::{
13 SignerInfo, SignerInfoSource,
13 existing::load_existing_login, 14 existing::load_existing_login,
14 key_encryption::decrypt_key, 15 key_encryption::decrypt_key,
15 print_logged_in_as, 16 print_logged_in_as,
16 user::{get_user_details, UserRef}, 17 user::{UserRef, get_user_details},
17 SignerInfo, SignerInfoSource,
18}; 18};
19#[cfg(not(test))] 19#[cfg(not(test))]
20use crate::client::Client; 20use crate::client::Client;
@@ -25,8 +25,8 @@ use crate::{
25 Interactor, InteractorPrompt, Printer, PromptChoiceParms, PromptConfirmParms, 25 Interactor, InteractorPrompt, Printer, PromptChoiceParms, PromptConfirmParms,
26 PromptInputParms, PromptPasswordParms, 26 PromptInputParms, PromptPasswordParms,
27 }, 27 },
28 client::{send_events, Connect}, 28 client::{Connect, send_events},
29 git::{remove_git_config_item, save_git_config_item, Repo, RepoActions}, 29 git::{Repo, RepoActions, remove_git_config_item, save_git_config_item},
30}; 30};
31 31
32pub async fn fresh_login_or_signup( 32pub async fn fresh_login_or_signup(
diff --git a/src/lib/login/mod.rs b/src/lib/login/mod.rs
index 0be1e5d..a1c45d5 100644
--- a/src/lib/login/mod.rs
+++ b/src/lib/login/mod.rs
@@ -79,15 +79,11 @@ fn print_logged_in_as(
79 "failed to find your relay list. consider using another nostr client to create one to enhance your nostr experience." 79 "failed to find your relay list. consider using another nostr client to create one to enhance your nostr experience."
80 ); 80 );
81 } 81 }
82 eprintln!( 82 eprintln!("logged in as {}{}", user_ref.metadata.name, match source {
83 "logged in as {}{}", 83 SignerInfoSource::CommandLineArguments => " via cli arguments",
84 user_ref.metadata.name, 84 SignerInfoSource::GitLocal => " to local repository",
85 match source { 85 SignerInfoSource::GitGlobal => "",
86 SignerInfoSource::CommandLineArguments => " via cli arguments", 86 });
87 SignerInfoSource::GitLocal => " to local repository",
88 SignerInfoSource::GitGlobal => "",
89 }
90 );
91 Ok(()) 87 Ok(())
92} 88}
93 89
diff --git a/src/lib/login/user.rs b/src/lib/login/user.rs
index de4a2d9..107e765 100644
--- a/src/lib/login/user.rs
+++ b/src/lib/login/user.rs
@@ -1,6 +1,6 @@
1use std::{collections::HashSet, path::Path}; 1use std::{collections::HashSet, path::Path};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{Context, Result, bail};
4use nostr::PublicKey; 4use nostr::PublicKey;
5use nostr_sdk::{Alphabet, JsonUtil, Kind, SingleLetterTag, Timestamp, ToBech32}; 5use nostr_sdk::{Alphabet, JsonUtil, Kind, SingleLetterTag, Timestamp, ToBech32};
6use serde::{self, Deserialize, Serialize}; 6use serde::{self, Deserialize, Serialize};
@@ -9,7 +9,7 @@ use serde::{self, Deserialize, Serialize};
9use crate::client::Client; 9use crate::client::Client;
10#[cfg(test)] 10#[cfg(test)]
11use crate::client::MockConnect; 11use crate::client::MockConnect;
12use crate::client::{get_event_from_global_cache, Connect}; 12use crate::client::{Connect, get_event_from_global_cache};
13 13
14#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] 14#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
15pub struct UserRef { 15pub struct UserRef {
diff --git a/src/lib/mod.rs b/src/lib/mod.rs
index 6e6f6fe..2072a80 100644
--- a/src/lib/mod.rs
+++ b/src/lib/mod.rs
@@ -6,7 +6,7 @@ pub mod login;
6pub mod repo_ref; 6pub mod repo_ref;
7pub mod repo_state; 7pub mod repo_state;
8 8
9use anyhow::{anyhow, Result}; 9use anyhow::{Result, anyhow};
10use directories::ProjectDirs; 10use directories::ProjectDirs;
11 11
12pub fn get_dirs() -> Result<ProjectDirs> { 12pub fn get_dirs() -> Result<ProjectDirs> {
diff --git a/src/lib/repo_ref.rs b/src/lib/repo_ref.rs
index 5d6f4eb..a9d1186 100644
--- a/src/lib/repo_ref.rs
+++ b/src/lib/repo_ref.rs
@@ -6,9 +6,9 @@ use std::{
6 sync::Arc, 6 sync::Arc,
7}; 7};
8 8
9use anyhow::{bail, Context, Result}; 9use anyhow::{Context, Result, bail};
10use console::Style; 10use console::Style;
11use nostr::{nips::nip01::Coordinate, FromBech32, PublicKey, Tag, TagStandard, ToBech32}; 11use nostr::{FromBech32, PublicKey, Tag, TagStandard, ToBech32, nips::nip01::Coordinate};
12use nostr_sdk::{Kind, NostrSigner, RelayUrl, Timestamp}; 12use nostr_sdk::{Kind, NostrSigner, RelayUrl, Timestamp};
13use serde::{Deserialize, Serialize}; 13use serde::{Deserialize, Serialize};
14 14
@@ -18,10 +18,10 @@ use crate::{
18 cli_interactor::{ 18 cli_interactor::{
19 Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms, PromptInputParms, 19 Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms, PromptInputParms,
20 }, 20 },
21 client::{consolidate_fetch_reports, get_repo_ref_from_cache, sign_event, Connect}, 21 client::{Connect, consolidate_fetch_reports, get_repo_ref_from_cache, sign_event},
22 git::{ 22 git::{
23 nostr_url::{use_nip05_git_config_cache_to_find_nip05_from_public_key, NostrUrlDecoded},
24 Repo, RepoActions, 23 Repo, RepoActions,
24 nostr_url::{NostrUrlDecoded, use_nip05_git_config_cache_to_find_nip05_from_public_key},
25 }, 25 },
26 login::user::get_user_details, 26 login::user::get_user_details,
27}; 27};
@@ -237,20 +237,17 @@ impl RepoRef {
237 237
238 pub fn to_nostr_git_url(&self, git_repo: &Option<&Repo>) -> String { 238 pub fn to_nostr_git_url(&self, git_repo: &Option<&Repo>) -> String {
239 let c = self.coordinate_with_hint(); 239 let c = self.coordinate_with_hint();
240 format!( 240 format!("{}", NostrUrlDecoded {
241 "{}", 241 original_string: String::new(),
242 NostrUrlDecoded { 242 nip05: use_nip05_git_config_cache_to_find_nip05_from_public_key(
243 original_string: String::new(), 243 &c.public_key,
244 nip05: use_nip05_git_config_cache_to_find_nip05_from_public_key( 244 git_repo,
245 &c.public_key, 245 )
246 git_repo, 246 .unwrap_or_default(),
247 ) 247 coordinate: c,
248 .unwrap_or_default(), 248 protocol: None,
249 coordinate: c, 249 user: None,
250 protocol: None, 250 })
251 user: None,
252 }
253 )
254 } 251 }
255} 252}
256 253
@@ -521,14 +518,11 @@ pub fn save_repo_config_to_yaml(
521 .context("failed to convert public key into npub")?, 518 .context("failed to convert public key into npub")?,
522 ); 519 );
523 } 520 }
524 serde_yaml::to_writer( 521 serde_yaml::to_writer(file, &RepoConfigYaml {
525 file, 522 identifier: Some(identifier),
526 &RepoConfigYaml { 523 maintainers: maintainers_npubs,
527 identifier: Some(identifier), 524 relays,
528 maintainers: maintainers_npubs, 525 })
529 relays,
530 },
531 )
532 .context("failed to write maintainers to maintainers.yaml file serde_yaml") 526 .context("failed to write maintainers to maintainers.yaml file serde_yaml")
533} 527}
534 528
diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs
index 5079c26..5c8d7a5 100644
--- a/test_utils/src/lib.rs
+++ b/test_utils/src/lib.rs
@@ -6,15 +6,15 @@ use std::{
6 time::Duration, 6 time::Duration,
7}; 7};
8 8
9use anyhow::{bail, ensure, Context, Result}; 9use anyhow::{Context, Result, bail, ensure};
10use dialoguer::theme::{ColorfulTheme, Theme}; 10use dialoguer::theme::{ColorfulTheme, Theme};
11use futures::executor::block_on; 11use futures::executor::block_on;
12use git::GitTestRepo; 12use git::GitTestRepo;
13use git2::{Signature, Time}; 13use git2::{Signature, Time};
14use nostr::{self, nips::nip65::RelayMetadata, Kind, Tag}; 14use nostr::{self, Kind, Tag, nips::nip65::RelayMetadata};
15use nostr_database::NostrEventsDatabase; 15use nostr_database::NostrEventsDatabase;
16use nostr_lmdb::NostrLMDB; 16use nostr_lmdb::NostrLMDB;
17use nostr_sdk::{serde_json, Client, NostrSigner, TagStandard}; 17use nostr_sdk::{Client, NostrSigner, TagStandard, serde_json};
18use once_cell::sync::Lazy; 18use once_cell::sync::Lazy;
19use rexpect::session::{Options, PtySession}; 19use rexpect::session::{Options, PtySession};
20use strip_ansi_escapes::strip_str; 20use strip_ansi_escapes::strip_str;
@@ -530,14 +530,10 @@ impl CliTesterConfirmPrompt<'_> {
530 let mut s = String::new(); 530 let mut s = String::new();
531 self.tester 531 self.tester
532 .formatter 532 .formatter
533 .format_confirm_prompt_selection( 533 .format_confirm_prompt_selection(&mut s, self.prompt.as_str(), match input {
534 &mut s, 534 None => self.default,
535 self.prompt.as_str(), 535 Some(_) => input,
536 match input { 536 })
537 None => self.default,
538 Some(_) => input,
539 },
540 )
541 .expect("diagluer theme formatter should succeed"); 537 .expect("diagluer theme formatter should succeed");
542 if !s.contains(self.prompt.as_str()) { 538 if !s.contains(self.prompt.as_str()) {
543 panic!("dialoguer must be broken as formatted prompt success doesnt contain prompt"); 539 panic!("dialoguer must be broken as formatted prompt success doesnt contain prompt");
@@ -1007,13 +1003,10 @@ where
1007 cmd.env("RUST_BACKTRACE", "0"); 1003 cmd.env("RUST_BACKTRACE", "0");
1008 cmd.args(args); 1004 cmd.args(args);
1009 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes 1005 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes
1010 rexpect::session::spawn_with_options( 1006 rexpect::session::spawn_with_options(cmd, Options {
1011 cmd, 1007 timeout_ms: Some(timeout_ms),
1012 Options { 1008 strip_ansi_escape_codes: true,
1013 timeout_ms: Some(timeout_ms), 1009 })
1014 strip_ansi_escape_codes: true,
1015 },
1016 )
1017} 1010}
1018 1011
1019pub fn rexpect_with_from_dir<I, S>( 1012pub fn rexpect_with_from_dir<I, S>(
@@ -1031,13 +1024,10 @@ where
1031 cmd.current_dir(dir); 1024 cmd.current_dir(dir);
1032 cmd.args(args); 1025 cmd.args(args);
1033 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes 1026 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes
1034 rexpect::session::spawn_with_options( 1027 rexpect::session::spawn_with_options(cmd, Options {
1035 cmd, 1028 timeout_ms: Some(timeout_ms),
1036 Options { 1029 strip_ansi_escape_codes: true,
1037 timeout_ms: Some(timeout_ms), 1030 })
1038 strip_ansi_escape_codes: true,
1039 },
1040 )
1041} 1031}
1042 1032
1043pub fn remote_helper_rexpect_with_from_dir( 1033pub fn remote_helper_rexpect_with_from_dir(
@@ -1052,13 +1042,10 @@ pub fn remote_helper_rexpect_with_from_dir(
1052 cmd.current_dir(dir); 1042 cmd.current_dir(dir);
1053 cmd.args([dir.as_os_str().to_str().unwrap(), nostr_remote_url]); 1043 cmd.args([dir.as_os_str().to_str().unwrap(), nostr_remote_url]);
1054 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes 1044 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes
1055 rexpect::session::spawn_with_options( 1045 rexpect::session::spawn_with_options(cmd, Options {
1056 cmd, 1046 timeout_ms: Some(timeout_ms),
1057 Options { 1047 strip_ansi_escape_codes: true,
1058 timeout_ms: Some(timeout_ms), 1048 })
1059 strip_ansi_escape_codes: true,
1060 },
1061 )
1062} 1049}
1063 1050
1064pub fn git_with_remote_helper_rexpect_with_from_dir<I, S>( 1051pub fn git_with_remote_helper_rexpect_with_from_dir<I, S>(
@@ -1102,13 +1089,10 @@ where
1102 cmd.current_dir(dir); 1089 cmd.current_dir(dir);
1103 cmd.args(args); 1090 cmd.args(args);
1104 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes 1091 // using branch for PR https://github.com/rust-cli/rexpect/pull/103 to strip ansi escape codes
1105 rexpect::session::spawn_with_options( 1092 rexpect::session::spawn_with_options(cmd, Options {
1106 cmd, 1093 timeout_ms: Some(timeout_ms),
1107 Options { 1094 strip_ansi_escape_codes: true,
1108 timeout_ms: Some(timeout_ms), 1095 })
1109 strip_ansi_escape_codes: true,
1110 },
1111 )
1112 .context("spawning failed") 1096 .context("spawning failed")
1113} 1097}
1114 1098
@@ -1137,14 +1121,11 @@ pub fn get_proposal_branch_name(
1137 test_repo: &GitTestRepo, 1121 test_repo: &GitTestRepo,
1138 branch_name_in_event: &str, 1122 branch_name_in_event: &str,
1139) -> Result<String> { 1123) -> Result<String> {
1140 let events = block_on(get_events_from_cache( 1124 let events = block_on(get_events_from_cache(&test_repo.dir, vec![
1141 &test_repo.dir, 1125 nostr::Filter::default()
1142 vec![ 1126 .kind(nostr_sdk::Kind::GitPatch)
1143 nostr::Filter::default() 1127 .hashtag("root"),
1144 .kind(nostr_sdk::Kind::GitPatch) 1128 ]))?;
1145 .hashtag("root"),
1146 ],
1147 ))?;
1148 get_proposal_branch_name_from_events(&events, branch_name_in_event) 1129 get_proposal_branch_name_from_events(&events, branch_name_in_event)
1149} 1130}
1150 1131
@@ -1296,54 +1277,45 @@ pub fn cli_tester_create_proposal(
1296 create_and_populate_branch(test_repo, branch_name, prefix, false, None)?; 1277 create_and_populate_branch(test_repo, branch_name, prefix, false, None)?;
1297 std::thread::sleep(std::time::Duration::from_millis(1000)); 1278 std::thread::sleep(std::time::Duration::from_millis(1000));
1298 if let Some(in_reply_to) = in_reply_to { 1279 if let Some(in_reply_to) = in_reply_to {
1299 let mut p = CliTester::new_from_dir( 1280 let mut p = CliTester::new_from_dir(&test_repo.dir, [
1300 &test_repo.dir, 1281 "--nsec",
1301 [ 1282 TEST_KEY_1_NSEC,
1302 "--nsec", 1283 "--password",
1303 TEST_KEY_1_NSEC, 1284 TEST_PASSWORD,
1304 "--password", 1285 "--disable-cli-spinners",
1305 TEST_PASSWORD, 1286 "send",
1306 "--disable-cli-spinners", 1287 "HEAD~2",
1307 "send", 1288 "--no-cover-letter",
1308 "HEAD~2", 1289 "--in-reply-to",
1309 "--no-cover-letter", 1290 in_reply_to.as_str(),
1310 "--in-reply-to", 1291 ]);
1311 in_reply_to.as_str(),
1312 ],
1313 );
1314 p.expect_end_eventually()?; 1292 p.expect_end_eventually()?;
1315 } else if let Some((title, description)) = cover_letter_title_and_description { 1293 } else if let Some((title, description)) = cover_letter_title_and_description {
1316 let mut p = CliTester::new_from_dir( 1294 let mut p = CliTester::new_from_dir(&test_repo.dir, [
1317 &test_repo.dir, 1295 "--nsec",
1318 [ 1296 TEST_KEY_1_NSEC,
1319 "--nsec", 1297 "--password",
1320 TEST_KEY_1_NSEC, 1298 TEST_PASSWORD,
1321 "--password", 1299 "--disable-cli-spinners",
1322 TEST_PASSWORD, 1300 "send",
1323 "--disable-cli-spinners", 1301 "HEAD~2",
1324 "send", 1302 "--title",
1325 "HEAD~2", 1303 format!("\"{title}\"").as_str(),
1326 "--title", 1304 "--description",
1327 format!("\"{title}\"").as_str(), 1305 format!("\"{description}\"").as_str(),
1328 "--description", 1306 ]);
1329 format!("\"{description}\"").as_str(),
1330 ],
1331 );
1332 p.expect_end_eventually()?; 1307 p.expect_end_eventually()?;
1333 } else { 1308 } else {
1334 let mut p = CliTester::new_from_dir( 1309 let mut p = CliTester::new_from_dir(&test_repo.dir, [
1335 &test_repo.dir, 1310 "--nsec",
1336 [ 1311 TEST_KEY_1_NSEC,
1337 "--nsec", 1312 "--password",
1338 TEST_KEY_1_NSEC, 1313 TEST_PASSWORD,
1339 "--password", 1314 "--disable-cli-spinners",
1340 TEST_PASSWORD, 1315 "send",
1341 "--disable-cli-spinners", 1316 "HEAD~2",
1342 "send", 1317 "--no-cover-letter",
1343 "HEAD~2", 1318 ]);
1344 "--no-cover-letter",
1345 ],
1346 );
1347 p.expect_end_eventually()?; 1319 p.expect_end_eventually()?;
1348 } 1320 }
1349 Ok(()) 1321 Ok(())
@@ -1375,14 +1347,11 @@ pub fn use_ngit_list_to_download_and_checkout_proposal_branch(
1375 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 1347 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1376 p.expect("fetching updates...\r\n")?; 1348 p.expect("fetching updates...\r\n")?;
1377 p.expect_eventually("\r\n")?; // some updates listed here 1349 p.expect_eventually("\r\n")?; // some updates listed here
1378 let mut c = p.expect_choice( 1350 let mut c = p.expect_choice("all proposals", vec![
1379 "all proposals", 1351 format!("\"{PROPOSAL_TITLE_3}\""),
1380 vec![ 1352 format!("\"{PROPOSAL_TITLE_2}\""),
1381 format!("\"{PROPOSAL_TITLE_3}\""), 1353 format!("\"{PROPOSAL_TITLE_1}\""),
1382 format!("\"{PROPOSAL_TITLE_2}\""), 1354 ])?;
1383 format!("\"{PROPOSAL_TITLE_1}\""),
1384 ],
1385 )?;
1386 c.succeeds_with( 1355 c.succeeds_with(
1387 if proposal_number == 3 { 1356 if proposal_number == 3 {
1388 0 1357 0
@@ -1394,15 +1363,12 @@ pub fn use_ngit_list_to_download_and_checkout_proposal_branch(
1394 true, 1363 true,
1395 None, 1364 None,
1396 )?; 1365 )?;
1397 let mut c = p.expect_choice( 1366 let mut c = p.expect_choice("", vec![
1398 "", 1367 format!("create and checkout proposal branch (2 ahead 0 behind 'main')"),
1399 vec![ 1368 format!("apply to current branch with `git am`"),
1400 format!("create and checkout proposal branch (2 ahead 0 behind 'main')"), 1369 format!("download to ./patches"),
1401 format!("apply to current branch with `git am`"), 1370 format!("back"),
1402 format!("download to ./patches"), 1371 ])?;
1403 format!("back"),
1404 ],
1405 )?;
1406 c.succeeds_with(0, true, Some(0))?; 1372 c.succeeds_with(0, true, Some(0))?;
1407 p.expect_end_eventually()?; 1373 p.expect_end_eventually()?;
1408 Ok(()) 1374 Ok(())
@@ -1505,18 +1471,15 @@ pub fn create_proposals_with_first_revised_and_repo_with_unrevised_proposal_chec
1505 1471
1506 amend_last_commit(&originating_repo, "add some ammended-commit.md")?; 1472 amend_last_commit(&originating_repo, "add some ammended-commit.md")?;
1507 1473
1508 let mut p = CliTester::new_from_dir( 1474 let mut p = CliTester::new_from_dir(&originating_repo.dir, [
1509 &originating_repo.dir, 1475 "--nsec",
1510 [ 1476 TEST_KEY_1_NSEC,
1511 "--nsec", 1477 "--password",
1512 TEST_KEY_1_NSEC, 1478 TEST_PASSWORD,
1513 "--password", 1479 "--disable-cli-spinners",
1514 TEST_PASSWORD, 1480 "push",
1515 "--disable-cli-spinners", 1481 "--force",
1516 "push", 1482 ]);
1517 "--force",
1518 ],
1519 );
1520 p.expect_end_eventually()?; 1483 p.expect_end_eventually()?;
1521 1484
1522 Ok((originating_repo, test_repo)) 1485 Ok((originating_repo, test_repo))
diff --git a/test_utils/src/relay.rs b/test_utils/src/relay.rs
index d767a5a..634b2d6 100644
--- a/test_utils/src/relay.rs
+++ b/test_utils/src/relay.rs
@@ -1,6 +1,6 @@
1use std::collections::HashMap; 1use std::collections::HashMap;
2 2
3use anyhow::{bail, Result}; 3use anyhow::{Result, bail};
4use nostr::{ClientMessage, JsonUtil, RelayMessage}; 4use nostr::{ClientMessage, JsonUtil, RelayMessage};
5 5
6use crate::CliTester; 6use crate::CliTester;
diff --git a/tests/git_remote_nostr/main.rs b/tests/git_remote_nostr/main.rs
index 5a1d416..686a5df 100644
--- a/tests/git_remote_nostr/main.rs
+++ b/tests/git_remote_nostr/main.rs
@@ -4,7 +4,7 @@ use anyhow::{Context, Result};
4use futures::join; 4use futures::join;
5use git2::Oid; 5use git2::Oid;
6use nostr::nips::nip01::Coordinate; 6use nostr::nips::nip01::Coordinate;
7use nostr_sdk::{secp256k1::rand, Event, JsonUtil, Kind, RelayUrl, ToBech32}; 7use nostr_sdk::{Event, JsonUtil, Kind, RelayUrl, ToBech32, secp256k1::rand};
8use relay::Relay; 8use relay::Relay;
9use serial_test::serial; 9use serial_test::serial;
10use test_utils::{git::GitTestRepo, *}; 10use test_utils::{git::GitTestRepo, *};
diff --git a/tests/git_remote_nostr/push.rs b/tests/git_remote_nostr/push.rs
index 30602c9..4e44642 100644
--- a/tests/git_remote_nostr/push.rs
+++ b/tests/git_remote_nostr/push.rs
@@ -925,10 +925,12 @@ async fn proposal_three_way_merge_commit_pushed_to_main_leads_to_status_event_is
925 std::fs::write(git_repo.dir.join("new.md"), "some content")?; 925 std::fs::write(git_repo.dir.join("new.md"), "some content")?;
926 git_repo.stage_and_commit("new.md")?; 926 git_repo.stage_and_commit("new.md")?;
927 927
928 CliTester::new_git_with_remote_helper_from_dir( 928 CliTester::new_git_with_remote_helper_from_dir(&git_repo.dir, [
929 &git_repo.dir, 929 "merge",
930 ["merge", &branch_name, "-m", "proposal merge commit message"], 930 &branch_name,
931 ) 931 "-m",
932 "proposal merge commit message",
933 ])
932 .expect_end_eventually_and_print()?; 934 .expect_end_eventually_and_print()?;
933 935
934 let oid = git_repo.get_tip_of_local_branch("main")?; 936 let oid = git_repo.get_tip_of_local_branch("main")?;
@@ -1079,10 +1081,12 @@ async fn proposal_fast_forward_merge_commits_pushed_to_main_leads_to_status_even
1079 git_repo.checkout_remote_branch(&branch_name)?; 1081 git_repo.checkout_remote_branch(&branch_name)?;
1080 git_repo.checkout("refs/heads/main")?; 1082 git_repo.checkout("refs/heads/main")?;
1081 1083
1082 CliTester::new_git_with_remote_helper_from_dir( 1084 CliTester::new_git_with_remote_helper_from_dir(&git_repo.dir, [
1083 &git_repo.dir, 1085 "merge",
1084 ["merge", &branch_name, "-m", "proposal merge commit message"], 1086 &branch_name,
1085 ) 1087 "-m",
1088 "proposal merge commit message",
1089 ])
1086 .expect_end_eventually_and_print()?; 1090 .expect_end_eventually_and_print()?;
1087 1091
1088 let oid = git_repo.get_tip_of_local_branch("main")?; 1092 let oid = git_repo.get_tip_of_local_branch("main")?;
@@ -1736,10 +1740,12 @@ async fn push_new_pr_branch_creates_proposal() -> Result<()> {
1736 std::fs::write(git_repo.dir.join("new2.md"), "some content")?; 1740 std::fs::write(git_repo.dir.join("new2.md"), "some content")?;
1737 git_repo.stage_and_commit("new2.md")?; 1741 git_repo.stage_and_commit("new2.md")?;
1738 1742
1739 let mut p = CliTester::new_git_with_remote_helper_from_dir( 1743 let mut p = CliTester::new_git_with_remote_helper_from_dir(&git_repo.dir, [
1740 &git_repo.dir, 1744 "push",
1741 ["push", "-u", "origin", branch_name], 1745 "-u",
1742 ); 1746 "origin",
1747 branch_name,
1748 ]);
1743 cli_expect_nostr_fetch(&mut p)?; 1749 cli_expect_nostr_fetch(&mut p)?;
1744 p.expect(format!("fetching {} ref list over filesystem...\r\n", source_path).as_str())?; 1750 p.expect(format!("fetching {} ref list over filesystem...\r\n", source_path).as_str())?;
1745 p.expect("list: connecting...\r\n\r\r\r")?; 1751 p.expect("list: connecting...\r\n\r\r\r")?;
diff --git a/tests/ngit_init.rs b/tests/ngit_init.rs
index da4091f..4b61559 100644
--- a/tests/ngit_init.rs
+++ b/tests/ngit_init.rs
@@ -84,14 +84,10 @@ mod when_repo_not_previously_claimed {
84 8051, 84 8051,
85 None, 85 None,
86 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 86 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
87 relay.respond_events( 87 relay.respond_events(client_id, &subscription_id, &vec![
88 client_id, 88 generate_test_key_1_metadata_event("fred"),
89 &subscription_id, 89 generate_test_key_1_relay_list_event(),
90 &vec![ 90 ])?;
91 generate_test_key_1_metadata_event("fred"),
92 generate_test_key_1_relay_list_event(),
93 ],
94 )?;
95 Ok(()) 91 Ok(())
96 }), 92 }),
97 ), 93 ),
@@ -211,14 +207,10 @@ mod when_repo_not_previously_claimed {
211 8051, 207 8051,
212 None, 208 None,
213 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 209 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
214 relay.respond_events( 210 relay.respond_events(client_id, &subscription_id, &vec![
215 client_id, 211 generate_test_key_1_metadata_event("fred"),
216 &subscription_id, 212 generate_test_key_1_relay_list_event(),
217 &vec![ 213 ])?;
218 generate_test_key_1_metadata_event("fred"),
219 generate_test_key_1_relay_list_event(),
220 ],
221 )?;
222 Ok(()) 214 Ok(())
223 }), 215 }),
224 ), 216 ),
@@ -471,14 +463,10 @@ mod when_repo_not_previously_claimed {
471 8051, 463 8051,
472 None, 464 None,
473 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 465 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
474 relay.respond_events( 466 relay.respond_events(client_id, &subscription_id, &vec![
475 client_id, 467 generate_test_key_1_metadata_event("fred"),
476 &subscription_id, 468 generate_test_key_1_relay_list_event(),
477 &vec![ 469 ])?;
478 generate_test_key_1_metadata_event("fred"),
479 generate_test_key_1_relay_list_event(),
480 ],
481 )?;
482 Ok(()) 470 Ok(())
483 }), 471 }),
484 ), 472 ),
diff --git a/tests/ngit_list.rs b/tests/ngit_list.rs
index 1d297b6..4a3aad5 100644
--- a/tests/ngit_list.rs
+++ b/tests/ngit_list.rs
@@ -49,7 +49,7 @@ async fn prep_proposals_repo_and_repo_with_proposal_pulled_and_checkedout(
49mod cannot_find_repo_event { 49mod cannot_find_repo_event {
50 use super::*; 50 use super::*;
51 mod cli_prompts { 51 mod cli_prompts {
52 use nostr::{nips::nip01::Coordinate, ToBech32}; 52 use nostr::{ToBech32, nips::nip01::Coordinate};
53 use nostr_sdk::RelayUrl; 53 use nostr_sdk::RelayUrl;
54 54
55 use super::*; 55 use super::*;
@@ -196,25 +196,20 @@ mod when_main_branch_is_uptodate {
196 196
197 p.expect("fetching updates...\r\n")?; 197 p.expect("fetching updates...\r\n")?;
198 p.expect_eventually("\r\n")?; // some updates listed here 198 p.expect_eventually("\r\n")?; // some updates listed here
199 let mut c = p.expect_choice( 199 let mut c = p.expect_choice("all proposals", vec![
200 "all proposals", 200 format!("\"{PROPOSAL_TITLE_3}\""),
201 vec![ 201 format!("\"{PROPOSAL_TITLE_2}\""),
202 format!("\"{PROPOSAL_TITLE_3}\""), 202 format!("\"{PROPOSAL_TITLE_1}\""),
203 format!("\"{PROPOSAL_TITLE_2}\""), 203 ])?;
204 format!("\"{PROPOSAL_TITLE_1}\""),
205 ],
206 )?;
207 c.succeeds_with(2, true, None)?; 204 c.succeeds_with(2, true, None)?;
208 let mut c = p.expect_choice( 205 let mut c = p.expect_choice("", vec![
209 "", 206 format!(
210 vec![ 207 "create and checkout proposal branch (2 ahead 0 behind 'main')"
211 format!( 208 ),
212 "create and checkout proposal branch (2 ahead 0 behind 'main')" ), 209 format!("apply to current branch with `git am`"),
213 format!("apply to current branch with `git am`"), 210 format!("download to ./patches"),
214 format!("download to ./patches"), 211 format!("back"),
215 format!("back"), 212 ])?;
216 ],
217 )?;
218 c.succeeds_with(0, true, None)?; 213 c.succeeds_with(0, true, None)?;
219 p.expect(format!( 214 p.expect(format!(
220 "checked out proposal as 'pr/{}(", 215 "checked out proposal as 'pr/{}(",
@@ -318,25 +313,20 @@ mod when_main_branch_is_uptodate {
318 313
319 p.expect("fetching updates...\r\n")?; 314 p.expect("fetching updates...\r\n")?;
320 p.expect_eventually("\r\n")?; // some updates listed here 315 p.expect_eventually("\r\n")?; // some updates listed here
321 let mut c = p.expect_choice( 316 let mut c = p.expect_choice("all proposals", vec![
322 "all proposals", 317 format!("\"{PROPOSAL_TITLE_3}\""),
323 vec![ 318 format!("\"{PROPOSAL_TITLE_2}\""),
324 format!("\"{PROPOSAL_TITLE_3}\""), 319 format!("\"{PROPOSAL_TITLE_1}\""),
325 format!("\"{PROPOSAL_TITLE_2}\""), 320 ])?;
326 format!("\"{PROPOSAL_TITLE_1}\""),
327 ],
328 )?;
329 c.succeeds_with(0, true, None)?; 321 c.succeeds_with(0, true, None)?;
330 let mut c = p.expect_choice( 322 let mut c = p.expect_choice("", vec![
331 "", 323 format!(
332 vec![ 324 "create and checkout proposal branch (2 ahead 0 behind 'main')"
333 format!( 325 ),
334 "create and checkout proposal branch (2 ahead 0 behind 'main')" ), 326 format!("apply to current branch with `git am`"),
335 format!("apply to current branch with `git am`"), 327 format!("download to ./patches"),
336 format!("download to ./patches"), 328 format!("back"),
337 format!("back"), 329 ])?;
338 ],
339 )?;
340 c.succeeds_with(0, true, Some(0))?; 330 c.succeeds_with(0, true, Some(0))?;
341 p.expect(format!( 331 p.expect(format!(
342 "checked out proposal as 'pr/{}(", 332 "checked out proposal as 'pr/{}(",
@@ -427,8 +417,8 @@ mod when_main_branch_is_uptodate {
427 r55.events.push(generate_test_key_1_metadata_event("fred")); 417 r55.events.push(generate_test_key_1_metadata_event("fred"));
428 r55.events.push(generate_test_key_1_relay_list_event()); 418 r55.events.push(generate_test_key_1_relay_list_event());
429 419
430 let cli_tester_handle = std::thread::spawn( 420 let cli_tester_handle =
431 move || -> Result<(GitTestRepo, GitTestRepo)> { 421 std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> {
432 let originating_repo = cli_tester_create_proposals()?; 422 let originating_repo = cli_tester_create_proposals()?;
433 cli_tester_create_proposal( 423 cli_tester_create_proposal(
434 &originating_repo, 424 &originating_repo,
@@ -443,26 +433,21 @@ mod when_main_branch_is_uptodate {
443 433
444 p.expect("fetching updates...\r\n")?; 434 p.expect("fetching updates...\r\n")?;
445 p.expect_eventually("\r\n")?; // some updates listed here 435 p.expect_eventually("\r\n")?; // some updates listed here
446 let mut c = p.expect_choice( 436 let mut c = p.expect_choice("all proposals", vec![
447 "all proposals", 437 format!("add d3.md"), // commit msg title
448 vec![ 438 format!("\"{PROPOSAL_TITLE_3}\""),
449 format!("add d3.md"), // commit msg title 439 format!("\"{PROPOSAL_TITLE_2}\""),
450 format!("\"{PROPOSAL_TITLE_3}\""), 440 format!("\"{PROPOSAL_TITLE_1}\""),
451 format!("\"{PROPOSAL_TITLE_2}\""), 441 ])?;
452 format!("\"{PROPOSAL_TITLE_1}\""),
453 ],
454 )?;
455 c.succeeds_with(0, true, None)?; 442 c.succeeds_with(0, true, None)?;
456 let mut c = p.expect_choice( 443 let mut c = p.expect_choice("", vec![
457 "", 444 format!(
458 vec![ 445 "create and checkout proposal branch (2 ahead 0 behind 'main')"
459 format!( 446 ),
460 "create and checkout proposal branch (2 ahead 0 behind 'main')" ), 447 format!("apply to current branch with `git am`"),
461 format!("apply to current branch with `git am`"), 448 format!("download to ./patches"),
462 format!("download to ./patches"), 449 format!("back"),
463 format!("back"), 450 ])?;
464 ],
465 )?;
466 c.succeeds_with(0, true, Some(0))?; 451 c.succeeds_with(0, true, Some(0))?;
467 p.expect_end_eventually_and_print()?; 452 p.expect_end_eventually_and_print()?;
468 453
@@ -470,8 +455,7 @@ mod when_main_branch_is_uptodate {
470 relay::shutdown_relay(8000 + p)?; 455 relay::shutdown_relay(8000 + p)?;
471 } 456 }
472 Ok((originating_repo, test_repo)) 457 Ok((originating_repo, test_repo))
473 }, 458 });
474 );
475 459
476 // launch relay 460 // launch relay
477 let _ = join!( 461 let _ = join!(
@@ -524,26 +508,21 @@ mod when_main_branch_is_uptodate {
524 508
525 p.expect("fetching updates...\r\n")?; 509 p.expect("fetching updates...\r\n")?;
526 p.expect_eventually("\r\n")?; // some updates listed here 510 p.expect_eventually("\r\n")?; // some updates listed here
527 let mut c = p.expect_choice( 511 let mut c = p.expect_choice("all proposals", vec![
528 "all proposals", 512 format!("add d3.md"), // commit msg title
529 vec![ 513 format!("\"{PROPOSAL_TITLE_3}\""),
530 format!("add d3.md"), // commit msg title 514 format!("\"{PROPOSAL_TITLE_2}\""),
531 format!("\"{PROPOSAL_TITLE_3}\""), 515 format!("\"{PROPOSAL_TITLE_1}\""),
532 format!("\"{PROPOSAL_TITLE_2}\""), 516 ])?;
533 format!("\"{PROPOSAL_TITLE_1}\""),
534 ],
535 )?;
536 c.succeeds_with(0, true, None)?; 517 c.succeeds_with(0, true, None)?;
537 let mut c = p.expect_choice( 518 let mut c = p.expect_choice("", vec![
538 "", 519 format!(
539 vec![ 520 "create and checkout proposal branch (2 ahead 0 behind 'main')"
540 format!( 521 ),
541 "create and checkout proposal branch (2 ahead 0 behind 'main')" ), 522 format!("apply to current branch with `git am`"),
542 format!("apply to current branch with `git am`"), 523 format!("download to ./patches"),
543 format!("download to ./patches"), 524 format!("back"),
544 format!("back"), 525 ])?;
545 ],
546 )?;
547 c.succeeds_with(0, true, Some(0))?; 526 c.succeeds_with(0, true, Some(0))?;
548 p.expect(format!( 527 p.expect(format!(
549 "checked out proposal as 'pr/{}(", 528 "checked out proposal as 'pr/{}(",
@@ -639,8 +618,8 @@ mod when_main_branch_is_uptodate {
639 r55.events.push(generate_test_key_1_metadata_event("fred")); 618 r55.events.push(generate_test_key_1_metadata_event("fred"));
640 r55.events.push(generate_test_key_1_relay_list_event()); 619 r55.events.push(generate_test_key_1_relay_list_event());
641 620
642 let cli_tester_handle = std::thread::spawn( 621 let cli_tester_handle =
643 move || -> Result<(GitTestRepo, GitTestRepo)> { 622 std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> {
644 let originating_repo = cli_tester_create_proposals()?; 623 let originating_repo = cli_tester_create_proposals()?;
645 624
646 let test_repo = GitTestRepo::default(); 625 let test_repo = GitTestRepo::default();
@@ -649,24 +628,20 @@ mod when_main_branch_is_uptodate {
649 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 628 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
650 p.expect("fetching updates...\r\n")?; 629 p.expect("fetching updates...\r\n")?;
651 p.expect_eventually("\r\n")?; // some updates listed here 630 p.expect_eventually("\r\n")?; // some updates listed here
652 let mut c = p.expect_choice( 631 let mut c = p.expect_choice("all proposals", vec![
653 "all proposals", 632 format!("\"{PROPOSAL_TITLE_3}\""),
654 vec![ 633 format!("\"{PROPOSAL_TITLE_2}\""),
655 format!("\"{PROPOSAL_TITLE_3}\""), 634 format!("\"{PROPOSAL_TITLE_1}\""),
656 format!("\"{PROPOSAL_TITLE_2}\""), 635 ])?;
657 format!("\"{PROPOSAL_TITLE_1}\""),
658 ],
659 )?;
660 c.succeeds_with(2, true, None)?; 636 c.succeeds_with(2, true, None)?;
661 let mut c = p.expect_choice( 637 let mut c = p.expect_choice("", vec![
662 "", 638 format!(
663 vec![ 639 "create and checkout proposal branch (2 ahead 0 behind 'main')"
664 format!("create and checkout proposal branch (2 ahead 0 behind 'main')"), 640 ),
665 format!("apply to current branch with `git am`"), 641 format!("apply to current branch with `git am`"),
666 format!("download to ./patches"), 642 format!("download to ./patches"),
667 format!("back"), 643 format!("back"),
668 ], 644 ])?;
669 )?;
670 c.succeeds_with(0, true, Some(0))?; 645 c.succeeds_with(0, true, Some(0))?;
671 p.expect_end_eventually()?; 646 p.expect_end_eventually()?;
672 647
@@ -675,24 +650,18 @@ mod when_main_branch_is_uptodate {
675 p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 650 p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
676 p.expect("fetching updates...\r\n")?; 651 p.expect("fetching updates...\r\n")?;
677 p.expect_eventually("\r\n")?; // some updates listed here 652 p.expect_eventually("\r\n")?; // some updates listed here
678 let mut c = p.expect_choice( 653 let mut c = p.expect_choice("all proposals", vec![
679 "all proposals", 654 format!("\"{PROPOSAL_TITLE_3}\""),
680 vec![ 655 format!("\"{PROPOSAL_TITLE_2}\""),
681 format!("\"{PROPOSAL_TITLE_3}\""), 656 format!("\"{PROPOSAL_TITLE_1}\""),
682 format!("\"{PROPOSAL_TITLE_2}\""), 657 ])?;
683 format!("\"{PROPOSAL_TITLE_1}\""),
684 ],
685 )?;
686 c.succeeds_with(2, true, None)?; 658 c.succeeds_with(2, true, None)?;
687 let mut c = p.expect_choice( 659 let mut c = p.expect_choice("", vec![
688 "", 660 format!("checkout proposal branch (2 ahead 0 behind 'main')"),
689 vec![ 661 format!("apply to current branch with `git am`"),
690 format!("checkout proposal branch (2 ahead 0 behind 'main')"), 662 format!("download to ./patches"),
691 format!("apply to current branch with `git am`"), 663 format!("back"),
692 format!("download to ./patches"), 664 ])?;
693 format!("back"),
694 ],
695 )?;
696 c.succeeds_with(0, true, Some(0))?; 665 c.succeeds_with(0, true, Some(0))?;
697 p.expect_end_eventually_and_print()?; 666 p.expect_end_eventually_and_print()?;
698 667
@@ -700,8 +669,7 @@ mod when_main_branch_is_uptodate {
700 relay::shutdown_relay(8000 + p)?; 669 relay::shutdown_relay(8000 + p)?;
701 } 670 }
702 Ok((originating_repo, test_repo)) 671 Ok((originating_repo, test_repo))
703 }, 672 });
704 );
705 673
706 // launch relay 674 // launch relay
707 let _ = join!( 675 let _ = join!(
@@ -747,24 +715,20 @@ mod when_main_branch_is_uptodate {
747 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 715 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
748 p.expect("fetching updates...\r\n")?; 716 p.expect("fetching updates...\r\n")?;
749 p.expect_eventually("\r\n")?; // some updates listed here 717 p.expect_eventually("\r\n")?; // some updates listed here
750 let mut c = p.expect_choice( 718 let mut c = p.expect_choice("all proposals", vec![
751 "all proposals", 719 format!("\"{PROPOSAL_TITLE_3}\""),
752 vec![ 720 format!("\"{PROPOSAL_TITLE_2}\""),
753 format!("\"{PROPOSAL_TITLE_3}\""), 721 format!("\"{PROPOSAL_TITLE_1}\""),
754 format!("\"{PROPOSAL_TITLE_2}\""), 722 ])?;
755 format!("\"{PROPOSAL_TITLE_1}\""),
756 ],
757 )?;
758 c.succeeds_with(2, true, None)?; 723 c.succeeds_with(2, true, None)?;
759 let mut c = p.expect_choice( 724 let mut c = p.expect_choice("", vec![
760 "", 725 format!(
761 vec![ 726 "create and checkout proposal branch (2 ahead 0 behind 'main')"
762 format!("create and checkout proposal branch (2 ahead 0 behind 'main')"), 727 ),
763 format!("apply to current branch with `git am`"), 728 format!("apply to current branch with `git am`"),
764 format!("download to ./patches"), 729 format!("download to ./patches"),
765 format!("back"), 730 format!("back"),
766 ], 731 ])?;
767 )?;
768 c.succeeds_with(0, true, Some(0))?; 732 c.succeeds_with(0, true, Some(0))?;
769 p.expect_end_eventually()?; 733 p.expect_end_eventually()?;
770 734
@@ -773,24 +737,18 @@ mod when_main_branch_is_uptodate {
773 p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 737 p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
774 p.expect("fetching updates...\r\n")?; 738 p.expect("fetching updates...\r\n")?;
775 p.expect_eventually("\r\n")?; // some updates listed here 739 p.expect_eventually("\r\n")?; // some updates listed here
776 let mut c = p.expect_choice( 740 let mut c = p.expect_choice("all proposals", vec![
777 "all proposals", 741 format!("\"{PROPOSAL_TITLE_3}\""),
778 vec![ 742 format!("\"{PROPOSAL_TITLE_2}\""),
779 format!("\"{PROPOSAL_TITLE_3}\""), 743 format!("\"{PROPOSAL_TITLE_1}\""),
780 format!("\"{PROPOSAL_TITLE_2}\""), 744 ])?;
781 format!("\"{PROPOSAL_TITLE_1}\""),
782 ],
783 )?;
784 c.succeeds_with(2, true, None)?; 745 c.succeeds_with(2, true, None)?;
785 let mut c = p.expect_choice( 746 let mut c = p.expect_choice("", vec![
786 "", 747 format!("checkout proposal branch (2 ahead 0 behind 'main')"),
787 vec![ 748 format!("apply to current branch with `git am`"),
788 format!("checkout proposal branch (2 ahead 0 behind 'main')"), 749 format!("download to ./patches"),
789 format!("apply to current branch with `git am`"), 750 format!("back"),
790 format!("download to ./patches"), 751 ])?;
791 format!("back"),
792 ],
793 )?;
794 c.succeeds_with(0, true, Some(0))?; 752 c.succeeds_with(0, true, Some(0))?;
795 p.expect(format!( 753 p.expect(format!(
796 "checked out proposal as 'pr/{}(", 754 "checked out proposal as 'pr/{}(",
@@ -864,24 +822,18 @@ mod when_main_branch_is_uptodate {
864 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 822 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
865 p.expect("fetching updates...\r\n")?; 823 p.expect("fetching updates...\r\n")?;
866 p.expect_eventually("\r\n")?; // some updates listed here 824 p.expect_eventually("\r\n")?; // some updates listed here
867 let mut c = p.expect_choice( 825 let mut c = p.expect_choice("all proposals", vec![
868 "all proposals", 826 format!("\"{PROPOSAL_TITLE_3}\""),
869 vec![ 827 format!("\"{PROPOSAL_TITLE_2}\""),
870 format!("\"{PROPOSAL_TITLE_3}\""), 828 format!("\"{PROPOSAL_TITLE_1}\""),
871 format!("\"{PROPOSAL_TITLE_2}\""), 829 ])?;
872 format!("\"{PROPOSAL_TITLE_1}\""),
873 ],
874 )?;
875 c.succeeds_with(2, true, None)?; 830 c.succeeds_with(2, true, None)?;
876 let mut c = p.expect_choice( 831 let mut c = p.expect_choice("", vec![
877 "", 832 format!("checkout proposal branch and apply 1 appendments"),
878 vec![ 833 format!("apply to current branch with `git am`"),
879 format!("checkout proposal branch and apply 1 appendments"), 834 format!("download to ./patches"),
880 format!("apply to current branch with `git am`"), 835 format!("back"),
881 format!("download to ./patches"), 836 ])?;
882 format!("back"),
883 ],
884 )?;
885 c.succeeds_with(0, true, Some(0))?; 837 c.succeeds_with(0, true, Some(0))?;
886 p.expect("checked out proposal branch and applied 1 appendments (2 ahead 0 behind 'main')\r\n")?; 838 p.expect("checked out proposal branch and applied 1 appendments (2 ahead 0 behind 'main')\r\n")?;
887 p.expect_end()?; 839 p.expect_end()?;
@@ -940,24 +892,18 @@ mod when_main_branch_is_uptodate {
940 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 892 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
941 p.expect("fetching updates...\r\n")?; 893 p.expect("fetching updates...\r\n")?;
942 p.expect_eventually("\r\n")?; // some updates listed here 894 p.expect_eventually("\r\n")?; // some updates listed here
943 let mut c = p.expect_choice( 895 let mut c = p.expect_choice("all proposals", vec![
944 "all proposals", 896 format!("\"{PROPOSAL_TITLE_3}\""),
945 vec![ 897 format!("\"{PROPOSAL_TITLE_2}\""),
946 format!("\"{PROPOSAL_TITLE_3}\""), 898 format!("\"{PROPOSAL_TITLE_1}\""),
947 format!("\"{PROPOSAL_TITLE_2}\""), 899 ])?;
948 format!("\"{PROPOSAL_TITLE_1}\""),
949 ],
950 )?;
951 c.succeeds_with(2, true, None)?; 900 c.succeeds_with(2, true, None)?;
952 let mut c = p.expect_choice( 901 let mut c = p.expect_choice("", vec![
953 "", 902 format!("checkout proposal branch and apply 1 appendments"),
954 vec![ 903 format!("apply to current branch with `git am`"),
955 format!("checkout proposal branch and apply 1 appendments"), 904 format!("download to ./patches"),
956 format!("apply to current branch with `git am`"), 905 format!("back"),
957 format!("download to ./patches"), 906 ])?;
958 format!("back"),
959 ],
960 )?;
961 c.succeeds_with(0, true, Some(0))?; 907 c.succeeds_with(0, true, Some(0))?;
962 p.expect("checked out proposal branch and applied 1 appendments (2 ahead 0 behind 'main')\r\n")?; 908 p.expect("checked out proposal branch and applied 1 appendments (2 ahead 0 behind 'main')\r\n")?;
963 p.expect_end()?; 909 p.expect_end()?;
@@ -1053,29 +999,21 @@ mod when_main_branch_is_uptodate {
1053 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 999 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1054 p.expect("fetching updates...\r\n")?; 1000 p.expect("fetching updates...\r\n")?;
1055 p.expect_eventually("\r\n")?; // some updates listed here 1001 p.expect_eventually("\r\n")?; // some updates listed here
1056 let mut c = p.expect_choice( 1002 let mut c = p.expect_choice("all proposals", vec![
1057 "all proposals", 1003 format!("\"{PROPOSAL_TITLE_3}\""),
1058 vec![ 1004 format!("\"{PROPOSAL_TITLE_2}\""),
1059 format!("\"{PROPOSAL_TITLE_3}\""), 1005 format!("\"{PROPOSAL_TITLE_1}\""),
1060 format!("\"{PROPOSAL_TITLE_2}\""), 1006 ])?;
1061 format!("\"{PROPOSAL_TITLE_1}\""),
1062 ],
1063 )?;
1064 c.succeeds_with(2, true, None)?; 1007 c.succeeds_with(2, true, None)?;
1065 p.expect_eventually("--force`\r\n")?; 1008 p.expect_eventually("--force`\r\n")?;
1066 1009
1067 let mut c = p.expect_choice( 1010 let mut c = p.expect_choice("", vec![
1068 "", 1011 format!("checkout local branch with unpublished changes"),
1069 vec![ 1012 format!("discard unpublished changes and checkout new revision"),
1070 format!("checkout local branch with unpublished changes"), 1013 format!("apply to current branch with `git am`"),
1071 format!( 1014 format!("download to ./patches"),
1072 "discard unpublished changes and checkout new revision" 1015 "back".to_string(),
1073 ), 1016 ])?;
1074 format!("apply to current branch with `git am`"),
1075 format!("download to ./patches"),
1076 "back".to_string(),
1077 ],
1078 )?;
1079 c.succeeds_with(1, true, Some(0))?; 1017 c.succeeds_with(1, true, Some(0))?;
1080 1018
1081 p.expect_end_eventually_and_print()?; 1019 p.expect_end_eventually_and_print()?;
@@ -1132,14 +1070,11 @@ mod when_main_branch_is_uptodate {
1132 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 1070 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1133 p.expect("fetching updates...\r\n")?; 1071 p.expect("fetching updates...\r\n")?;
1134 p.expect_eventually("\r\n")?; // some updates listed here 1072 p.expect_eventually("\r\n")?; // some updates listed here
1135 let mut c = p.expect_choice( 1073 let mut c = p.expect_choice("all proposals", vec![
1136 "all proposals", 1074 format!("\"{PROPOSAL_TITLE_3}\""),
1137 vec![ 1075 format!("\"{PROPOSAL_TITLE_2}\""),
1138 format!("\"{PROPOSAL_TITLE_3}\""), 1076 format!("\"{PROPOSAL_TITLE_1}\""),
1139 format!("\"{PROPOSAL_TITLE_2}\""), 1077 ])?;
1140 format!("\"{PROPOSAL_TITLE_1}\""),
1141 ],
1142 )?;
1143 c.succeeds_with(2, true, None)?; 1078 c.succeeds_with(2, true, None)?;
1144 p.expect("you have an amended/rebase version the proposal that is unpublished\r\n")?; 1079 p.expect("you have an amended/rebase version the proposal that is unpublished\r\n")?;
1145 p.expect("you have previously applied the latest version of the proposal (2 ahead 0 behind 'main') but your local proposal branch has amended or rebased it (2 ahead 0 behind 'main')\r\n")?; 1080 p.expect("you have previously applied the latest version of the proposal (2 ahead 0 behind 'main') but your local proposal branch has amended or rebased it (2 ahead 0 behind 'main')\r\n")?;
@@ -1148,18 +1083,13 @@ mod when_main_branch_is_uptodate {
1148 p.expect(" 2) run `ngit list` and checkout the latest published version of this proposal\r\n")?; 1083 p.expect(" 2) run `ngit list` and checkout the latest published version of this proposal\r\n")?;
1149 p.expect("if you are confident in your changes consider running `ngit push --force`\r\n")?; 1084 p.expect("if you are confident in your changes consider running `ngit push --force`\r\n")?;
1150 1085
1151 let mut c = p.expect_choice( 1086 let mut c = p.expect_choice("", vec![
1152 "", 1087 format!("checkout local branch with unpublished changes"),
1153 vec![ 1088 format!("discard unpublished changes and checkout new revision"),
1154 format!("checkout local branch with unpublished changes"), 1089 format!("apply to current branch with `git am`"),
1155 format!( 1090 format!("download to ./patches"),
1156 "discard unpublished changes and checkout new revision" 1091 "back".to_string(),
1157 ), 1092 ])?;
1158 format!("apply to current branch with `git am`"),
1159 format!("download to ./patches"),
1160 "back".to_string(),
1161 ],
1162 )?;
1163 c.succeeds_with(1, true, Some(1))?; 1093 c.succeeds_with(1, true, Some(1))?;
1164 p.expect_end_with("checked out latest version of proposal (2 ahead 0 behind 'main'), replacing unpublished version (2 ahead 0 behind 'main')\r\n")?; 1094 p.expect_end_with("checked out latest version of proposal (2 ahead 0 behind 'main'), replacing unpublished version (2 ahead 0 behind 'main')\r\n")?;
1165 1095
@@ -1237,26 +1167,20 @@ mod when_main_branch_is_uptodate {
1237 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 1167 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1238 p.expect("fetching updates...\r\n")?; 1168 p.expect("fetching updates...\r\n")?;
1239 p.expect_eventually("\r\n")?; // some updates listed here 1169 p.expect_eventually("\r\n")?; // some updates listed here
1240 let mut c = p.expect_choice( 1170 let mut c = p.expect_choice("all proposals", vec![
1241 "all proposals", 1171 format!("\"{PROPOSAL_TITLE_3}\""),
1242 vec![ 1172 format!("\"{PROPOSAL_TITLE_2}\""),
1243 format!("\"{PROPOSAL_TITLE_3}\""), 1173 format!("\"{PROPOSAL_TITLE_1}\""),
1244 format!("\"{PROPOSAL_TITLE_2}\""), 1174 ])?;
1245 format!("\"{PROPOSAL_TITLE_1}\""),
1246 ],
1247 )?;
1248 c.succeeds_with(2, true, None)?; 1175 c.succeeds_with(2, true, None)?;
1249 p.expect( 1176 p.expect(
1250 "local proposal branch exists with 1 unpublished commits on top of the most up-to-date version of the proposal (3 ahead 0 behind 'main')\r\n", 1177 "local proposal branch exists with 1 unpublished commits on top of the most up-to-date version of the proposal (3 ahead 0 behind 'main')\r\n",
1251 )?; 1178 )?;
1252 1179
1253 let mut c = p.expect_choice( 1180 let mut c = p.expect_choice("", vec![
1254 "", 1181 format!("checkout proposal branch with 1 unpublished commits"),
1255 vec![ 1182 format!("back"),
1256 format!("checkout proposal branch with 1 unpublished commits"), 1183 ])?;
1257 format!("back"),
1258 ],
1259 )?;
1260 c.succeeds_with(0, true, Some(0))?; 1184 c.succeeds_with(0, true, Some(0))?;
1261 p.expect("checked out proposal branch with 1 unpublished commits (3 ahead 0 behind 'main')\r\n")?; 1185 p.expect("checked out proposal branch with 1 unpublished commits (3 ahead 0 behind 'main')\r\n")?;
1262 p.expect_end()?; 1186 p.expect_end()?;
@@ -1319,26 +1243,20 @@ mod when_main_branch_is_uptodate {
1319 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 1243 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1320 p.expect("fetching updates...\r\n")?; 1244 p.expect("fetching updates...\r\n")?;
1321 p.expect_eventually("\r\n")?; // some updates listed here 1245 p.expect_eventually("\r\n")?; // some updates listed here
1322 let mut c = p.expect_choice( 1246 let mut c = p.expect_choice("all proposals", vec![
1323 "all proposals", 1247 format!("\"{PROPOSAL_TITLE_3}\""),
1324 vec![ 1248 format!("\"{PROPOSAL_TITLE_2}\""),
1325 format!("\"{PROPOSAL_TITLE_3}\""), 1249 format!("\"{PROPOSAL_TITLE_1}\""),
1326 format!("\"{PROPOSAL_TITLE_2}\""), 1250 ])?;
1327 format!("\"{PROPOSAL_TITLE_1}\""),
1328 ],
1329 )?;
1330 c.succeeds_with(2, true, None)?; 1251 c.succeeds_with(2, true, None)?;
1331 p.expect( 1252 p.expect(
1332 "local proposal branch exists with 1 unpublished commits on top of the most up-to-date version of the proposal (3 ahead 0 behind 'main')\r\n", 1253 "local proposal branch exists with 1 unpublished commits on top of the most up-to-date version of the proposal (3 ahead 0 behind 'main')\r\n",
1333 )?; 1254 )?;
1334 1255
1335 let mut c = p.expect_choice( 1256 let mut c = p.expect_choice("", vec![
1336 "", 1257 format!("checkout proposal branch with 1 unpublished commits"),
1337 vec![ 1258 format!("back"),
1338 format!("checkout proposal branch with 1 unpublished commits"), 1259 ])?;
1339 format!("back"),
1340 ],
1341 )?;
1342 c.succeeds_with(0, true, Some(0))?; 1260 c.succeeds_with(0, true, Some(0))?;
1343 p.expect("checked out proposal branch with 1 unpublished commits (3 ahead 0 behind 'main')\r\n")?; 1261 p.expect("checked out proposal branch with 1 unpublished commits (3 ahead 0 behind 'main')\r\n")?;
1344 p.expect_end()?; 1262 p.expect_end()?;
@@ -1421,26 +1339,20 @@ mod when_main_branch_is_uptodate {
1421 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 1339 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1422 p.expect("fetching updates...\r\n")?; 1340 p.expect("fetching updates...\r\n")?;
1423 p.expect_eventually("\r\n")?; // some updates listed here 1341 p.expect_eventually("\r\n")?; // some updates listed here
1424 let mut c = p.expect_choice( 1342 let mut c = p.expect_choice("all proposals", vec![
1425 "all proposals", 1343 format!("\"{PROPOSAL_TITLE_3}\""),
1426 vec![ 1344 format!("\"{PROPOSAL_TITLE_2}\""),
1427 format!("\"{PROPOSAL_TITLE_3}\""), 1345 format!("\"{PROPOSAL_TITLE_1}\""),
1428 format!("\"{PROPOSAL_TITLE_2}\""), 1346 ])?;
1429 format!("\"{PROPOSAL_TITLE_1}\""),
1430 ],
1431 )?;
1432 c.succeeds_with(2, true, None)?; 1347 c.succeeds_with(2, true, None)?;
1433 p.expect("updated proposal available (2 ahead 0 behind 'main'). existing version is 2 ahead 1 behind 'main'\r\n")?; 1348 p.expect("updated proposal available (2 ahead 0 behind 'main'). existing version is 2 ahead 1 behind 'main'\r\n")?;
1434 let mut c = p.expect_choice( 1349 let mut c = p.expect_choice("", vec![
1435 "", 1350 format!("checkout and overwrite existing proposal branch"),
1436 vec![ 1351 format!("checkout existing outdated proposal branch"),
1437 format!("checkout and overwrite existing proposal branch"), 1352 format!("apply to current branch with `git am`"),
1438 format!("checkout existing outdated proposal branch"), 1353 format!("download to ./patches"),
1439 format!("apply to current branch with `git am`"), 1354 format!("back"),
1440 format!("download to ./patches"), 1355 ])?;
1441 format!("back"),
1442 ],
1443 )?;
1444 c.succeeds_with(0, true, Some(0))?; 1356 c.succeeds_with(0, true, Some(0))?;
1445 p.expect("checked out new version of proposal (2 ahead 0 behind 'main'), replacing old version (2 ahead 1 behind 'main')\r\n")?; 1357 p.expect("checked out new version of proposal (2 ahead 0 behind 'main'), replacing old version (2 ahead 1 behind 'main')\r\n")?;
1446 p.expect_end()?; 1358 p.expect_end()?;
@@ -1494,26 +1406,20 @@ mod when_main_branch_is_uptodate {
1494 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]); 1406 let mut p = CliTester::new_from_dir(&test_repo.dir, ["list"]);
1495 p.expect("fetching updates...\r\n")?; 1407 p.expect("fetching updates...\r\n")?;
1496 p.expect_eventually("\r\n")?; // some updates listed here 1408 p.expect_eventually("\r\n")?; // some updates listed here
1497 let mut c = p.expect_choice( 1409 let mut c = p.expect_choice("all proposals", vec![
1498 "all proposals", 1410 format!("\"{PROPOSAL_TITLE_3}\""),
1499 vec![ 1411 format!("\"{PROPOSAL_TITLE_2}\""),
1500 format!("\"{PROPOSAL_TITLE_3}\""), 1412 format!("\"{PROPOSAL_TITLE_1}\""),
1501 format!("\"{PROPOSAL_TITLE_2}\""), 1413 ])?;
1502 format!("\"{PROPOSAL_TITLE_1}\""),
1503 ],
1504 )?;
1505 c.succeeds_with(2, true, None)?; 1414 c.succeeds_with(2, true, None)?;
1506 p.expect("updated proposal available (2 ahead 0 behind 'main'). existing version is 2 ahead 1 behind 'main'\r\n")?; 1415 p.expect("updated proposal available (2 ahead 0 behind 'main'). existing version is 2 ahead 1 behind 'main'\r\n")?;
1507 let mut c = p.expect_choice( 1416 let mut c = p.expect_choice("", vec![
1508 "", 1417 format!("checkout and overwrite existing proposal branch"),
1509 vec![ 1418 format!("checkout existing outdated proposal branch"),
1510 format!("checkout and overwrite existing proposal branch"), 1419 format!("apply to current branch with `git am`"),
1511 format!("checkout existing outdated proposal branch"), 1420 format!("download to ./patches"),
1512 format!("apply to current branch with `git am`"), 1421 format!("back"),
1513 format!("download to ./patches"), 1422 ])?;
1514 format!("back"),
1515 ],
1516 )?;
1517 c.succeeds_with(0, true, Some(0))?; 1423 c.succeeds_with(0, true, Some(0))?;
1518 p.expect("checked out new version of proposal (2 ahead 0 behind 'main'), replacing old version (2 ahead 1 behind 'main')\r\n")?; 1424 p.expect("checked out new version of proposal (2 ahead 0 behind 'main'), replacing old version (2 ahead 1 behind 'main')\r\n")?;
1519 p.expect_end()?; 1425 p.expect_end()?;
diff --git a/tests/ngit_login.rs b/tests/ngit_login.rs
index 78a160c..b1e2676 100644
--- a/tests/ngit_login.rs
+++ b/tests/ngit_login.rs
@@ -6,27 +6,21 @@ use test_utils::*;
6static EXPECTED_NSEC_PROMPT: &str = "nsec"; 6static EXPECTED_NSEC_PROMPT: &str = "nsec";
7 7
8fn show_first_time_login_choices(p: &mut CliTester) -> Result<CliTesterChoicePrompt> { 8fn show_first_time_login_choices(p: &mut CliTester) -> Result<CliTesterChoicePrompt> {
9 p.expect_choice( 9 p.expect_choice("login to nostr", vec![
10 "login to nostr", 10 "secret key (nsec / ncryptsec)".to_string(),
11 vec![ 11 "nostr connect (remote signer)".to_string(),
12 "secret key (nsec / ncryptsec)".to_string(), 12 "create account".to_string(),
13 "nostr connect (remote signer)".to_string(), 13 "help".to_string(),
14 "create account".to_string(), 14 ])
15 "help".to_string(),
16 ],
17 )
18} 15}
19 16
20fn first_time_login_choices_succeeds_with_nsec(p: &mut CliTester, nsec: &str) -> Result<()> { 17fn first_time_login_choices_succeeds_with_nsec(p: &mut CliTester, nsec: &str) -> Result<()> {
21 p.expect_choice( 18 p.expect_choice("login to nostr", vec![
22 "login to nostr", 19 "secret key (nsec / ncryptsec)".to_string(),
23 vec![ 20 "nostr connect (remote signer)".to_string(),
24 "secret key (nsec / ncryptsec)".to_string(), 21 "create account".to_string(),
25 "nostr connect (remote signer)".to_string(), 22 "help".to_string(),
26 "create account".to_string(), 23 ])?
27 "help".to_string(),
28 ],
29 )?
30 .succeeds_with(0, false, Some(0))?; 24 .succeeds_with(0, false, Some(0))?;
31 25
32 p.expect_input(EXPECTED_NSEC_PROMPT)? 26 p.expect_input(EXPECTED_NSEC_PROMPT)?
@@ -49,7 +43,7 @@ fn standard_first_time_login_with_nsec() -> Result<CliTester> {
49mod with_relays { 43mod with_relays {
50 use anyhow::Ok; 44 use anyhow::Ok;
51 use futures::join; 45 use futures::join;
52 use test_utils::relay::{shutdown_relay, ListenerReqFunc, Relay}; 46 use test_utils::relay::{ListenerReqFunc, Relay, shutdown_relay};
53 47
54 use super::*; 48 use super::*;
55 49
@@ -137,25 +131,17 @@ mod with_relays {
137 async fn when_latest_metadata_and_relay_list_on_all_relays() -> Result<()> { 131 async fn when_latest_metadata_and_relay_list_on_all_relays() -> Result<()> {
138 run_test_displays_correct_name( 132 run_test_displays_correct_name(
139 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 133 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
140 relay.respond_events( 134 relay.respond_events(client_id, &subscription_id, &vec![
141 client_id, 135 generate_test_key_1_metadata_event("fred"),
142 &subscription_id, 136 generate_test_key_1_relay_list_event_same_as_fallback(),
143 &vec![ 137 ])?;
144 generate_test_key_1_metadata_event("fred"),
145 generate_test_key_1_relay_list_event_same_as_fallback(),
146 ],
147 )?;
148 Ok(()) 138 Ok(())
149 }), 139 }),
150 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 140 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
151 relay.respond_events( 141 relay.respond_events(client_id, &subscription_id, &vec![
152 client_id, 142 generate_test_key_1_metadata_event("fred"),
153 &subscription_id, 143 generate_test_key_1_relay_list_event_same_as_fallback(),
154 &vec![ 144 ])?;
155 generate_test_key_1_metadata_event("fred"),
156 generate_test_key_1_relay_list_event_same_as_fallback(),
157 ],
158 )?;
159 Ok(()) 145 Ok(())
160 }), 146 }),
161 ) 147 )
@@ -170,18 +156,14 @@ mod with_relays {
170 async fn when_metadata_contains_only_display_name() -> Result<()> { 156 async fn when_metadata_contains_only_display_name() -> Result<()> {
171 run_test_displays_correct_name( 157 run_test_displays_correct_name(
172 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 158 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
173 relay.respond_events( 159 relay.respond_events(client_id, &subscription_id, &vec![
174 client_id, 160 nostr::event::EventBuilder::metadata(
175 &subscription_id, 161 &nostr::Metadata::new().display_name("fred"),
176 &vec![ 162 )
177 nostr::event::EventBuilder::metadata( 163 .sign_with_keys(&TEST_KEY_1_KEYS)
178 &nostr::Metadata::new().display_name("fred"), 164 .unwrap(),
179 ) 165 generate_test_key_1_relay_list_event_same_as_fallback(),
180 .sign_with_keys(&TEST_KEY_1_KEYS) 166 ])?;
181 .unwrap(),
182 generate_test_key_1_relay_list_event_same_as_fallback(),
183 ],
184 )?;
185 Ok(()) 167 Ok(())
186 }), 168 }),
187 None, 169 None,
@@ -207,19 +189,14 @@ mod with_relays {
207 189
208 run_test_displays_correct_name( 190 run_test_displays_correct_name(
209 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 191 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
210 relay.respond_events( 192 relay.respond_events(client_id, &subscription_id, &vec![
211 client_id, 193 nostr::event::EventBuilder::metadata(
212 &subscription_id, 194 &nostr::Metadata::new().custom_field("displayName", "fred"),
213 &vec![ 195 )
214 nostr::event::EventBuilder::metadata( 196 .sign_with_keys(&TEST_KEY_1_KEYS)
215 &nostr::Metadata::new() 197 .unwrap(),
216 .custom_field("displayName", "fred"), 198 generate_test_key_1_relay_list_event_same_as_fallback(),
217 ) 199 ])?;
218 .sign_with_keys(&TEST_KEY_1_KEYS)
219 .unwrap(),
220 generate_test_key_1_relay_list_event_same_as_fallback(),
221 ],
222 )?;
223 Ok(()) 200 Ok(())
224 }), 201 }),
225 None, 202 None,
@@ -233,18 +210,14 @@ mod with_relays {
233 -> Result<()> { 210 -> Result<()> {
234 run_test_displays_fallback_to_npub( 211 run_test_displays_fallback_to_npub(
235 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 212 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
236 relay.respond_events( 213 relay.respond_events(client_id, &subscription_id, &vec![
237 client_id, 214 nostr::event::EventBuilder::metadata(
238 &subscription_id, 215 &nostr::Metadata::new().about("other info in metadata"),
239 &vec![ 216 )
240 nostr::event::EventBuilder::metadata( 217 .sign_with_keys(&TEST_KEY_1_KEYS)
241 &nostr::Metadata::new().about("other info in metadata"), 218 .unwrap(),
242 ) 219 generate_test_key_1_relay_list_event_same_as_fallback(),
243 .sign_with_keys(&TEST_KEY_1_KEYS) 220 ])?;
244 .unwrap(),
245 generate_test_key_1_relay_list_event_same_as_fallback(),
246 ],
247 )?;
248 Ok(()) 221 Ok(())
249 }), 222 }),
250 None, 223 None,
@@ -259,14 +232,10 @@ mod with_relays {
259 -> Result<()> { 232 -> Result<()> {
260 run_test_displays_correct_name( 233 run_test_displays_correct_name(
261 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 234 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
262 relay.respond_events( 235 relay.respond_events(client_id, &subscription_id, &vec![
263 client_id, 236 generate_test_key_1_metadata_event("fred"),
264 &subscription_id, 237 generate_test_key_1_relay_list_event_same_as_fallback(),
265 &vec![ 238 ])?;
266 generate_test_key_1_metadata_event("fred"),
267 generate_test_key_1_relay_list_event_same_as_fallback(),
268 ],
269 )?;
270 Ok(()) 239 Ok(())
271 }), 240 }),
272 None, 241 None,
@@ -280,19 +249,15 @@ mod with_relays {
280 { 249 {
281 run_test_displays_correct_name( 250 run_test_displays_correct_name(
282 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 251 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
283 relay.respond_events( 252 relay.respond_events(client_id, &subscription_id, &vec![
284 client_id, 253 generate_test_key_1_metadata_event("fred"),
285 &subscription_id, 254 ])?;
286 &vec![generate_test_key_1_metadata_event("fred")],
287 )?;
288 Ok(()) 255 Ok(())
289 }), 256 }),
290 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 257 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
291 relay.respond_events( 258 relay.respond_events(client_id, &subscription_id, &vec![
292 client_id, 259 generate_test_key_1_relay_list_event_same_as_fallback(),
293 &subscription_id, 260 ])?;
294 &vec![generate_test_key_1_relay_list_event_same_as_fallback()],
295 )?;
296 Ok(()) 261 Ok(())
297 }), 262 }),
298 ) 263 )
@@ -304,22 +269,16 @@ mod with_relays {
304 async fn when_some_relays_return_old_metadata_event() -> Result<()> { 269 async fn when_some_relays_return_old_metadata_event() -> Result<()> {
305 run_test_displays_correct_name( 270 run_test_displays_correct_name(
306 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 271 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
307 relay.respond_events( 272 relay.respond_events(client_id, &subscription_id, &vec![
308 client_id, 273 generate_test_key_1_metadata_event("fred"),
309 &subscription_id, 274 generate_test_key_1_relay_list_event_same_as_fallback(),
310 &vec![ 275 ])?;
311 generate_test_key_1_metadata_event("fred"),
312 generate_test_key_1_relay_list_event_same_as_fallback(),
313 ],
314 )?;
315 Ok(()) 276 Ok(())
316 }), 277 }),
317 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 278 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
318 relay.respond_events( 279 relay.respond_events(client_id, &subscription_id, &vec![
319 client_id, 280 generate_test_key_1_metadata_event_old("fred old"),
320 &subscription_id, 281 ])?;
321 &vec![generate_test_key_1_metadata_event_old("fred old")],
322 )?;
323 Ok(()) 282 Ok(())
324 }), 283 }),
325 ) 284 )
@@ -331,22 +290,16 @@ mod with_relays {
331 async fn when_some_relays_return_other_users_metadata() -> Result<()> { 290 async fn when_some_relays_return_other_users_metadata() -> Result<()> {
332 run_test_displays_correct_name( 291 run_test_displays_correct_name(
333 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 292 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
334 relay.respond_events( 293 relay.respond_events(client_id, &subscription_id, &vec![
335 client_id, 294 generate_test_key_2_metadata_event("carole"),
336 &subscription_id, 295 ])?;
337 &vec![generate_test_key_2_metadata_event("carole")],
338 )?;
339 Ok(()) 296 Ok(())
340 }), 297 }),
341 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 298 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
342 relay.respond_events( 299 relay.respond_events(client_id, &subscription_id, &vec![
343 client_id, 300 generate_test_key_1_metadata_event_old("fred"),
344 &subscription_id, 301 generate_test_key_1_relay_list_event_same_as_fallback(),
345 &vec![ 302 ])?;
346 generate_test_key_1_metadata_event_old("fred"),
347 generate_test_key_1_relay_list_event_same_as_fallback(),
348 ],
349 )?;
350 Ok(()) 303 Ok(())
351 }), 304 }),
352 ) 305 )
@@ -359,22 +312,16 @@ mod with_relays {
359 run_test_displays_correct_name( 312 run_test_displays_correct_name(
360 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 313 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
361 let event = generate_test_key_1_kind_event(nostr::Kind::TextNote); 314 let event = generate_test_key_1_kind_event(nostr::Kind::TextNote);
362 relay.respond_events( 315 relay.respond_events(client_id, &subscription_id, &vec![
363 client_id, 316 make_event_old_or_change_user(event, &TEST_KEY_1_KEYS, 0),
364 &subscription_id, 317 ])?;
365 &vec![make_event_old_or_change_user(event, &TEST_KEY_1_KEYS, 0)],
366 )?;
367 Ok(()) 318 Ok(())
368 }), 319 }),
369 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 320 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
370 relay.respond_events( 321 relay.respond_events(client_id, &subscription_id, &vec![
371 client_id, 322 generate_test_key_1_metadata_event_old("fred"),
372 &subscription_id, 323 generate_test_key_1_relay_list_event_same_as_fallback(),
373 &vec![ 324 ])?;
374 generate_test_key_1_metadata_event_old("fred"),
375 generate_test_key_1_relay_list_event_same_as_fallback(),
376 ],
377 )?;
378 Ok(()) 325 Ok(())
379 }), 326 }),
380 ) 327 )
@@ -389,14 +336,10 @@ mod with_relays {
389 async fn displays_correct_name() -> Result<()> { 336 async fn displays_correct_name() -> Result<()> {
390 run_test_when_specifying_command_line_nsec_only_displays_correct_name( 337 run_test_when_specifying_command_line_nsec_only_displays_correct_name(
391 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 338 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
392 relay.respond_events( 339 relay.respond_events(client_id, &subscription_id, &vec![
393 client_id, 340 generate_test_key_1_metadata_event("fred"),
394 &subscription_id, 341 generate_test_key_1_relay_list_event_same_as_fallback(),
395 &vec![ 342 ])?;
396 generate_test_key_1_metadata_event("fred"),
397 generate_test_key_1_relay_list_event_same_as_fallback(),
398 ],
399 )?;
400 Ok(()) 343 Ok(())
401 }), 344 }),
402 None, 345 None,
@@ -414,10 +357,12 @@ mod with_relays {
414 357
415 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 358 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
416 let test_repo = GitTestRepo::default(); 359 let test_repo = GitTestRepo::default();
417 let mut p = CliTester::new_from_dir( 360 let mut p = CliTester::new_from_dir(&test_repo.dir, [
418 &test_repo.dir, 361 "account",
419 ["account", "login", "--nsec", TEST_KEY_1_NSEC], 362 "login",
420 ); 363 "--nsec",
364 TEST_KEY_1_NSEC,
365 ]);
421 366
422 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?; 367 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?;
423 368
@@ -489,11 +434,9 @@ mod with_relays {
489 async fn warm_user_and_displays_name() -> Result<()> { 434 async fn warm_user_and_displays_name() -> Result<()> {
490 run_test_when_no_relay_list_found_warns_user_and_uses_npub( 435 run_test_when_no_relay_list_found_warns_user_and_uses_npub(
491 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 436 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
492 relay.respond_events( 437 relay.respond_events(client_id, &subscription_id, &vec![
493 client_id, 438 generate_test_key_1_metadata_event("fred"),
494 &subscription_id, 439 ])?;
495 &vec![generate_test_key_1_metadata_event("fred")],
496 )?;
497 Ok(()) 440 Ok(())
498 }), 441 }),
499 None, 442 None,
@@ -584,25 +527,17 @@ mod with_relays {
584 async fn displays_correct_name() -> Result<()> { 527 async fn displays_correct_name() -> Result<()> {
585 run_test_displays_correct_name( 528 run_test_displays_correct_name(
586 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 529 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
587 relay.respond_events( 530 relay.respond_events(client_id, &subscription_id, &vec![
588 client_id, 531 generate_test_key_1_metadata_event_old("Fred"),
589 &subscription_id, 532 generate_test_key_1_relay_list_event(),
590 &vec![ 533 ])?;
591 generate_test_key_1_metadata_event_old("Fred"),
592 generate_test_key_1_relay_list_event(),
593 ],
594 )?;
595 Ok(()) 534 Ok(())
596 }), 535 }),
597 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 536 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
598 relay.respond_events( 537 relay.respond_events(client_id, &subscription_id, &vec![
599 client_id, 538 generate_test_key_1_metadata_event("fred"),
600 &subscription_id, 539 generate_test_key_1_relay_list_event(),
601 &vec![ 540 ])?;
602 generate_test_key_1_metadata_event("fred"),
603 generate_test_key_1_relay_list_event(),
604 ],
605 )?;
606 Ok(()) 541 Ok(())
607 }), 542 }),
608 ) 543 )
@@ -674,10 +609,10 @@ mod with_offline_flag {
674 true, 609 true,
675 )?; 610 )?;
676 611
677 p.expect_choice( 612 p.expect_choice("login to nostr", vec![
678 "login to nostr", 613 "try again with nsec".to_string(),
679 vec!["try again with nsec".to_string(), "back".to_string()], 614 "back".to_string(),
680 )? 615 ])?
681 .succeeds_with(0, false, Some(0))?; 616 .succeeds_with(0, false, Some(0))?;
682 } 617 }
683 618
@@ -697,10 +632,13 @@ mod with_offline_flag {
697 #[test] 632 #[test]
698 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> { 633 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> {
699 let test_repo = GitTestRepo::default(); 634 let test_repo = GitTestRepo::default();
700 let mut p = CliTester::new_from_dir( 635 let mut p = CliTester::new_from_dir(&test_repo.dir, [
701 &test_repo.dir, 636 "account",
702 ["account", "login", "--offline", "--nsec", TEST_KEY_1_NSEC], 637 "login",
703 ); 638 "--offline",
639 "--nsec",
640 TEST_KEY_1_NSEC,
641 ]);
704 642
705 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?; 643 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?;
706 644
@@ -712,10 +650,13 @@ mod with_offline_flag {
712 #[test] 650 #[test]
713 fn invalid_nsec_param_fails_without_prompts() -> Result<()> { 651 fn invalid_nsec_param_fails_without_prompts() -> Result<()> {
714 let test_repo = GitTestRepo::default(); 652 let test_repo = GitTestRepo::default();
715 let mut p = CliTester::new_from_dir( 653 let mut p = CliTester::new_from_dir(&test_repo.dir, [
716 &test_repo.dir, 654 "account",
717 ["account", "login", "--offline", "--nsec", TEST_INVALID_NSEC], 655 "login",
718 ); 656 "--offline",
657 "--nsec",
658 TEST_INVALID_NSEC,
659 ]);
719 660
720 p.expect_end_with( 661 p.expect_end_with(
721 "Error: invalid nsec parameter\r\n\r\nCaused by:\r\n Invalid secret key\r\n", 662 "Error: invalid nsec parameter\r\n\r\nCaused by:\r\n Invalid secret key\r\n",
@@ -729,18 +670,15 @@ mod with_offline_flag {
729 #[test] 670 #[test]
730 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> { 671 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> {
731 let test_repo = GitTestRepo::default(); 672 let test_repo = GitTestRepo::default();
732 let mut p = CliTester::new_from_dir( 673 let mut p = CliTester::new_from_dir(&test_repo.dir, [
733 &test_repo.dir, 674 "account",
734 [ 675 "login",
735 "account", 676 "--offline",
736 "login", 677 "--nsec",
737 "--offline", 678 TEST_KEY_1_NSEC,
738 "--nsec", 679 "--password",
739 TEST_KEY_1_NSEC, 680 TEST_PASSWORD,
740 "--password", 681 ]);
741 TEST_PASSWORD,
742 ],
743 );
744 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?; 682 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?;
745 683
746 p.expect_end_with( 684 p.expect_end_with(
@@ -751,18 +689,15 @@ mod with_offline_flag {
751 #[test] 689 #[test]
752 fn parameters_can_be_called_globally() -> Result<()> { 690 fn parameters_can_be_called_globally() -> Result<()> {
753 let test_repo = GitTestRepo::default(); 691 let test_repo = GitTestRepo::default();
754 let mut p = CliTester::new_from_dir( 692 let mut p = CliTester::new_from_dir(&test_repo.dir, [
755 &test_repo.dir, 693 "--nsec",
756 [ 694 TEST_KEY_1_NSEC,
757 "--nsec", 695 "--password",
758 TEST_KEY_1_NSEC, 696 TEST_PASSWORD,
759 "--password", 697 "account",
760 TEST_PASSWORD, 698 "login",
761 "account", 699 "--offline",
762 "login", 700 ]);
763 "--offline",
764 ],
765 );
766 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?; 701 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?;
767 702
768 p.expect_end_with( 703 p.expect_end_with(
@@ -777,18 +712,15 @@ mod with_offline_flag {
777 fn valid_nsec_param_succeeds_without_prompts_and_logs_in() -> Result<()> { 712 fn valid_nsec_param_succeeds_without_prompts_and_logs_in() -> Result<()> {
778 standard_first_time_login_with_nsec()?.exit()?; 713 standard_first_time_login_with_nsec()?.exit()?;
779 let test_repo = GitTestRepo::default(); 714 let test_repo = GitTestRepo::default();
780 let mut p = CliTester::new_from_dir( 715 let mut p = CliTester::new_from_dir(&test_repo.dir, [
781 &test_repo.dir, 716 "account",
782 [ 717 "login",
783 "account", 718 "--offline",
784 "login", 719 "--nsec",
785 "--offline", 720 TEST_KEY_2_NSEC,
786 "--nsec", 721 "--password",
787 TEST_KEY_2_NSEC, 722 TEST_PASSWORD,
788 "--password", 723 ]);
789 TEST_PASSWORD,
790 ],
791 );
792 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?; 724 p.expect("saved login details to local git config. you are only logged in to this local repository.\r\n")?;
793 725
794 p.expect_end_with( 726 p.expect_end_with(
diff --git a/tests/ngit_send.rs b/tests/ngit_send.rs
index 1ffb515..d728d9c 100644
--- a/tests/ngit_send.rs
+++ b/tests/ngit_send.rs
@@ -181,14 +181,10 @@ async fn prep_run_create_proposal(
181 8051, 181 8051,
182 None, 182 None,
183 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 183 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
184 relay.respond_events( 184 relay.respond_events(client_id, &subscription_id, &vec![
185 client_id, 185 generate_test_key_1_metadata_event("fred"),
186 &subscription_id, 186 generate_test_key_1_relay_list_event(),
187 &vec![ 187 ])?;
188 generate_test_key_1_metadata_event("fred"),
189 generate_test_key_1_relay_list_event(),
190 ],
191 )?;
192 Ok(()) 188 Ok(())
193 }), 189 }),
194 ), 190 ),
@@ -198,11 +194,9 @@ async fn prep_run_create_proposal(
198 8055, 194 8055,
199 None, 195 None,
200 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 196 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
201 relay.respond_events( 197 relay.respond_events(client_id, &subscription_id, &vec![
202 client_id, 198 generate_repo_ref_event(),
203 &subscription_id, 199 ])?;
204 &vec![generate_repo_ref_event()],
205 )?;
206 Ok(()) 200 Ok(())
207 }), 201 }),
208 ), 202 ),
@@ -764,14 +758,10 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
764 8051, 758 8051,
765 None, 759 None,
766 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 760 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
767 relay.respond_events( 761 relay.respond_events(client_id, &subscription_id, &vec![
768 client_id, 762 generate_test_key_1_metadata_event("fred"),
769 &subscription_id, 763 generate_test_key_1_relay_list_event(),
770 &vec![ 764 ])?;
771 generate_test_key_1_metadata_event("fred"),
772 generate_test_key_1_relay_list_event(),
773 ],
774 )?;
775 Ok(()) 765 Ok(())
776 }), 766 }),
777 ), 767 ),
@@ -781,11 +771,9 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
781 8055, 771 8055,
782 None, 772 None,
783 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 773 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
784 relay.respond_events( 774 relay.respond_events(client_id, &subscription_id, &vec![
785 client_id, 775 generate_repo_ref_event(),
786 &subscription_id, 776 ])?;
787 &vec![generate_repo_ref_event()],
788 )?;
789 Ok(()) 777 Ok(())
790 }), 778 }),
791 ), 779 ),
@@ -844,14 +832,10 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
844 8051, 832 8051,
845 None, 833 None,
846 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 834 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
847 relay.respond_events( 835 relay.respond_events(client_id, &subscription_id, &vec![
848 client_id, 836 generate_test_key_1_metadata_event("fred"),
849 &subscription_id, 837 generate_test_key_1_relay_list_event(),
850 &vec![ 838 ])?;
851 generate_test_key_1_metadata_event("fred"),
852 generate_test_key_1_relay_list_event(),
853 ],
854 )?;
855 Ok(()) 839 Ok(())
856 }), 840 }),
857 ), 841 ),
@@ -861,11 +845,9 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
861 8055, 845 8055,
862 None, 846 None,
863 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 847 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
864 relay.respond_events( 848 relay.respond_events(client_id, &subscription_id, &vec![
865 client_id, 849 generate_repo_ref_event(),
866 &subscription_id, 850 ])?;
867 &vec![generate_repo_ref_event()],
868 )?;
869 Ok(()) 851 Ok(())
870 }), 852 }),
871 ), 853 ),
@@ -918,14 +900,10 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
918 8051, 900 8051,
919 None, 901 None,
920 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 902 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
921 relay.respond_events( 903 relay.respond_events(client_id, &subscription_id, &vec![
922 client_id, 904 generate_test_key_1_metadata_event("fred"),
923 &subscription_id, 905 generate_test_key_1_relay_list_event(),
924 &vec![ 906 ])?;
925 generate_test_key_1_metadata_event("fred"),
926 generate_test_key_1_relay_list_event(),
927 ],
928 )?;
929 Ok(()) 907 Ok(())
930 }), 908 }),
931 ), 909 ),
@@ -935,11 +913,9 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
935 8055, 913 8055,
936 None, 914 None,
937 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 915 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
938 relay.respond_events( 916 relay.respond_events(client_id, &subscription_id, &vec![
939 client_id, 917 generate_repo_ref_event(),
940 &subscription_id, 918 ])?;
941 &vec![generate_repo_ref_event()],
942 )?;
943 Ok(()) 919 Ok(())
944 }), 920 }),
945 ), 921 ),
@@ -1012,14 +988,10 @@ mod when_no_cover_letter_flag_set_with_range_of_head_2_sends_2_patches_without_c
1012 8051, 988 8051,
1013 None, 989 None,
1014 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 990 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1015 relay.respond_events( 991 relay.respond_events(client_id, &subscription_id, &vec![
1016 client_id, 992 generate_test_key_1_metadata_event("fred"),
1017 &subscription_id, 993 generate_test_key_1_relay_list_event(),
1018 &vec![ 994 ])?;
1019 generate_test_key_1_metadata_event("fred"),
1020 generate_test_key_1_relay_list_event(),
1021 ],
1022 )?;
1023 Ok(()) 995 Ok(())
1024 }), 996 }),
1025 ), 997 ),
@@ -1029,11 +1001,9 @@ mod when_no_cover_letter_flag_set_with_range_of_head_2_sends_2_patches_without_c
1029 8055, 1001 8055,
1030 None, 1002 None,
1031 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1003 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1032 relay.respond_events( 1004 relay.respond_events(client_id, &subscription_id, &vec![
1033 client_id, 1005 generate_repo_ref_event(),
1034 &subscription_id, 1006 ])?;
1035 &vec![generate_repo_ref_event()],
1036 )?;
1037 Ok(()) 1007 Ok(())
1038 }), 1008 }),
1039 ), 1009 ),
@@ -1200,16 +1170,13 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1200 fn expect_msgs_first(p: &mut CliTester) -> Result<()> { 1170 fn expect_msgs_first(p: &mut CliTester) -> Result<()> {
1201 p.expect("fetching updates...\r\n")?; 1171 p.expect("fetching updates...\r\n")?;
1202 p.expect_eventually("\r\n")?; // may be 'no updates' or some updates 1172 p.expect_eventually("\r\n")?; // may be 'no updates' or some updates
1203 let mut selector = p.expect_multi_select( 1173 let mut selector = p.expect_multi_select("select commits for proposal", vec![
1204 "select commits for proposal", 1174 "(Joe Bloggs) add t4.md [feature] fe973a8".to_string(),
1205 vec![ 1175 "(Joe Bloggs) add t3.md 232efb3".to_string(),
1206 "(Joe Bloggs) add t4.md [feature] fe973a8".to_string(), 1176 "(Joe Bloggs) add t2.md [main] 431b84e".to_string(),
1207 "(Joe Bloggs) add t3.md 232efb3".to_string(), 1177 "(Joe Bloggs) add t1.md af474d8".to_string(),
1208 "(Joe Bloggs) add t2.md [main] 431b84e".to_string(), 1178 "(Joe Bloggs) Initial commit 9ee507f".to_string(),
1209 "(Joe Bloggs) add t1.md af474d8".to_string(), 1179 ])?;
1210 "(Joe Bloggs) Initial commit 9ee507f".to_string(),
1211 ],
1212 )?;
1213 selector.succeeds_with(vec![0, 1], false, vec![0, 1])?; 1180 selector.succeeds_with(vec![0, 1], false, vec![0, 1])?;
1214 p.expect("creating proposal from 2 commits:\r\n")?; 1181 p.expect("creating proposal from 2 commits:\r\n")?;
1215 p.expect("fe973a8 add t4.md\r\n")?; 1182 p.expect("fe973a8 add t4.md\r\n")?;
@@ -1234,14 +1201,10 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1234 8051, 1201 8051,
1235 None, 1202 None,
1236 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1203 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1237 relay.respond_events( 1204 relay.respond_events(client_id, &subscription_id, &vec![
1238 client_id, 1205 generate_test_key_1_metadata_event("fred"),
1239 &subscription_id, 1206 generate_test_key_1_relay_list_event(),
1240 &vec![ 1207 ])?;
1241 generate_test_key_1_metadata_event("fred"),
1242 generate_test_key_1_relay_list_event(),
1243 ],
1244 )?;
1245 Ok(()) 1208 Ok(())
1246 }), 1209 }),
1247 ), 1210 ),
@@ -1251,11 +1214,9 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1251 8055, 1214 8055,
1252 None, 1215 None,
1253 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1216 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1254 relay.respond_events( 1217 relay.respond_events(client_id, &subscription_id, &vec![
1255 client_id, 1218 generate_repo_ref_event(),
1256 &subscription_id, 1219 ])?;
1257 &vec![generate_repo_ref_event()],
1258 )?;
1259 Ok(()) 1220 Ok(())
1260 }), 1221 }),
1261 ), 1222 ),
@@ -1297,14 +1258,10 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1297 8051, 1258 8051,
1298 None, 1259 None,
1299 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1260 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1300 relay.respond_events( 1261 relay.respond_events(client_id, &subscription_id, &vec![
1301 client_id, 1262 generate_test_key_1_metadata_event("fred"),
1302 &subscription_id, 1263 generate_test_key_1_relay_list_event(),
1303 &vec![ 1264 ])?;
1304 generate_test_key_1_metadata_event("fred"),
1305 generate_test_key_1_relay_list_event(),
1306 ],
1307 )?;
1308 Ok(()) 1265 Ok(())
1309 }), 1266 }),
1310 ), 1267 ),
@@ -1314,11 +1271,9 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1314 8055, 1271 8055,
1315 None, 1272 None,
1316 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1273 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1317 relay.respond_events( 1274 relay.respond_events(client_id, &subscription_id, &vec![
1318 client_id, 1275 generate_repo_ref_event(),
1319 &subscription_id, 1276 ])?;
1320 &vec![generate_repo_ref_event()],
1321 )?;
1322 Ok(()) 1277 Ok(())
1323 }), 1278 }),
1324 ), 1279 ),
@@ -1435,15 +1390,11 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1435 8051, 1390 8051,
1436 None, 1391 None,
1437 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1392 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1438 relay.respond_events( 1393 relay.respond_events(client_id, &subscription_id, &vec![
1439 client_id, 1394 generate_test_key_1_metadata_event("fred"),
1440 &subscription_id, 1395 generate_test_key_1_relay_list_event(),
1441 &vec![ 1396 get_pretend_proposal_root_event(),
1442 generate_test_key_1_metadata_event("fred"), 1397 ])?;
1443 generate_test_key_1_relay_list_event(),
1444 get_pretend_proposal_root_event(),
1445 ],
1446 )?;
1447 Ok(()) 1398 Ok(())
1448 }), 1399 }),
1449 ), 1400 ),
@@ -1453,11 +1404,10 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1453 8055, 1404 8055,
1454 None, 1405 None,
1455 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1406 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1456 relay.respond_events( 1407 relay.respond_events(client_id, &subscription_id, &vec![
1457 client_id, 1408 generate_repo_ref_event(),
1458 &subscription_id, 1409 get_pretend_proposal_root_event(),
1459 &vec![generate_repo_ref_event(), get_pretend_proposal_root_event()], 1410 ])?;
1460 )?;
1461 Ok(()) 1411 Ok(())
1462 }), 1412 }),
1463 ), 1413 ),
@@ -1498,15 +1448,11 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1498 8051, 1448 8051,
1499 None, 1449 None,
1500 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1450 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1501 relay.respond_events( 1451 relay.respond_events(client_id, &subscription_id, &vec![
1502 client_id, 1452 generate_test_key_1_metadata_event("fred"),
1503 &subscription_id, 1453 generate_test_key_1_relay_list_event(),
1504 &vec![ 1454 get_pretend_proposal_root_event(),
1505 generate_test_key_1_metadata_event("fred"), 1455 ])?;
1506 generate_test_key_1_relay_list_event(),
1507 get_pretend_proposal_root_event(),
1508 ],
1509 )?;
1510 Ok(()) 1456 Ok(())
1511 }), 1457 }),
1512 ), 1458 ),
@@ -1516,11 +1462,10 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1516 8055, 1462 8055,
1517 None, 1463 None,
1518 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1464 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1519 relay.respond_events( 1465 relay.respond_events(client_id, &subscription_id, &vec![
1520 client_id, 1466 generate_repo_ref_event(),
1521 &subscription_id, 1467 get_pretend_proposal_root_event(),
1522 &vec![generate_repo_ref_event(), get_pretend_proposal_root_event()], 1468 ])?;
1523 )?;
1524 Ok(()) 1469 Ok(())
1525 }), 1470 }),
1526 ), 1471 ),
@@ -1697,15 +1642,11 @@ mod in_reply_to_mentions_issue {
1697 8051, 1642 8051,
1698 None, 1643 None,
1699 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1644 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1700 relay.respond_events( 1645 relay.respond_events(client_id, &subscription_id, &vec![
1701 client_id, 1646 generate_test_key_1_metadata_event("fred"),
1702 &subscription_id, 1647 generate_test_key_1_relay_list_event(),
1703 &vec![ 1648 get_pretend_issue_event(),
1704 generate_test_key_1_metadata_event("fred"), 1649 ])?;
1705 generate_test_key_1_relay_list_event(),
1706 get_pretend_issue_event(),
1707 ],
1708 )?;
1709 Ok(()) 1650 Ok(())
1710 }), 1651 }),
1711 ), 1652 ),
@@ -1715,11 +1656,10 @@ mod in_reply_to_mentions_issue {
1715 8055, 1656 8055,
1716 None, 1657 None,
1717 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1658 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1718 relay.respond_events( 1659 relay.respond_events(client_id, &subscription_id, &vec![
1719 client_id, 1660 generate_repo_ref_event(),
1720 &subscription_id, 1661 get_pretend_issue_event(),
1721 &vec![generate_repo_ref_event(), get_pretend_issue_event()], 1662 ])?;
1722 )?;
1723 Ok(()) 1663 Ok(())
1724 }), 1664 }),
1725 ), 1665 ),
@@ -1821,14 +1761,10 @@ mod in_reply_to_mentions_npub_and_nprofile_which_get_mentioned_in_proposal_root
1821 8051, 1761 8051,
1822 None, 1762 None,
1823 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1763 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1824 relay.respond_events( 1764 relay.respond_events(client_id, &subscription_id, &vec![
1825 client_id, 1765 generate_test_key_1_metadata_event("fred"),
1826 &subscription_id, 1766 generate_test_key_1_relay_list_event(),
1827 &vec![ 1767 ])?;
1828 generate_test_key_1_metadata_event("fred"),
1829 generate_test_key_1_relay_list_event(),
1830 ],
1831 )?;
1832 Ok(()) 1768 Ok(())
1833 }), 1769 }),
1834 ), 1770 ),
@@ -1838,11 +1774,9 @@ mod in_reply_to_mentions_npub_and_nprofile_which_get_mentioned_in_proposal_root
1838 8055, 1774 8055,
1839 None, 1775 None,
1840 Some(&|relay, client_id, subscription_id, _| -> Result<()> { 1776 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1841 relay.respond_events( 1777 relay.respond_events(client_id, &subscription_id, &vec![
1842 client_id, 1778 generate_repo_ref_event(),
1843 &subscription_id, 1779 ])?;
1844 &vec![generate_repo_ref_event()],
1845 )?;
1846 Ok(()) 1780 Ok(())
1847 }), 1781 }),
1848 ), 1782 ),