diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-03 15:30:37 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-03 15:30:37 +0100 |
| commit | a825311f2c55661aaab3a163bda9109295c96044 (patch) | |
| tree | af56db8858187a540ae90c38998a5222c8cc1f01 /src | |
| parent | a0fdc17426afa0e55a2a3b733983bab763226e5a (diff) | |
feat(remote): enhance nostr url format
add protocol and user parameters so that users can overide the
protcol in the clone url and use specific protocols for
fetch and push. see:
nostr:nevent1qvzqqqqqqypzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqyxhwumn8ghj7mn0wvhxcmmvqqsp6a5ck6grd9lq0nu25dcfzggxde67erut76w0ucal5rcfq4y5gzc7gmpzm
the override feature hasn't been implemented yet but
this is an enabler.
also added a new format so that macos (zsh) users don't
have to use quotes:
nostr://<optional-protocol>/npub123/<optional-relay>/identifer
Diffstat (limited to 'src')
| -rw-r--r-- | src/git.rs | 145 | ||||
| -rw-r--r-- | src/git_remote_helper.rs | 267 | ||||
| -rw-r--r-- | src/repo_ref.rs | 6 |
3 files changed, 318 insertions, 100 deletions
| @@ -835,55 +835,128 @@ fn extract_sig_from_patch_tags<'a>( | |||
| 835 | .context("failed to create git signature") | 835 | .context("failed to create git signature") |
| 836 | } | 836 | } |
| 837 | 837 | ||
| 838 | pub fn nostr_git_url_to_repo_coordinates(url: &str) -> Result<HashSet<Coordinate>> { | 838 | #[derive(Debug, PartialEq)] |
| 839 | let mut repo_coordinattes = HashSet::new(); | 839 | pub enum ServerProtocol { |
| 840 | let url = Url::parse(url)?; | 840 | Ssh, |
| 841 | Https, | ||
| 842 | Http, | ||
| 843 | Git, | ||
| 844 | } | ||
| 841 | 845 | ||
| 842 | if url.scheme().ne("nostr") { | 846 | #[derive(Debug, PartialEq)] |
| 843 | bail!("nostr git url must start with nostr://") | 847 | pub struct NostrUrlDecoded { |
| 844 | } | 848 | pub coordinates: HashSet<Coordinate>, |
| 849 | pub protocol: Option<ServerProtocol>, | ||
| 850 | pub user: Option<String>, | ||
| 851 | } | ||
| 845 | 852 | ||
| 846 | if let Ok(coordinate) = Coordinate::parse(url.domain().context("no naddr")?) { | 853 | static INCORRECT_NOSTR_URL_FORMAT_ERROR: &str = "incorrect nostr git url format. try nostr://naddr123 or nostr://npub123/my-repo or nostr://ssh/npub123/relay.damus.io/my-repo"; |
| 847 | if coordinate.kind.eq(&nostr_sdk::Kind::GitRepoAnnouncement) { | 854 | |
| 848 | repo_coordinattes.insert(coordinate); | 855 | impl NostrUrlDecoded { |
| 849 | return Ok(repo_coordinattes); | 856 | pub fn from_str(url: &str) -> Result<Self> { |
| 857 | let mut coordinates = HashSet::new(); | ||
| 858 | let mut protocol = None; | ||
| 859 | let mut user = None; | ||
| 860 | let mut relays = vec![]; | ||
| 861 | |||
| 862 | if !url.starts_with("nostr://") { | ||
| 863 | bail!("nostr git url must start with nostr://"); | ||
| 864 | } | ||
| 865 | // process get url parameters if present | ||
| 866 | for (name, value) in Url::parse(url)?.query_pairs() { | ||
| 867 | if name.contains("relay") { | ||
| 868 | let mut decoded = urlencoding::decode(&value) | ||
| 869 | .context("could not parse relays in nostr git url")? | ||
| 870 | .to_string(); | ||
| 871 | if !decoded.starts_with("ws://") && !decoded.starts_with("wss://") { | ||
| 872 | decoded = format!("wss://{decoded}"); | ||
| 873 | } | ||
| 874 | let url = | ||
| 875 | Url::parse(&decoded).context("could not parse relays in nostr git url")?; | ||
| 876 | relays.push(url.to_string()); | ||
| 877 | } else if name == "protocol" { | ||
| 878 | protocol = match value.as_ref() { | ||
| 879 | "ssh" => Some(ServerProtocol::Ssh), | ||
| 880 | "https" => Some(ServerProtocol::Https), | ||
| 881 | "http" => Some(ServerProtocol::Http), | ||
| 882 | "git" => Some(ServerProtocol::Git), | ||
| 883 | _ => None, | ||
| 884 | }; | ||
| 885 | } else if name == "user" { | ||
| 886 | user = Some(value.to_string()); | ||
| 887 | } | ||
| 850 | } | 888 | } |
| 851 | bail!("naddr doesnt point to a git repository announcement"); | ||
| 852 | } | ||
| 853 | 889 | ||
| 854 | if let Some(domain) = url.domain() { | 890 | let mut parts: Vec<&str> = url[8..] |
| 855 | if let Ok(public_key) = PublicKey::parse(domain) { | 891 | .split('?') |
| 856 | if url.path().len() < 2 { | 892 | .next() |
| 857 | bail!( | 893 | .unwrap_or("") |
| 858 | "nostr git url should include the repo identifier eg nostr://npub123/the-repo-identifer" | 894 | .split('/') |
| 859 | ); | 895 | .collect(); |
| 896 | |||
| 897 | // extract optional protocol | ||
| 898 | if protocol.is_none() { | ||
| 899 | let part = parts.first().context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?; | ||
| 900 | let protocol_str = if let Some(at_index) = part.find('@') { | ||
| 901 | user = Some(part[..at_index].to_string()); | ||
| 902 | &part[at_index + 1..] | ||
| 903 | } else { | ||
| 904 | part | ||
| 905 | }; | ||
| 906 | protocol = match protocol_str { | ||
| 907 | "ssh" => Some(ServerProtocol::Ssh), | ||
| 908 | "https" => Some(ServerProtocol::Https), | ||
| 909 | "http" => Some(ServerProtocol::Http), | ||
| 910 | "git" => Some(ServerProtocol::Git), | ||
| 911 | _ => protocol, | ||
| 912 | }; | ||
| 913 | if protocol.is_some() { | ||
| 914 | parts.remove(0); | ||
| 860 | } | 915 | } |
| 861 | let mut relays = vec![]; | 916 | } |
| 862 | for (name, value) in url.query_pairs() { | 917 | // extract naddr npub/<optional-relays>/identifer |
| 863 | if name.contains("relay") { | 918 | let part = parts.first().context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?; |
| 864 | let mut decoded = urlencoding::decode(&value) | 919 | // naddr used |
| 865 | .context("could not parse relays in nostr git url")? | 920 | if let Ok(coordinate) = Coordinate::parse(part) { |
| 866 | .to_string(); | 921 | if coordinate.kind.eq(&nostr_sdk::Kind::GitRepoAnnouncement) { |
| 867 | if !decoded.starts_with("ws://") && !decoded.starts_with("wss://") { | 922 | coordinates.insert(coordinate); |
| 868 | decoded = format!("wss://{decoded}"); | 923 | } else { |
| 869 | } | 924 | bail!("naddr doesnt point to a git repository announcement"); |
| 870 | let url = | 925 | } |
| 871 | Url::parse(&decoded).context("could not parse relays in nostr git url")?; | 926 | // npub/<optional-relays>/identifer used |
| 872 | relays.push(url.to_string()); | 927 | } else if let Ok(public_key) = PublicKey::parse(part) { |
| 928 | parts.remove(0); | ||
| 929 | let identifier = parts | ||
| 930 | .pop() | ||
| 931 | .context("nostr url must have an identifier eg. nostr://npub123/repo-identifier")? | ||
| 932 | .to_string(); | ||
| 933 | for relay in parts { | ||
| 934 | let mut decoded = urlencoding::decode(relay) | ||
| 935 | .context("could not parse relays in nostr git url")? | ||
| 936 | .to_string(); | ||
| 937 | if !decoded.starts_with("ws://") && !decoded.starts_with("wss://") { | ||
| 938 | decoded = format!("wss://{decoded}"); | ||
| 873 | } | 939 | } |
| 940 | let url = | ||
| 941 | Url::parse(&decoded).context("could not parse relays in nostr git url")?; | ||
| 942 | relays.push(url.to_string()); | ||
| 874 | } | 943 | } |
| 875 | repo_coordinattes.insert(Coordinate { | 944 | coordinates.insert(Coordinate { |
| 876 | identifier: url.path()[1..].to_string(), | 945 | identifier, |
| 877 | public_key, | 946 | public_key, |
| 878 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | 947 | kind: nostr_sdk::Kind::GitRepoAnnouncement, |
| 879 | relays, | 948 | relays, |
| 880 | }); | 949 | }); |
| 881 | return Ok(repo_coordinattes); | 950 | } else { |
| 951 | bail!(INCORRECT_NOSTR_URL_FORMAT_ERROR); | ||
| 882 | } | 952 | } |
| 953 | |||
| 954 | Ok(Self { | ||
| 955 | coordinates, | ||
| 956 | protocol, | ||
| 957 | user, | ||
| 958 | }) | ||
| 883 | } | 959 | } |
| 884 | bail!( | ||
| 885 | "nostr git url must be in format nostr://naddr123 or nostr://npub123/identifer?relay=wss://relay-example.com&relay1=wss://relay-example.org" | ||
| 886 | ); | ||
| 887 | } | 960 | } |
| 888 | 961 | ||
| 889 | /** produce error when using local repo or custom protocols */ | 962 | /** produce error when using local repo or custom protocols */ |
diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs index d00ad0e..a5244bf 100644 --- a/src/git_remote_helper.rs +++ b/src/git_remote_helper.rs | |||
| @@ -19,7 +19,7 @@ use client::{ | |||
| 19 | get_state_from_cache, sign_event, Connect, STATE_KIND, | 19 | get_state_from_cache, sign_event, Connect, STATE_KIND, |
| 20 | }; | 20 | }; |
| 21 | use console::Term; | 21 | use console::Term; |
| 22 | use git::{nostr_git_url_to_repo_coordinates, sha1_to_oid, RepoActions}; | 22 | use git::{sha1_to_oid, NostrUrlDecoded, RepoActions}; |
| 23 | use git2::{Oid, Repository}; | 23 | use git2::{Oid, Repository}; |
| 24 | use nostr::nips::{nip01::Coordinate, nip10::Marker}; | 24 | use nostr::nips::{nip01::Coordinate, nip10::Marker}; |
| 25 | use nostr_sdk::{ | 25 | use nostr_sdk::{ |
| @@ -81,12 +81,12 @@ async fn main() -> Result<()> { | |||
| 81 | #[cfg(test)] | 81 | #[cfg(test)] |
| 82 | let client = <MockConnect as std::default::Default>::default(); | 82 | let client = <MockConnect as std::default::Default>::default(); |
| 83 | 83 | ||
| 84 | let repo_coordinates = | 84 | let decoded_nostr_url = |
| 85 | nostr_git_url_to_repo_coordinates(nostr_remote_url).context("invalid nostr url")?; | 85 | NostrUrlDecoded::from_str(nostr_remote_url).context("invalid nostr url")?; |
| 86 | 86 | ||
| 87 | fetching_with_report_for_helper(git_repo_path, &client, &repo_coordinates).await?; | 87 | fetching_with_report_for_helper(git_repo_path, &client, &decoded_nostr_url.coordinates).await?; |
| 88 | 88 | ||
| 89 | let repo_ref = get_repo_ref_from_cache(git_repo_path, &repo_coordinates).await?; | 89 | let repo_ref = get_repo_ref_from_cache(git_repo_path, &decoded_nostr_url.coordinates).await?; |
| 90 | 90 | ||
| 91 | let stdin = io::stdin(); | 91 | let stdin = io::stdin(); |
| 92 | let mut line = String::new(); | 92 | let mut line = String::new(); |
| @@ -1639,7 +1639,8 @@ impl RepoState { | |||
| 1639 | mod tests { | 1639 | mod tests { |
| 1640 | use super::*; | 1640 | use super::*; |
| 1641 | 1641 | ||
| 1642 | mod nostr_git_url_to_repo_coordinates { | 1642 | mod nostr_git_url_paramemters_from_str { |
| 1643 | use git::ServerProtocol; | ||
| 1643 | use nostr_sdk::PublicKey; | 1644 | use nostr_sdk::PublicKey; |
| 1644 | 1645 | ||
| 1645 | use super::*; | 1646 | use super::*; |
| @@ -1663,79 +1664,223 @@ mod tests { | |||
| 1663 | #[test] | 1664 | #[test] |
| 1664 | fn from_naddr() -> Result<()> { | 1665 | fn from_naddr() -> Result<()> { |
| 1665 | assert_eq!( | 1666 | assert_eq!( |
| 1666 | nostr_git_url_to_repo_coordinates( | 1667 | NostrUrlDecoded::from_str( |
| 1667 | "nostr://naddr1qqzxuemfwsqs6amnwvaz7tmwdaejumr0dspzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqvzqqqrhnym0k2qj" | 1668 | "nostr://naddr1qqzxuemfwsqs6amnwvaz7tmwdaejumr0dspzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqvzqqqrhnym0k2qj" |
| 1668 | )?, | 1669 | )?, |
| 1669 | HashSet::from([Coordinate { | 1670 | NostrUrlDecoded { |
| 1670 | identifier: "ngit".to_string(), | 1671 | coordinates: HashSet::from([Coordinate { |
| 1671 | public_key: PublicKey::parse( | 1672 | identifier: "ngit".to_string(), |
| 1672 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", | 1673 | public_key: PublicKey::parse( |
| 1673 | ) | 1674 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", |
| 1674 | .unwrap(), | 1675 | ) |
| 1675 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | 1676 | .unwrap(), |
| 1676 | relays: vec!["wss://nos.lol".to_string()], // wont add the slash | 1677 | kind: nostr_sdk::Kind::GitRepoAnnouncement, |
| 1677 | }]), | 1678 | relays: vec!["wss://nos.lol".to_string()], // wont add the slash |
| 1679 | }]), | ||
| 1680 | protocol: None, | ||
| 1681 | user: None, | ||
| 1682 | }, | ||
| 1678 | ); | 1683 | ); |
| 1679 | Ok(()) | 1684 | Ok(()) |
| 1680 | } | 1685 | } |
| 1681 | mod from_npub_slah_identifier { | 1686 | mod from_npub_slash_identifier { |
| 1682 | use super::*; | 1687 | use super::*; |
| 1683 | 1688 | ||
| 1684 | #[test] | 1689 | #[test] |
| 1685 | fn without_relay() -> Result<()> { | 1690 | fn without_relay() -> Result<()> { |
| 1686 | assert_eq!( | 1691 | assert_eq!( |
| 1687 | nostr_git_url_to_repo_coordinates( | 1692 | NostrUrlDecoded::from_str( |
| 1688 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit" | 1693 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit" |
| 1689 | )?, | 1694 | )?, |
| 1690 | HashSet::from([get_model_coordinate(false)]), | 1695 | NostrUrlDecoded { |
| 1696 | coordinates: HashSet::from([get_model_coordinate(false)]), | ||
| 1697 | protocol: None, | ||
| 1698 | user: None, | ||
| 1699 | }, | ||
| 1691 | ); | 1700 | ); |
| 1692 | Ok(()) | 1701 | Ok(()) |
| 1693 | } | 1702 | } |
| 1694 | 1703 | ||
| 1695 | #[test] | 1704 | mod with_url_parameters { |
| 1696 | fn with_relay_without_scheme_defaults_to_wss() -> Result<()> { | 1705 | |
| 1697 | assert_eq!( | 1706 | use super::*; |
| 1698 | nostr_git_url_to_repo_coordinates( | 1707 | |
| 1699 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay=nos.lol" | 1708 | #[test] |
| 1700 | )?, | 1709 | fn with_relay_without_scheme_defaults_to_wss() -> Result<()> { |
| 1701 | HashSet::from([get_model_coordinate(true)]), | 1710 | assert_eq!( |
| 1702 | ); | 1711 | NostrUrlDecoded::from_str( |
| 1703 | Ok(()) | 1712 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay=nos.lol" |
| 1704 | } | 1713 | )?, |
| 1714 | NostrUrlDecoded { | ||
| 1715 | coordinates: HashSet::from([get_model_coordinate(true)]), | ||
| 1716 | protocol: None, | ||
| 1717 | user: None, | ||
| 1718 | }, | ||
| 1719 | ); | ||
| 1720 | Ok(()) | ||
| 1721 | } | ||
| 1705 | 1722 | ||
| 1706 | #[test] | 1723 | #[test] |
| 1707 | fn with_encoded_relay() -> Result<()> { | 1724 | fn with_encoded_relay() -> Result<()> { |
| 1708 | assert_eq!( | 1725 | assert_eq!( |
| 1709 | nostr_git_url_to_repo_coordinates(&format!( | 1726 | NostrUrlDecoded::from_str(&format!( |
| 1710 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay={}", | 1727 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay={}", |
| 1711 | urlencoding::encode("wss://nos.lol") | 1728 | urlencoding::encode("wss://nos.lol") |
| 1712 | ))?, | 1729 | ))?, |
| 1713 | HashSet::from([get_model_coordinate(true)]), | 1730 | NostrUrlDecoded { |
| 1714 | ); | 1731 | coordinates: HashSet::from([get_model_coordinate(true)]), |
| 1715 | Ok(()) | 1732 | protocol: None, |
| 1733 | user: None, | ||
| 1734 | }, | ||
| 1735 | ); | ||
| 1736 | Ok(()) | ||
| 1737 | } | ||
| 1738 | #[test] | ||
| 1739 | fn with_multiple_encoded_relays() -> Result<()> { | ||
| 1740 | assert_eq!( | ||
| 1741 | NostrUrlDecoded::from_str(&format!( | ||
| 1742 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay={}&relay1={}", | ||
| 1743 | urlencoding::encode("wss://nos.lol"), | ||
| 1744 | urlencoding::encode("wss://relay.damus.io"), | ||
| 1745 | ))?, | ||
| 1746 | NostrUrlDecoded { | ||
| 1747 | coordinates: HashSet::from([Coordinate { | ||
| 1748 | identifier: "ngit".to_string(), | ||
| 1749 | public_key: PublicKey::parse( | ||
| 1750 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", | ||
| 1751 | ) | ||
| 1752 | .unwrap(), | ||
| 1753 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | ||
| 1754 | relays: vec![ | ||
| 1755 | "wss://nos.lol/".to_string(), | ||
| 1756 | "wss://relay.damus.io/".to_string(), | ||
| 1757 | ], | ||
| 1758 | }]), | ||
| 1759 | protocol: None, | ||
| 1760 | user: None, | ||
| 1761 | }, | ||
| 1762 | ); | ||
| 1763 | Ok(()) | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | #[test] | ||
| 1767 | fn with_server_protocol() -> Result<()> { | ||
| 1768 | assert_eq!( | ||
| 1769 | NostrUrlDecoded::from_str( | ||
| 1770 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?protocol=ssh" | ||
| 1771 | )?, | ||
| 1772 | NostrUrlDecoded { | ||
| 1773 | coordinates: HashSet::from([get_model_coordinate(false)]), | ||
| 1774 | protocol: Some(ServerProtocol::Ssh), | ||
| 1775 | user: None, | ||
| 1776 | }, | ||
| 1777 | ); | ||
| 1778 | Ok(()) | ||
| 1779 | } | ||
| 1780 | #[test] | ||
| 1781 | fn with_server_protocol_and_user() -> Result<()> { | ||
| 1782 | assert_eq!( | ||
| 1783 | NostrUrlDecoded::from_str( | ||
| 1784 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?protocol=ssh&user=fred" | ||
| 1785 | )?, | ||
| 1786 | NostrUrlDecoded { | ||
| 1787 | coordinates: HashSet::from([get_model_coordinate(false)]), | ||
| 1788 | protocol: Some(ServerProtocol::Ssh), | ||
| 1789 | user: Some("fred".to_string()), | ||
| 1790 | }, | ||
| 1791 | ); | ||
| 1792 | Ok(()) | ||
| 1793 | } | ||
| 1716 | } | 1794 | } |
| 1717 | #[test] | 1795 | mod with_parameters_embedded_with_slashes { |
| 1718 | fn with_multiple_encoded_relays() -> Result<()> { | 1796 | use super::*; |
| 1719 | assert_eq!( | 1797 | |
| 1720 | nostr_git_url_to_repo_coordinates(&format!( | 1798 | #[test] |
| 1721 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay={}&relay1={}", | 1799 | fn with_relay_without_scheme_defaults_to_wss() -> Result<()> { |
| 1722 | urlencoding::encode("wss://nos.lol"), | 1800 | assert_eq!( |
| 1723 | urlencoding::encode("wss://relay.damus.io"), | 1801 | NostrUrlDecoded::from_str( |
| 1724 | ))?, | 1802 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit" |
| 1725 | HashSet::from([Coordinate { | 1803 | )?, |
| 1726 | identifier: "ngit".to_string(), | 1804 | NostrUrlDecoded { |
| 1727 | public_key: PublicKey::parse( | 1805 | coordinates: HashSet::from([get_model_coordinate(true)]), |
| 1728 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", | 1806 | protocol: None, |
| 1729 | ) | 1807 | user: None, |
| 1730 | .unwrap(), | 1808 | }, |
| 1731 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | 1809 | ); |
| 1732 | relays: vec![ | 1810 | Ok(()) |
| 1733 | "wss://nos.lol/".to_string(), | 1811 | } |
| 1734 | "wss://relay.damus.io/".to_string(), | 1812 | |
| 1735 | ], | 1813 | #[test] |
| 1736 | }]), | 1814 | fn with_encoded_relay() -> Result<()> { |
| 1737 | ); | 1815 | assert_eq!( |
| 1738 | Ok(()) | 1816 | NostrUrlDecoded::from_str(&format!( |
| 1817 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/{}/ngit", | ||
| 1818 | urlencoding::encode("wss://nos.lol") | ||
| 1819 | ))?, | ||
| 1820 | NostrUrlDecoded { | ||
| 1821 | coordinates: HashSet::from([get_model_coordinate(true)]), | ||
| 1822 | protocol: None, | ||
| 1823 | user: None, | ||
| 1824 | }, | ||
| 1825 | ); | ||
| 1826 | Ok(()) | ||
| 1827 | } | ||
| 1828 | #[test] | ||
| 1829 | fn with_multiple_encoded_relays() -> Result<()> { | ||
| 1830 | assert_eq!( | ||
| 1831 | NostrUrlDecoded::from_str(&format!( | ||
| 1832 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/{}/{}/ngit", | ||
| 1833 | urlencoding::encode("wss://nos.lol"), | ||
| 1834 | urlencoding::encode("wss://relay.damus.io"), | ||
| 1835 | ))?, | ||
| 1836 | NostrUrlDecoded { | ||
| 1837 | coordinates: HashSet::from([Coordinate { | ||
| 1838 | identifier: "ngit".to_string(), | ||
| 1839 | public_key: PublicKey::parse( | ||
| 1840 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", | ||
| 1841 | ) | ||
| 1842 | .unwrap(), | ||
| 1843 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | ||
| 1844 | relays: vec![ | ||
| 1845 | "wss://nos.lol/".to_string(), | ||
| 1846 | "wss://relay.damus.io/".to_string(), | ||
| 1847 | ], | ||
| 1848 | }]), | ||
| 1849 | protocol: None, | ||
| 1850 | user: None, | ||
| 1851 | }, | ||
| 1852 | ); | ||
| 1853 | Ok(()) | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | #[test] | ||
| 1857 | fn with_server_protocol() -> Result<()> { | ||
| 1858 | assert_eq!( | ||
| 1859 | NostrUrlDecoded::from_str( | ||
| 1860 | "nostr://ssh/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit" | ||
| 1861 | )?, | ||
| 1862 | NostrUrlDecoded { | ||
| 1863 | coordinates: HashSet::from([get_model_coordinate(false)]), | ||
| 1864 | protocol: Some(ServerProtocol::Ssh), | ||
| 1865 | user: None, | ||
| 1866 | }, | ||
| 1867 | ); | ||
| 1868 | Ok(()) | ||
| 1869 | } | ||
| 1870 | #[test] | ||
| 1871 | fn with_server_protocol_and_user() -> Result<()> { | ||
| 1872 | assert_eq!( | ||
| 1873 | NostrUrlDecoded::from_str( | ||
| 1874 | "nostr://fred@ssh/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit" | ||
| 1875 | )?, | ||
| 1876 | NostrUrlDecoded { | ||
| 1877 | coordinates: HashSet::from([get_model_coordinate(false)]), | ||
| 1878 | protocol: Some(ServerProtocol::Ssh), | ||
| 1879 | user: Some("fred".to_string()), | ||
| 1880 | }, | ||
| 1881 | ); | ||
| 1882 | Ok(()) | ||
| 1883 | } | ||
| 1739 | } | 1884 | } |
| 1740 | } | 1885 | } |
| 1741 | } | 1886 | } |
diff --git a/src/repo_ref.rs b/src/repo_ref.rs index 94af864..0e57d96 100644 --- a/src/repo_ref.rs +++ b/src/repo_ref.rs | |||
| @@ -16,7 +16,7 @@ use crate::client::Client; | |||
| 16 | use crate::{ | 16 | use crate::{ |
| 17 | cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, | 17 | cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, |
| 18 | client::{get_event_from_global_cache, get_events_from_cache, sign_event, Connect}, | 18 | client::{get_event_from_global_cache, get_events_from_cache, sign_event, Connect}, |
| 19 | git::{nostr_git_url_to_repo_coordinates, Repo, RepoActions}, | 19 | git::{NostrUrlDecoded, Repo, RepoActions}, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | #[derive(Default)] | 22 | #[derive(Default)] |
| @@ -263,8 +263,8 @@ fn get_repo_coordinates_from_nostr_remotes(git_repo: &Repo) -> Result<HashSet<Co | |||
| 263 | let mut repo_coordinates = HashSet::new(); | 263 | let mut repo_coordinates = HashSet::new(); |
| 264 | for remote_name in git_repo.git_repo.remotes()?.iter().flatten() { | 264 | for remote_name in git_repo.git_repo.remotes()?.iter().flatten() { |
| 265 | if let Some(remote_url) = git_repo.git_repo.find_remote(remote_name)?.url() { | 265 | if let Some(remote_url) = git_repo.git_repo.find_remote(remote_name)?.url() { |
| 266 | if let Ok(coordinates) = nostr_git_url_to_repo_coordinates(remote_url) { | 266 | if let Ok(nostr_url_decoded) = NostrUrlDecoded::from_str(remote_url) { |
| 267 | for c in coordinates { | 267 | for c in nostr_url_decoded.coordinates { |
| 268 | repo_coordinates.insert(c); | 268 | repo_coordinates.insert(c); |
| 269 | } | 269 | } |
| 270 | } | 270 | } |