Skip to main content

git_same/output/progress/
clone.rs

1use crate::operations::clone::CloneProgress;
2use crate::output::Verbosity;
3use crate::types::OwnedRepo;
4use console::style;
5use indicatif::{MultiProgress, ProgressBar};
6
7use super::styles::progress_style;
8
9/// Progress reporter for clone operations.
10pub struct CloneProgressBar {
11    #[allow(dead_code)]
12    multi: MultiProgress,
13    main_bar: ProgressBar,
14    verbosity: Verbosity,
15}
16
17impl CloneProgressBar {
18    /// Creates a new clone progress bar.
19    pub fn new(total: usize, verbosity: Verbosity) -> Self {
20        let multi = MultiProgress::new();
21        let main_bar = multi.add(ProgressBar::new(total as u64));
22        main_bar.set_style(progress_style());
23        main_bar.set_message("Cloning repositories...");
24        main_bar.enable_steady_tick(std::time::Duration::from_millis(100));
25
26        Self {
27            multi,
28            main_bar,
29            verbosity,
30        }
31    }
32
33    /// Finishes the progress bar.
34    pub fn finish(&self, success: usize, failed: usize, skipped: usize) {
35        let msg = format!(
36            "{} {} cloned, {} failed, {} skipped",
37            style("✓").green(),
38            success,
39            failed,
40            skipped
41        );
42        self.main_bar.finish_with_message(msg);
43    }
44}
45
46impl CloneProgress for CloneProgressBar {
47    fn on_start(&self, repo: &OwnedRepo, _index: usize, _total: usize) {
48        if self.verbosity >= Verbosity::Verbose {
49            self.main_bar
50                .set_message(format!("Cloning {}...", style(repo.full_name()).cyan()));
51        }
52    }
53
54    fn on_complete(&self, repo: &OwnedRepo, _index: usize, _total: usize) {
55        self.main_bar.inc(1);
56        if self.verbosity >= Verbosity::Debug {
57            self.main_bar.suspend(|| {
58                println!("{} Cloned {}", style("✓").green(), repo.full_name());
59            });
60        }
61    }
62
63    fn on_error(&self, repo: &OwnedRepo, error: &str, _index: usize, _total: usize) {
64        self.main_bar.inc(1);
65        if self.verbosity >= Verbosity::Normal {
66            self.main_bar.suspend(|| {
67                eprintln!(
68                    "{} Failed to clone {}: {}",
69                    style("✗").red(),
70                    repo.full_name(),
71                    error
72                );
73            });
74        }
75    }
76
77    fn on_skip(&self, repo: &OwnedRepo, reason: &str, _index: usize, _total: usize) {
78        self.main_bar.inc(1);
79        if self.verbosity >= Verbosity::Verbose {
80            self.main_bar.suspend(|| {
81                println!(
82                    "{} Skipped {}: {}",
83                    style("→").dim(),
84                    repo.full_name(),
85                    reason
86                );
87            });
88        }
89    }
90}
91
92#[cfg(test)]
93#[path = "clone_tests.rs"]
94mod tests;