upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-09-12 15:13:50 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-09-12 15:13:50 +0100
commite882fde7d3fc7f2113196585b450f7065061abb9 (patch)
tree222ecde50be06a5873a3080762c072b28f50666c /src
parent1a38f98807a3244b77d2525136f3d6976f61dcc4 (diff)
fix(remote): improve `push` status updates
to bring them more into line to the native git client
Diffstat (limited to 'src')
-rw-r--r--src/bin/git_remote_nostr/fetch.rs84
-rw-r--r--src/bin/git_remote_nostr/push.rs23
-rw-r--r--src/bin/git_remote_nostr/utils.rs82
3 files changed, 121 insertions, 68 deletions
diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs
index 1b19347..1e38e0e 100644
--- a/src/bin/git_remote_nostr/fetch.rs
+++ b/src/bin/git_remote_nostr/fetch.rs
@@ -18,6 +18,7 @@ use ngit::{
18use crate::utils::{ 18use crate::utils::{
19 fetch_or_list_error_is_not_authentication_failure, find_proposal_and_patches_by_branch_name, 19 fetch_or_list_error_is_not_authentication_failure, find_proposal_and_patches_by_branch_name,
20 get_oids_from_fetch_batch, get_open_proposals, get_read_protocols_to_try, join_with_and, 20 get_oids_from_fetch_batch, get_open_proposals, get_read_protocols_to_try, join_with_and,
21 report_on_sideband_progress, report_on_transfer_progress, ProgressStatus, TransferDirection,
21}; 22};
22 23
23pub async fn run_fetch( 24pub async fn run_fetch(
@@ -187,31 +188,19 @@ fn fetch_from_git_server_url(
187 let mut fetch_options = git2::FetchOptions::new(); 188 let mut fetch_options = git2::FetchOptions::new();
188 let mut remote_callbacks = git2::RemoteCallbacks::new(); 189 let mut remote_callbacks = git2::RemoteCallbacks::new();
189 remote_callbacks.sideband_progress(|data| { 190 remote_callbacks.sideband_progress(|data| {
190 if let Ok(data) = str::from_utf8(data) { 191 report_on_sideband_progress(data, term);
191 let data = data 192 true
192 .split(['\n', '\r']) 193 });
193 .find(|line| !line.is_empty()) 194 remote_callbacks.transfer_progress(|stats| {
194 .unwrap_or(""); 195 let _ = term.clear_last_lines(1);
195 if !data.is_empty() { 196 report_on_transfer_progress(
196 let s = format!("remote: {data}"); 197 &stats,
197 let _ = term.clear_last_lines(1); 198 term,
198 let _ = term.write_line(s.as_str()); 199 TransferDirection::Fetch,
199 if !s.contains('%') || s.contains("100%") { 200 ProgressStatus::InProgress,
200 // print it twice so the next sideband_progress doesn't delete it 201 );
201 let _ = term.write_line(s.as_str());
202 }
203 }
204 }
205 true 202 true
206 }); 203 });
207 remote_callbacks.transfer_progress(
208 #[allow(clippy::cast_precision_loss)]
209 |stats| {
210 let _ = term.clear_last_lines(1);
211 report_on_transfer_progress(&stats, term, false);
212 true
213 },
214 );
215 204
216 if !dont_authenticate { 205 if !dont_authenticate {
217 remote_callbacks.credentials(auth.credentials(&git_config)); 206 remote_callbacks.credentials(auth.credentials(&git_config));
@@ -220,50 +209,13 @@ fn fetch_from_git_server_url(
220 term.write_line("")?; 209 term.write_line("")?;
221 git_server_remote.download(oids, Some(&mut fetch_options))?; 210 git_server_remote.download(oids, Some(&mut fetch_options))?;
222 211
223 report_on_transfer_progress(&git_server_remote.stats(), term, true); 212 report_on_transfer_progress(
213 &git_server_remote.stats(),
214 term,
215 TransferDirection::Fetch,
216 ProgressStatus::Complete,
217 );
224 218
225 git_server_remote.disconnect()?; 219 git_server_remote.disconnect()?;
226 Ok(()) 220 Ok(())
227} 221}
228
229#[allow(clippy::cast_precision_loss)]
230#[allow(clippy::float_cmp)]
231fn report_on_transfer_progress(stats: &git2::Progress<'_>, term: &console::Term, complete: bool) {
232 let total = stats.total_objects() as f64;
233 if total == 0.0 {
234 return;
235 }
236 let received = stats.received_objects() as f64;
237 let percentage = (received / total) * 100.0;
238
239 // Get the total received bytes
240 let received_bytes = stats.received_bytes() as f64;
241
242 // Determine whether to use KiB or MiB
243 let (size, unit) = if received_bytes >= (1024.0 * 1024.0) {
244 // Convert to MiB
245 (received_bytes / (1024.0 * 1024.0), "MiB")
246 } else {
247 // Convert to KiB
248 (received_bytes / 1024.0, "KiB")
249 };
250
251 // Format the output for receiving objects
252 if received < total || complete {
253 let _ = term.write_line(
254 format!(
255 "Receiving objects: {percentage:.0}% ({received}/{total}) {size:.2} {unit}, done.\r"
256 )
257 .as_str(),
258 );
259 }
260 if received == total || complete {
261 let indexed_deltas = stats.indexed_deltas() as f64;
262 let total_deltas = stats.total_deltas() as f64;
263 let percentage = (indexed_deltas / total_deltas) * 100.0;
264 let _ = term.write_line(
265 format!("Resolving deltas: {percentage:.0}% ({indexed_deltas}/{total_deltas}) done.\r")
266 .as_str(),
267 );
268 }
269}
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index 7f63eb0..5a19bb0 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -38,7 +38,8 @@ use crate::{
38 utils::{ 38 utils::{
39 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,
40 get_short_git_server_name, get_write_protocols_to_try, join_with_and, 40 get_short_git_server_name, get_write_protocols_to_try, join_with_and,
41 push_error_is_not_authentication_failure, read_line, 41 push_error_is_not_authentication_failure, read_line, report_on_sideband_progress,
42 report_on_transfer_progress, ProgressStatus, TransferDirection,
42 }, 43 },
43}; 44};
44 45
@@ -355,7 +356,11 @@ fn push_to_remote(
355 356
356 for protocol in &protocols_to_attempt { 357 for protocol in &protocols_to_attempt {
357 term.write_line( 358 term.write_line(
358 format!("fetching {} ref list over {protocol}...", server_url.short_name(),).as_str(), 359 format!(
360 "fetching {} ref list over {protocol}...",
361 server_url.short_name(),
362 )
363 .as_str(),
359 )?; 364 )?;
360 365
361 let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; 366 let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?;
@@ -419,6 +424,20 @@ fn push_to_remote_url(
419 } 424 }
420 Ok(()) 425 Ok(())
421 }); 426 });
427 remote_callbacks.transfer_progress(|stats| {
428 let _ = term.clear_last_lines(1);
429 report_on_transfer_progress(
430 &stats,
431 term,
432 TransferDirection::Push,
433 ProgressStatus::InProgress,
434 );
435 true
436 });
437 remote_callbacks.sideband_progress(|data| {
438 report_on_sideband_progress(data, term);
439 true
440 });
422 push_options.remote_callbacks(remote_callbacks); 441 push_options.remote_callbacks(remote_callbacks);
423 git_server_remote.push(remote_refspecs, Some(&mut push_options))?; 442 git_server_remote.push(remote_refspecs, Some(&mut push_options))?;
424 let _ = git_server_remote.disconnect(); 443 let _ = git_server_remote.disconnect();
diff --git a/src/bin/git_remote_nostr/utils.rs b/src/bin/git_remote_nostr/utils.rs
index 9be2580..1d65e3c 100644
--- a/src/bin/git_remote_nostr/utils.rs
+++ b/src/bin/git_remote_nostr/utils.rs
@@ -1,3 +1,4 @@
1use core::str;
1use std::{ 2use std::{
2 collections::HashMap, 3 collections::HashMap,
3 io::{self, Stdin}, 4 io::{self, Stdin},
@@ -307,6 +308,87 @@ pub fn error_might_be_authentication_related(error: &anyhow::Error) -> bool {
307 false 308 false
308} 309}
309 310
311pub enum TransferDirection {
312 Fetch,
313 Push,
314}
315
316pub enum ProgressStatus {
317 InProgress,
318 Complete,
319}
320
321#[allow(clippy::cast_precision_loss)]
322#[allow(clippy::float_cmp)]
323#[allow(clippy::needless_pass_by_value)]
324pub fn report_on_transfer_progress(
325 progress_stats: &git2::Progress<'_>,
326 term: &console::Term,
327 direction: TransferDirection,
328 status: ProgressStatus,
329) {
330 let total = progress_stats.total_objects() as f64;
331 if total == 0.0 {
332 return;
333 }
334 let received = progress_stats.received_objects() as f64;
335 let percentage = (received / total) * 100.0;
336
337 // Get the total received bytes
338 let received_bytes = progress_stats.received_bytes() as f64;
339
340 // Determine whether to use KiB or MiB
341 let (size, unit) = if received_bytes >= (1024.0 * 1024.0) {
342 // Convert to MiB
343 (received_bytes / (1024.0 * 1024.0), "MiB")
344 } else {
345 // Convert to KiB
346 (received_bytes / 1024.0, "KiB")
347 };
348
349 // Format the output for receiving objects
350 if received < total || matches!(status, ProgressStatus::Complete) {
351 let _ = term.write_line(
352 format!(
353 "{} objects: {percentage:.0}% ({received}/{total}) {size:.2} {unit}, done.\r",
354 if matches!(direction, TransferDirection::Fetch) {
355 "Receiving"
356 } else {
357 "Writing"
358 },
359 )
360 .as_str(),
361 );
362 }
363 if received == total || matches!(status, ProgressStatus::Complete) {
364 let indexed_deltas = progress_stats.indexed_deltas() as f64;
365 let total_deltas = progress_stats.total_deltas() as f64;
366 let percentage = (indexed_deltas / total_deltas) * 100.0;
367 let _ = term.write_line(
368 format!("Resolving deltas: {percentage:.0}% ({indexed_deltas}/{total_deltas}) done.\r")
369 .as_str(),
370 );
371 }
372}
373
374pub fn report_on_sideband_progress(data: &[u8], term: &console::Term) {
375 if let Ok(data) = str::from_utf8(data) {
376 let data = data
377 .split(['\n', '\r'])
378 .find(|line| !line.is_empty())
379 .unwrap_or("");
380 if !data.is_empty() {
381 let s = format!("remote: {data}");
382 let _ = term.clear_last_lines(1);
383 let _ = term.write_line(s.as_str());
384 if !s.contains('%') || s.contains("100%") {
385 // print it twice so the next sideband_progress doesn't delete it
386 let _ = term.write_line(s.as_str());
387 }
388 }
389 }
390}
391
310#[cfg(test)] 392#[cfg(test)]
311mod tests { 393mod tests {
312 use super::*; 394 use super::*;