sagiegurari / cargo-make
1
//! # version
2
//!
3
//! Checks if the currently running version is the most up to date version and
4
//! if not, it will print a notification message.
5
//!
6

7
#[cfg(test)]
8
#[path = "./version_test.rs"]
9
mod version_test;
10

11
use crate::cache;
12
use crate::command;
13
use crate::types::{Cache, GlobalConfig};
14
use semver::Version;
15
use std::process::Command;
16
use std::time::{SystemTime, UNIX_EPOCH};
17

18
static VERSION: &str = env!("CARGO_PKG_VERSION");
19

20 8
fn get_version_from_output(line: &str) -> Option<String> {
21 8
    let parts: Vec<&str> = line.split(' ').collect();
22

23 8
    if parts.len() >= 3 {
24 8
        let version_part = parts[2];
25 8
        let version = str::replace(version_part, "\"", "");
26

27 8
        Some(version)
28
    } else {
29 8
        None
30
    }
31 8
}
32

33 8
fn get_latest_version() -> Option<String> {
34 8
    let result = Command::new("cargo")
35
        .arg("search")
36
        .arg("cargo-make")
37 8
        .output();
38

39 8
    match result {
40 8
        Ok(output) => {
41 8
            let exit_code = command::get_exit_code(Ok(output.status), false);
42 8
            if exit_code == 0 {
43 8
                let stdout = String::from_utf8_lossy(&output.stdout);
44 8
                let lines: Vec<&str> = stdout.split('\n').collect();
45

46 8
                let mut output = None;
47 8
                for mut line in lines {
48 8
                    line = line.trim();
49

50 8
                    debug!("Checking: {}", &line);
51

52 8
                    if line.starts_with("cargo-make = ") {
53 8
                        output = get_version_from_output(line);
54

55 6
                        break;
56
                    }
57 8
                }
58

59 8
                output
60 8
            } else {
61 0
                None
62
            }
63 6
        }
64 2
        _ => None,
65
    }
66 8
}
67

68 8
pub(crate) fn is_newer(old_string: &str, new_string: &str, default_result: bool) -> bool {
69 8
    let old_version = Version::parse(old_string);
70 8
    match old_version {
71 8
        Ok(old_values) => {
72 8
            let new_version = Version::parse(new_string);
73

74 8
            match new_version {
75 8
                Ok(new_values) => {
76 8
                    if new_values.major > old_values.major {
77 8
                        true
78 8
                    } else if new_values.major == old_values.major {
79 8
                        if new_values.minor > old_values.minor {
80 8
                            true
81
                        } else {
82 8
                            new_values.minor == old_values.minor
83 8
                                && new_values.patch > old_values.patch
84
                        }
85
                    } else {
86 8
                        false
87
                    }
88 6
                }
89 8
                _ => default_result,
90
            }
91 4
        }
92 2
        _ => default_result,
93
    }
94 8
}
95

96 8
pub(crate) fn is_newer_found(version_string: &str) -> bool {
97 8
    debug!("Checking Version: {}", &version_string);
98

99 8
    is_newer(&VERSION, &version_string, false)
100 8
}
101

102 8
fn print_notification(latest_string: &str) {
103 8
    warn!("#####################################################################");
104 8
    warn!("#                                                                   #");
105 8
    warn!("#                                                                   #");
106 8
    warn!("#                  NEW CARGO-MAKE VERSION FOUND!!!                  #");
107 8
    warn!(
108 0
        "#                  Current: {}, Latest: {}\t\t\t#",
109
        VERSION, latest_string
110
    );
111 8
    warn!("#    Run 'cargo install --force cargo-make' to get latest version   #");
112 8
    warn!("#                                                                   #");
113 8
    warn!("#                                                                   #");
114 8
    warn!("#####################################################################");
115 8
}
116

117 8
fn get_now_as_seconds() -> u64 {
118 8
    let now = SystemTime::now();
119 8
    match now.duration_since(UNIX_EPOCH) {
120 8
        Ok(duration) => duration.as_secs(),
121 0
        _ => 0,
122
    }
123 8
}
124

125 8
fn has_amount_of_days_passed_from_last_check(days: u64, last_check_seconds: u64) -> bool {
126 8
    let now_seconds = get_now_as_seconds();
127 8
    if now_seconds > 0 && days > 0 {
128 8
        if last_check_seconds > now_seconds {
129 0
            false
130
        } else {
131 8
            let diff_seconds = now_seconds - last_check_seconds;
132 8
            let minimum_diff_seconds = days * 24 * 60 * 60;
133

134 8
            diff_seconds >= minimum_diff_seconds
135
        }
136
    } else {
137 8
        true
138
    }
139 8
}
140

141 8
fn has_amount_of_days_passed(days: u64, cache_data: &Cache) -> bool {
142 8
    match cache_data.last_update_check {
143 8
        Some(last_check_seconds) => {
144 8
            has_amount_of_days_passed_from_last_check(days, last_check_seconds)
145
        }
146 8
        None => true,
147
    }
148 8
}
149

150 8
fn get_days(global_config: &GlobalConfig) -> u64 {
151 8
    match global_config.update_check_minimum_interval {
152 8
        Some(ref value) => {
153 8
            if value == "always" {
154 8
                0
155 8
            } else if value == "daily" {
156 8
                1
157 8
            } else if value == "monthly" {
158 8
                30
159
            } else {
160
                // default to weekly
161 8
                7
162
            }
163
        }
164 8
        None => 7, // default to weekly
165
    }
166 8
}
167

168 8
pub(crate) fn should_check(global_config: &GlobalConfig) -> bool {
169 8
    let days = get_days(global_config);
170

171 8
    if days > 0 {
172 8
        let cache_data = cache::load();
173 8
        has_amount_of_days_passed(1, &cache_data)
174 8
    } else {
175 8
        true
176
    }
177 8
}
178

179 8
pub(crate) fn check() {
180 8
    let latest = get_latest_version();
181

182 8
    let mut cache_data = cache::load();
183 8
    let now = get_now_as_seconds();
184 8
    if now > 0 {
185 8
        cache_data.last_update_check = Some(now);
186 8
        cache::store(&cache_data);
187
    }
188

189 8
    match latest {
190 8
        Some(value) => {
191 8
            if is_newer_found(&value) {
192 0
                print_notification(&value);
193
            }
194 6
        }
195 2
        None => (),
196
    }
197 8
}

Read our documentation on viewing source code .

Loading