From a7c81d59767236706c28a58137adf8c03312bf4d Mon Sep 17 00:00:00 2001 From: qwjyh Date: Wed, 19 Jun 2024 18:31:29 +0900 Subject: [PATCH 01/28] bump to v0.2.1 --- CHANGELOG.md | 4 ++-- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7000c8b..982082d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [Unreleased] +## [0.2.1] - 2024-06-19 ### Changed - Dependencies are updated. @@ -30,6 +30,6 @@ - `backup done` subcommand - `completion` subcommand -[Unreleased]: https://github.com/qwjyh/xdbm/compare/v0.2.0...HEAD +[0.2.1]: https://github.com/qwjyh/xdbm/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/qwjyh/xdbm/releases/tag/v0.2.0 [0.1.0]: https://github.com/qwjyh/xdbm/releases/tag/v0.1.0 diff --git a/Cargo.lock b/Cargo.lock index 8b744bd..efc48ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1825,7 +1825,7 @@ dependencies = [ [[package]] name = "xdbm" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow", "assert_cmd", diff --git a/Cargo.toml b/Cargo.toml index 3148273..8c7aa5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "xdbm" -version = "0.2.0" +version = "0.2.1" authors = ["qwjyh "] edition = "2021" description = "Cross device backup manager, which manages backups on several storages mounted on multiple devices." From ea0acf177ce1f4caec7fb07bebedbe42f8299c4b Mon Sep 17 00:00:00 2001 From: qwjyh <62229267+qwjyh@users.noreply.github.com> Date: Thu, 27 Jun 2024 18:06:27 +0900 Subject: [PATCH 02/28] pretty printing (#15) * pretty printing for `backup list` and `backup list --long` * switch coloring crate from colored to console - console can handle Style separately * Style for storage list --- Cargo.lock | 26 +++++++++++++++ Cargo.toml | 1 + src/cmd_backup.rs | 80 +++++++++++++++++++++++++++++++++++----------- src/cmd_storage.rs | 20 ++++++------ src/storages.rs | 11 ++++++- src/util.rs | 1 + 6 files changed, 111 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efc48ce..acb12dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -347,6 +347,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -454,6 +467,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "env_filter" version = "0.1.0" @@ -724,6 +743,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -1835,6 +1860,7 @@ dependencies = [ "clap", "clap-verbosity-flag", "clap_complete", + "console", "dirs", "dunce", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 8c7aa5a..c11d975 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ byte-unit = "5.1.4" anyhow = "1.0" pathdiff = "0.2.1" unicode-width = "0.1.13" +console = "0.15" [dev-dependencies] assert_cmd = "2.0.14" diff --git a/src/cmd_backup.rs b/src/cmd_backup.rs index 618ad6c..bcfd42b 100644 --- a/src/cmd_backup.rs +++ b/src/cmd_backup.rs @@ -5,7 +5,8 @@ use std::{ }; use anyhow::{anyhow, Context, Ok, Result}; -use chrono::Local; +use chrono::{Local, TimeDelta}; +use console::Style; use dunce::canonicalize; use git2::Repository; use unicode_width::UnicodeWidthStr; @@ -153,6 +154,17 @@ pub fn cmd_backup_list( Ok(()) } +fn duration_style(time: TimeDelta) -> Style { + match time { + x if x < TimeDelta::days(7) => Style::new().green(), + x if x < TimeDelta::days(14) => Style::new().yellow(), + x if x < TimeDelta::days(28) => Style::new().magenta(), + x if x < TimeDelta::days(28 * 3) => Style::new().red(), + x if x < TimeDelta::days(180) => Style::new().red().bold(), + _ => Style::new().on_red().black(), + } +} + /// TODO: status printing fn write_backups_list( mut writer: impl io::Write, @@ -188,39 +200,71 @@ fn write_backups_list( // main printing for ((dev, _name), backup) in &backups { let device = backup.device(devices).context(format!( - "Couldn't find device specified in backup config {}", + "Couldn't find the device specified in the backup config: {}", backup.name() ))?; let src = backup.source().path(storages, device)?; let dest = backup.destination().path(storages, device)?; let cmd_name = backup.command().name(); - let last_backup_elapsed = match backup.last_backup() { + let (last_backup_elapsed, style_on_time_elapsed) = match backup.last_backup() { Some(log) => { let time = Local::now() - log.datetime; - util::format_summarized_duration(time) + let s = util::format_summarized_duration(time); + let style = duration_style(time); + (style.apply_to(s), style) } - None => "---".to_string(), + None => { + let style = Style::new().red(); + (style.apply_to("---".to_string()), style) + }, }; - writeln!( - writer, - "{name: date.datetime.format("%Y-%m-%d %T").to_string(), + None => "never".to_string(), + }; + let cmd_note = backup.command().note(); + writeln!( + writer, + "{s_src} {src}", + s_src = console::style("src :").italic().bright().black(), + src = src.display() + )?; + writeln!( + writer, + "{s_dest} {dest}", + s_dest = console::style("dest:").italic().bright().black(), dest = dest.display() )?; writeln!( writer, - " {cmd_name:10} {parent:10} {parent: s.kind(), - Storage::SubDirectory(s) => &s.notes, - Storage::Online(s) => &s.provider, + Storage::Physical(s) => format!("kind: {}", s.kind()), + Storage::SubDirectory(s) => s.notes.clone(), + Storage::Online(s) => s.provider.clone(), }; - writeln!(writer, " {}", note)?; + writeln!(writer, " {}", style(note).italic())?; } } Ok(()) diff --git a/src/storages.rs b/src/storages.rs index 8137546..7562b0e 100644 --- a/src/storages.rs +++ b/src/storages.rs @@ -1,5 +1,6 @@ //! Manipulates storages. +use console::{style, Style, StyledObject}; use crate::devices; use crate::storages::{ directory::Directory, online_storage::OnlineStorage, @@ -9,7 +10,7 @@ use anyhow::{anyhow, Context, Result}; use clap::ValueEnum; use core::panic; use serde::{Deserialize, Serialize}; -use std::{collections::BTreeMap, fmt, fs, io, path, u64}; +use std::{collections::BTreeMap, fmt, fs, io, path}; /// YAML file to store known storages.. pub const STORAGESFILE: &str = "storages.yml"; @@ -50,6 +51,14 @@ impl Storage { Self::Online(_) => "O", } } + + pub fn typestyle(&self) -> Style { + match self { + Storage::Physical(_) => Style::new().cyan(), + Storage::SubDirectory(_) => Style::new().yellow(), + Storage::Online(_) => Style::new().green(), + } + } } impl StorageExt for Storage { diff --git a/src/util.rs b/src/util.rs index 36c6714..820de33 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,7 @@ use std::path::{self, PathBuf}; use anyhow::{Context, Result}; +use console::Style; use crate::{ devices::Device, From 3b7e2387bdee8579bc802172c0b545342f43a9c7 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Thu, 27 Jun 2024 20:41:54 +0900 Subject: [PATCH 03/28] update CHANGELOG & README for #15 --- CHANGELOG.md | 6 ++++++ README.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 982082d..685004c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [Unreleased] + +### Changed +- Colored output for `storage list` and `backup list` ([#15](https://github.com/qwjyh/xdbm/pull/15)) + ## [0.2.1] - 2024-06-19 ### Changed @@ -30,6 +35,7 @@ - `backup done` subcommand - `completion` subcommand +[Unreleased]: https://github.com/qwjyh/xdbm/compare/v0.2.1...HEAD [0.2.1]: https://github.com/qwjyh/xdbm/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/qwjyh/xdbm/releases/tag/v0.2.0 [0.1.0]: https://github.com/qwjyh/xdbm/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 15010ee..c626656 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ which manages backups on several storages mounted on multiple devices with a sin - [x] backup list - [x] status printing - [x] backup done -- [ ] fancy display +- [x] fancy display - [ ] json output - [ ] no commit option From b9bb207f35c6f5fb1af96866d06d36098618c7fa Mon Sep 17 00:00:00 2001 From: qwjyh Date: Fri, 28 Jun 2024 00:32:49 +0900 Subject: [PATCH 04/28] add integrated test --- tests/cli.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/tests/cli.rs b/tests/cli.rs index 45bc945..ae5bd81 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -5,11 +5,11 @@ mod integrated_test { }; use anyhow::{Context, Ok, Result}; - use assert_cmd::{assert::OutputAssertExt, Command}; + use assert_cmd::{assert::OutputAssertExt, cargo::CommandCargoExt, Command}; use dirs::home_dir; use git2::Repository; use log::trace; - use predicates::prelude::predicate; + use predicates::{boolean::PredicateBooleanExt, prelude::predicate}; /// Setup global gitconfig if it doesn't exist. /// @@ -157,7 +157,14 @@ mod integrated_test { // set up upstream branch let (mut repo_1_branch, _branch_type) = repo_1.branches(None)?.next().unwrap()?; println!("head {}", repo_1.head().unwrap().name().unwrap()); - repo_1_branch.set_upstream(Some(format!("{}/{}", upstream_name, repo_1_branch.name().unwrap().unwrap()).as_str()))?; + repo_1_branch.set_upstream(Some( + format!( + "{}/{}", + upstream_name, + repo_1_branch.name().unwrap().unwrap() + ) + .as_str(), + ))?; // 2nd device let config_dir_2 = assert_fs::TempDir::new()?; @@ -231,7 +238,14 @@ mod integrated_test { println!("{:?}", bare_repo_dir.read_dir()?); // set up upstream branch let (mut repo_1_branch, _branch_type) = repo_1.branches(None)?.next().unwrap()?; - repo_1_branch.set_upstream(Some(format!("{}/{}", upstream_name, repo_1_branch.name().unwrap().unwrap()).as_str()))?; + repo_1_branch.set_upstream(Some( + format!( + "{}/{}", + upstream_name, + repo_1_branch.name().unwrap().unwrap() + ) + .as_str(), + ))?; // 2nd device let config_dir_2 = assert_fs::TempDir::new()?; @@ -358,6 +372,7 @@ mod integrated_test { .assert() .success(); + // storage list Command::cargo_bin("xdbm")? .arg("-c") .arg(config_dir_2.path()) @@ -365,7 +380,9 @@ mod integrated_test { .arg("list") .arg("-l") .assert() - .success(); + .success() + .stdout(predicate::str::contains("gdrive_docs").and(predicate::str::contains("nas"))); + // backup add let backup_src = &sample_storage_2.join("foo").join("bar"); DirBuilder::new().recursive(true).create(backup_src)?; @@ -387,6 +404,7 @@ mod integrated_test { .assert() .success(); + // backup add but with existing name Command::cargo_bin("xdbm")? .arg("-c") .arg(config_dir_2.path()) @@ -404,6 +422,32 @@ mod integrated_test { .failure() .stderr(predicate::str::contains("already")); + // backup list + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("backup") + .arg("list") + .assert() + .success() + .stdout( + predicate::str::contains("foodoc") + .and(predicate::str::contains("nas")) + .and(predicate::str::contains("gdrive_docs")) + .and(predicate::str::contains("---")), + ); + + // backup done + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("backup") + .arg("done") + .arg("foodoc") + .arg("0") + .assert() + .success(); + Ok(()) } } From 6e1619aa18f9fc40d5b9b7ed6ee9a1f9856f4444 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Fri, 28 Jun 2024 00:33:45 +0900 Subject: [PATCH 05/28] fmt --- src/cmd_args.rs | 4 +--- src/cmd_backup.rs | 2 +- src/storages.rs | 2 +- src/storages/directory.rs | 4 +--- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/cmd_args.rs b/src/cmd_args.rs index 28a41ec..70a8033 100644 --- a/src/cmd_args.rs +++ b/src/cmd_args.rs @@ -57,9 +57,7 @@ pub(crate) enum Commands { Check {}, /// Generate completion script. - Completion { - shell: clap_complete::Shell, - } + Completion { shell: clap_complete::Shell }, } #[derive(Args, Debug)] diff --git a/src/cmd_backup.rs b/src/cmd_backup.rs index bcfd42b..7ae9767 100644 --- a/src/cmd_backup.rs +++ b/src/cmd_backup.rs @@ -216,7 +216,7 @@ fn write_backups_list( None => { let style = Style::new().red(); (style.apply_to("---".to_string()), style) - }, + } }; if !longprint { writeln!( diff --git a/src/storages.rs b/src/storages.rs index 7562b0e..4031d61 100644 --- a/src/storages.rs +++ b/src/storages.rs @@ -1,6 +1,5 @@ //! Manipulates storages. -use console::{style, Style, StyledObject}; use crate::devices; use crate::storages::{ directory::Directory, online_storage::OnlineStorage, @@ -8,6 +7,7 @@ use crate::storages::{ }; use anyhow::{anyhow, Context, Result}; use clap::ValueEnum; +use console::{style, Style, StyledObject}; use core::panic; use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, fmt, fs, io, path}; diff --git a/src/storages/directory.rs b/src/storages/directory.rs index 7887c7b..4cd7803 100644 --- a/src/storages/directory.rs +++ b/src/storages/directory.rs @@ -180,9 +180,7 @@ mod test { local_infos, ); let mut storages = Storages::new(); - storages - .add(storages::Storage::Physical(physical)) - .unwrap(); + storages.add(storages::Storage::Physical(physical)).unwrap(); storages.add(Storage::SubDirectory(directory)).unwrap(); // assert_eq!(directory.name(), "test_name"); assert_eq!( From 0abf9c0693e9c6210c3ffbb7fb8126b3a0579cb0 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 15 Jul 2024 12:12:38 +0900 Subject: [PATCH 06/28] update readme --- README.md | 5 ++++- tests/cli.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c626656..8dd916f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ _Cross device backup manager_, which manages backups on several storages mounted on multiple devices with a single repository. +## Install +- `git` is required for sync + ## Usage 1. `xdbm init` to setup new device(i.e. PC). 2. `xdbm storage add` to add storages, or `xdbm storage bind` to make existing storages available on new device. @@ -24,7 +27,7 @@ which manages backups on several storages mounted on multiple devices with a sin - [ ] write test for storage subcommand - [x] storage add online - [x] storage add directory - - [ ] storage list + - [x] storage list - [x] update storage bind command - [ ] add storage remove command - [ ] add sync subcommand diff --git a/tests/cli.rs b/tests/cli.rs index ae5bd81..4dd4fe6 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -5,7 +5,7 @@ mod integrated_test { }; use anyhow::{Context, Ok, Result}; - use assert_cmd::{assert::OutputAssertExt, cargo::CommandCargoExt, Command}; + use assert_cmd::{assert::OutputAssertExt, Command}; use dirs::home_dir; use git2::Repository; use log::trace; From 37782c934c2b76f8319e8d83a9c0d284fbb04ed3 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Wed, 7 Aug 2024 11:39:58 +0200 Subject: [PATCH 07/28] (WIP) new: implement `status` subcommand - Error while getting mount path of Storages - Need to redesign the API of LocalInfo or something --- src/cmd_args.rs | 12 +++++++ src/cmd_status.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 6 ++++ src/storages.rs | 1 - 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/cmd_status.rs diff --git a/src/cmd_args.rs b/src/cmd_args.rs index 70a8033..4627f97 100644 --- a/src/cmd_args.rs +++ b/src/cmd_args.rs @@ -44,6 +44,18 @@ pub(crate) enum Commands { #[command(subcommand)] Backup(BackupSubCommands), + /// Print status for the given path. + Status { + /// Target path. Default is the current directory. + path: Option, + /// Show storage which the path belongs to. + #[arg(short)] + storage: bool, + /// Show backup config covering the path. + #[arg(short)] + backup: bool, + }, + /// Print config dir. Path {}, diff --git a/src/cmd_status.rs b/src/cmd_status.rs new file mode 100644 index 0000000..eebc2cc --- /dev/null +++ b/src/cmd_status.rs @@ -0,0 +1,81 @@ +use anyhow::{Context, Result}; +use console::Style; +use std::{ + env, + path::{self, Path, PathBuf}, +}; + +use crate::{ + backups::Backups, + devices::{self, Device}, + storages::{self, StorageExt, Storages}, + util, +}; + +// TODO: fine styling like `backup list`, or should I just use the same style? +pub(crate) fn cmd_status( + path: Option, + show_storage: bool, + show_backup: bool, + config_dir: &Path, +) -> Result<()> { + let path = path.unwrap_or(env::current_dir().context("Failed to get current directory.")?); + let device = devices::get_device(config_dir)?; + + if show_storage { + let storages = storages::Storages::read(config_dir)?; + let storage = util::min_parent_storage(&path, &storages, &device); + + match storage { + Some(storage) => { + println!("Storage: {}", storage.0.name()) + } + None => { + println!("Storage: None"); + } + } + } + if show_backup { + let devices = devices::get_devices(config_dir)?; + let storages = storages::Storages::read(config_dir)?; + let backups = Backups::read(config_dir, &device)?; + let covering_backup = devices + .iter() + .map(|device| (device, parent_backups(&path, &backups, &storages, device))); + + for (backup_device, covering_backups) in covering_backup { + println!("Device: {}", backup_device.name()); + for backup in covering_backups { + println!(" {}", console::style(backup.0).bold()); + } + } + } + todo!() +} + +fn parent_backups<'a>( + target_path: &'a PathBuf, + backups: &'a Backups, + storages: &'a Storages, + device: &'a Device, +) -> Vec<(&'a String, PathBuf)> { + backups + .list + .iter() + .filter_map(|(k, v)| { + let backup_path = match v.source().path(storages, device) { + Ok(path) => path, + Err(e) => { + error!("Error while getting backup source path: {}", e); + return None; + } + }; + let diff = pathdiff::diff_paths(target_path, backup_path)?; + if diff.components().any(|c| c == path::Component::ParentDir) { + None + } else { + Some((k, diff)) + } + }) + .collect() +} diff --git a/src/main.rs b/src/main.rs index 18e332d..23dadcd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ mod cmd_backup; mod cmd_check; mod cmd_completion; mod cmd_init; +mod cmd_status; mod cmd_storage; mod cmd_sync; mod devices; @@ -91,6 +92,11 @@ fn main() -> Result<()> { println!("{}", &config_dir.display()); } Commands::Sync { remote_name } => cmd_sync::cmd_sync(&config_dir, remote_name)?, + Commands::Status { + path, + storage, + backup, + } => cmd_status::cmd_status(path, storage, backup, &config_dir)?, Commands::Check {} => cmd_check::cmd_check(&config_dir)?, Commands::Backup(backup) => { trace!("backup subcommand with args: {:?}", backup); diff --git a/src/storages.rs b/src/storages.rs index 4031d61..b80536e 100644 --- a/src/storages.rs +++ b/src/storages.rs @@ -144,7 +144,6 @@ pub trait StorageExt { fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo>; /// Get mount path of `self` on `device`. - /// `storages` is a `BTreeMap` with key of storage name and value of the storage. fn mount_path(&self, device: &devices::Device) -> Result; /// Add local info of `device` to `self`. From a409a439061e3ccd6687b8ef2456937445337f84 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Fri, 9 Aug 2024 21:45:44 +0200 Subject: [PATCH 08/28] (WIP) feat: stat for backup with name - replace path funcs return from Result to Option - add tests for `parent_backups` --- src/backups.rs | 8 +- src/cmd_backup.rs | 20 ++- src/cmd_status.rs | 217 ++++++++++++++++++++--- src/cmd_storage.rs | 4 +- src/storages.rs | 5 +- src/storages/directory.rs | 13 +- src/storages/online_storage.rs | 8 +- src/storages/physical_drive_partition.rs | 9 +- src/util.rs | 5 +- 9 files changed, 236 insertions(+), 53 deletions(-) diff --git a/src/backups.rs b/src/backups.rs index fbb4c1f..896fcd9 100644 --- a/src/backups.rs +++ b/src/backups.rs @@ -44,10 +44,12 @@ impl BackupTarget { } } - pub fn path(&self, storages: &Storages, device: &Device) -> Result { + /// Get full path of the [`BackupTarget`]. + pub fn path(&self, storages: &Storages, device: &Device) -> Option { let parent = storages.get(&self.storage).unwrap(); - let parent_path = parent.mount_path(device)?; - Ok(parent_path.join(self.path.clone())) + let parent_path = parent + .mount_path(device)?; + Some(parent_path.join(self.path.clone())) } } diff --git a/src/cmd_backup.rs b/src/cmd_backup.rs index 7ae9767..df6d13d 100644 --- a/src/cmd_backup.rs +++ b/src/cmd_backup.rs @@ -188,10 +188,16 @@ fn write_backups_list( ))?; name_width = name_width.max(backup.name().width()); dev_width = dev_width.max(dev.width()); - let src = backup.source().path(storages, device)?; + let src = backup + .source() + .path(storages, device) + .context("Couldn't get path for source")?; src_width = src_width.max(format!("{}", src.display()).width()); src_storage_width = src_storage_width.max(backup.source().storage.width()); - let dest = backup.destination().path(storages, device)?; + let dest = backup + .destination() + .path(storages, device) + .context("Couldn't get path for destination")?; dest_width = dest_width.max(format!("{}", dest.display()).width()); dest_storage_width = dest_storage_width.max(backup.destination().storage.width()); let cmd_name = backup.command().name(); @@ -203,8 +209,14 @@ fn write_backups_list( "Couldn't find the device specified in the backup config: {}", backup.name() ))?; - let src = backup.source().path(storages, device)?; - let dest = backup.destination().path(storages, device)?; + let src = backup + .source() + .path(storages, device) + .context("Couldn't get path for source")?; + let dest = backup + .destination() + .path(storages, device) + .context("Couldn't get path for destination")?; let cmd_name = backup.command().name(); let (last_backup_elapsed, style_on_time_elapsed) = match backup.last_backup() { Some(log) => { diff --git a/src/cmd_status.rs b/src/cmd_status.rs index eebc2cc..cd90860 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -6,9 +6,9 @@ use std::{ }; use crate::{ - backups::Backups, + backups::{Backup, Backups}, devices::{self, Device}, - storages::{self, StorageExt, Storages}, + storages::{self, Storage, StorageExt, Storages}, util, }; @@ -20,12 +20,14 @@ pub(crate) fn cmd_status( config_dir: &Path, ) -> Result<()> { let path = path.unwrap_or(env::current_dir().context("Failed to get current directory.")?); - let device = devices::get_device(config_dir)?; + let currrent_device = devices::get_device(config_dir)?; if show_storage { let storages = storages::Storages::read(config_dir)?; - let storage = util::min_parent_storage(&path, &storages, &device); + let storage = util::min_parent_storage(&path, &storages, &currrent_device); + trace!("storage {:?}", storage); + // TODO: recursively trace all storages for subdirectory? match storage { Some(storage) => { println!("Storage: {}", storage.0.name()) @@ -38,44 +40,217 @@ pub(crate) fn cmd_status( if show_backup { let devices = devices::get_devices(config_dir)?; let storages = storages::Storages::read(config_dir)?; - let backups = Backups::read(config_dir, &device)?; - let covering_backup = devices + let backups = Backups::read(config_dir, &currrent_device)?; + + let (target_storage, target_diff_from_storage) = + util::min_parent_storage(&path, &storages, &currrent_device) + .context("Target path is not covered in any storage")?; + + let covering_backup: Vec<_> = devices .iter() - .map(|device| (device, parent_backups(&path, &backups, &storages, device))); + .map(|device| { + ( + device, + parent_backups( + &target_diff_from_storage, + target_storage, + &backups, + &storages, + device, + ), + ) + }) + .collect(); + trace!("{:?}", covering_backup.first()); + + let name_len = &covering_backup + .iter() + .map(|(_, backups)| { + backups + .iter() + .map(|(backup, _path)| backup.name().len()) + .max() + .unwrap_or(0) + }) + .max() + .unwrap_or(5); for (backup_device, covering_backups) in covering_backup { println!("Device: {}", backup_device.name()); - for backup in covering_backups { - println!(" {}", console::style(backup.0).bold()); + for (backup, path_from_backup) in covering_backups { + println!( + " {:( - target_path: &'a PathBuf, + target_path_from_storage: &'a Path, + target_storage: &'a Storage, backups: &'a Backups, storages: &'a Storages, device: &'a Device, -) -> Vec<(&'a String, PathBuf)> { +) -> Vec<(&'a Backup, PathBuf)> { + trace!("Dev {:?}", device.name()); + let target_path = match target_storage.mount_path(device) { + Some(target_path) => target_path.join(target_path_from_storage), + None => return vec![], + }; + trace!("Path on the device {:?}", target_path); backups .list .iter() - .filter_map(|(k, v)| { - let backup_path = match v.source().path(storages, device) { - Ok(path) => path, - Err(e) => { - error!("Error while getting backup source path: {}", e); - return None; - } - }; - let diff = pathdiff::diff_paths(target_path, backup_path)?; + .filter_map(|(_k, backup)| { + let backup_path = backup.source().path(storages, device)?; + let diff = pathdiff::diff_paths(&target_path, backup_path)?; if diff.components().any(|c| c == path::Component::ParentDir) { None } else { - Some((k, diff)) + Some((backup, diff)) } }) .collect() } + +#[cfg(test)] +mod test { + use std::path::PathBuf; + + use crate::{ + backups::{self, ExternallyInvoked}, + devices, + storages::{self, online_storage::OnlineStorage, StorageExt}, + util, + }; + + use super::parent_backups; + + #[test] + fn test_parent_backups() { + let device1 = devices::Device::new("device_1".to_string()); + let mut storage1 = storages::Storage::Online(OnlineStorage::new( + "storage_1".to_string(), + "smb".to_string(), + 1_000_000, + "str1".to_string(), + PathBuf::from("/home/foo/"), + &device1, + )); + let storage2 = storages::Storage::Online(OnlineStorage::new( + "storage_2".to_string(), + "smb".to_string(), + 1_000_000_000, + "str2".to_string(), + PathBuf::from("/"), + &device1, + )); + let device2 = devices::Device::new("device_2".to_string()); + storage1 + .bound_on_device("alias".to_string(), PathBuf::from("/mnt/dev"), &device2) + .unwrap(); + let storage3 = storages::Storage::Online(OnlineStorage::new( + "storage_3".to_string(), + "smb".to_string(), + 2_000_000_000, + "str2".to_string(), + PathBuf::from("/"), + &device2, + )); + let storages = { + let mut storages = storages::Storages::new(); + storages.add(storage1).unwrap(); + storages.add(storage2).unwrap(); + storages.add(storage3).unwrap(); + storages + }; + + let backup1 = backups::Backup::new( + "backup_1".to_string(), + device1.name().to_string(), + backups::BackupTarget { + storage: "storage_1".to_string(), + path: PathBuf::from("bar"), + }, + backups::BackupTarget { + storage: "storage_1".to_string(), + path: PathBuf::from("hoge"), + }, + backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new( + "cmd".to_string(), + "".to_string(), + )), + ); + let backup2 = backups::Backup::new( + "backup_2".to_string(), + device2.name().to_string(), + backups::BackupTarget { + storage: "storage_1".to_string(), + path: PathBuf::from(""), + }, + backups::BackupTarget { + storage: "storage_3".to_string(), + path: PathBuf::from("foo"), + }, + backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new( + "cmd".to_string(), + "".to_string(), + )), + ); + + let backups = { + let mut backups = backups::Backups::new(); + backups.add(backup1).unwrap(); + backups.add(backup2).unwrap(); + backups + }; + + let target_path1 = PathBuf::from("/home/foo/bar/hoo"); + let (target_storage1, target_path_from_storage1) = + util::min_parent_storage(&target_path1, &storages, &device1) + .expect("Failed to get storage"); + let covering_backups_1 = parent_backups( + &target_path_from_storage1, + target_storage1, + &backups, + &storages, + &device1, + ); + assert_eq!(covering_backups_1.len(), 2); + + let target_path2 = PathBuf::from("/mnt/"); + let (target_storage2, target_path_from_storage2) = + util::min_parent_storage(&target_path2, &storages, &device2) + .expect("Failed to get storage"); + let covering_backups_2 = parent_backups( + &target_path_from_storage2, + target_storage2, + &backups, + &storages, + &device2, + ); + assert_eq!(covering_backups_2.len(), 0); + + let target_path3 = PathBuf::from("/mnt/dev/foo"); + let (target_storage3, target_path_from_storage3) = + util::min_parent_storage(&target_path3, &storages, &device2) + .expect("Failed to get storage"); + let covering_backups_3 = parent_backups( + &target_path_from_storage3, + target_storage3, + &backups, + &storages, + &device2, + ); + assert_eq!(covering_backups_3.len(), 1); + let mut covering_backup_names_3 = covering_backups_3.iter().map(|(backup, _)| backup.name()); + assert_eq!(covering_backup_names_3.next().unwrap(), "backup_2"); + assert!(covering_backup_names_3.next().is_none()); + } +} diff --git a/src/cmd_storage.rs b/src/cmd_storage.rs index 8c39646..2cb9414 100644 --- a/src/cmd_storage.rs +++ b/src/cmd_storage.rs @@ -215,8 +215,8 @@ fn write_storages_list( "" }; let path = storage.mount_path(device).map_or_else( - |e| { - info!("Not found: {}", e); + || { + info!("Mount path not found"); "".to_string() }, |v| v.display().to_string(), diff --git a/src/storages.rs b/src/storages.rs index b80536e..d4b9dd4 100644 --- a/src/storages.rs +++ b/src/storages.rs @@ -78,7 +78,7 @@ impl StorageExt for Storage { } } - fn mount_path(&self, device: &devices::Device) -> Result { + fn mount_path(&self, device: &devices::Device) -> Option { match self { Self::Physical(s) => s.mount_path(device), Self::SubDirectory(s) => s.mount_path(device), @@ -144,7 +144,8 @@ pub trait StorageExt { fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo>; /// Get mount path of `self` on `device`. - fn mount_path(&self, device: &devices::Device) -> Result; + /// Return [`None`] if the storage([`self`]) is not configured for the `device`. + fn mount_path(&self, device: &devices::Device) -> Option; /// Add local info of `device` to `self`. fn bound_on_device( diff --git a/src/storages/directory.rs b/src/storages/directory.rs index 4cd7803..f1e460c 100644 --- a/src/storages/directory.rs +++ b/src/storages/directory.rs @@ -19,7 +19,7 @@ pub struct Directory { /// Relative path to the parent storage. relative_path: path::PathBuf, pub notes: String, - /// Device and localinfo pairs. + /// [`devices::Device`] name and localinfo pairs. local_infos: BTreeMap, } @@ -80,7 +80,8 @@ impl Directory { let parent_mount_path = self .parent(storages) .context("Can't find parent storage")? - .mount_path(device)?; + .mount_path(device) + .context("Can't find mount path")?; Ok(parent_mount_path.join(self.relative_path.clone())) } } @@ -98,12 +99,10 @@ impl StorageExt for Directory { self.local_infos.get(&device.name()) } - fn mount_path(&self, device: &devices::Device) -> Result { - Ok(self - .local_infos + fn mount_path(&self, device: &devices::Device) -> Option { + self.local_infos .get(&device.name()) - .context(format!("LocalInfo for storage: {} not found", &self.name()))? - .mount_path()) + .map(|info| info.mount_path()) } /// This method doesn't use `mount_path`. diff --git a/src/storages/online_storage.rs b/src/storages/online_storage.rs index 4ce2459..6c4d62c 100644 --- a/src/storages/online_storage.rs +++ b/src/storages/online_storage.rs @@ -61,12 +61,10 @@ impl StorageExt for OnlineStorage { self.local_infos.get(&device.name()) } - fn mount_path(&self, device: &devices::Device) -> Result { - Ok(self - .local_infos + fn mount_path(&self, device: &devices::Device) -> Option { + self.local_infos .get(&device.name()) - .context(format!("LocalInfo for storage: {} not found", &self.name()))? - .mount_path()) + .map(|info| info.mount_path()) } fn bound_on_device( diff --git a/src/storages/physical_drive_partition.rs b/src/storages/physical_drive_partition.rs index 95dec3f..14a35a6 100644 --- a/src/storages/physical_drive_partition.rs +++ b/src/storages/physical_drive_partition.rs @@ -21,6 +21,7 @@ pub struct PhysicalDrivePartition { fs: String, is_removable: bool, // system_names: BTreeMap, + /// [`Device`] name and [`LocalInfo`] mapping. local_infos: BTreeMap, } @@ -112,12 +113,10 @@ impl StorageExt for PhysicalDrivePartition { self.local_infos.get(&device.name()) } - fn mount_path(&self, device: &devices::Device) -> Result { - Ok(self - .local_infos + fn mount_path(&self, device: &devices::Device) -> Option { + self.local_infos .get(&device.name()) - .context(format!("LocalInfo for storage: {} not found", &self.name()))? - .mount_path()) + .map(|info| info.mount_path()) } fn bound_on_device( diff --git a/src/util.rs b/src/util.rs index 820de33..8f27bc4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -18,10 +18,7 @@ pub fn min_parent_storage<'a>( .list .iter() .filter_map(|(k, storage)| { - let storage_path = match storage.mount_path(device) { - Ok(path) => path, - Err(_) => return None, - }; + let storage_path = storage.mount_path(device)?; let diff = pathdiff::diff_paths(path, storage_path)?; if diff.components().any(|c| c == path::Component::ParentDir) { None From bc3939c9bc09bee4e5b0c943e6ecde3f652aa947 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Fri, 8 Nov 2024 06:09:04 +0900 Subject: [PATCH 09/28] (WIP): implementing multi device backup search --- src/backups.rs | 17 ++++++++-------- src/cmd_backup.rs | 15 ++------------ src/cmd_status.rs | 52 +++++++++++++++++++++++++++++++++++------------ src/util.rs | 12 +++++++++++ 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/src/backups.rs b/src/backups.rs index 896fcd9..5b39e61 100644 --- a/src/backups.rs +++ b/src/backups.rs @@ -27,7 +27,7 @@ pub fn backups_file(device: &Device) -> PathBuf { } /// Targets for backup source or destination. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackupTarget { /// `name()` of [`crate::storages::Storage`]. /// Use `String` for serialization/deserialization. @@ -47,14 +47,13 @@ impl BackupTarget { /// Get full path of the [`BackupTarget`]. pub fn path(&self, storages: &Storages, device: &Device) -> Option { let parent = storages.get(&self.storage).unwrap(); - let parent_path = parent - .mount_path(device)?; + let parent_path = parent.mount_path(device)?; Some(parent_path.join(self.path.clone())) } } /// Type of backup commands. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum BackupCommand { ExternallyInvoked(ExternallyInvoked), } @@ -81,7 +80,7 @@ impl BackupCommandExt for BackupCommand { /// Backup commands which is not invoked from xdbm itself. /// Call xdbm externally to record backup datetime and status. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExternallyInvoked { name: String, pub note: String, @@ -104,7 +103,7 @@ impl BackupCommandExt for ExternallyInvoked { } /// Backup execution log. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackupLog { pub datetime: DateTime, status: BackupResult, @@ -124,7 +123,7 @@ impl BackupLog { } /// Result of backup. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum BackupResult { Success, Failure, @@ -141,7 +140,7 @@ impl BackupResult { } /// Backup source, destination, command and logs. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Backup { /// must be unique name: String, @@ -202,7 +201,7 @@ impl Backup { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Backups { pub list: BTreeMap, } diff --git a/src/cmd_backup.rs b/src/cmd_backup.rs index df6d13d..9c58378 100644 --- a/src/cmd_backup.rs +++ b/src/cmd_backup.rs @@ -5,7 +5,7 @@ use std::{ }; use anyhow::{anyhow, Context, Ok, Result}; -use chrono::{Local, TimeDelta}; +use chrono::Local; use console::Style; use dunce::canonicalize; use git2::Repository; @@ -154,17 +154,6 @@ pub fn cmd_backup_list( Ok(()) } -fn duration_style(time: TimeDelta) -> Style { - match time { - x if x < TimeDelta::days(7) => Style::new().green(), - x if x < TimeDelta::days(14) => Style::new().yellow(), - x if x < TimeDelta::days(28) => Style::new().magenta(), - x if x < TimeDelta::days(28 * 3) => Style::new().red(), - x if x < TimeDelta::days(180) => Style::new().red().bold(), - _ => Style::new().on_red().black(), - } -} - /// TODO: status printing fn write_backups_list( mut writer: impl io::Write, @@ -222,7 +211,7 @@ fn write_backups_list( Some(log) => { let time = Local::now() - log.datetime; let s = util::format_summarized_duration(time); - let style = duration_style(time); + let style = util::duration_style(time); (style.apply_to(s), style) } None => { diff --git a/src/cmd_status.rs b/src/cmd_status.rs index cd90860..ba1ad87 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -1,5 +1,5 @@ use anyhow::{Context, Result}; -use console::Style; +use chrono::Local; use std::{ env, path::{self, Path, PathBuf}, @@ -40,7 +40,11 @@ pub(crate) fn cmd_status( if show_backup { let devices = devices::get_devices(config_dir)?; let storages = storages::Storages::read(config_dir)?; - let backups = Backups::read(config_dir, &currrent_device)?; + let backups = devices.iter().map(|device| { + Backups::read(config_dir, device) + .context("Backups were not found") + .unwrap() + }); let (target_storage, target_diff_from_storage) = util::min_parent_storage(&path, &storages, &currrent_device) @@ -48,13 +52,27 @@ pub(crate) fn cmd_status( let covering_backup: Vec<_> = devices .iter() - .map(|device| { + .zip(backups) + .map(|(device, backups)| { + debug!( + "dev {}, storage {:?}", + device.name(), + backups + .list + .iter() + .map(|(backup_name, backup)| format!( + "{} {}", + backup_name, + backup.source().storage + )) + .collect::>() + ); ( device, parent_backups( &target_diff_from_storage, target_storage, - &backups, + backups, &storages, device, ), @@ -78,9 +96,14 @@ pub(crate) fn cmd_status( for (backup_device, covering_backups) in covering_backup { println!("Device: {}", backup_device.name()); for (backup, path_from_backup) in covering_backups { + let last_backup = match backup.last_backup() { + Some(log) => util::format_summarized_duration(Local::now() - log.datetime), + None => "---".to_string(), + }; println!( - " {:( target_path_from_storage: &'a Path, target_storage: &'a Storage, - backups: &'a Backups, + backups: Backups, storages: &'a Storages, device: &'a Device, -) -> Vec<(&'a Backup, PathBuf)> { +) -> Vec<(Backup, PathBuf)> { trace!("Dev {:?}", device.name()); let target_path = match target_storage.mount_path(device) { Some(target_path) => target_path.join(target_path_from_storage), @@ -106,10 +129,12 @@ fn parent_backups<'a>( trace!("Path on the device {:?}", target_path); backups .list - .iter() + .into_iter() .filter_map(|(_k, backup)| { let backup_path = backup.source().path(storages, device)?; - let diff = pathdiff::diff_paths(&target_path, backup_path)?; + trace!("{:?}", backup_path.components()); + let diff = pathdiff::diff_paths(&target_path, backup_path.clone())?; + trace!("Backup: {:?}, Diff: {:?}", backup_path, diff); if diff.components().any(|c| c == path::Component::ParentDir) { None } else { @@ -218,7 +243,7 @@ mod test { let covering_backups_1 = parent_backups( &target_path_from_storage1, target_storage1, - &backups, + backups.clone(), &storages, &device1, ); @@ -231,7 +256,7 @@ mod test { let covering_backups_2 = parent_backups( &target_path_from_storage2, target_storage2, - &backups, + backups.clone(), &storages, &device2, ); @@ -244,12 +269,13 @@ mod test { let covering_backups_3 = parent_backups( &target_path_from_storage3, target_storage3, - &backups, + backups, &storages, &device2, ); assert_eq!(covering_backups_3.len(), 1); - let mut covering_backup_names_3 = covering_backups_3.iter().map(|(backup, _)| backup.name()); + let mut covering_backup_names_3 = + covering_backups_3.iter().map(|(backup, _)| backup.name()); assert_eq!(covering_backup_names_3.next().unwrap(), "backup_2"); assert!(covering_backup_names_3.next().is_none()); } diff --git a/src/util.rs b/src/util.rs index 8f27bc4..5730dc7 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,7 @@ use std::path::{self, PathBuf}; use anyhow::{Context, Result}; +use chrono::TimeDelta; use console::Style; use crate::{ @@ -59,6 +60,17 @@ pub fn format_summarized_duration(dt: chrono::Duration) -> String { } } +pub fn duration_style(time: TimeDelta) -> Style { + match time { + x if x < TimeDelta::days(7) => Style::new().green(), + x if x < TimeDelta::days(14) => Style::new().yellow(), + x if x < TimeDelta::days(28) => Style::new().magenta(), + x if x < TimeDelta::days(28 * 3) => Style::new().red(), + x if x < TimeDelta::days(180) => Style::new().red().bold(), + _ => Style::new().on_red().black(), + } +} + #[cfg(test)] mod test { use anyhow::Result; From 772689ab6af36974df642e4a7e326c358e33cdd5 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 19:14:57 +0900 Subject: [PATCH 10/28] change: change type of relative path shared on multiple platforms to Vector Parsers for path on Windows and Unix are different on separator character treatment. Replacing to Vector avoids this differenct for cross-platform compatibility. --- src/backups.rs | 15 ++++++++++----- src/cmd_backup.rs | 8 ++++---- src/cmd_status.rs | 10 +++++----- src/storages/directory.rs | 37 ++++++++++++++++++++++--------------- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/backups.rs b/src/backups.rs index 5b39e61..2816a6a 100644 --- a/src/backups.rs +++ b/src/backups.rs @@ -33,22 +33,27 @@ pub struct BackupTarget { /// Use `String` for serialization/deserialization. pub storage: String, /// Relative path to the `storage`. - pub path: PathBuf, + pub path: Vec, } impl BackupTarget { - pub fn new(storage_name: String, relative_path: PathBuf) -> Self { - BackupTarget { + pub fn new(storage_name: String, relative_path: PathBuf) -> Result { + let relative_path = relative_path + .components() + .map(|c| c.as_os_str().to_str().map(|s| s.to_owned())) + .collect::>() + .context("Path contains non-utf8 character")?; + Ok(BackupTarget { storage: storage_name, path: relative_path, - } + }) } /// Get full path of the [`BackupTarget`]. pub fn path(&self, storages: &Storages, device: &Device) -> Option { let parent = storages.get(&self.storage).unwrap(); let parent_path = parent.mount_path(device)?; - Some(parent_path.join(self.path.clone())) + Some(parent_path.join(self.path.clone().iter().collect::())) } } diff --git a/src/cmd_backup.rs b/src/cmd_backup.rs index 9c58378..cab7a9e 100644 --- a/src/cmd_backup.rs +++ b/src/cmd_backup.rs @@ -89,8 +89,8 @@ fn new_backup( Ok(Backup::new( name, device.name(), - src_target, - dest_target, + src_target?, + dest_target?, command, )) } @@ -361,9 +361,9 @@ mod test { &storages, )?; assert!(backup.source().storage == "online"); - assert_eq!(backup.source().path, PathBuf::from("docs")); + assert_eq!(backup.source().path, vec!["docs"]); assert!(backup.destination().storage == "online"); - assert!(backup.destination().path == PathBuf::from("tmp")); + assert!(backup.destination().path == vec!["tmp"]); Ok(()) } } diff --git a/src/cmd_status.rs b/src/cmd_status.rs index ba1ad87..c93e641 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -146,7 +146,7 @@ fn parent_backups<'a>( #[cfg(test)] mod test { - use std::path::PathBuf; + use std::{path::PathBuf, vec}; use crate::{ backups::{self, ExternallyInvoked}, @@ -201,11 +201,11 @@ mod test { device1.name().to_string(), backups::BackupTarget { storage: "storage_1".to_string(), - path: PathBuf::from("bar"), + path: vec!["bar".to_string()], }, backups::BackupTarget { storage: "storage_1".to_string(), - path: PathBuf::from("hoge"), + path: vec!["hoge".to_string()], }, backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new( "cmd".to_string(), @@ -217,11 +217,11 @@ mod test { device2.name().to_string(), backups::BackupTarget { storage: "storage_1".to_string(), - path: PathBuf::from(""), + path: vec!["".to_string()], }, backups::BackupTarget { storage: "storage_3".to_string(), - path: PathBuf::from("foo"), + path: vec!["foo".to_string()], }, backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new( "cmd".to_string(), diff --git a/src/storages/directory.rs b/src/storages/directory.rs index f1e460c..1777ec3 100644 --- a/src/storages/directory.rs +++ b/src/storages/directory.rs @@ -2,6 +2,7 @@ use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; use std::{collections::BTreeMap, fmt, path}; use crate::devices; @@ -17,7 +18,7 @@ pub struct Directory { /// ID of parent storage. parent: String, /// Relative path to the parent storage. - relative_path: path::PathBuf, + relative_path: Vec, pub notes: String, /// [`devices::Device`] name and localinfo pairs. local_infos: BTreeMap, @@ -34,14 +35,19 @@ impl Directory { relative_path: path::PathBuf, notes: String, local_infos: BTreeMap, - ) -> Directory { - Directory { + ) -> Result { + let relative_path = relative_path + .components() + .map(|c| c.as_os_str().to_str().map(|s| s.to_owned())) + .collect::>>() + .context("Path contains non-utf8 character")?; + Ok(Directory { name, parent, relative_path, notes, local_infos, - } + }) } pub fn try_from_device_path( @@ -56,23 +62,23 @@ impl Directory { .context("Failed to compare diff of paths")?; trace!("Selected parent: {}", parent.name()); let local_info = LocalInfo::new(alias, path); - Ok(Directory::new( + Directory::new( name, parent.name().to_string(), diff_path, notes, BTreeMap::from([(device.name(), local_info)]), - )) + ) } pub fn update_note(self, notes: String) -> Directory { - Directory::new( - self.name, - self.parent, - self.relative_path, + Directory { + name: self.name, + parent: self.parent, + relative_path: self.relative_path, notes, - self.local_infos, - ) + local_infos: self.local_infos, + } } /// Resolve mount path of directory with current device. @@ -82,7 +88,7 @@ impl Directory { .context("Can't find parent storage")? .mount_path(device) .context("Can't find mount path")?; - Ok(parent_mount_path.join(self.relative_path.clone())) + Ok(parent_mount_path.join(self.relative_path.clone().iter().collect::())) } } @@ -133,7 +139,7 @@ impl fmt::Display for Directory { "S {name:<10} < {parent:<10}{relative_path:<10} : {notes}", name = self.name(), parent = self.parent, - relative_path = self.relative_path.display(), + relative_path = self.relative_path.iter().collect::().display(), notes = self.notes, ) } @@ -177,7 +183,8 @@ mod test { "subdir".into(), "some note".to_string(), local_infos, - ); + ) + .unwrap(); let mut storages = Storages::new(); storages.add(storages::Storage::Physical(physical)).unwrap(); storages.add(Storage::SubDirectory(directory)).unwrap(); From 8b0dbb2314d2ab3cd9081163899ea4e52a193e4d Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 19:19:28 +0900 Subject: [PATCH 11/28] fix: add lifetime annotation (clippy) --- src/backups.rs | 2 +- src/storages/directory.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backups.rs b/src/backups.rs index 2816a6a..8f70509 100644 --- a/src/backups.rs +++ b/src/backups.rs @@ -180,7 +180,7 @@ impl Backup { &self.name } - pub fn device<'a>(&'a self, devices: &'a [Device]) -> Option<&Device> { + pub fn device<'a>(&'a self, devices: &'a [Device]) -> Option<&'a Device> { devices.iter().find(|dev| dev.name() == self.device) } diff --git a/src/storages/directory.rs b/src/storages/directory.rs index 1777ec3..1642518 100644 --- a/src/storages/directory.rs +++ b/src/storages/directory.rs @@ -127,7 +127,7 @@ impl StorageExt for Directory { } // Get parent `&Storage` of directory. - fn parent<'a>(&'a self, storages: &'a Storages) -> Option<&Storage> { + fn parent<'a>(&'a self, storages: &'a Storages) -> Option<&'a Storage> { storages.get(&self.parent) } } From dbc0d78f99de53077ebf3c3577b779e35a39fc50 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 19:36:33 +0900 Subject: [PATCH 12/28] update: CHANGELOG on path type change --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 685004c..dd526a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Changed - Colored output for `storage list` and `backup list` ([#15](https://github.com/qwjyh/xdbm/pull/15)) +- **BREAKING** Relative path is changed from `PathBuf` to `Vector` for portability. This means that existing config files need to be changed. ## [0.2.1] - 2024-06-19 From ced354bf583425a0f7fe6d38b5b283a04e2da2d7 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 20:37:23 +0900 Subject: [PATCH 13/28] fix: sub directory decision logic on windows Diff of "C:\foo" from "D:\" is "C:\foo" and doesn't contain "..". In old logic, "C:\foo" is treated as subpath of "D:\" but this is not intuitive. --- src/cmd_status.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd_status.rs b/src/cmd_status.rs index c93e641..c80ff89 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -135,7 +135,11 @@ fn parent_backups<'a>( trace!("{:?}", backup_path.components()); let diff = pathdiff::diff_paths(&target_path, backup_path.clone())?; trace!("Backup: {:?}, Diff: {:?}", backup_path, diff); - if diff.components().any(|c| c == path::Component::ParentDir) { + // note: Should `RootDir` is included in this list? + if diff + .components() + .any(|c| matches!(c, path::Component::ParentDir | path::Component::Prefix(_))) + { None } else { Some((backup, diff)) From 6a0abd03d5843fc6432d28523eeb49bfe1ca2447 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 20:55:49 +0900 Subject: [PATCH 14/28] fix: apply subpath logic patch to `util::min_parent_storage` --- src/util.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/util.rs b/src/util.rs index 5730dc7..ea2c947 100644 --- a/src/util.rs +++ b/src/util.rs @@ -21,7 +21,10 @@ pub fn min_parent_storage<'a>( .filter_map(|(k, storage)| { let storage_path = storage.mount_path(device)?; let diff = pathdiff::diff_paths(path, storage_path)?; - if diff.components().any(|c| c == path::Component::ParentDir) { + if diff + .components() + .any(|c| matches!(c, path::Component::ParentDir | path::Component::Prefix(_))) + { None } else { Some((k, diff)) From 8fc8029435eac304098b4164344f5279de783836 Mon Sep 17 00:00:00 2001 From: qwjyh <62229267+qwjyh@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:13:42 +0900 Subject: [PATCH 15/28] Update CI and add lint (#18) * fix: update actions/checkout from v3 to v4 * update(CI): add clippy --- .github/workflows/rust.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 31000a2..7cee19b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,13 +10,17 @@ env: CARGO_TERM_COLOR: always jobs: - build: + build-and-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Setup + run: rustup component add clippy - name: Build run: cargo build --verbose - name: Run tests run: cargo test --verbose + - name: Lint + run: cargo clippy --all-targets --all-features From d743e607accea646a41c56f9a7e3cbd7ca9ede57 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 23:14:50 +0900 Subject: [PATCH 16/28] update: remove todo!() at the end of cmd_status --- src/cmd_status.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd_status.rs b/src/cmd_status.rs index c80ff89..ebc61d2 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -109,7 +109,8 @@ pub(crate) fn cmd_status( } } } - todo!() + + Ok(()) } /// Get [`Backup`]s for `device` which covers `target_path`. From 315a75424aded1688c97ea9a716927c2b50f8428 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 23:31:58 +0900 Subject: [PATCH 17/28] add(test): command backup after done doesn't include --- --- tests/cli.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/cli.rs b/tests/cli.rs index 4dd4fe6..3c399cd 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -448,6 +448,21 @@ mod integrated_test { .assert() .success(); + // backup list after backup done + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("backup") + .arg("list") + .assert() + .success() + .stdout( + predicate::str::contains("foodoc") + .and(predicate::str::contains("nas")) + .and(predicate::str::contains("gdrive_docs")) + .and(predicate::str::contains("---").not()), + ); + Ok(()) } } From bce9f3710c001964eca9a720464cf6776507bf0b Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 23:32:36 +0900 Subject: [PATCH 18/28] add(test): command status test --- tests/cli.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/cli.rs b/tests/cli.rs index 3c399cd..bad49e8 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -463,6 +463,49 @@ mod integrated_test { .and(predicate::str::contains("---").not()), ); + // status + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("status") + .assert() + .success(); + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("status") + .arg("-s") + .arg(backup_src.clone().join("foo")) + .assert() + .success() + .stdout(predicate::str::contains("nas").and(predicate::str::contains("foodoc").not())); + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("status") + .arg("-sb") + .arg(backup_src.clone().join("foo")) + .assert() + .success() + .stdout( + predicate::str::contains("nas") + .and(predicate::str::contains("second")) + .and(predicate::str::contains("foodoc")), + ); + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("status") + .arg("-sb") + .arg(backup_src.clone().parent().unwrap()) + .assert() + .success() + .stdout( + predicate::str::contains("nas") + .and(predicate::str::contains("second")) + .and(predicate::str::contains("foodoc").not()), + ); + Ok(()) } } From 697c9c0712ce7958f08aeaa4636ed14e5fc3845c Mon Sep 17 00:00:00 2001 From: qwjyh Date: Sun, 1 Dec 2024 23:33:24 +0900 Subject: [PATCH 19/28] add(test): test for multiple backups and status & add comment comment for current config --- tests/cli.rs | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) diff --git a/tests/cli.rs b/tests/cli.rs index bad49e8..b082182 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -216,6 +216,8 @@ mod integrated_test { #[test] fn two_devices() -> Result<()> { // 1st device + // + // devices: first let config_dir_1 = assert_fs::TempDir::new()?; setup_gitconfig()?; let mut cmd1 = Command::cargo_bin("xdbm")?; @@ -248,6 +250,8 @@ mod integrated_test { ))?; // 2nd device + // + // devices: first, second let config_dir_2 = assert_fs::TempDir::new()?; let mut cmd2 = Command::cargo_bin("xdbm")?; cmd2.arg("-c") @@ -271,6 +275,7 @@ mod integrated_test { assert!(config_dir_2.join("backups").join("first.yml").exists()); assert!(config_dir_2.join("backups").join("second.yml").exists()); + // sync std::process::Command::new("git") .arg("push") .current_dir(&config_dir_2) @@ -287,6 +292,11 @@ mod integrated_test { .success(); // Add storage + // + // devices: first, second + // storages: + // - gdrive @ sample_storage (online) + // - first: sample_storage let sample_storage = assert_fs::TempDir::new()?; let mut cmd_add_storage_1 = Command::cargo_bin("xdbm")?; cmd_add_storage_1 @@ -308,6 +318,13 @@ mod integrated_test { .success() .stdout(predicate::str::contains("")); // Add storage (directory) + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first let sample_directory = &sample_storage.join("foo").join("bar"); DirBuilder::new().recursive(true).create(sample_directory)?; Command::cargo_bin("xdbm")? @@ -339,6 +356,14 @@ mod integrated_test { .success(); // bind + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory Command::cargo_bin("xdbm")? .arg("-c") .arg(config_dir_2.path()) @@ -354,6 +379,16 @@ mod integrated_test { .stdout(predicate::str::contains("")); // storage 3 + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - second: sample_storage_2 let sample_storage_2 = assert_fs::TempDir::new()?; Command::cargo_bin("xdbm")? .arg("-c") @@ -384,6 +419,19 @@ mod integrated_test { .stdout(predicate::str::contains("gdrive_docs").and(predicate::str::contains("nas"))); // backup add + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - second: sample_storage_2 + // backups: + // - foodoc: second + // - sample_storage_2/foo/bar -> sample_directory/docs let backup_src = &sample_storage_2.join("foo").join("bar"); DirBuilder::new().recursive(true).create(backup_src)?; let backup_dest = &sample_directory.join("docs"); @@ -438,6 +486,19 @@ mod integrated_test { ); // backup done + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - second: sample_storage_2 + // backups: + // - foodoc: second + // - sample_storage_2/foo/bar -> sample_directory/docs (done 1) Command::cargo_bin("xdbm")? .arg("-c") .arg(config_dir_2.path()) @@ -506,6 +567,219 @@ mod integrated_test { .and(predicate::str::contains("foodoc").not()), ); + std::process::Command::new("git") + .arg("push") + .current_dir(&config_dir_2) + .assert() + .success(); + std::process::Command::new("git") + .arg("pull") + .current_dir(&config_dir_1) + .assert() + .success(); + + // bind + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - first: sample_storage_2_first_path + // - second: sample_storage_2 + // backups: + // - foodoc: second + // - sample_storage_2/foo/bar -> sample_directory/docs (done 1) + let sample_storage_2_first_path = assert_fs::TempDir::new()?; + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_1.path()) + .arg("storage") + .arg("bind") + .arg("--alias") + .arg("sample2") + .arg("--path") + .arg(sample_storage_2_first_path.path()) + .arg("nas") + .assert() + .success() + .stdout(predicate::str::contains("")); + + // backup add + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - first: sample_storage_2_first_path + // - second: sample_storage_2 + // backups: + // - foodoc: second + // - sample_storage_2/foo/bar -> sample_directory/docs (done 1) + // - abcdbackup: first + // - sample_storage_2_first_path/abcd/efgh -> sample_storage/Downloads/abcd/efgh + let backup_src = &sample_storage_2_first_path.join("abcd").join("efgh"); + DirBuilder::new().recursive(true).create(backup_src)?; + let backup_dest = &sample_storage.join("Downloads").join("abcd").join("efgh"); + DirBuilder::new().recursive(true).create(backup_dest)?; + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_1.path()) + .arg("backup") + .arg("add") + .arg("--src") + .arg(backup_src) + .arg("--dest") + .arg(backup_dest) + .arg("abcdbackup") + .arg("external") + .arg("rsync") + .arg("note: nonsense") + .assert() + .success(); + + // backup add + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - first: sample_storage_2_first_path + // - second: sample_storage_2 + // backups: + // - foodoc: second + // - sample_storage_2/foo/bar -> sample_directory/docs (done 1) + // - abcdbackup: first + // - sample_storage_2_first_path/abcd/efgh -> sample_storage/Downloads/abcd/efgh + // - abcdsubbackup: first + // - sample_storage_2_first_path/abcd/efgh/sub -> sample_storage/Downloads/abcd/efgh/sub + let backup_src = &sample_storage_2_first_path + .join("abcd") + .join("efgh") + .join("sub"); + DirBuilder::new().recursive(true).create(backup_src)?; + let backup_dest = &sample_storage + .join("Downloads") + .join("abcd") + .join("efgh") + .join("sub"); + DirBuilder::new().recursive(true).create(backup_dest)?; + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_1.path()) + .arg("backup") + .arg("add") + .arg("--src") + .arg(backup_src) + .arg("--dest") + .arg(backup_dest) + .arg("abcdsubbackup") + .arg("external") + .arg("rsync") + .arg("note: only subdirectory") + .assert() + .success(); + + std::process::Command::new("git") + .arg("push") + .current_dir(&config_dir_1) + .assert() + .success(); + std::process::Command::new("git") + .arg("pull") + .current_dir(&config_dir_2) + .assert() + .success(); + + // backup add + // + // devices: first, second + // storages: + // - gdrive (online) + // - first: sample_storage + // - gdrive_docs (subdir of sample_storage/foo/bar) + // - first + // - second: sample_directory + // - nas (online) + // - first: sample_storage_2_first_path + // - second: sample_storage_2 + // backups: + // - foodoc: second + // - sample_storage_2/foo/bar -> sample_directory/docs (done 1) + // - abcdbackup: first + // - sample_storage_2_first_path/abcd/efgh -> sample_storage/Downloads/abcd/efgh + // - abcdsubbackup: first + // - sample_storage_2_first_path/abcd/efgh/sub -> sample_storage/Downloads/abcd/efgh/sub + // - abcdbackup2: second + // - sample_storage_2/abcd/efgh -> sample_directory/Downloads/abcd/efgh + let backup_src = &sample_storage_2.join("abcd").join("efgh"); + DirBuilder::new().recursive(true).create(backup_src)?; + let backup_dest = &sample_directory + .join("Downloads") + .join("abcd") + .join("efgh"); + DirBuilder::new().recursive(true).create(backup_dest)?; + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("backup") + .arg("add") + .arg("--src") + .arg(backup_src) + .arg("--dest") + .arg(backup_dest) + .arg("abcdbackup2") + .arg("external") + .arg("rsync") + .arg("note: only subdirectory") + .assert() + .success(); + + // status + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("status") + .arg("-sb") + .arg(backup_src) + .assert() + .success() + .stdout( + predicate::str::contains("nas") + .and(predicate::str::contains("first")) + .and(predicate::str::contains("abcdbackup")) + .and(predicate::str::contains("abcdsubbackup").not()) + .and(predicate::str::contains("second")) + .and(predicate::str::contains("abcdbackup2")), + ); + Command::cargo_bin("xdbm")? + .arg("-c") + .arg(config_dir_2.path()) + .arg("status") + .arg("-sb") + .arg(backup_src.join("sub")) + .assert() + .success() + .stdout( + predicate::str::contains("nas") + .and(predicate::str::contains("first")) + .and(predicate::str::contains("abcdbackup")) + .and(predicate::str::contains("abcdsubbackup")) + .and(predicate::str::contains("second")) + .and(predicate::str::contains("abcdbackup2")), + ); + Ok(()) } } From c4aa76d1251301dd815ed298de9cb59ff2e820ef Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 02:15:49 +0900 Subject: [PATCH 20/28] update(test): add prefix '_' to unused variables --- tests/cli.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cli.rs b/tests/cli.rs index b082182..3407c86 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -145,7 +145,7 @@ mod integrated_test { // bare-repo let bare_repo_dir = assert_fs::TempDir::new()?; - let bare_repo = Repository::init_bare(&bare_repo_dir)?; + let _bare_repo = Repository::init_bare(&bare_repo_dir)?; // push to bare repository let repo_1 = Repository::open(&config_dir_1)?; let upstream_name = "remote"; @@ -229,7 +229,7 @@ mod integrated_test { // bare-repo let bare_repo_dir = assert_fs::TempDir::new()?; - let bare_repo = Repository::init_bare(&bare_repo_dir)?; + let _bare_repo = Repository::init_bare(&bare_repo_dir)?; // push to bare repository let repo_1 = Repository::open(&config_dir_1)?; let upstream_name = "remote"; From af1b56eee21a151ebdf5e2f51352db48bb3a6b47 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 02:52:53 +0900 Subject: [PATCH 21/28] add: style to cmd_status --- src/cmd_status.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/cmd_status.rs b/src/cmd_status.rs index ebc61d2..7c7f7f2 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -1,5 +1,6 @@ use anyhow::{Context, Result}; use chrono::Local; +use console::Style; use std::{ env, path::{self, Path, PathBuf}, @@ -96,14 +97,20 @@ pub(crate) fn cmd_status( for (backup_device, covering_backups) in covering_backup { println!("Device: {}", backup_device.name()); for (backup, path_from_backup) in covering_backups { - let last_backup = match backup.last_backup() { - Some(log) => util::format_summarized_duration(Local::now() - log.datetime), - None => "---".to_string(), + let (last_backup, style) = match backup.last_backup() { + Some(log) => { + let timediff = Local::now() - log.datetime; + ( + util::format_summarized_duration(timediff), + util::duration_style(timediff), + ) + } + None => ("---".to_string(), Style::new().red()), }; println!( " {: Date: Mon, 2 Dec 2024 02:53:30 +0900 Subject: [PATCH 22/28] update: don't display devices with no backups in cmd_status --- src/cmd_status.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd_status.rs b/src/cmd_status.rs index 7c7f7f2..5215ac7 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -95,6 +95,10 @@ pub(crate) fn cmd_status( .unwrap_or(5); for (backup_device, covering_backups) in covering_backup { + if covering_backups.is_empty() { + continue; + } + println!("Device: {}", backup_device.name()); for (backup, path_from_backup) in covering_backups { let (last_backup, style) = match backup.last_backup() { From 24f13566854805b0bd3105642554b9ba34a48a37 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 02:59:34 +0900 Subject: [PATCH 23/28] fix(test): for commit 7e043a652ca7a9c48582e8a7ed784715d3eaa1aa --- tests/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli.rs b/tests/cli.rs index 3407c86..fe9a837 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -563,7 +563,7 @@ mod integrated_test { .success() .stdout( predicate::str::contains("nas") - .and(predicate::str::contains("second")) + .and(predicate::str::contains("second").not()) .and(predicate::str::contains("foodoc").not()), ); From 996ca7e4b3af0c8acd2933fca1d4a43c6d2ccf1f Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 03:00:56 +0900 Subject: [PATCH 24/28] run fmt --- tests/cli.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/cli.rs b/tests/cli.rs index fe9a837..929a74e 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -725,10 +725,7 @@ mod integrated_test { // - sample_storage_2/abcd/efgh -> sample_directory/Downloads/abcd/efgh let backup_src = &sample_storage_2.join("abcd").join("efgh"); DirBuilder::new().recursive(true).create(backup_src)?; - let backup_dest = &sample_directory - .join("Downloads") - .join("abcd") - .join("efgh"); + let backup_dest = &sample_directory.join("Downloads").join("abcd").join("efgh"); DirBuilder::new().recursive(true).create(backup_dest)?; Command::cargo_bin("xdbm")? .arg("-c") From 3d8aa7bca0ecf1bb745d4733cea7c56e7bad2dfb Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 03:05:43 +0900 Subject: [PATCH 25/28] update: CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd526a2..16a827f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Changed - Colored output for `storage list` and `backup list` ([#15](https://github.com/qwjyh/xdbm/pull/15)) - **BREAKING** Relative path is changed from `PathBuf` to `Vector` for portability. This means that existing config files need to be changed. +- Add `status` subcommand to see storage and backup on given path or current working directory ([#17](https://github.com/qwjyh/xdbm/pull/17)). ## [0.2.1] - 2024-06-19 From 07ef49ca7b203b995823fb3fb0f91b5bc052495e Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 03:07:25 +0900 Subject: [PATCH 26/28] add: long argument option to cmd_status --- src/cmd_args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd_args.rs b/src/cmd_args.rs index 4627f97..c0b46b7 100644 --- a/src/cmd_args.rs +++ b/src/cmd_args.rs @@ -49,10 +49,10 @@ pub(crate) enum Commands { /// Target path. Default is the current directory. path: Option, /// Show storage which the path belongs to. - #[arg(short)] + #[arg(short, long)] storage: bool, /// Show backup config covering the path. - #[arg(short)] + #[arg(short, long)] backup: bool, }, From 4e8387e3b05477db78288b0dd27a10ab000f82c5 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 03:07:48 +0900 Subject: [PATCH 27/28] fix typo --- src/cmd_status.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd_status.rs b/src/cmd_status.rs index 5215ac7..560c02f 100644 --- a/src/cmd_status.rs +++ b/src/cmd_status.rs @@ -21,11 +21,11 @@ pub(crate) fn cmd_status( config_dir: &Path, ) -> Result<()> { let path = path.unwrap_or(env::current_dir().context("Failed to get current directory.")?); - let currrent_device = devices::get_device(config_dir)?; + let current_device = devices::get_device(config_dir)?; if show_storage { let storages = storages::Storages::read(config_dir)?; - let storage = util::min_parent_storage(&path, &storages, &currrent_device); + let storage = util::min_parent_storage(&path, &storages, ¤t_device); trace!("storage {:?}", storage); // TODO: recursively trace all storages for subdirectory? @@ -48,7 +48,7 @@ pub(crate) fn cmd_status( }); let (target_storage, target_diff_from_storage) = - util::min_parent_storage(&path, &storages, &currrent_device) + util::min_parent_storage(&path, &storages, ¤t_device) .context("Target path is not covered in any storage")?; let covering_backup: Vec<_> = devices From 51e90b28cd2bfcd26e81b80e0bcad991c352c1f6 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Mon, 2 Dec 2024 12:26:02 +0900 Subject: [PATCH 28/28] Update dependencies cargo update update clap update sysinfo 0.30 to 0.31 update sysninfo 0.31 to 0.32 update clap-verbosity-flag 2.2 -> 3.0 update env_logger 0.11.3 -> 0.11.5 update dependencies(unicode-width, dunce, pathdiff, byte-unit) update test dependencies --- Cargo.lock | 879 ++++++++++++++++++++++++++++++++++++----------------- Cargo.toml | 22 +- 2 files changed, 603 insertions(+), 298 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acb12dd..57deb60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -54,59 +54,60 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert_cmd" -version = "2.0.14" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" dependencies = [ "anstyle", "bstr", "doc-comment", + "libc", "predicates", "predicates-core", "predicates-tree", @@ -115,9 +116,9 @@ dependencies = [ [[package]] name = "assert_fs" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd762e110c8ed629b11b6cde59458cc1c71de78ebbcc30099fc8e0403a2a2ec" +checksum = "7efdb1fdb47602827a342857666feb372712cbc64b414172bd6b167a02927674" dependencies = [ "anstyle", "doc-comment", @@ -130,9 +131,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" @@ -142,9 +143,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -160,9 +161,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" dependencies = [ "borsh-derive", "cfg_aliases", @@ -170,23 +171,22 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" +checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", - "syn_derive", + "syn 2.0.90", ] [[package]] name = "bstr" -version = "1.9.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", "regex-automata", @@ -201,9 +201,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-unit" -version = "5.1.4" +version = "5.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ac19bdf0b2665407c39d82dbc937e951e7e2001609f0fb32edd0af45a2d63e" +checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174" dependencies = [ "rust_decimal", "serde", @@ -240,19 +240,19 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.0.99" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -279,14 +279,14 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "clap" -version = "4.5.7" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -294,9 +294,9 @@ dependencies = [ [[package]] name = "clap-verbosity-flag" -version = "2.2.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb9b20c0dd58e4c2e991c8d203bbeb76c11304d1011659686b5b644bc29aa478" +checksum = "54381ae56ad222eea3f529c692879e9c65e07945ae48d3dc4d1cb18dbec8cf44" dependencies = [ "clap", "log", @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -316,36 +316,36 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.5" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4" +checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "console" @@ -356,15 +356,15 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", - "unicode-width", + "unicode-width 0.1.14", "windows-sys 0.52.0", ] [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crossbeam-deque" @@ -443,6 +443,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -451,9 +462,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" @@ -463,9 +474,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encode_unicode" @@ -475,9 +486,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", "regex", @@ -485,9 +496,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -504,19 +515,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "float-cmp" @@ -577,7 +588,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "libgit2-sys", "log", @@ -588,9 +599,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -605,7 +616,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "ignore", "walkdir", ] @@ -621,9 +632,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -639,16 +650,16 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -661,20 +672,149 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.5.0" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ "crossbeam-deque", "globset", @@ -688,12 +828,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", ] [[package]] @@ -702,7 +842,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossterm", "dyn-clone", "fuzzy-matcher", @@ -710,36 +850,37 @@ dependencies = [ "newline-converter", "once_cell", "unicode-segmentation", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -751,9 +892,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libgit2-sys" @@ -775,7 +916,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -795,9 +936,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.18" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -811,6 +952,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -823,9 +970,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" @@ -880,9 +1027,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl-probe" @@ -892,9 +1039,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -928,14 +1075,14 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" @@ -945,21 +1092,24 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" -version = "3.1.0" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "difflib", @@ -971,15 +1121,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -987,41 +1137,18 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1048,9 +1175,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1113,18 +1240,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -1133,9 +1260,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1145,9 +1272,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1156,9 +1283,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rend" @@ -1171,9 +1298,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec", "bytecheck", @@ -1189,9 +1316,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ "proc-macro2", "quote", @@ -1200,9 +1327,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.35.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", "borsh", @@ -1216,11 +1343,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1256,31 +1383,32 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1298,6 +1426,12 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" @@ -1310,9 +1444,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio", @@ -1330,9 +1464,9 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "smallvec" @@ -1340,6 +1474,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -1359,9 +1499,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1369,28 +1509,26 @@ dependencies = [ ] [[package]] -name = "syn_derive" -version = "0.1.8" +name = "synstructure" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.90", ] [[package]] name = "sysinfo" -version = "0.30.12" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" +checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", + "memchr", "ntapi", - "once_cell", "rayon", "serde", "windows", @@ -1404,14 +1542,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1422,22 +1561,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.90", ] [[package]] @@ -1451,10 +1590,20 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1467,53 +1616,44 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "toml_datetime", "winnow", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unsafe-libyaml" @@ -1523,21 +1663,33 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + [[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1546,9 +1698,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[package]] name = "vcpkg" @@ -1558,9 +1710,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -1589,34 +1741,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1624,22 +1777,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "winapi" @@ -1659,11 +1812,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1674,12 +1827,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.52.0" +version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ - "windows-core", - "windows-targets 0.52.5", + "windows-core 0.57.0", + "windows-targets 0.52.6", ] [[package]] @@ -1688,7 +1841,50 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1706,7 +1902,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1726,18 +1931,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1748,9 +1953,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1760,9 +1965,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1772,15 +1977,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1790,9 +1995,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1802,9 +2007,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1814,9 +2019,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1826,19 +2031,31 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.40" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -1872,5 +2089,93 @@ dependencies = [ "serde", "serde_yaml", "sysinfo", - "unicode-width", + "unicode-width 0.2.0", +] + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] diff --git a/Cargo.toml b/Cargo.toml index c11d975..e573c59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,26 +13,26 @@ keywords = ["cli", "backup"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.4.0", features = ["cargo", "derive"] } -sysinfo = { version = "0.30", features = ["serde"] } +clap = { version = "4.5", features = ["cargo", "derive"] } +sysinfo = { version = "0.32", features = ["serde"] } log = "0.4" -clap-verbosity-flag = "2.2" +clap-verbosity-flag = "3.0" clap_complete = "4.5" chrono = { version = "0.4", features = ["serde"] } -env_logger = "0.11.3" +env_logger = "0.11.5" inquire = "0.7.5" git2 = "0.19" dirs = "5.0" -dunce = "1.0.4" +dunce = "1.0.5" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" -byte-unit = "5.1.4" +byte-unit = "5.1" anyhow = "1.0" -pathdiff = "0.2.1" -unicode-width = "0.1.13" +pathdiff = "0.2.3" +unicode-width = "0.2.0" console = "0.15" [dev-dependencies] -assert_cmd = "2.0.14" -assert_fs = "1.1.1" -predicates = "3.1.0" +assert_cmd = "2.0.16" +assert_fs = "1.1.2" +predicates = "3.1.2"