purple_ssh/app/
reload_state.rs1use std::path::{Path, PathBuf};
4use std::time::SystemTime;
5
6use crate::ssh_config::model::SshConfigFile;
7
8#[derive(Default)]
10pub struct ReloadState {
11 pub(in crate::app) config_path: PathBuf,
12 pub(in crate::app) last_modified: Option<SystemTime>,
13 pub(in crate::app) include_mtimes: Vec<(PathBuf, Option<SystemTime>)>,
14 pub(in crate::app) include_dir_mtimes: Vec<(PathBuf, Option<SystemTime>)>,
15 pub(in crate::app) keys_dir_mtime: Option<SystemTime>,
19 pub(in crate::app) key_file_mtimes: Vec<(PathBuf, Option<SystemTime>)>,
23}
24
25#[derive(Default)]
27pub struct ConflictState {
28 pub form_mtime: Option<SystemTime>,
29 pub form_include_mtimes: Vec<(PathBuf, Option<SystemTime>)>,
30 pub form_include_dir_mtimes: Vec<(PathBuf, Option<SystemTime>)>,
31 pub provider_form_mtime: Option<SystemTime>,
32}
33
34impl ConflictState {
35 pub fn clear_form_mtimes(&mut self) {
37 self.form_mtime = None;
38 self.form_include_mtimes.clear();
39 self.form_include_dir_mtimes.clear();
40 self.provider_form_mtime = None;
41 }
42}
43
44pub(crate) fn config_changed(conflict: &ConflictState, config_path: &Path) -> bool {
47 match conflict.form_mtime {
48 Some(open_mtime) => {
49 if get_mtime(config_path) != Some(open_mtime) {
50 return true;
51 }
52 conflict
53 .form_include_mtimes
54 .iter()
55 .any(|(path, old_mtime)| get_mtime(path) != *old_mtime)
56 || conflict
57 .form_include_dir_mtimes
58 .iter()
59 .any(|(path, old_mtime)| get_mtime(path) != *old_mtime)
60 }
61 None => false,
62 }
63}
64
65impl ReloadState {
66 pub fn config_path(&self) -> &Path {
67 &self.config_path
68 }
69
70 pub fn from_config(config: &SshConfigFile) -> Self {
73 let config_path = config.path.clone();
74 let last_modified = get_mtime(&config_path);
75 let include_mtimes = snapshot_include_mtimes(config);
76 let include_dir_mtimes = snapshot_include_dir_mtimes(config);
77 Self {
78 config_path,
79 last_modified,
80 include_mtimes,
81 include_dir_mtimes,
82 keys_dir_mtime: None,
83 key_file_mtimes: Vec::new(),
84 }
85 }
86}
87
88pub fn get_mtime(path: &Path) -> Option<SystemTime> {
90 std::fs::metadata(path).ok()?.modified().ok()
91}
92
93pub fn snapshot_include_mtimes(config: &SshConfigFile) -> Vec<(PathBuf, Option<SystemTime>)> {
95 config
96 .include_paths()
97 .into_iter()
98 .map(|p| {
99 let mtime = get_mtime(&p);
100 (p, mtime)
101 })
102 .collect()
103}
104
105pub fn snapshot_include_dir_mtimes(config: &SshConfigFile) -> Vec<(PathBuf, Option<SystemTime>)> {
107 config
108 .include_glob_dirs()
109 .into_iter()
110 .map(|p| {
111 let mtime = get_mtime(&p);
112 (p, mtime)
113 })
114 .collect()
115}
116
117pub fn snapshot_key_mtimes(
122 ssh_dir: &Path,
123 keys: &[crate::ssh_keys::SshKeyInfo],
124) -> Vec<(PathBuf, Option<SystemTime>)> {
125 keys.iter()
126 .map(|k| {
127 let pub_path = ssh_dir.join(format!("{}.pub", k.name));
128 let mtime = get_mtime(&pub_path);
129 (pub_path, mtime)
130 })
131 .collect()
132}