upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-05-22 17:37:54 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2025-05-22 17:37:54 +0100
commitb6407944cc8f670d33b828f7b77836ceeed2fcfa (patch)
treef95dcec39680d374eaeac801d31c34f715c08cca /src
parent4dc5d0c9fb170981cf4fade5558d7cc8da404aa3 (diff)
feat(init): add blossom
add a blossom tag to the repo announcement
Diffstat (limited to 'src')
-rw-r--r--src/bin/ngit/sub_commands/init.rs66
-rw-r--r--src/lib/repo_ref.rs20
2 files changed, 83 insertions, 3 deletions
diff --git a/src/bin/ngit/sub_commands/init.rs b/src/bin/ngit/sub_commands/init.rs
index 83e434f..4f82d5e 100644
--- a/src/bin/ngit/sub_commands/init.rs
+++ b/src/bin/ngit/sub_commands/init.rs
@@ -48,6 +48,9 @@ pub struct SubCommandArgs {
48 /// relays contributors push patches and comments to 48 /// relays contributors push patches and comments to
49 relays: Vec<String>, 49 relays: Vec<String>,
50 #[clap(short, long, value_parser, num_args = 1..)] 50 #[clap(short, long, value_parser, num_args = 1..)]
51 /// blossom servers
52 blossoms: Vec<String>,
53 #[clap(short, long, value_parser, num_args = 1..)]
51 /// npubs of other maintainers 54 /// npubs of other maintainers
52 other_maintainers: Vec<String>, 55 other_maintainers: Vec<String>,
53 #[clap(long)] 56 #[clap(long)]
@@ -222,6 +225,24 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
222 }; 225 };
223 226
224 227
228 let mut blossoms_defaults = if args.blossoms.is_empty() {
229 if let Some(repo_ref) = &repo_ref {
230 repo_ref
231 .blossoms
232 .iter()
233 .map(std::string::ToString::to_string)
234 .collect::<Vec<String>>()
235 // } else if user_ref.blossoms.read().is_empty() {
236 // client.get_fallback_relays().clone()
237 } else {
238 vec![]
239 // user_ref.relays.read().clone()
240 }
241 } else {
242 args.blossoms.clone()
243 };
244
245
225 let selected_ngit_relays = if has_server_and_relay_flags { 246 let selected_ngit_relays = if has_server_and_relay_flags {
226 // ignore so a script running `ngit init` can contiue without prompts 247 // ignore so a script running `ngit init` can contiue without prompts
227 vec![] 248 vec![]
@@ -261,13 +282,18 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
261 git_server_defaults.push(clone_url); 282 git_server_defaults.push(clone_url);
262 } 283 }
263 } 284 }
264 if args.clone_url.is_empty() { 285 if args.relays.is_empty() {
265 let relay_url = format_ngit_relay_url_as_relay_url(ngit_relay)?; 286 let relay_url = format_ngit_relay_url_as_relay_url(ngit_relay)?;
266 if !relay_defaults.contains(&relay_url) { 287 if !relay_defaults.contains(&relay_url) {
267 relay_defaults.push(relay_url); 288 relay_defaults.push(relay_url);
268 } 289 }
269 } 290 }
270 // TODO blossom 291 if args.blossoms.is_empty() {
292 let blossom = format_ngit_blossom_url_as_relay_url(ngit_relay)?;
293 if !blossoms_defaults.contains(&blossom) {
294 blossoms_defaults.push(blossom);
295 }
296 }
271 } 297 }
272 298
273 let no_state = if let Ok(Some(s)) = git_repo.get_git_config_item("nostr.nostate", None) { 299 let no_state = if let Ok(Some(s)) = git_repo.get_git_config_item("nostr.nostate", None) {
@@ -416,6 +442,33 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
416 } 442 }
417 }; 443 };
418 444
445 let blossoms: Vec<Url> = {
446 if simple_mode || has_server_and_relay_flags {
447 blossoms_defaults
448 .iter().filter_map(|b| Url::parse(b).ok()).collect()
449 } else {
450 let selections: Vec<bool> = vec![true; blossoms_defaults.len()];
451 if args.blossoms.is_empty() {
452 let selected = multi_select_with_custom_value(
453 "blossom servers",
454 "blossom server",
455 blossoms_defaults,
456 selections,
457 |s| {
458 Url::parse(s)
459 .map(|_| s.to_string())
460 .context(format!("Invalid blossom URL format: {s}"))
461 },
462 )?;
463 show_multi_input_prompt_success("nostr relays", &selected);
464 selected.iter().filter_map(|b| Url::parse(b).ok()).collect()
465 } else {
466 blossoms_defaults.iter().filter_map(|b| Url::parse(b).ok()).collect()
467 }
468 }
469 };
470
471
419 let default_maintainers = { 472 let default_maintainers = {
420 let mut maintainers = vec![user_ref.public_key]; 473 let mut maintainers = vec![user_ref.public_key];
421 if args.other_maintainers.is_empty() { 474 if args.other_maintainers.is_empty() {
@@ -593,6 +646,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
593 git_server, 646 git_server,
594 web, 647 web,
595 relays: relays.clone(), 648 relays: relays.clone(),
649 blossoms,
596 trusted_maintainer: user_ref.public_key, 650 trusted_maintainer: user_ref.public_key,
597 maintainers: maintainers.clone(), 651 maintainers: maintainers.clone(),
598 events: HashMap::new(), 652 events: HashMap::new(),
@@ -875,6 +929,14 @@ fn format_ngit_relay_url_as_relay_url(url:&str) -> Result<String> {
875 Ok(format!("wss://{ngit_relay_url}")) 929 Ok(format!("wss://{ngit_relay_url}"))
876} 930}
877 931
932fn format_ngit_blossom_url_as_relay_url(url:&str) -> Result<String> {
933 let ngit_relay_url = normalize_ngit_relay_url(url)?;
934 if ngit_relay_url.contains("http://") {
935 return Ok(ngit_relay_url.to_string())
936 }
937 Ok(format!("https://{ngit_relay_url}"))
938}
939
878fn extract_npub(s: &str) -> Result<&str> { 940fn extract_npub(s: &str) -> Result<&str> {
879 // Find the starting index of "npub1" 941 // Find the starting index of "npub1"
880 if let Some(start) = s.find("npub1") { 942 if let Some(start) = s.find("npub1") {
diff --git a/src/lib/repo_ref.rs b/src/lib/repo_ref.rs
index d37d7a9..1a0fe85 100644
--- a/src/lib/repo_ref.rs
+++ b/src/lib/repo_ref.rs
@@ -12,7 +12,7 @@ use nostr::{
12 FromBech32, PublicKey, Tag, TagStandard, ToBech32, 12 FromBech32, PublicKey, Tag, TagStandard, ToBech32,
13 nips::{nip01::Coordinate, nip19::Nip19Coordinate}, 13 nips::{nip01::Coordinate, nip19::Nip19Coordinate},
14}; 14};
15use nostr_sdk::{Kind, NostrSigner, RelayUrl, Timestamp}; 15use nostr_sdk::{Kind, NostrSigner, RelayUrl, Timestamp, Url};
16use serde::{Deserialize, Serialize}; 16use serde::{Deserialize, Serialize};
17 17
18#[cfg(not(test))] 18#[cfg(not(test))]
@@ -38,6 +38,7 @@ pub struct RepoRef {
38 pub git_server: Vec<String>, 38 pub git_server: Vec<String>,
39 pub web: Vec<String>, 39 pub web: Vec<String>,
40 pub relays: Vec<RelayUrl>, 40 pub relays: Vec<RelayUrl>,
41 pub blossoms: Vec<Url>,
41 pub maintainers: Vec<PublicKey>, 42 pub maintainers: Vec<PublicKey>,
42 pub trusted_maintainer: PublicKey, 43 pub trusted_maintainer: PublicKey,
43 pub events: HashMap<Nip19Coordinate, nostr::Event>, 44 pub events: HashMap<Nip19Coordinate, nostr::Event>,
@@ -61,6 +62,7 @@ impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef {
61 git_server: Vec::new(), 62 git_server: Vec::new(),
62 web: Vec::new(), 63 web: Vec::new(),
63 relays: Vec::new(), 64 relays: Vec::new(),
65 blossoms: Vec::new(),
64 maintainers: Vec::new(), 66 maintainers: Vec::new(),
65 trusted_maintainer: trusted_maintainer.unwrap_or(event.pubkey), 67 trusted_maintainer: trusted_maintainer.unwrap_or(event.pubkey),
66 events: HashMap::new(), 68 events: HashMap::new(),
@@ -100,6 +102,13 @@ impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef {
100 } 102 }
101 } 103 }
102 } 104 }
105 [t, blossoms @ ..] if t == "blossoms" => {
106 for b in blossoms {
107 if let Ok(b) = Url::parse(b) {
108 r.blossoms.push(b);
109 }
110 }
111 }
103 [t, maintainers @ ..] if t == "maintainers" => { 112 [t, maintainers @ ..] if t == "maintainers" => {
104 if !maintainers.contains(&event.pubkey.to_string()) { 113 if !maintainers.contains(&event.pubkey.to_string()) {
105 r.maintainers.push(event.pubkey); 114 r.maintainers.push(event.pubkey);
@@ -190,6 +199,14 @@ impl RepoRef {
190 vec![format!("git repository: {}", self.name.clone())], 199 vec![format!("git repository: {}", self.name.clone())],
191 ), 200 ),
192 ], 201 ],
202 if self.blossoms.is_empty() {
203 vec![]
204 } else {
205 vec![Tag::custom(
206 nostr::TagKind::Custom(std::borrow::Cow::Borrowed("blossoms")),
207 self.blossoms.iter().map(|r| r.to_string()),
208 )]
209 },
193 // code languages and hashtags 210 // code languages and hashtags
194 ] 211 ]
195 .concat(), 212 .concat(),
@@ -566,6 +583,7 @@ mod tests {
566 RelayUrl::parse("ws://relay1.io").unwrap(), 583 RelayUrl::parse("ws://relay1.io").unwrap(),
567 RelayUrl::parse("ws://relay2.io").unwrap(), 584 RelayUrl::parse("ws://relay2.io").unwrap(),
568 ], 585 ],
586 blossoms: vec![],
569 trusted_maintainer: TEST_KEY_1_KEYS.public_key(), 587 trusted_maintainer: TEST_KEY_1_KEYS.public_key(),
570 maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], 588 maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()],
571 events: HashMap::new(), 589 events: HashMap::new(),