git_same/output/progress/
discovery.rs1use crate::output::Verbosity;
2use crate::provider::DiscoveryProgress;
3use console::style;
4use indicatif::{MultiProgress, ProgressBar};
5use std::sync::atomic::{AtomicUsize, Ordering};
6use std::sync::Arc;
7
8use super::styles::spinner_style;
9
10pub struct DiscoveryProgressBar {
12 #[allow(dead_code)]
13 multi: MultiProgress,
14 main_bar: ProgressBar,
15 repo_count: Arc<AtomicUsize>,
16 verbosity: Verbosity,
17}
18
19impl DiscoveryProgressBar {
20 pub fn new(verbosity: Verbosity) -> Self {
22 let multi = MultiProgress::new();
23 let main_bar = multi.add(ProgressBar::new_spinner());
24 main_bar.set_style(spinner_style());
25 main_bar.set_message("Discovering repositories...");
26 main_bar.enable_steady_tick(std::time::Duration::from_millis(100));
27
28 Self {
29 multi,
30 main_bar,
31 repo_count: Arc::new(AtomicUsize::new(0)),
32 verbosity,
33 }
34 }
35
36 pub fn finish(&self) {
38 let count = self.repo_count.load(Ordering::SeqCst);
39 self.main_bar.finish_with_message(format!(
40 "{} Discovered {} repositories",
41 style("✓").green(),
42 count
43 ));
44 }
45}
46
47impl DiscoveryProgress for DiscoveryProgressBar {
48 fn on_orgs_discovered(&self, count: usize) {
49 if self.verbosity >= Verbosity::Verbose {
50 self.main_bar
51 .set_message(format!("Found {} organizations", count));
52 }
53 }
54
55 fn on_org_started(&self, org_name: &str) {
56 if self.verbosity >= Verbosity::Verbose {
57 self.main_bar
58 .set_message(format!("Discovering: {}", style(org_name).cyan()));
59 }
60 }
61
62 fn on_org_complete(&self, org_name: &str, repo_count: usize) {
63 self.repo_count.fetch_add(repo_count, Ordering::SeqCst);
64 let total = self.repo_count.load(Ordering::SeqCst);
65 self.main_bar.set_message(format!(
66 "Discovered {} repos ({} from {})",
67 total,
68 repo_count,
69 style(org_name).cyan()
70 ));
71 }
72
73 fn on_personal_repos_started(&self) {
74 if self.verbosity >= Verbosity::Verbose {
75 self.main_bar
76 .set_message("Discovering personal repositories...");
77 }
78 }
79
80 fn on_personal_repos_complete(&self, count: usize) {
81 self.repo_count.fetch_add(count, Ordering::SeqCst);
82 let total = self.repo_count.load(Ordering::SeqCst);
83 self.main_bar
84 .set_message(format!("Discovered {} repos (including personal)", total));
85 }
86
87 fn on_error(&self, message: &str) {
88 if self.verbosity >= Verbosity::Normal {
89 self.main_bar.suspend(|| {
90 eprintln!("{} {}", style("⚠").yellow(), message);
91 });
92 }
93 }
94}
95
96#[cfg(test)]
97#[path = "discovery_tests.rs"]
98mod tests;