mirror of
https://github.com/edu4rdshl/rusnapshot.git
synced 2026-07-17 23:24:55 +00:00
Add support for TOML config files
This commit is contained in:
parent
c32742b355
commit
bac3a8c69e
8 changed files with 134 additions and 18 deletions
75
Cargo.lock
generated
75
Cargo.lock
generated
|
|
@ -224,6 +224,12 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
|
@ -245,6 +251,12 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
|
@ -280,6 +292,16 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.10"
|
version = "0.4.10"
|
||||||
|
|
@ -437,6 +459,7 @@ dependencies = [
|
||||||
"prettytable-rs",
|
"prettytable-rs",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlite",
|
"sqlite",
|
||||||
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -484,6 +507,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlite"
|
name = "sqlite"
|
||||||
version = "0.33.0"
|
version = "0.33.0"
|
||||||
|
|
@ -562,6 +594,40 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
|
|
@ -736,3 +802,12 @@ name = "windows_x86_64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.5.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ md5 = "0.7.0"
|
||||||
chrono = "0.4.33"
|
chrono = "0.4.33"
|
||||||
prettytable-rs = "0.10.0"
|
prettytable-rs = "0.10.0"
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
|
toml = "0.8.9"
|
||||||
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
# Example configuration file for rustnapshot
|
# Example configuration file for rusnapshot
|
||||||
# These are all the current available options
|
# These are all the current available options
|
||||||
|
|
||||||
# Snapshots directory
|
# Snapshots directory
|
||||||
dest_dir = "/mnt/defvol/_snapshots/"
|
dest_dir = "/mnt/defvol/_snapshots/"
|
||||||
# Directory to be snapshoted
|
# Directory to be snapshot-ed
|
||||||
source_dir = "/mnt/defvol/_active/root/"
|
source_dir = "/mnt/defvol/_active/root/"
|
||||||
# SQLite database file PATH, created if no exists, recommended to be in the snapshots dir
|
# SQLite database file PATH, created if no exists, recommended to be in the snapshots dir
|
||||||
database_file = "/mnt/defvol/_snapshots/rustnapshot.sqlite"
|
database_file = "/mnt/defvol/_snapshots/rusnapshot.sqlite"
|
||||||
# Prefix for the snapshots, they will be saved in the format prefix-$current_date
|
# Prefix for the snapshots, they will be saved in the format prefix-$current_date
|
||||||
snapshot_prefix = "root"
|
snapshot_prefix = "root"
|
||||||
# Snapshots identifier
|
# Snapshots identifier
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
dest_dir = "/mnt/defvol/_snapshots/"
|
dest_dir = "/mnt/defvol/_snapshots/"
|
||||||
source_dir = "/home/"
|
source_dir = "/home/"
|
||||||
database_file = "/mnt/defvol/_snapshots/rustnapshot.sqlite"
|
database_file = "/mnt/defvol/_snapshots/rusnapshot.sqlite"
|
||||||
snapshot_prefix = "home"
|
snapshot_prefix = "home"
|
||||||
keep_only = "2"
|
keep_only = "2"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
dest_dir = "/mnt/defvol/_snapshots/"
|
dest_dir = "/mnt/defvol/_snapshots/"
|
||||||
source_dir = "/"
|
source_dir = "/"
|
||||||
database_file = "/mnt/defvol/_snapshots/rustnapshot.sqlite"
|
database_file = "/mnt/defvol/_snapshots/rusnapshot.sqlite"
|
||||||
snapshot_prefix = "root"
|
snapshot_prefix = "root"
|
||||||
keep_only = "2"
|
keep_only = "2"
|
||||||
|
|
|
||||||
36
src/args.rs
36
src/args.rs
|
|
@ -4,6 +4,7 @@ use {
|
||||||
clap::Parser,
|
clap::Parser,
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
sqlite::Connection,
|
sqlite::Connection,
|
||||||
|
std::collections::BTreeMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Simple and handy btrfs snapshoting tool.
|
/// Simple and handy btrfs snapshoting tool.
|
||||||
|
|
@ -46,7 +47,7 @@ pub struct Args {
|
||||||
#[clap(long = "create", conflicts_with_all = &["restore_snapshot", "delete_snapshot", "list_snapshots", "clean_snapshots"])]
|
#[clap(long = "create", conflicts_with_all = &["restore_snapshot", "delete_snapshot", "list_snapshots", "clean_snapshots"])]
|
||||||
pub create_snapshot: bool,
|
pub create_snapshot: bool,
|
||||||
/// Enable snapshots cleaning, will keep only the last X snapshots specified with -k/--keep.
|
/// Enable snapshots cleaning, will keep only the last X snapshots specified with -k/--keep.
|
||||||
#[clap(long = "clean")]
|
#[clap(long = "clean", requires_all = &["keep_only", "snapshot_kind", "snapshot_prefix"])]
|
||||||
pub clean_snapshots: bool,
|
pub clean_snapshots: bool,
|
||||||
/// Delete a snapshot.
|
/// Delete a snapshot.
|
||||||
#[clap(long = "del", requires_all = &["snapshot_id"])]
|
#[clap(long = "del", requires_all = &["snapshot_id"])]
|
||||||
|
|
@ -95,3 +96,36 @@ impl Args {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deserialize the configuration file.
|
||||||
|
impl Args {
|
||||||
|
/// Deserialize the configuration file.
|
||||||
|
pub fn from_config_file(&mut self) -> Result<()> {
|
||||||
|
let config_file = std::fs::read_to_string(self.config_file.as_deref().unwrap())?;
|
||||||
|
let config: BTreeMap<String, toml::Value> = toml::from_str(&config_file)?;
|
||||||
|
|
||||||
|
if let Some(dest_dir) = config.get("dest_dir") {
|
||||||
|
self.dest_dir = dest_dir.as_str().unwrap().to_string();
|
||||||
|
}
|
||||||
|
if let Some(source_dir) = config.get("source_dir") {
|
||||||
|
self.source_dir = source_dir.as_str().unwrap().to_string();
|
||||||
|
}
|
||||||
|
if let Some(snapshot_prefix) = config.get("snapshot_prefix") {
|
||||||
|
self.snapshot_prefix = snapshot_prefix.as_str().unwrap().to_string();
|
||||||
|
}
|
||||||
|
if let Some(snapshot_kind) = config.get("snapshot_kind") {
|
||||||
|
self.snapshot_kind = snapshot_kind.as_str().unwrap().to_string();
|
||||||
|
}
|
||||||
|
if let Some(database_file) = config.get("database_file") {
|
||||||
|
self.database_file = database_file.as_str().unwrap().to_string();
|
||||||
|
}
|
||||||
|
if let Some(keep_only) = config.get("keep_only") {
|
||||||
|
self.keep_only = keep_only.as_integer().unwrap() as usize;
|
||||||
|
}
|
||||||
|
if let Some(timeout) = config.get("timeout") {
|
||||||
|
self.timeout = timeout.as_integer().unwrap() as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,9 +95,11 @@ pub fn manage_listing(database_connection: &Connection) -> Result<()> {
|
||||||
|
|
||||||
pub fn keep_only_x(args: &mut Args, extra_args: &mut ExtraArgs) -> Result<()> {
|
pub fn keep_only_x(args: &mut Args, extra_args: &mut ExtraArgs) -> Result<()> {
|
||||||
let snaps_data = database::return_only_x_items(&extra_args.database_connection, args)?;
|
let snaps_data = database::return_only_x_items(&extra_args.database_connection, args)?;
|
||||||
|
|
||||||
for data in &snaps_data {
|
for data in &snaps_data {
|
||||||
extra_args.snapshot_name = data.destination.clone() + &data.name;
|
extra_args.snapshot_name = data.destination.clone() + &data.name;
|
||||||
args.snapshot_id = data.snap_id.clone();
|
args.snapshot_id = data.snap_id.clone();
|
||||||
|
|
||||||
manage_deletion(args, extra_args)?;
|
manage_deletion(args, extra_args)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
28
src/main.rs
28
src/main.rs
|
|
@ -8,6 +8,10 @@ use rusnapshot::{args, controller, structs::ExtraArgs};
|
||||||
fn try_run() -> Result<()> {
|
fn try_run() -> Result<()> {
|
||||||
let mut arguments = args::Args::parse();
|
let mut arguments = args::Args::parse();
|
||||||
|
|
||||||
|
if arguments.config_file.is_some() {
|
||||||
|
arguments.from_config_file()?;
|
||||||
|
}
|
||||||
|
|
||||||
let mut extra_args = ExtraArgs {
|
let mut extra_args = ExtraArgs {
|
||||||
snapshot_name: format!(
|
snapshot_name: format!(
|
||||||
"{}-{}",
|
"{}-{}",
|
||||||
|
|
@ -19,19 +23,19 @@ fn try_run() -> Result<()> {
|
||||||
|
|
||||||
arguments.init(&extra_args)?;
|
arguments.init(&extra_args)?;
|
||||||
|
|
||||||
// It's required to have a trailing slash for the source and destination directories.
|
|
||||||
// Otherwise, when we retrieve the snapshot data from the database, we won't be able to
|
|
||||||
// restore/delete the snapshot because the source/destination paths won't match.
|
|
||||||
if !arguments.source_dir.is_empty() && !arguments.source_dir.ends_with('/') {
|
|
||||||
arguments.source_dir += "/";
|
|
||||||
}
|
|
||||||
if !arguments.dest_dir.is_empty() && !arguments.dest_dir.ends_with('/') {
|
|
||||||
arguments.dest_dir += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we need to make sure that the paths for source and destination are full paths.
|
|
||||||
// If they are not, we will use the current working directory to build the full path.
|
|
||||||
if arguments.create_snapshot {
|
if arguments.create_snapshot {
|
||||||
|
// It's required to have a trailing slash for the source and destination directories.
|
||||||
|
// Otherwise, when we retrieve the snapshot data from the database, we won't be able to
|
||||||
|
// restore/delete the snapshot because the source/destination paths won't match.
|
||||||
|
if !arguments.source_dir.is_empty() && !arguments.source_dir.ends_with('/') {
|
||||||
|
arguments.source_dir += "/";
|
||||||
|
}
|
||||||
|
if !arguments.dest_dir.is_empty() && !arguments.dest_dir.ends_with('/') {
|
||||||
|
arguments.dest_dir += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we need to make sure that the paths for source and destination are full paths.
|
||||||
|
// If they are not, we will use the current working directory to build the full path.
|
||||||
if !Path::new(&arguments.source_dir).is_absolute() {
|
if !Path::new(&arguments.source_dir).is_absolute() {
|
||||||
arguments.source_dir = std::env::current_dir()?
|
arguments.source_dir = std::env::current_dir()?
|
||||||
.join(&arguments.source_dir)
|
.join(&arguments.source_dir)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue