Skip to main content

git_same/output/progress/
discovery.rs

1use 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
10/// Progress reporter for discovery operations.
11pub 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    /// Creates a new discovery progress bar.
21    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    /// Finishes the progress bar.
37    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;