summaryrefslogtreecommitdiff
path: root/src/backup_progress.rs
blob: e3995f01f366e624b687c70647cf36efe026fc90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Progress bars for Obnam.

use crate::generation::GenId;
use indicatif::{ProgressBar, ProgressStyle};
use std::{path::Path, time::Duration};

const SHOW_PROGRESS: bool = true;

/// A progress bar abstraction specific to backups.
///
/// The progress bar is different for initial and incremental backups,
/// and for different phases of making a backup.
pub struct BackupProgress {
    progress: ProgressBar,
}

impl BackupProgress {
    /// Create a progress bar for an initial backup.
    pub fn initial() -> Self {
        let progress = if SHOW_PROGRESS {
            ProgressBar::new(0)
        } else {
            ProgressBar::hidden()
        };
        let parts = [
            "initial backup",
            "elapsed: {elapsed}",
            "files: {pos}",
            "current: {wide_msg}",
            "{spinner}",
        ];
        progress.set_style(
            ProgressStyle::default_bar()
                .template(&parts.join("\n"))
                .expect("create indicatif ProgressStyle value"),
        );
        progress.enable_steady_tick(Duration::from_millis(100));

        Self { progress }
    }

    /// Create a progress bar for an incremental backup.
    pub fn incremental() -> Self {
        let progress = if SHOW_PROGRESS {
            ProgressBar::new(0)
        } else {
            ProgressBar::hidden()
        };
        let parts = [
            "incremental backup",
            "{wide_bar}",
            "elapsed: {elapsed}",
            "files: {pos}/{len}",
            "current: {wide_msg}",
            "{spinner}",
        ];
        progress.set_style(
            ProgressStyle::default_bar()
                .template(&parts.join("\n"))
                .expect("create indicatif ProgressStyle value"),
        );
        progress.enable_steady_tick(Duration::from_millis(100));

        Self { progress }
    }

    /// Create a progress bar for uploading a new generation's metadata.
    pub fn upload_generation() -> Self {
        let progress = ProgressBar::new(0);
        let parts = [
            "uploading new generation metadata",
            "elapsed: {elapsed}",
            "{spinner}",
        ];
        progress.set_style(
            ProgressStyle::default_bar()
                .template(&parts.join("\n"))
                .expect("create indicatif ProgressStyle value"),
        );
        progress.enable_steady_tick(Duration::from_millis(100));

        Self { progress }
    }

    /// Create a progress bar for downloading an existing generation's
    /// metadata.
    pub fn download_generation(gen_id: &GenId) -> Self {
        let progress = ProgressBar::new(0);
        let parts = ["{msg}", "elapsed: {elapsed}", "{spinner}"];
        progress.set_style(
            ProgressStyle::default_bar()
                .template(&parts.join("\n"))
                .expect("create indicatif ProgressStyle value"),
        );
        progress.enable_steady_tick(Duration::from_millis(100));
        progress.set_message(format!(
            "downloading previous generation metadata: {}",
            gen_id
        ));

        Self { progress }
    }

    /// Set the number of files that were in the previous generation.
    ///
    /// The new generation usually has about the same number of files,
    /// so the progress bar can show progress for incremental backups
    /// without having to count all the files that actually exist first.
    pub fn files_in_previous_generation(&self, count: u64) {
        self.progress.set_length(count);
    }

    /// Update progress bar about number of problems found during a backup.
    pub fn found_problem(&self) {
        self.progress.inc(1);
    }

    /// Update progress bar about number of actual files found.
    pub fn found_live_file(&self, filename: &Path) {
        self.progress.inc(1);
        if self.progress.length() < Some(self.progress.position()) {
            self.progress.set_length(self.progress.position());
        }
        self.progress.set_message(format!("{}", filename.display()));
    }

    /// Tell progress bar it's finished.
    ///
    /// This will remove all traces of the progress bar from the
    /// screen.
    pub fn finish(&self) {
        self.progress.set_length(self.progress.position());
        self.progress.finish_and_clear();
    }
}