upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/bin/git_remote_nostr/push.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/git_remote_nostr/push.rs')
-rw-r--r--src/bin/git_remote_nostr/push.rs92
1 files changed, 74 insertions, 18 deletions
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index 2c9c7e1..364555a 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -4,7 +4,7 @@ use std::{
4 io::Stdin, 4 io::Stdin,
5}; 5};
6 6
7use anyhow::{bail, Context, Result}; 7use anyhow::{anyhow, bail, Context, Result};
8use auth_git2::GitAuthenticator; 8use auth_git2::GitAuthenticator;
9use client::{get_events_from_cache, get_state_from_cache, send_events, sign_event, STATE_KIND}; 9use client::{get_events_from_cache, get_state_from_cache, send_events, sign_event, STATE_KIND};
10use console::Term; 10use console::Term;
@@ -15,7 +15,10 @@ use git_events::{
15}; 15};
16use ngit::{ 16use ngit::{
17 client::{self, get_event_from_cache_by_id}, 17 client::{self, get_event_from_cache_by_id},
18 git::{self, nostr_url::NostrUrlDecoded}, 18 git::{
19 self,
20 nostr_url::{CloneUrl, NostrUrlDecoded},
21 },
19 git_events::{self, get_event_root}, 22 git_events::{self, get_event_root},
20 login::{self, get_curent_user}, 23 login::{self, get_curent_user},
21 repo_ref, repo_state, 24 repo_ref, repo_state,
@@ -34,7 +37,8 @@ use crate::{
34 list::list_from_remotes, 37 list::list_from_remotes,
35 utils::{ 38 utils::{
36 find_proposal_and_patches_by_branch_name, get_all_proposals, get_remote_name_by_url, 39 find_proposal_and_patches_by_branch_name, get_all_proposals, get_remote_name_by_url,
37 get_short_git_server_name, read_line, switch_clone_url_between_ssh_and_https, 40 get_short_git_server_name, get_write_protocols_to_try, join_with_and,
41 push_error_is_not_authentication_failure, read_line,
38 }, 42 },
39}; 43};
40 44
@@ -315,27 +319,21 @@ pub async fn run_push(
315 } 319 }
316 320
317 // TODO make async - check gitlib2 callbacks work async 321 // TODO make async - check gitlib2 callbacks work async
322
318 for (git_server_url, remote_refspecs) in remote_refspecs { 323 for (git_server_url, remote_refspecs) in remote_refspecs {
319 let remote_refspecs = remote_refspecs 324 let remote_refspecs = remote_refspecs
320 .iter() 325 .iter()
321 .filter(|refspec| git_server_refspecs.contains(refspec)) 326 .filter(|refspec| git_server_refspecs.contains(refspec))
322 .cloned() 327 .cloned()
323 .collect::<Vec<String>>(); 328 .collect::<Vec<String>>();
324 if !refspecs.is_empty() 329 if !refspecs.is_empty() {
325 && push_to_remote(git_repo, &git_server_url, &remote_refspecs, &term).is_err() 330 let _ = push_to_remote(
326 { 331 git_repo,
327 if let Ok(alternative_url) = switch_clone_url_between_ssh_and_https(&git_server_url) { 332 &git_server_url,
328 if push_to_remote(git_repo, &alternative_url, &remote_refspecs, &term).is_err() { 333 decoded_nostr_url,
329 // errors get printed as part of callback 334 &remote_refspecs,
330 // TODO prevent 2 warning messages and instead use one 335 &term,
331 // to say it didnt work over either https or ssh 336 );
332 } else {
333 term.write_line(
334 format!("but succeed over alterantive protocol {alternative_url}",)
335 .as_str(),
336 )?;
337 }
338 }
339 } 337 }
340 } 338 }
341 println!(); 339 println!();
@@ -345,6 +343,64 @@ pub async fn run_push(
345fn push_to_remote( 343fn push_to_remote(
346 git_repo: &Repo, 344 git_repo: &Repo,
347 git_server_url: &str, 345 git_server_url: &str,
346 decoded_nostr_url: &NostrUrlDecoded,
347 remote_refspecs: &[String],
348 term: &Term,
349) -> Result<()> {
350 let server_url = git_server_url.parse::<CloneUrl>()?;
351 let protocols_to_attempt = get_write_protocols_to_try(&server_url, decoded_nostr_url);
352
353 let mut failed_protocols = vec![];
354 let mut success = false;
355
356 for protocol in &protocols_to_attempt {
357 term.write_line(
358 format!(
359 "fetching ref list over {protocol} from {}...",
360 server_url.short_name(),
361 )
362 .as_str(),
363 )?;
364
365 let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?;
366
367 if let Err(error) = push_to_remote_url(git_repo, &formatted_url, remote_refspecs, term) {
368 term.write_line(
369 format!("push: {formatted_url} failed over {protocol}: {error}").as_str(),
370 )?;
371 failed_protocols.push(protocol);
372 if push_error_is_not_authentication_failure(&error) {
373 break;
374 }
375 } else {
376 success = true;
377 if !failed_protocols.is_empty() {
378 term.write_line(format!("fetch: succeeded over {protocol}").as_str())?;
379 }
380 }
381 term.clear_last_lines(1)?;
382 }
383 if success {
384 Ok(())
385 } else {
386 let error = anyhow!(
387 "{} failed over {}{}",
388 server_url.short_name(),
389 join_with_and(&failed_protocols),
390 if decoded_nostr_url.protocol.is_some() {
391 " and nostr url contains protocol override so no other protocols were attempted"
392 } else {
393 ""
394 },
395 );
396 term.write_line(format!("fetch: {error}").as_str())?;
397 Err(error)
398 }
399}
400
401fn push_to_remote_url(
402 git_repo: &Repo,
403 git_server_url: &str,
348 remote_refspecs: &[String], 404 remote_refspecs: &[String],
349 term: &Term, 405 term: &Term,
350) -> Result<()> { 406) -> Result<()> {