upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/lib/push.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-01-16 09:23:05 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-10-17 12:18:24 +0100
commitb126e5b7acfce55bd101b06cb5baf7f251cd0fda (patch)
treedd3eb721a49496ce2a686a43ce4d007b26ee7d7c /src/lib/push.rs
parent6cb9e1f5071a6dee8f8e5b98c3c2e699cafd2921 (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.rs43
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 @@
1use std::{ 1use 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(
127pub fn push_to_remote_url( 146pub 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