diff options
Diffstat (limited to 'src/bin/git_remote_nostr/main.rs')
| -rw-r--r-- | src/bin/git_remote_nostr/main.rs | 307 |
1 files changed, 22 insertions, 285 deletions
diff --git a/src/bin/git_remote_nostr/main.rs b/src/bin/git_remote_nostr/main.rs index a5244bf..3e08efe 100644 --- a/src/bin/git_remote_nostr/main.rs +++ b/src/bin/git_remote_nostr/main.rs | |||
| @@ -15,12 +15,19 @@ use std::{ | |||
| 15 | use anyhow::{anyhow, bail, Context, Result}; | 15 | use anyhow::{anyhow, bail, Context, Result}; |
| 16 | use auth_git2::GitAuthenticator; | 16 | use auth_git2::GitAuthenticator; |
| 17 | use client::{ | 17 | use client::{ |
| 18 | consolidate_fetch_reports, get_events_from_cache, get_repo_ref_from_cache, | 18 | consolidate_fetch_reports, get_all_proposal_patch_events_from_cache, get_events_from_cache, |
| 19 | get_state_from_cache, sign_event, Connect, STATE_KIND, | 19 | get_proposals_and_revisions_from_cache, get_repo_ref_from_cache, get_state_from_cache, |
| 20 | send_events, sign_event, Connect, STATE_KIND, | ||
| 20 | }; | 21 | }; |
| 21 | use console::Term; | 22 | use console::Term; |
| 22 | use git::{sha1_to_oid, NostrUrlDecoded, RepoActions}; | 23 | use git::{nostr_url::NostrUrlDecoded, sha1_to_oid, RepoActions}; |
| 23 | use git2::{Oid, Repository}; | 24 | use git2::{Oid, Repository}; |
| 25 | use git_events::{ | ||
| 26 | event_is_revision_root, event_to_cover_letter, generate_cover_letter_and_patch_events, | ||
| 27 | generate_patch_event, get_commit_id_from_patch, get_most_recent_patch_with_ancestors, | ||
| 28 | status_kinds, tag_value, | ||
| 29 | }; | ||
| 30 | use ngit::{client, git, git_events, login, repo_ref, repo_state}; | ||
| 24 | use nostr::nips::{nip01::Coordinate, nip10::Marker}; | 31 | use nostr::nips::{nip01::Coordinate, nip10::Marker}; |
| 25 | use nostr_sdk::{ | 32 | use nostr_sdk::{ |
| 26 | hashes::sha1::Hash as Sha1Hash, Event, EventBuilder, EventId, Kind, PublicKey, Tag, Url, | 33 | hashes::sha1::Hash as Sha1Hash, Event, EventBuilder, EventId, Kind, PublicKey, Tag, Url, |
| @@ -28,34 +35,8 @@ use nostr_sdk::{ | |||
| 28 | use nostr_signer::NostrSigner; | 35 | use nostr_signer::NostrSigner; |
| 29 | use repo_ref::RepoRef; | 36 | use repo_ref::RepoRef; |
| 30 | use repo_state::RepoState; | 37 | use repo_state::RepoState; |
| 31 | use sub_commands::{ | ||
| 32 | list::{ | ||
| 33 | get_all_proposal_patch_events_from_cache, get_commit_id_from_patch, | ||
| 34 | get_most_recent_patch_with_ancestors, get_proposals_and_revisions_from_cache, status_kinds, | ||
| 35 | tag_value, | ||
| 36 | }, | ||
| 37 | send::{ | ||
| 38 | event_is_revision_root, event_to_cover_letter, generate_cover_letter_and_patch_events, | ||
| 39 | generate_patch_event, send_events, | ||
| 40 | }, | ||
| 41 | }; | ||
| 42 | 38 | ||
| 43 | #[cfg(not(test))] | 39 | use crate::{client::Client, git::Repo}; |
| 44 | use crate::client::Client; | ||
| 45 | #[cfg(test)] | ||
| 46 | use crate::client::MockConnect; | ||
| 47 | use crate::git::Repo; | ||
| 48 | |||
| 49 | mod cli; | ||
| 50 | mod cli_interactor; | ||
| 51 | mod client; | ||
| 52 | mod config; | ||
| 53 | mod git; | ||
| 54 | mod key_handling; | ||
| 55 | mod login; | ||
| 56 | mod repo_ref; | ||
| 57 | mod repo_state; | ||
| 58 | mod sub_commands; | ||
| 59 | 40 | ||
| 60 | #[tokio::main] | 41 | #[tokio::main] |
| 61 | async fn main() -> Result<()> { | 42 | async fn main() -> Result<()> { |
| @@ -76,10 +57,7 @@ async fn main() -> Result<()> { | |||
| 76 | ))?; | 57 | ))?; |
| 77 | let git_repo_path = git_repo.get_path()?; | 58 | let git_repo_path = git_repo.get_path()?; |
| 78 | 59 | ||
| 79 | #[cfg(not(test))] | ||
| 80 | let client = Client::default(); | 60 | let client = Client::default(); |
| 81 | #[cfg(test)] | ||
| 82 | let client = <MockConnect as std::default::Default>::default(); | ||
| 83 | 61 | ||
| 84 | let decoded_nostr_url = | 62 | let decoded_nostr_url = |
| 85 | NostrUrlDecoded::from_str(nostr_remote_url).context("invalid nostr url")?; | 63 | NostrUrlDecoded::from_str(nostr_remote_url).context("invalid nostr url")?; |
| @@ -155,8 +133,7 @@ pub(crate) fn read_line<'a>(stdin: &io::Stdin, line: &'a mut String) -> io::Resu | |||
| 155 | 133 | ||
| 156 | async fn fetching_with_report_for_helper( | 134 | async fn fetching_with_report_for_helper( |
| 157 | git_repo_path: &Path, | 135 | git_repo_path: &Path, |
| 158 | #[cfg(test)] client: &crate::client::MockConnect, | 136 | client: &Client, |
| 159 | #[cfg(not(test))] client: &Client, | ||
| 160 | repo_coordinates: &HashSet<Coordinate>, | 137 | repo_coordinates: &HashSet<Coordinate>, |
| 161 | ) -> Result<()> { | 138 | ) -> Result<()> { |
| 162 | let term = console::Term::stderr(); | 139 | let term = console::Term::stderr(); |
| @@ -662,8 +639,7 @@ async fn push( | |||
| 662 | nostr_remote_url: &str, | 639 | nostr_remote_url: &str, |
| 663 | stdin: &Stdin, | 640 | stdin: &Stdin, |
| 664 | initial_refspec: &str, | 641 | initial_refspec: &str, |
| 665 | #[cfg(test)] client: &crate::client::MockConnect, | 642 | client: &Client, |
| 666 | #[cfg(not(test))] client: &Client, | ||
| 667 | list_outputs: Option<HashMap<String, HashMap<String, String>>>, | 643 | list_outputs: Option<HashMap<String, HashMap<String, String>>>, |
| 668 | ) -> Result<()> { | 644 | ) -> Result<()> { |
| 669 | let refspecs = get_refspecs_from_push_batch(stdin, initial_refspec)?; | 645 | let refspecs = get_refspecs_from_push_batch(stdin, initial_refspec)?; |
| @@ -1613,8 +1589,15 @@ fn get_refspecs_from_push_batch(stdin: &Stdin, initial_refspec: &str) -> Result< | |||
| 1613 | Ok(refspecs) | 1589 | Ok(refspecs) |
| 1614 | } | 1590 | } |
| 1615 | 1591 | ||
| 1616 | impl RepoState { | 1592 | trait BuildRepoState { |
| 1617 | pub async fn build( | 1593 | async fn build( |
| 1594 | identifier: String, | ||
| 1595 | state: HashMap<String, String>, | ||
| 1596 | signer: &NostrSigner, | ||
| 1597 | ) -> Result<RepoState>; | ||
| 1598 | } | ||
| 1599 | impl BuildRepoState for RepoState { | ||
| 1600 | async fn build( | ||
| 1618 | identifier: String, | 1601 | identifier: String, |
| 1619 | state: HashMap<String, String>, | 1602 | state: HashMap<String, String>, |
| 1620 | signer: &NostrSigner, | 1603 | signer: &NostrSigner, |
| @@ -1639,252 +1622,6 @@ impl RepoState { | |||
| 1639 | mod tests { | 1622 | mod tests { |
| 1640 | use super::*; | 1623 | use super::*; |
| 1641 | 1624 | ||
| 1642 | mod nostr_git_url_paramemters_from_str { | ||
| 1643 | use git::ServerProtocol; | ||
| 1644 | use nostr_sdk::PublicKey; | ||
| 1645 | |||
| 1646 | use super::*; | ||
| 1647 | |||
| 1648 | fn get_model_coordinate(relays: bool) -> Coordinate { | ||
| 1649 | Coordinate { | ||
| 1650 | identifier: "ngit".to_string(), | ||
| 1651 | public_key: PublicKey::parse( | ||
| 1652 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", | ||
| 1653 | ) | ||
| 1654 | .unwrap(), | ||
| 1655 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | ||
| 1656 | relays: if relays { | ||
| 1657 | vec!["wss://nos.lol/".to_string()] | ||
| 1658 | } else { | ||
| 1659 | vec![] | ||
| 1660 | }, | ||
| 1661 | } | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | #[test] | ||
| 1665 | fn from_naddr() -> Result<()> { | ||
| 1666 | assert_eq!( | ||
| 1667 | NostrUrlDecoded::from_str( | ||
| 1668 | "nostr://naddr1qqzxuemfwsqs6amnwvaz7tmwdaejumr0dspzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqvzqqqrhnym0k2qj" | ||
| 1669 | )?, | ||
| 1670 | NostrUrlDecoded { | ||
| 1671 | coordinates: HashSet::from([Coordinate { | ||
| 1672 | identifier: "ngit".to_string(), | ||
| 1673 | public_key: PublicKey::parse( | ||
| 1674 | "npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr", | ||
| 1675 | ) | ||
| 1676 | .unwrap(), | ||
| 1677 | kind: nostr_sdk::Kind::GitRepoAnnouncement, | ||
| 1678 | relays: vec!["wss://nos.lol".to_string()], // wont add the slash | ||
| 1679 | }]), | ||
| 1680 | protocol: None, | ||
| 1681 | user: None, | ||
| 1682 | }, | ||
| 1683 | ); | ||
| 1684 | Ok(()) | ||
| 1685 | } | ||
| 1686 | mod from_npub_slash_identifier { | ||
| 1687 | use super::*; | ||
| 1688 | |||
| 1689 | #[test] | ||
| 1690 | fn without_relay() -> Result<()> { | ||
| 1691 | assert_eq!( | ||
| 1692 | NostrUrlDecoded::from_str( | ||
| 1693 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit" | ||
| 1694 | )?, | ||
| 1695 | NostrUrlDecoded { | ||
| 1696 | coordinates: HashSet::from([get_model_coordinate(false)]), | ||
| 1697 | protocol: None, | ||
| 1698 | user: None, | ||
| 1699 | }, | ||
| 1700 | ); | ||
| 1701 | Ok(()) | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | mod with_url_parameters { | ||
| 1705 | |||
| 1706 | use super::*; | ||
| 1707 | |||
| 1708 | #[test] | ||
| 1709 | fn with_relay_without_scheme_defaults_to_wss() -> Result<()> { | ||
| 1710 | assert_eq!( | ||
| 1711 | NostrUrlDecoded::from_str( | ||
| 1712 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay=nos.lol" | ||
| 1713 | )?, | ||
| 1714 | NostrUrlDecoded { | ||
| 1715 | coordinates: HashSet::from([get_model_coordinate(true)]), | ||
| 1716 | protocol: None, | ||
| 1717 | user: None, | ||
| 1718 | }, | ||
| 1719 | ); | ||
| 1720 | Ok(()) | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | #[test] | ||
| 1724 | fn with_encoded_relay() -> Result<()> { | ||
| 1725 | assert_eq!( | ||
| 1726 | NostrUrlDecoded::from_str(&format!( | ||
| 1727 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit?relay={}", | ||
| 1728 | urlencoding::encode("wss://nos.lol") | ||
| 1729 | ))?, | ||
| 1730 | NostrUrlDecoded { | ||
| 1731 | coordinates: HashSet::from([get_model_coordinate(true)]), | ||
| 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 | } | ||
| 1794 | } | ||
| 1795 | mod with_parameters_embedded_with_slashes { | ||
| 1796 | use super::*; | ||
| 1797 | |||
| 1798 | #[test] | ||
| 1799 | fn with_relay_without_scheme_defaults_to_wss() -> Result<()> { | ||
| 1800 | assert_eq!( | ||
| 1801 | NostrUrlDecoded::from_str( | ||
| 1802 | "nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/ngit" | ||
| 1803 | )?, | ||
| 1804 | NostrUrlDecoded { | ||
| 1805 | coordinates: HashSet::from([get_model_coordinate(true)]), | ||
| 1806 | protocol: None, | ||
| 1807 | user: None, | ||
| 1808 | }, | ||
| 1809 | ); | ||
| 1810 | Ok(()) | ||
| 1811 | } | ||
| 1812 | |||
| 1813 | #[test] | ||
| 1814 | fn with_encoded_relay() -> Result<()> { | ||
| 1815 | assert_eq!( | ||
| 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 | } | ||
| 1884 | } | ||
| 1885 | } | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | mod refspec_to_from_to { | 1625 | mod refspec_to_from_to { |
| 1889 | use super::*; | 1626 | use super::*; |
| 1890 | 1627 | ||