diff options
Diffstat (limited to 'src/lib/repo_ref.rs')
| -rw-r--r-- | src/lib/repo_ref.rs | 87 |
1 files changed, 82 insertions, 5 deletions
diff --git a/src/lib/repo_ref.rs b/src/lib/repo_ref.rs index bca4a3b..b2bd381 100644 --- a/src/lib/repo_ref.rs +++ b/src/lib/repo_ref.rs | |||
| @@ -40,6 +40,7 @@ pub struct RepoRef { | |||
| 40 | pub web: Vec<String>, | 40 | pub web: Vec<String>, |
| 41 | pub relays: Vec<RelayUrl>, | 41 | pub relays: Vec<RelayUrl>, |
| 42 | pub blossoms: Vec<Url>, | 42 | pub blossoms: Vec<Url>, |
| 43 | pub hashtags: Vec<String>, | ||
| 43 | pub maintainers: Vec<PublicKey>, | 44 | pub maintainers: Vec<PublicKey>, |
| 44 | pub trusted_maintainer: PublicKey, | 45 | pub trusted_maintainer: PublicKey, |
| 45 | // set to None if not known | 46 | // set to None if not known |
| @@ -71,6 +72,7 @@ impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef { | |||
| 71 | web: Vec::new(), | 72 | web: Vec::new(), |
| 72 | relays: Vec::new(), | 73 | relays: Vec::new(), |
| 73 | blossoms: Vec::new(), | 74 | blossoms: Vec::new(), |
| 75 | hashtags: Vec::new(), | ||
| 74 | maintainers: Vec::new(), | 76 | maintainers: Vec::new(), |
| 75 | trusted_maintainer: trusted_maintainer.unwrap_or(event.pubkey), | 77 | trusted_maintainer: trusted_maintainer.unwrap_or(event.pubkey), |
| 76 | maintainers_without_annoucnement: None, | 78 | maintainers_without_annoucnement: None, |
| @@ -118,6 +120,7 @@ impl TryFrom<(nostr::Event, Option<PublicKey>)> for RepoRef { | |||
| 118 | } | 120 | } |
| 119 | } | 121 | } |
| 120 | } | 122 | } |
| 123 | [t, hashtag, ..] if t == "t" => r.hashtags.push(hashtag.clone()), | ||
| 121 | [t, blossoms @ ..] if t == "blossoms" => { | 124 | [t, blossoms @ ..] if t == "blossoms" => { |
| 122 | for b in blossoms { | 125 | for b in blossoms { |
| 123 | if let Ok(b) = Url::parse(b) { | 126 | if let Ok(b) = Url::parse(b) { |
| @@ -217,6 +220,15 @@ impl RepoRef { | |||
| 217 | vec![format!("git repository: {}", self.name.clone())], | 220 | vec![format!("git repository: {}", self.name.clone())], |
| 218 | ), | 221 | ), |
| 219 | ], | 222 | ], |
| 223 | self.hashtags | ||
| 224 | .iter() | ||
| 225 | .map(|h| { | ||
| 226 | Tag::custom( | ||
| 227 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("t")), | ||
| 228 | vec![h.clone()], | ||
| 229 | ) | ||
| 230 | }) | ||
| 231 | .collect(), | ||
| 220 | if self.blossoms.is_empty() { | 232 | if self.blossoms.is_empty() { |
| 221 | vec![] | 233 | vec![] |
| 222 | } else { | 234 | } else { |
| @@ -311,6 +323,29 @@ impl RepoRef { | |||
| 311 | pub fn grasp_servers(&self) -> Vec<String> { | 323 | pub fn grasp_servers(&self) -> Vec<String> { |
| 312 | detect_existing_grasp_servers(Some(self), &[], &[], &self.identifier) | 324 | detect_existing_grasp_servers(Some(self), &[], &[], &self.identifier) |
| 313 | } | 325 | } |
| 326 | |||
| 327 | // returns false if already present so didn't need adding | ||
| 328 | pub fn add_grasp_server(&mut self, clone_url: &str) -> Result<bool> { | ||
| 329 | if !is_grasp_server_clone_url(clone_url) { | ||
| 330 | bail!("invalid grasp server clone url. does not end with .git"); | ||
| 331 | } | ||
| 332 | |||
| 333 | let relay_url = RelayUrl::parse( | ||
| 334 | &format_grasp_server_url_as_relay_url(clone_url) | ||
| 335 | .context("invalid grasp server clone url")?, | ||
| 336 | ) | ||
| 337 | .context("invalid grasp server clone url")?; | ||
| 338 | |||
| 339 | if !self.relays.contains(&relay_url) { | ||
| 340 | self.relays.push(relay_url); | ||
| 341 | } | ||
| 342 | if !self.git_server.contains(&clone_url.to_string()) { | ||
| 343 | self.git_server.push(clone_url.to_string()); | ||
| 344 | Ok(true) | ||
| 345 | } else { | ||
| 346 | Ok(false) | ||
| 347 | } | ||
| 348 | } | ||
| 314 | } | 349 | } |
| 315 | 350 | ||
| 316 | pub async fn get_repo_coordinates_when_remote_unknown( | 351 | pub async fn get_repo_coordinates_when_remote_unknown( |
| @@ -448,7 +483,7 @@ async fn get_repo_coordinate_from_user_prompt( | |||
| 448 | println!( | 483 | println!( |
| 449 | "{}", | 484 | "{}", |
| 450 | dim.apply_to( | 485 | dim.apply_to( |
| 451 | "hint: https://gitworkshop.dev/repos lists repositories and their nostr address" | 486 | "hint: https://gitworkshop.dev/search lists repositories and their nostr address" |
| 452 | ), | 487 | ), |
| 453 | ); | 488 | ); |
| 454 | let git_repo_path = git_repo.get_path()?; | 489 | let git_repo_path = git_repo.get_path()?; |
| @@ -699,13 +734,54 @@ pub fn extract_npub(s: &str) -> Result<&str> { | |||
| 699 | } | 734 | } |
| 700 | } | 735 | } |
| 701 | 736 | ||
| 702 | pub fn is_grasp_server(url: &str, grasp_servers: &[String]) -> bool { | 737 | pub fn is_grasp_server_in_list(url: &str, grasp_servers: &[String]) -> bool { |
| 703 | if !grasp_servers.is_empty() { | 738 | if !grasp_servers.is_empty() { |
| 704 | if let Ok(n) = normalize_grasp_server_url(url) { | 739 | if let Ok(url) = normalize_grasp_server_url(url) { |
| 705 | return grasp_servers.contains(&n); | 740 | grasp_servers.iter().any(|s| { |
| 741 | if let Ok(s) = normalize_grasp_server_url(s) { | ||
| 742 | s == url | ||
| 743 | } else { | ||
| 744 | false | ||
| 745 | } | ||
| 746 | }) | ||
| 747 | } else { | ||
| 748 | false | ||
| 706 | } | 749 | } |
| 750 | } else { | ||
| 751 | false | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 755 | pub fn is_grasp_server_clone_url(url: &str) -> bool { | ||
| 756 | extract_npub(url).is_ok() | ||
| 757 | && (url.ends_with(".git") || url.ends_with(".git/")) | ||
| 758 | && url.starts_with("http") | ||
| 759 | } | ||
| 760 | |||
| 761 | pub fn format_grasp_server_url_as_relay_url(url: &str) -> Result<String> { | ||
| 762 | let grasp_server_url = normalize_grasp_server_url(url)?; | ||
| 763 | if grasp_server_url.contains("http://") { | ||
| 764 | return Ok(grasp_server_url.replace("http://", "ws://")); | ||
| 707 | } | 765 | } |
| 708 | false | 766 | Ok(format!("wss://{grasp_server_url}")) |
| 767 | } | ||
| 768 | |||
| 769 | pub fn format_grasp_server_url_as_clone_url( | ||
| 770 | grasp_server: &str, | ||
| 771 | public_key: &PublicKey, | ||
| 772 | identifier: &str, | ||
| 773 | ) -> Result<String> { | ||
| 774 | let grasp_server_url = normalize_grasp_server_url(grasp_server)?; | ||
| 775 | |||
| 776 | let prefix = if grasp_server_url.contains("http://") { | ||
| 777 | "" | ||
| 778 | } else { | ||
| 779 | "https://" | ||
| 780 | }; | ||
| 781 | Ok(format!( | ||
| 782 | "{prefix}{grasp_server_url}/{}/{identifier}.git", | ||
| 783 | public_key.to_bech32()? | ||
| 784 | )) | ||
| 709 | } | 785 | } |
| 710 | 786 | ||
| 711 | #[cfg(test)] | 787 | #[cfg(test)] |
| @@ -730,6 +806,7 @@ mod tests { | |||
| 730 | RelayUrl::parse("ws://relay2.io").unwrap(), | 806 | RelayUrl::parse("ws://relay2.io").unwrap(), |
| 731 | ], | 807 | ], |
| 732 | blossoms: vec![], | 808 | blossoms: vec![], |
| 809 | hashtags: vec![], | ||
| 733 | trusted_maintainer: TEST_KEY_1_KEYS.public_key(), | 810 | trusted_maintainer: TEST_KEY_1_KEYS.public_key(), |
| 734 | maintainers_without_annoucnement: None, | 811 | maintainers_without_annoucnement: None, |
| 735 | maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], | 812 | maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], |