upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/lib/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/client.rs')
-rw-r--r--src/lib/client.rs81
1 files changed, 77 insertions, 4 deletions
diff --git a/src/lib/client.rs b/src/lib/client.rs
index 42f3f6d..34fdb50 100644
--- a/src/lib/client.rs
+++ b/src/lib/client.rs
@@ -2459,6 +2459,8 @@ pub async fn send_events(
2459 let is_test = std::env::var("NGITTEST").is_ok(); 2459 let is_test = std::env::var("NGITTEST").is_ok();
2460 let use_concise = !is_test || (!verbose && !silent && animate); 2460 let use_concise = !is_test || (!verbose && !silent && animate);
2461 2461
2462 let events_description = describe_events(&events);
2463
2462 // Set up the two-MultiProgress pattern (same as fetch_all): 2464 // Set up the two-MultiProgress pattern (same as fetch_all):
2463 // 1. A spinner MultiProgress shown immediately (concise mode only) 2465 // 1. A spinner MultiProgress shown immediately (concise mode only)
2464 // 2. A detail MultiProgress that starts hidden and becomes visible after a 2466 // 2. A detail MultiProgress that starts hidden and becomes visible after a
@@ -2472,7 +2474,9 @@ pub async fn send_events(
2472 .unwrap() 2474 .unwrap()
2473 .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈"), 2475 .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈"),
2474 ) 2476 )
2475 .with_message("Publishing to nostr relays..."), 2477 .with_message(format!(
2478 "Publishing {events_description} to nostr relays..."
2479 )),
2476 ); 2480 );
2477 spinner.enable_steady_tick(Duration::from_millis(100)); 2481 spinner.enable_steady_tick(Duration::from_millis(100));
2478 Some((sm, spinner)) 2482 Some((sm, spinner))
@@ -2492,7 +2496,9 @@ pub async fn send_events(
2492 let bar = 2496 let bar =
2493 m.add(ProgressBar::new(0).with_style(ProgressStyle::with_template("{msg}").unwrap())); 2497 m.add(ProgressBar::new(0).with_style(ProgressStyle::with_template("{msg}").unwrap()));
2494 if !is_test { 2498 if !is_test {
2495 bar.set_message("Publishing to nostr relays..."); 2499 bar.set_message(format!(
2500 "Publishing {events_description} to nostr relays..."
2501 ));
2496 } 2502 }
2497 Some(bar) 2503 Some(bar)
2498 }; 2504 };
@@ -2511,6 +2517,7 @@ pub async fn send_events(
2511 let spinner_for_timer = spinner_multi.as_ref().map(|(_, s)| s.clone()); 2517 let spinner_for_timer = spinner_multi.as_ref().map(|(_, s)| s.clone());
2512 let reveal_state_for_timer = reveal_state.clone(); 2518 let reveal_state_for_timer = reveal_state.clone();
2513 let heading_bar_for_timer = heading_bar.clone(); 2519 let heading_bar_for_timer = heading_bar.clone();
2520 let events_description_for_timer = events_description.clone();
2514 let timer_handle = if use_concise { 2521 let timer_handle = if use_concise {
2515 let handle = tokio::spawn(async move { 2522 let handle = tokio::spawn(async move {
2516 tokio::time::sleep(Duration::from_millis(SPINNER_EXPAND_DELAY_MS)).await; 2523 tokio::time::sleep(Duration::from_millis(SPINNER_EXPAND_DELAY_MS)).await;
@@ -2519,7 +2526,9 @@ pub async fn send_events(
2519 } 2526 }
2520 detail_multi_for_timer.set_draw_target(ProgressDrawTarget::stderr()); 2527 detail_multi_for_timer.set_draw_target(ProgressDrawTarget::stderr());
2521 if let Some(heading) = heading_bar_for_timer { 2528 if let Some(heading) = heading_bar_for_timer {
2522 heading.finish_with_message("publishing to nostr relays..."); 2529 heading.finish_with_message(format!(
2530 "Publishing {events_description_for_timer} to nostr relays..."
2531 ));
2523 } 2532 }
2524 if let Some(state) = reveal_state_for_timer { 2533 if let Some(state) = reveal_state_for_timer {
2525 let mut deferred = state.deferred.lock().unwrap(); 2534 let mut deferred = state.deferred.lock().unwrap();
@@ -2650,12 +2659,76 @@ pub async fn send_events(
2650 } 2659 }
2651 if let Some((_, spinner)) = &spinner_multi { 2660 if let Some((_, spinner)) = &spinner_multi {
2652 spinner.set_style(ProgressStyle::with_template("{msg}").unwrap()); 2661 spinner.set_style(ProgressStyle::with_template("{msg}").unwrap());
2653 spinner.finish_with_message("Published to nostr relays"); 2662 spinner.finish_with_message(format!("Published {events_description} to nostr relays"));
2654 } 2663 }
2655 2664
2656 Ok(()) 2665 Ok(())
2657} 2666}
2658 2667
2668/// Builds a human-readable description of what is being published, e.g.
2669/// "3 patches", "1 announcement and 1 state event", "2 patches and 1 cover
2670/// letter".
2671fn describe_events(events: &[nostr::Event]) -> String {
2672 use crate::git_events::{KIND_PULL_REQUEST, KIND_PULL_REQUEST_UPDATE, KIND_USER_GRASP_LIST};
2673
2674 // key = singular, value = (plural, count)
2675 let mut counts: std::collections::BTreeMap<&str, (&str, usize)> =
2676 std::collections::BTreeMap::new();
2677
2678 for event in events {
2679 let (singular, plural) = if event.kind.eq(&Kind::GitRepoAnnouncement) {
2680 ("announcement", "announcements")
2681 } else if event.kind.eq(&STATE_KIND) {
2682 ("state event", "state events")
2683 } else if event_is_cover_letter(event) {
2684 ("cover letter", "cover letters")
2685 } else if event.kind.eq(&Kind::GitPatch) {
2686 ("patch", "patches")
2687 } else if event.kind.eq(&KIND_PULL_REQUEST) {
2688 ("PR", "PRs")
2689 } else if event.kind.eq(&KIND_PULL_REQUEST_UPDATE) {
2690 ("PR update", "PR updates")
2691 } else if [
2692 Kind::GitStatusOpen,
2693 Kind::GitStatusDraft,
2694 Kind::GitStatusClosed,
2695 Kind::GitStatusApplied,
2696 ]
2697 .contains(&event.kind)
2698 {
2699 ("status update", "status updates")
2700 } else if event.kind.eq(&KIND_USER_GRASP_LIST) {
2701 ("user relay list", "user relay lists")
2702 } else {
2703 ("event", "events")
2704 };
2705 counts
2706 .entry(singular)
2707 .and_modify(|(_, c)| *c += 1)
2708 .or_insert((plural, 1));
2709 }
2710
2711 let parts: Vec<String> = counts
2712 .iter()
2713 .map(|(singular, (plural, n))| {
2714 if *n == 1 {
2715 format!("1 {singular}")
2716 } else {
2717 format!("{n} {plural}")
2718 }
2719 })
2720 .collect();
2721
2722 match parts.len() {
2723 0 => "0 events".to_string(),
2724 1 => parts[0].clone(),
2725 _ => {
2726 let (last, rest) = parts.split_last().unwrap();
2727 format!("{} and {last}", rest.join(", "))
2728 }
2729 }
2730}
2731
2659fn remove_trailing_slash(s: &str) -> String { 2732fn remove_trailing_slash(s: &str) -> String {
2660 match s.strip_suffix('/') { 2733 match s.strip_suffix('/') {
2661 Some(s) => s, 2734 Some(s) => s,