diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-01-16 09:23:05 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-10-17 12:18:24 +0100 |
| commit | b126e5b7acfce55bd101b06cb5baf7f251cd0fda (patch) | |
| tree | dd3eb721a49496ce2a686a43ce4d007b26ee7d7c /src/lib/push.rs | |
| parent | 6cb9e1f5071a6dee8f8e5b98c3c2e699cafd2921 (diff) | |
feat!(nostr_url): replace user with ssh_key_file
replaces the "user" in the nostr_url format with
"ssh_key_file", to support the original intent, which was to allow
users to specify different authentication credentials.
most git servers always expect the ssh user to be 'git'.
the idiumatic way of specifying logging in as a different user is to
specify a different ssh key.
the idiomatic way of storing non-default ssh keys is in the location
`~/.ssh/key_name`. "ssh_key_file" can be specified as `key_name`,
for keys in the default location, or as a relative or absolute custom
location eg. `/other_keys/.ssh/nym1` or `../.ssh/nym1`.
BREAKING CHANGE: in nostr git url nym1@ssh/npub123/identifer, nym1 is
now treated as ssh key file location rather than a ssh user. it can
be specified as a file within `~/.ssh` eg `~/.ssh/nym1` or a full or
relative path.
Diffstat (limited to 'src/lib/push.rs')
| -rw-r--r-- | src/lib/push.rs | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/src/lib/push.rs b/src/lib/push.rs index aafcf35..c9b8791 100644 --- a/src/lib/push.rs +++ b/src/lib/push.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | use std::{ | 1 | use std::{ |
| 2 | collections::{HashMap, HashSet}, | 2 | collections::{HashMap, HashSet}, |
| 3 | path::PathBuf, | ||
| 3 | str::FromStr, | 4 | str::FromStr, |
| 4 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
| 5 | thread, | 6 | thread, |
| @@ -25,7 +26,7 @@ use crate::{ | |||
| 25 | client::{Connect, get_repo_ref_from_cache, send_events, sign_draft_event, sign_event}, | 26 | client::{Connect, get_repo_ref_from_cache, send_events, sign_draft_event, sign_event}, |
| 26 | git::{ | 27 | git::{ |
| 27 | Repo, RepoActions, | 28 | Repo, RepoActions, |
| 28 | nostr_url::{CloneUrl, NostrUrlDecoded}, | 29 | nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol}, |
| 29 | oid_to_shorthand_string, | 30 | oid_to_shorthand_string, |
| 30 | }, | 31 | }, |
| 31 | git_events::{KIND_PULL_REQUEST_UPDATE, generate_unsigned_pr_or_update_event}, | 32 | git_events::{KIND_PULL_REQUEST_UPDATE, generate_unsigned_pr_or_update_event}, |
| @@ -60,12 +61,30 @@ pub fn push_to_remote( | |||
| 60 | for protocol in &protocols_to_attempt { | 61 | for protocol in &protocols_to_attempt { |
| 61 | term.write_line(format!("push: {} over {protocol}...", server_url.short_name(),).as_str())?; | 62 | term.write_line(format!("push: {} over {protocol}...", server_url.short_name(),).as_str())?; |
| 62 | 63 | ||
| 63 | let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; | 64 | let formatted_url = server_url.format_as(protocol)?; |
| 64 | 65 | ||
| 65 | match push_to_remote_url(git_repo, &formatted_url, remote_refspecs, term) { | 66 | match push_to_remote_url( |
| 67 | git_repo, | ||
| 68 | &formatted_url, | ||
| 69 | decoded_nostr_url.ssh_key_file_path().as_ref(), | ||
| 70 | remote_refspecs, | ||
| 71 | term, | ||
| 72 | ) { | ||
| 66 | Err(error) => { | 73 | Err(error) => { |
| 67 | term.write_line( | 74 | term.write_line( |
| 68 | format!("push: {formatted_url} failed over {protocol}: {error}").as_str(), | 75 | format!( |
| 76 | "push: {formatted_url} failed over {protocol}{}: {error}", | ||
| 77 | if protocol == &ServerProtocol::Ssh { | ||
| 78 | if let Some(ssh_key_file) = &decoded_nostr_url.ssh_key_file_path() { | ||
| 79 | format!(" with ssh key from {ssh_key_file}") | ||
| 80 | } else { | ||
| 81 | String::new() | ||
| 82 | } | ||
| 83 | } else { | ||
| 84 | String::new() | ||
| 85 | } | ||
| 86 | ) | ||
| 87 | .as_str(), | ||
| 69 | )?; | 88 | )?; |
| 70 | failed_protocols.push(protocol); | 89 | failed_protocols.push(protocol); |
| 71 | } | 90 | } |
| @@ -127,12 +146,24 @@ pub fn push_to_remote( | |||
| 127 | pub fn push_to_remote_url( | 146 | pub fn push_to_remote_url( |
| 128 | git_repo: &Repo, | 147 | git_repo: &Repo, |
| 129 | git_server_url: &str, | 148 | git_server_url: &str, |
| 149 | ssh_key_file: Option<&String>, | ||
| 130 | remote_refspecs: &[String], | 150 | remote_refspecs: &[String], |
| 131 | term: &Term, | 151 | term: &Term, |
| 132 | ) -> Result<HashMap<String, Option<String>>> { | 152 | ) -> Result<HashMap<String, Option<String>>> { |
| 133 | let git_config = git_repo.git_repo.config()?; | 153 | let git_config = git_repo.git_repo.config()?; |
| 134 | let mut git_server_remote = git_repo.git_repo.remote_anonymous(git_server_url)?; | 154 | let mut git_server_remote = git_repo.git_repo.remote_anonymous(git_server_url)?; |
| 135 | let auth = GitAuthenticator::default(); | 155 | let auth = { |
| 156 | if git_server_url.contains("git@") { | ||
| 157 | if let Some(ssh_key_file) = ssh_key_file { | ||
| 158 | GitAuthenticator::default() | ||
| 159 | .add_ssh_key_from_file(PathBuf::from_str(ssh_key_file)?, None) | ||
| 160 | } else { | ||
| 161 | GitAuthenticator::default() | ||
| 162 | } | ||
| 163 | } else { | ||
| 164 | GitAuthenticator::default() | ||
| 165 | } | ||
| 166 | }; | ||
| 136 | let mut push_options = git2::PushOptions::new(); | 167 | let mut push_options = git2::PushOptions::new(); |
| 137 | let mut remote_callbacks = git2::RemoteCallbacks::new(); | 168 | let mut remote_callbacks = git2::RemoteCallbacks::new(); |
| 138 | let push_reporter = Arc::new(Mutex::new(PushReporter::new(term))); | 169 | let push_reporter = Arc::new(Mutex::new(PushReporter::new(term))); |
| @@ -716,7 +747,7 @@ pub async fn push_refs_and_generate_pr_or_pr_update_event( | |||
| 716 | let refspec = format!("{tip}:{git_ref_used}"); | 747 | let refspec = format!("{tip}:{git_ref_used}"); |
| 717 | 748 | ||
| 718 | let res = if is_grasp_server_clone_url(clone_url) { | 749 | let res = if is_grasp_server_clone_url(clone_url) { |
| 719 | push_to_remote_url(git_repo, clone_url, &[refspec], term) | 750 | push_to_remote_url(git_repo, clone_url, None, &[refspec], term) |
| 720 | } else { | 751 | } else { |
| 721 | // anticipated only when pushing to user's own repo or a personal-fork with | 752 | // anticipated only when pushing to user's own repo or a personal-fork with |
| 722 | // non-grasp git servers. this is used to extract prefered protocols / ssh | 753 | // non-grasp git servers. this is used to extract prefered protocols / ssh |