diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs index 1e38e0e..59067fa 100644 --- a/src/bin/git_remote_nostr/fetch.rs +++ b/src/bin/git_remote_nostr/fetch.rs @@ -18,7 +18,7 @@ use ngit::{ use crate::utils::{ fetch_or_list_error_is_not_authentication_failure, find_proposal_and_patches_by_branch_name, get_oids_from_fetch_batch, get_open_proposals, get_read_protocols_to_try, join_with_and, - report_on_sideband_progress, report_on_transfer_progress, ProgressStatus, TransferDirection, + report_on_sideband_progress, }; pub async fn run_fetch( @@ -172,6 +172,58 @@ fn fetch_from_git_server( } } +enum ProgressStatus { + InProgress, + Complete, +} + +#[allow(clippy::cast_precision_loss)] +#[allow(clippy::float_cmp)] +#[allow(clippy::needless_pass_by_value)] +fn report_on_transfer_progress( + progress_stats: &git2::Progress<'_>, + term: &console::Term, + status: ProgressStatus, +) { + let total = progress_stats.total_objects() as f64; + if total == 0.0 { + return; + } + let received = progress_stats.received_objects() as f64; + let percentage = (received / total) * 100.0; + + // Get the total received bytes + let received_bytes = progress_stats.received_bytes() as f64; + + // Determine whether to use KiB or MiB + let (size, unit) = if received_bytes >= (1024.0 * 1024.0) { + // Convert to MiB + (received_bytes / (1024.0 * 1024.0), "MiB") + } else { + // Convert to KiB + (received_bytes / 1024.0, "KiB") + }; + + // Format the output for receiving objects + if received < total || matches!(status, ProgressStatus::Complete) { + let _ = term.write_line( + format!( + "Receiving objects: {percentage:.0}% ({received}/{total}) {size:.2} {unit}, done.", + ) + .as_str(), + ); + } + if received == total || matches!(status, ProgressStatus::Complete) { + let indexed_deltas = progress_stats.indexed_deltas() as f64; + let total_deltas = progress_stats.total_deltas() as f64; + let percentage = (indexed_deltas / total_deltas) * 100.0; + let _ = term.write_line( + format!("Resolving deltas: {percentage:.0}% ({indexed_deltas}/{total_deltas}) done.") + .as_str(), + ); + } +} + fn fetch_from_git_server_url( git_repo: &Repository, oids: &[String], @@ -193,12 +245,7 @@ fn fetch_from_git_server_url( }); remote_callbacks.transfer_progress(|stats| { let _ = term.clear_last_lines(1); - report_on_transfer_progress( - &stats, - term, - TransferDirection::Fetch, - ProgressStatus::InProgress, - ); + report_on_transfer_progress(&stats, term, ProgressStatus::InProgress); true }); @@ -209,12 +256,7 @@ fn fetch_from_git_server_url( term.write_line("")?; git_server_remote.download(oids, Some(&mut fetch_options))?; - report_on_transfer_progress( - &git_server_remote.stats(), - term, - TransferDirection::Fetch, - ProgressStatus::Complete, - ); + report_on_transfer_progress(&git_server_remote.stats(), term, ProgressStatus::Complete); git_server_remote.disconnect()?; Ok(()) diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs index 5a19bb0..0a7f1a6 100644 --- a/src/bin/git_remote_nostr/push.rs +++ b/src/bin/git_remote_nostr/push.rs @@ -18,6 +18,7 @@ use ngit::{ git::{ self, nostr_url::{CloneUrl, NostrUrlDecoded}, + oid_to_shorthand_string, }, git_events::{self, get_event_root}, login::{self, get_curent_user}, @@ -39,7 +40,6 @@ use crate::{ find_proposal_and_patches_by_branch_name, get_all_proposals, get_remote_name_by_url, get_short_git_server_name, get_write_protocols_to_try, join_with_and, push_error_is_not_authentication_failure, read_line, report_on_sideband_progress, - report_on_transfer_progress, ProgressStatus, TransferDirection, }, }; @@ -355,13 +355,7 @@ fn push_to_remote( let mut success = false; for protocol in &protocols_to_attempt { - term.write_line( - format!( - "fetching {} ref list over {protocol}...", - server_url.short_name(), - ) - .as_str(), - )?; + term.write_line(format!("push: {} over {protocol}...", server_url.short_name(),).as_str())?; let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; @@ -424,16 +418,50 @@ fn push_to_remote_url( } Ok(()) }); - remote_callbacks.transfer_progress(|stats| { - let _ = term.clear_last_lines(1); - report_on_transfer_progress( - &stats, - term, - TransferDirection::Push, - ProgressStatus::InProgress, - ); - true + remote_callbacks.push_negotiation(|updates| { + for update in updates { + let _ = term.write_line( + format!( + " {}..{} {} -> {}", + oid_to_shorthand_string(update.dst()).unwrap(), + oid_to_shorthand_string(update.src()).unwrap(), + update + .src_refname() + .unwrap_or("") + .replace("refs/heads/", "") + .replace("refs/tags/", "tags/"), + update + .dst_refname() + .unwrap_or("") + .replace("refs/heads/", "") + .replace("refs/tags/", "tags/"), + ) + .as_str(), + ); + // now a blank line for transfer progress to delete + let _ = term.write_line(""); + } + Ok(()) }); + remote_callbacks.push_transfer_progress( + #[allow(clippy::cast_precision_loss)] + |current, total, bytes| { + let _ = term.clear_last_lines(1); + let percentage = (current as f64 / total as f64) * 100.0; + let (size, unit) = if bytes >= (1024 * 1024) { + (bytes as f64 / (1024.0 * 1024.0), "MiB") + } else { + (bytes as f64 / 1024.0, "KiB") + }; + let _ = term.write_line( + format!( + "Writing objects: {percentage:.0}% ({current}/{total}) {size:.2} {unit}, done." + ) + .as_str(), + ); + }, + ); + remote_callbacks.sideband_progress(|data| { report_on_sideband_progress(data, term); true diff --git a/src/bin/git_remote_nostr/utils.rs b/src/bin/git_remote_nostr/utils.rs index 6e09851..15a0d76 100644 --- a/src/bin/git_remote_nostr/utils.rs +++ b/src/bin/git_remote_nostr/utils.rs @@ -310,69 +310,6 @@ pub fn error_might_be_authentication_related(error: &anyhow::Error) -> bool { false } -pub enum TransferDirection { - Fetch, - Push, -} - -pub enum ProgressStatus { - InProgress, - Complete, -} - -#[allow(clippy::cast_precision_loss)] -#[allow(clippy::float_cmp)] -#[allow(clippy::needless_pass_by_value)] -pub fn report_on_transfer_progress( - progress_stats: &git2::Progress<'_>, - term: &console::Term, - direction: TransferDirection, - status: ProgressStatus, -) { - let total = progress_stats.total_objects() as f64; - if total == 0.0 { - return; - } - let received = progress_stats.received_objects() as f64; - let percentage = (received / total) * 100.0; - - // Get the total received bytes - let received_bytes = progress_stats.received_bytes() as f64; - - // Determine whether to use KiB or MiB - let (size, unit) = if received_bytes >= (1024.0 * 1024.0) { - // Convert to MiB - (received_bytes / (1024.0 * 1024.0), "MiB") - } else { - // Convert to KiB - (received_bytes / 1024.0, "KiB") - }; - - // Format the output for receiving objects - if received < total || matches!(status, ProgressStatus::Complete) { - let _ = term.write_line( - format!( - "{} objects: {percentage:.0}% ({received}/{total}) {size:.2} {unit}, done.\r", - if matches!(direction, TransferDirection::Fetch) { - "Receiving" - } else { - "Writing" - }, - ) - .as_str(), - ); - } - if received == total || matches!(status, ProgressStatus::Complete) { - let indexed_deltas = progress_stats.indexed_deltas() as f64; - let total_deltas = progress_stats.total_deltas() as f64; - let percentage = (indexed_deltas / total_deltas) * 100.0; - let _ = term.write_line( - format!("Resolving deltas: {percentage:.0}% ({indexed_deltas}/{total_deltas}) done.\r") - .as_str(), - ); - } -} - pub fn report_on_sideband_progress(data: &[u8], term: &console::Term) { if let Ok(data) = str::from_utf8(data) { let data = data diff --git a/src/lib/git/mod.rs b/src/lib/git/mod.rs index 00d84f6..fb7ae74 100644 --- a/src/lib/git/mod.rs +++ b/src/lib/git/mod.rs @@ -765,12 +765,12 @@ fn oid_to_u8_20_bytes(oid: &Oid) -> [u8; 20] { ] } -// fn oid_to_shorthand_string(oid: Oid) -> Result { -// let binding = oid.to_string(); -// let b = binding.as_bytes(); -// String::from_utf8(vec![b[0], b[1], b[2], b[3], b[4], b[5], b[6]]) -// .context("oid should always start with 7 u8 btyes of utf8") -// } +pub fn oid_to_shorthand_string(oid: Oid) -> Result { + let binding = oid.to_string(); + let b = binding.as_bytes(); + String::from_utf8(vec![b[0], b[1], b[2], b[3], b[4], b[5], b[6]]) + .context("oid should always start with 7 u8 btyes of utf8") +} // fn oid_to_sha1_string(oid: Oid) -> Result { // let b = oid.as_bytes();