diff options
| -rw-r--r-- | Cargo.lock | 125 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/main.rs | 77 |
3 files changed, 181 insertions, 23 deletions
| @@ -3,6 +3,15 @@ | |||
| 3 | version = 3 | 3 | version = 3 |
| 4 | 4 | ||
| 5 | [[package]] | 5 | [[package]] |
| 6 | name = "aho-corasick" | ||
| 7 | version = "0.7.18" | ||
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" | ||
| 10 | dependencies = [ | ||
| 11 | "memchr", | ||
| 12 | ] | ||
| 13 | |||
| 14 | [[package]] | ||
| 6 | name = "ansi_term" | 15 | name = "ansi_term" |
| 7 | version = "0.12.1" | 16 | version = "0.12.1" |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | 17 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -41,6 +50,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 41 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | 50 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" |
| 42 | 51 | ||
| 43 | [[package]] | 52 | [[package]] |
| 53 | name = "cfg-if" | ||
| 54 | version = "1.0.0" | ||
| 55 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 56 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||
| 57 | |||
| 58 | [[package]] | ||
| 44 | name = "clap" | 59 | name = "clap" |
| 45 | version = "3.0.14" | 60 | version = "3.0.14" |
| 46 | source = "registry+https://github.com/rust-lang/crates.io-index" | 61 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -77,12 +92,37 @@ dependencies = [ | |||
| 77 | "ansi_term", | 92 | "ansi_term", |
| 78 | "anyhow", | 93 | "anyhow", |
| 79 | "clap", | 94 | "clap", |
| 95 | "flexi_logger", | ||
| 96 | "log", | ||
| 80 | "serde", | 97 | "serde", |
| 81 | "slotmap", | 98 | "slotmap", |
| 82 | "toml", | 99 | "toml", |
| 83 | ] | 100 | ] |
| 84 | 101 | ||
| 85 | [[package]] | 102 | [[package]] |
| 103 | name = "flexi_logger" | ||
| 104 | version = "0.22.3" | ||
| 105 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 106 | checksum = "969940c39bc718475391e53a3a59b0157e64929c80cf83ad5dde5f770ecdc423" | ||
| 107 | dependencies = [ | ||
| 108 | "ansi_term", | ||
| 109 | "atty", | ||
| 110 | "glob", | ||
| 111 | "lazy_static", | ||
| 112 | "log", | ||
| 113 | "regex", | ||
| 114 | "rustversion", | ||
| 115 | "thiserror", | ||
| 116 | "time", | ||
| 117 | ] | ||
| 118 | |||
| 119 | [[package]] | ||
| 120 | name = "glob" | ||
| 121 | version = "0.3.0" | ||
| 122 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 123 | checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" | ||
| 124 | |||
| 125 | [[package]] | ||
| 86 | name = "hashbrown" | 126 | name = "hashbrown" |
| 87 | version = "0.11.2" | 127 | version = "0.11.2" |
| 88 | source = "registry+https://github.com/rust-lang/crates.io-index" | 128 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -114,6 +154,12 @@ dependencies = [ | |||
| 114 | ] | 154 | ] |
| 115 | 155 | ||
| 116 | [[package]] | 156 | [[package]] |
| 157 | name = "itoa" | ||
| 158 | version = "1.0.1" | ||
| 159 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 160 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" | ||
| 161 | |||
| 162 | [[package]] | ||
| 117 | name = "lazy_static" | 163 | name = "lazy_static" |
| 118 | version = "1.4.0" | 164 | version = "1.4.0" |
| 119 | source = "registry+https://github.com/rust-lang/crates.io-index" | 165 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -126,12 +172,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 126 | checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" | 172 | checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" |
| 127 | 173 | ||
| 128 | [[package]] | 174 | [[package]] |
| 175 | name = "log" | ||
| 176 | version = "0.4.14" | ||
| 177 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 178 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" | ||
| 179 | dependencies = [ | ||
| 180 | "cfg-if", | ||
| 181 | ] | ||
| 182 | |||
| 183 | [[package]] | ||
| 129 | name = "memchr" | 184 | name = "memchr" |
| 130 | version = "2.4.1" | 185 | version = "2.4.1" |
| 131 | source = "registry+https://github.com/rust-lang/crates.io-index" | 186 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 132 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" | 187 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" |
| 133 | 188 | ||
| 134 | [[package]] | 189 | [[package]] |
| 190 | name = "num_threads" | ||
| 191 | version = "0.1.3" | ||
| 192 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 193 | checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" | ||
| 194 | dependencies = [ | ||
| 195 | "libc", | ||
| 196 | ] | ||
| 197 | |||
| 198 | [[package]] | ||
| 135 | name = "os_str_bytes" | 199 | name = "os_str_bytes" |
| 136 | version = "6.0.0" | 200 | version = "6.0.0" |
| 137 | source = "registry+https://github.com/rust-lang/crates.io-index" | 201 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -183,6 +247,29 @@ dependencies = [ | |||
| 183 | ] | 247 | ] |
| 184 | 248 | ||
| 185 | [[package]] | 249 | [[package]] |
| 250 | name = "regex" | ||
| 251 | version = "1.5.4" | ||
| 252 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 253 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" | ||
| 254 | dependencies = [ | ||
| 255 | "aho-corasick", | ||
| 256 | "memchr", | ||
| 257 | "regex-syntax", | ||
| 258 | ] | ||
| 259 | |||
| 260 | [[package]] | ||
| 261 | name = "regex-syntax" | ||
| 262 | version = "0.6.25" | ||
| 263 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 264 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" | ||
| 265 | |||
| 266 | [[package]] | ||
| 267 | name = "rustversion" | ||
| 268 | version = "1.0.6" | ||
| 269 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 270 | checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" | ||
| 271 | |||
| 272 | [[package]] | ||
| 186 | name = "serde" | 273 | name = "serde" |
| 187 | version = "1.0.136" | 274 | version = "1.0.136" |
| 188 | source = "registry+https://github.com/rust-lang/crates.io-index" | 275 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -244,6 +331,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 244 | checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" | 331 | checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" |
| 245 | 332 | ||
| 246 | [[package]] | 333 | [[package]] |
| 334 | name = "thiserror" | ||
| 335 | version = "1.0.30" | ||
| 336 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 337 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" | ||
| 338 | dependencies = [ | ||
| 339 | "thiserror-impl", | ||
| 340 | ] | ||
| 341 | |||
| 342 | [[package]] | ||
| 343 | name = "thiserror-impl" | ||
| 344 | version = "1.0.30" | ||
| 345 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 346 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" | ||
| 347 | dependencies = [ | ||
| 348 | "proc-macro2", | ||
| 349 | "quote", | ||
| 350 | "syn", | ||
| 351 | ] | ||
| 352 | |||
| 353 | [[package]] | ||
| 354 | name = "time" | ||
| 355 | version = "0.3.7" | ||
| 356 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 357 | checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" | ||
| 358 | dependencies = [ | ||
| 359 | "itoa", | ||
| 360 | "libc", | ||
| 361 | "num_threads", | ||
| 362 | "time-macros", | ||
| 363 | ] | ||
| 364 | |||
| 365 | [[package]] | ||
| 366 | name = "time-macros" | ||
| 367 | version = "0.2.3" | ||
| 368 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 369 | checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" | ||
| 370 | |||
| 371 | [[package]] | ||
| 247 | name = "toml" | 372 | name = "toml" |
| 248 | version = "0.5.8" | 373 | version = "0.5.8" |
| 249 | source = "registry+https://github.com/rust-lang/crates.io-index" | 374 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -9,6 +9,8 @@ edition = "2021" | |||
| 9 | ansi_term = "0.12.1" | 9 | ansi_term = "0.12.1" |
| 10 | anyhow = "1.0.53" | 10 | anyhow = "1.0.53" |
| 11 | clap = { version = "3.0.14", features = ["derive"] } | 11 | clap = { version = "3.0.14", features = ["derive"] } |
| 12 | flexi_logger = "0.22.3" | ||
| 13 | log = "0.4.14" | ||
| 12 | serde = { version = "1.0.136", features = ["derive"] } | 14 | serde = { version = "1.0.136", features = ["derive"] } |
| 13 | slotmap = "1.0.6" | 15 | slotmap = "1.0.6" |
| 14 | toml = "0.5.8" | 16 | toml = "0.5.8" |
diff --git a/src/main.rs b/src/main.rs index 1cb68d4..f623450 100644 --- a/src/main.rs +++ b/src/main.rs | |||
| @@ -923,7 +923,7 @@ pub mod dotup { | |||
| 923 | 923 | ||
| 924 | pub fn link(&mut self, origin: impl AsRef<Path>, destination: impl AsRef<Path>) { | 924 | pub fn link(&mut self, origin: impl AsRef<Path>, destination: impl AsRef<Path>) { |
| 925 | let link_result: anyhow::Result<()> = try { | 925 | let link_result: anyhow::Result<()> = try { |
| 926 | let origin = self.prepare_origin_path(origin.as_ref())?; | 926 | let origin = self.prepare_relative_path(origin.as_ref())?; |
| 927 | let destination = destination.as_ref(); | 927 | let destination = destination.as_ref(); |
| 928 | self.depot.link_create(origin, destination)?; | 928 | self.depot.link_create(origin, destination)?; |
| 929 | }; | 929 | }; |
| @@ -936,7 +936,7 @@ pub mod dotup { | |||
| 936 | pub fn unlink(&mut self, paths: impl Iterator<Item = impl AsRef<Path>>) { | 936 | pub fn unlink(&mut self, paths: impl Iterator<Item = impl AsRef<Path>>) { |
| 937 | for origin in paths { | 937 | for origin in paths { |
| 938 | let unlink_result: anyhow::Result<()> = try { | 938 | let unlink_result: anyhow::Result<()> = try { |
| 939 | let origin = self.prepare_origin_path(origin.as_ref())?; | 939 | let origin = self.prepare_relative_path(origin.as_ref())?; |
| 940 | let search_results = self.depot.link_search(&origin)?; | 940 | let search_results = self.depot.link_search(&origin)?; |
| 941 | match search_results { | 941 | match search_results { |
| 942 | depot::SearchResult::Found(link_id) => { | 942 | depot::SearchResult::Found(link_id) => { |
| @@ -959,7 +959,7 @@ pub mod dotup { | |||
| 959 | let mut already_linked: HashSet<LinkID> = Default::default(); | 959 | let mut already_linked: HashSet<LinkID> = Default::default(); |
| 960 | for origin in paths { | 960 | for origin in paths { |
| 961 | let install_result: anyhow::Result<()> = try { | 961 | let install_result: anyhow::Result<()> = try { |
| 962 | let origin = self.prepare_origin_path(origin.as_ref())?; | 962 | let origin = self.prepare_relative_path(origin.as_ref())?; |
| 963 | let canonical_pairs = self.canonical_pairs_under(&origin)?; | 963 | let canonical_pairs = self.canonical_pairs_under(&origin)?; |
| 964 | for pair in canonical_pairs { | 964 | for pair in canonical_pairs { |
| 965 | if already_linked.contains(&pair.link_id) { | 965 | if already_linked.contains(&pair.link_id) { |
| @@ -978,7 +978,7 @@ pub mod dotup { | |||
| 978 | pub fn uninstall(&self, paths: impl Iterator<Item = impl AsRef<Path>>) { | 978 | pub fn uninstall(&self, paths: impl Iterator<Item = impl AsRef<Path>>) { |
| 979 | for origin in paths { | 979 | for origin in paths { |
| 980 | let uninstall_result: anyhow::Result<()> = try { | 980 | let uninstall_result: anyhow::Result<()> = try { |
| 981 | let origin = self.prepare_origin_path(origin.as_ref())?; | 981 | let origin = self.prepare_relative_path(origin.as_ref())?; |
| 982 | let canonical_pairs = self.canonical_pairs_under(&origin)?; | 982 | let canonical_pairs = self.canonical_pairs_under(&origin)?; |
| 983 | for pair in canonical_pairs { | 983 | for pair in canonical_pairs { |
| 984 | self.symlink_uninstall(&pair.origin, &pair.destination)?; | 984 | self.symlink_uninstall(&pair.origin, &pair.destination)?; |
| @@ -1001,7 +1001,7 @@ pub mod dotup { | |||
| 1001 | let origins = { | 1001 | let origins = { |
| 1002 | let mut v = Vec::new(); | 1002 | let mut v = Vec::new(); |
| 1003 | for origin in origins { | 1003 | for origin in origins { |
| 1004 | match self.prepare_origin_path(origin.as_ref()) { | 1004 | match self.prepare_relative_path(origin.as_ref()) { |
| 1005 | Ok(origin) => v.push(origin), | 1005 | Ok(origin) => v.push(origin), |
| 1006 | Err(e) => { | 1006 | Err(e) => { |
| 1007 | println!("invalid link {} : {e}", origin.as_ref().display()); | 1007 | println!("invalid link {} : {e}", origin.as_ref().display()); |
| @@ -1066,7 +1066,7 @@ pub mod dotup { | |||
| 1066 | fn status_path_to_item(&self, canonical_path: &Path) -> anyhow::Result<StatusItem> { | 1066 | fn status_path_to_item(&self, canonical_path: &Path) -> anyhow::Result<StatusItem> { |
| 1067 | debug_assert!(canonical_path.is_absolute()); | 1067 | debug_assert!(canonical_path.is_absolute()); |
| 1068 | debug_assert!(canonical_path.exists()); | 1068 | debug_assert!(canonical_path.exists()); |
| 1069 | let relative_path = self.prepare_origin_path(&canonical_path)?; | 1069 | let relative_path = self.prepare_relative_path(&canonical_path)?; |
| 1070 | 1070 | ||
| 1071 | let item = if canonical_path.is_dir() { | 1071 | let item = if canonical_path.is_dir() { |
| 1072 | if let Some(link_id) = self.depot.link_find(&relative_path)? { | 1072 | if let Some(link_id) = self.depot.link_find(&relative_path)? { |
| @@ -1204,7 +1204,7 @@ pub mod dotup { | |||
| 1204 | .unwrap_or_default() | 1204 | .unwrap_or_default() |
| 1205 | } | 1205 | } |
| 1206 | 1206 | ||
| 1207 | fn prepare_origin_path(&self, origin: &Path) -> anyhow::Result<PathBuf> { | 1207 | fn prepare_relative_path(&self, origin: &Path) -> anyhow::Result<PathBuf> { |
| 1208 | let canonical = utils::weakly_canonical(origin); | 1208 | let canonical = utils::weakly_canonical(origin); |
| 1209 | let relative = canonical | 1209 | let relative = canonical |
| 1210 | .strip_prefix(&self.depot_dir) | 1210 | .strip_prefix(&self.depot_dir) |
| @@ -1214,7 +1214,7 @@ pub mod dotup { | |||
| 1214 | 1214 | ||
| 1215 | // returns the canonical pairs for all links under `path`. | 1215 | // returns the canonical pairs for all links under `path`. |
| 1216 | fn canonical_pairs_under(&self, path: &Path) -> anyhow::Result<Vec<CanonicalPair>> { | 1216 | fn canonical_pairs_under(&self, path: &Path) -> anyhow::Result<Vec<CanonicalPair>> { |
| 1217 | let origin = self.prepare_origin_path(path)?; | 1217 | let origin = self.prepare_relative_path(path)?; |
| 1218 | let mut canonical_pairs = Vec::new(); | 1218 | let mut canonical_pairs = Vec::new(); |
| 1219 | for link_id in self.depot.links_under(origin)? { | 1219 | for link_id in self.depot.links_under(origin)? { |
| 1220 | canonical_pairs.push(self.canonical_pair_from_link_id(link_id)); | 1220 | canonical_pairs.push(self.canonical_pair_from_link_id(link_id)); |
| @@ -1250,11 +1250,19 @@ pub mod dotup { | |||
| 1250 | fn symlink_install(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> { | 1250 | fn symlink_install(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> { |
| 1251 | debug_assert!(origin.is_absolute()); | 1251 | debug_assert!(origin.is_absolute()); |
| 1252 | debug_assert!(destination.is_absolute()); | 1252 | debug_assert!(destination.is_absolute()); |
| 1253 | log::debug!( | ||
| 1254 | "symlink_install : {} -> {}", | ||
| 1255 | origin.display(), | ||
| 1256 | destination.display() | ||
| 1257 | ); | ||
| 1253 | 1258 | ||
| 1254 | if let Some(destination_parent) = destination.parent() { | 1259 | let destination_parent = destination |
| 1255 | std::fs::create_dir_all(destination_parent) | 1260 | .parent() |
| 1256 | .context("Failed to create directories")?; | 1261 | .ok_or_else(|| anyhow::anyhow!("destination has no parent component"))?; |
| 1257 | } | 1262 | std::fs::create_dir_all(destination_parent).context("Failed to create directories")?; |
| 1263 | // need to do this beacause if the destination path ends in '/' because the symlink | ||
| 1264 | // functions will treat it as a directory but we want a file with that name. | ||
| 1265 | let destination = destination.with_file_name(destination.file_name().unwrap()); | ||
| 1258 | 1266 | ||
| 1259 | let destination_exists = destination.exists(); | 1267 | let destination_exists = destination.exists(); |
| 1260 | let destination_is_symlink = destination.is_symlink(); | 1268 | let destination_is_symlink = destination.is_symlink(); |
| @@ -1264,9 +1272,16 @@ pub mod dotup { | |||
| 1264 | } | 1272 | } |
| 1265 | 1273 | ||
| 1266 | if destination_is_symlink { | 1274 | if destination_is_symlink { |
| 1275 | log::debug!("symlink already exists, removing before recreating"); | ||
| 1267 | std::fs::remove_file(&destination)?; | 1276 | std::fs::remove_file(&destination)?; |
| 1268 | } | 1277 | } |
| 1269 | std::os::unix::fs::symlink(origin, destination).context("Failed to create symlink")?; | 1278 | |
| 1279 | log::debug!( | ||
| 1280 | "creating filesystem symlink {} -> {}", | ||
| 1281 | origin.display(), | ||
| 1282 | destination.display() | ||
| 1283 | ); | ||
| 1284 | std::os::unix::fs::symlink(origin, destination).context("failed to create symlink")?; | ||
| 1270 | 1285 | ||
| 1271 | Ok(()) | 1286 | Ok(()) |
| 1272 | } | 1287 | } |
| @@ -1274,6 +1289,7 @@ pub mod dotup { | |||
| 1274 | fn symlink_uninstall(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> { | 1289 | fn symlink_uninstall(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> { |
| 1275 | debug_assert!(origin.is_absolute()); | 1290 | debug_assert!(origin.is_absolute()); |
| 1276 | debug_assert!(destination.is_absolute()); | 1291 | debug_assert!(destination.is_absolute()); |
| 1292 | let destination = destination.with_file_name(destination.file_name().unwrap()); | ||
| 1277 | 1293 | ||
| 1278 | if destination.is_symlink() { | 1294 | if destination.is_symlink() { |
| 1279 | let symlink_destination = destination.read_link()?.canonicalize()?; | 1295 | let symlink_destination = destination.read_link()?.canonicalize()?; |
| @@ -1329,16 +1345,6 @@ mod utils { | |||
| 1329 | 1345 | ||
| 1330 | pub const DEFAULT_DEPOT_FILE_NAME: &str = ".depot"; | 1346 | pub const DEFAULT_DEPOT_FILE_NAME: &str = ".depot"; |
| 1331 | 1347 | ||
| 1332 | /// collects the result of std::fs::read_dir into two vecs, the first one contains all the | ||
| 1333 | /// directories and the second one all the files. | ||
| 1334 | pub fn collect_read_dir_split( | ||
| 1335 | dir: impl AsRef<Path>, | ||
| 1336 | ) -> anyhow::Result<(Vec<PathBuf>, Vec<PathBuf>)> { | ||
| 1337 | Ok(collect_paths_in_dir(dir)? | ||
| 1338 | .into_iter() | ||
| 1339 | .partition(|p| p.is_dir())) | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | pub fn collect_paths_in_dir(dir: impl AsRef<Path>) -> anyhow::Result<Vec<PathBuf>> { | 1348 | pub fn collect_paths_in_dir(dir: impl AsRef<Path>) -> anyhow::Result<Vec<PathBuf>> { |
| 1343 | Ok(std::fs::read_dir(dir)? | 1349 | Ok(std::fs::read_dir(dir)? |
| 1344 | .filter_map(|e| e.ok()) | 1350 | .filter_map(|e| e.ok()) |
| @@ -1465,6 +1471,7 @@ mod utils { | |||
| 1465 | use std::path::PathBuf; | 1471 | use std::path::PathBuf; |
| 1466 | 1472 | ||
| 1467 | use clap::Parser; | 1473 | use clap::Parser; |
| 1474 | use flexi_logger::Logger; | ||
| 1468 | use utils::DEFAULT_DEPOT_FILE_NAME; | 1475 | use utils::DEFAULT_DEPOT_FILE_NAME; |
| 1469 | 1476 | ||
| 1470 | #[derive(Parser, Debug)] | 1477 | #[derive(Parser, Debug)] |
| @@ -1478,8 +1485,19 @@ pub struct Flags { | |||
| 1478 | #[derive(Parser, Debug)] | 1485 | #[derive(Parser, Debug)] |
| 1479 | #[clap(author, version, about, long_about = None)] | 1486 | #[clap(author, version, about, long_about = None)] |
| 1480 | struct Args { | 1487 | struct Args { |
| 1488 | /// A level of verbosity, and can be used multiple times | ||
| 1489 | /// | ||
| 1490 | /// Level 1 - Info | ||
| 1491 | /// | ||
| 1492 | /// Level 2 - Debug | ||
| 1493 | /// | ||
| 1494 | /// Level 3 - Trace | ||
| 1495 | #[clap(short, long, parse(from_occurrences))] | ||
| 1496 | verbose: i32, | ||
| 1497 | |||
| 1481 | #[clap(flatten)] | 1498 | #[clap(flatten)] |
| 1482 | flags: Flags, | 1499 | flags: Flags, |
| 1500 | |||
| 1483 | #[clap(subcommand)] | 1501 | #[clap(subcommand)] |
| 1484 | command: SubCommand, | 1502 | command: SubCommand, |
| 1485 | } | 1503 | } |
| @@ -1497,6 +1515,19 @@ enum SubCommand { | |||
| 1497 | 1515 | ||
| 1498 | fn main() -> anyhow::Result<()> { | 1516 | fn main() -> anyhow::Result<()> { |
| 1499 | let args = Args::parse(); | 1517 | let args = Args::parse(); |
| 1518 | |||
| 1519 | let log_level = match args.verbose { | ||
| 1520 | 0 => "warn", | ||
| 1521 | 1 => "info", | ||
| 1522 | 2 => "debug", | ||
| 1523 | _ => "trace", | ||
| 1524 | }; | ||
| 1525 | |||
| 1526 | Logger::try_with_env_or_str(log_level)? | ||
| 1527 | .format(flexi_logger::colored_default_format) | ||
| 1528 | .set_palette("196;208;32;198;15".to_string()) | ||
| 1529 | .start()?; | ||
| 1530 | |||
| 1500 | match args.command { | 1531 | match args.command { |
| 1501 | SubCommand::Init(cmd_args) => command_init(args.flags, cmd_args), | 1532 | SubCommand::Init(cmd_args) => command_init(args.flags, cmd_args), |
| 1502 | SubCommand::Link(cmd_args) => command_link(args.flags, cmd_args), | 1533 | SubCommand::Link(cmd_args) => command_link(args.flags, cmd_args), |
