refactor: use conflate instead of merge crate

Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
This commit is contained in:
simonsan 2024-09-26 15:27:28 +02:00
parent 85c350972c
commit dae2cf7497
No known key found for this signature in database
GPG Key ID: E11D13668EC3B71B
9 changed files with 82 additions and 32 deletions

46
Cargo.lock generated
View File

@ -800,6 +800,28 @@ dependencies = [
"triomphe",
]
[[package]]
name = "conflate"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06f57b4959992e02db0da86fcb4b0c80dc112d31b823de27f61576b1c809bc45"
dependencies = [
"conflate_derive",
"num-traits",
]
[[package]]
name = "conflate_derive"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9395ace5316656ca6a778aa2c28ab0c4ea2c94a8f7dc942898c20be9b7a9a4b9"
dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "console"
version = "0.15.8"
@ -3153,6 +3175,28 @@ dependencies = [
"version_check",
]
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "proc-macro-error2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
@ -3674,6 +3718,7 @@ dependencies = [
"clap",
"clap_complete",
"comfy-table",
"conflate",
"convert_case",
"crossterm 0.28.1",
"dav-server",
@ -3690,7 +3735,6 @@ dependencies = [
"jemallocator-global",
"libc",
"log",
"merge",
"mimalloc",
"once_cell",
"predicates",

View File

@ -85,6 +85,7 @@ bytesize = "1"
cached = "0.53.1"
clap = { version = "4", features = ["derive", "env", "wrap_help"] }
clap_complete = "4"
conflate = "0.2"
convert_case = "0.6.0"
dialoguer = "0.11.0"
directories = "5"
@ -94,7 +95,6 @@ human-panic = "2.0.1"
humantime = "2"
indicatif = "0.17"
itertools = "0.13"
merge = "0.1"
once_cell = "1.19"
self_update = { version = "0.41", default-features = false, optional = true, features = ["rustls", "archive-tar", "compression-flate2"] }
toml = "0.8"

View File

@ -12,8 +12,8 @@ use abscissa_core::{Command, Runnable, Shutdown};
use anyhow::{bail, Context, Result};
use clap::ValueHint;
use comfy_table::Cell;
use conflate::Merge;
use log::{debug, info, warn};
use merge::Merge;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
@ -47,10 +47,12 @@ pub struct BackupCmd {
/// Start the given command and use its output as stdin
#[clap(long, value_name = "COMMAND")]
#[merge(strategy = conflate::option::overwrite_none)]
stdin_command: Option<CommandInput>,
/// Manually set backup path in snapshot
#[clap(long, value_name = "PATH", value_hint = ValueHint::DirPath)]
#[merge(strategy = conflate::option::overwrite_none)]
as_path: Option<PathBuf>,
/// Ignore save options
@ -60,27 +62,27 @@ pub struct BackupCmd {
/// Don't scan the backup source for its size - this disables ETA estimation for backup.
#[clap(long)]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
pub no_scan: bool,
/// Output generated snapshot in json format
#[clap(long)]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
json: bool,
/// Show detailed information about generated snapshot
#[clap(long, conflicts_with = "json")]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
long: bool,
/// Don't show any output
#[clap(long, conflicts_with_all = ["json", "long"])]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
quiet: bool,
/// Initialize repository, if it doesn't exist yet
#[clap(long)]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
init: bool,
/// Parent processing options

View File

@ -7,8 +7,8 @@ use crate::{
};
use abscissa_core::{config::Override, Command, FrameworkError, Runnable, Shutdown};
use anyhow::{bail, Result};
use conflate::Merge;
use log::{error, info, log, Level};
use merge::Merge;
use serde::{Deserialize, Serialize};
use rustic_core::{CopySnapshot, Id, KeyOptions};
@ -30,7 +30,7 @@ pub struct CopyCmd {
/// Target repository (can be specified multiple times)
#[clap(long = "target", value_name = "TARGET")]
#[merge(strategy = merge::vec::overwrite_empty)]
#[merge(strategy = conflate::vec::overwrite_empty)]
targets: Vec<String>,
/// Key options (when using --init)

View File

@ -10,7 +10,7 @@ use abscissa_core::{Command, FrameworkError, Runnable};
use anyhow::Result;
use chrono::Local;
use merge::Merge;
use conflate::Merge;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
@ -70,11 +70,12 @@ pub struct ForgetOptions {
/// Group snapshots by any combination of host,label,paths,tags (default: "host,label,paths")
#[clap(long, short = 'g', value_name = "CRITERION")]
#[serde_as(as = "Option<DisplayFromStr>")]
#[merge(strategy = conflate::option::overwrite_none)]
group_by: Option<SnapshotGroupCriterion>,
/// Also prune the repository
#[clap(long)]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
prune: bool,
/// Snapshot filter options

View File

@ -8,8 +8,8 @@ use std::{net::ToSocketAddrs, str::FromStr};
use crate::{commands::open_repository_indexed, status_err, Application, RusticConfig, RUSTIC_APP};
use abscissa_core::{config::Override, Command, FrameworkError, Runnable, Shutdown};
use anyhow::{anyhow, Result};
use conflate::Merge;
use dav_server::{warp::dav_handler, DavHandler};
use merge::Merge;
use serde::{Deserialize, Serialize};
use rustic_core::vfs::{FilePolicy, IdenticalSnapshot, Latest, Vfs};
@ -19,27 +19,32 @@ use rustic_core::vfs::{FilePolicy, IdenticalSnapshot, Latest, Vfs};
pub struct WebDavCmd {
/// Address to bind the webdav server to. [default: "localhost:8000"]
#[clap(long, value_name = "ADDRESS")]
#[merge(strategy = conflate::option::overwrite_none)]
address: Option<String>,
/// The path template to use for snapshots. {id}, {id_long}, {time}, {username}, {hostname}, {label}, {tags}, {backup_start}, {backup_end} are replaced. [default: "[{hostname}]/[{label}]/{time}"]
#[clap(long)]
#[merge(strategy = conflate::option::overwrite_none)]
path_template: Option<String>,
/// The time template to use to display times in the path template. See https://docs.rs/chrono/latest/chrono/format/strftime/index.html for format options. [default: "%Y-%m-%d_%H-%M-%S"]
#[clap(long)]
#[merge(strategy = conflate::option::overwrite_none)]
time_template: Option<String>,
/// Use symlinks. This may not be supported by all WebDAV clients
#[clap(long)]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
symlinks: bool,
/// How to handle access to files. [default: "forbidden" for hot/cold repositories, else "read"]
#[clap(long)]
#[merge(strategy = conflate::option::overwrite_none)]
file_access: Option<String>,
/// Specify directly which snapshot/path to serve
#[clap(value_name = "SNAPSHOT[:PATH]")]
#[merge(strategy = conflate::option::overwrite_none)]
snapshot_path: Option<String>,
}

View File

@ -12,10 +12,10 @@ use abscissa_core::config::Config;
use abscissa_core::path::AbsPathBuf;
use abscissa_core::FrameworkError;
use clap::{Parser, ValueHint};
use conflate::Merge;
use directories::ProjectDirs;
use itertools::Itertools;
use log::Level;
use merge::Merge;
use rustic_backend::BackendOptions;
use rustic_core::RepositoryOptions;
use serde::{Deserialize, Serialize};
@ -136,21 +136,22 @@ pub struct GlobalOptions {
value_name = "PROFILE",
env = "RUSTIC_USE_PROFILE"
)]
#[merge(strategy = merge::vec::append)]
#[merge(strategy = conflate::vec::append)]
pub use_profiles: Vec<String>,
/// Only show what would be done without modifying anything. Does not affect read-only commands.
#[clap(long, short = 'n', global = true, env = "RUSTIC_DRY_RUN")]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
pub dry_run: bool,
/// Check if index matches pack files and read pack headers if neccessary
#[clap(long, global = true, env = "RUSTIC_CHECK_INDEX")]
#[merge(strategy = merge::bool::overwrite_false)]
#[merge(strategy = conflate::bool::overwrite_false)]
pub check_index: bool,
/// Use this log level [default: info]
#[clap(long, global = true, env = "RUSTIC_LOG_LEVEL")]
#[merge(strategy = conflate::option::overwrite_none)]
pub log_level: Option<String>,
/// Write log messages to the given file instead of printing them.
@ -159,6 +160,7 @@ pub struct GlobalOptions {
///
/// Warnings and errors are still additionally printed unless they are ignored by `--log-level`
#[clap(long, global = true, env = "RUSTIC_LOG_FILE", value_name = "LOGFILE", value_hint = ValueHint::FilePath)]
#[merge(strategy = conflate::option::overwrite_none)]
pub log_file: Option<PathBuf>,
/// Settings to customize progress bars
@ -168,16 +170,10 @@ pub struct GlobalOptions {
/// List of environment variables to set (only in config file)
#[clap(skip)]
#[merge(strategy = extend)]
#[merge(strategy = conflate::hashmap::overwrite)]
pub env: HashMap<String, String>,
}
/// Extend the contents of a [`HashMap`] with the contents of another
/// [`HashMap`] with the same key and value types.
fn extend(left: &mut HashMap<String, String>, right: HashMap<String, String>) {
left.extend(right);
}
/// Get the paths to the config file
///
/// # Arguments

View File

@ -5,7 +5,7 @@ use std::{borrow::Cow, fmt::Write, time::Duration};
use indicatif::{HumanDuration, ProgressBar, ProgressState, ProgressStyle};
use clap::Parser;
use merge::Merge;
use conflate::Merge;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
@ -19,7 +19,7 @@ use rustic_core::{Progress, ProgressBars};
pub struct ProgressOptions {
/// Don't show any progress bar
#[clap(long, global = true, env = "RUSTIC_NO_PROGRESS")]
#[merge(strategy=merge::bool::overwrite_false)]
#[merge(strategy=conflate::bool::overwrite_false)]
pub no_progress: bool,
/// Interval to update progress bars
@ -31,6 +31,7 @@ pub struct ProgressOptions {
conflicts_with = "no_progress"
)]
#[serde_as(as = "Option<DisplayFromStr>")]
#[merge(strategy = conflate::option::overwrite_none)]
pub progress_interval: Option<humantime::Duration>,
}

View File

@ -55,34 +55,35 @@ impl SnapshotFn {
}
#[serde_as]
#[derive(Clone, Default, Debug, Serialize, Deserialize, merge::Merge, clap::Parser)]
#[derive(Clone, Default, Debug, Serialize, Deserialize, conflate::Merge, clap::Parser)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
pub struct SnapshotFilter {
/// Hostname to filter (can be specified multiple times)
#[clap(long = "filter-host", global = true, value_name = "HOSTNAME")]
#[merge(strategy=merge::vec::overwrite_empty)]
#[merge(strategy=conflate::vec::overwrite_empty)]
filter_hosts: Vec<String>,
/// Label to filter (can be specified multiple times)
#[clap(long = "filter-label", global = true, value_name = "LABEL")]
#[merge(strategy=merge::vec::overwrite_empty)]
#[merge(strategy=conflate::vec::overwrite_empty)]
filter_labels: Vec<String>,
/// Path list to filter (can be specified multiple times)
#[clap(long, global = true, value_name = "PATH[,PATH,..]")]
#[serde_as(as = "Vec<DisplayFromStr>")]
#[merge(strategy=merge::vec::overwrite_empty)]
#[merge(strategy=conflate::vec::overwrite_empty)]
filter_paths: Vec<StringList>,
/// Tag list to filter (can be specified multiple times)
#[clap(long, global = true, value_name = "TAG[,TAG,..]")]
#[serde_as(as = "Vec<DisplayFromStr>")]
#[merge(strategy=merge::vec::overwrite_empty)]
#[merge(strategy=conflate::vec::overwrite_empty)]
filter_tags: Vec<StringList>,
/// Function to filter snapshots
#[clap(long, global = true, value_name = "FUNC")]
#[serde_as(as = "Option<DisplayFromStr>")]
#[merge(strategy = conflate::option::overwrite_none)]
filter_fn: Option<String>,
}