feat(storage): add configuration format, accept custom fs dir
This commit is contained in:
119
Cargo.lock
generated
119
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.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
@@ -284,12 +290,28 @@ dependencies = [
|
|||||||
"wasip2",
|
"wasip2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indicatif"
|
name = "indicatif"
|
||||||
version = "0.18.3"
|
version = "0.18.3"
|
||||||
@@ -374,14 +396,18 @@ name = "minecraft-sync"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"console",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dirs",
|
"dirs",
|
||||||
"flate2",
|
"flate2",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
|
"serde",
|
||||||
|
"shellexpand",
|
||||||
"tar",
|
"tar",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"thiserror-ext",
|
"thiserror-ext",
|
||||||
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
@@ -552,6 +578,45 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@@ -561,6 +626,15 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shellexpand"
|
||||||
|
version = "3.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
@@ -665,6 +739,45 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.9.11+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde_core",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_parser",
|
||||||
|
"toml_writer",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.7.5+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_parser"
|
||||||
|
version = "1.0.6+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
|
||||||
|
dependencies = [
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_writer"
|
||||||
|
version = "1.0.6+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@@ -860,6 +973,12 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|||||||
@@ -5,14 +5,18 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.56", features = ["derive"] }
|
clap = { version = "4.5.56", features = ["derive"] }
|
||||||
|
console = "0.16.2"
|
||||||
ctrlc = "3.5.1"
|
ctrlc = "3.5.1"
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
flate2 = "1.1.8"
|
flate2 = "1.1.8"
|
||||||
indicatif = "0.18.3"
|
indicatif = "0.18.3"
|
||||||
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
shellexpand = "3.1.1"
|
||||||
tar = "0.4.44"
|
tar = "0.4.44"
|
||||||
tempfile = "3.24.0"
|
tempfile = "3.24.0"
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
thiserror-ext = "0.3.0"
|
thiserror-ext = "0.3.0"
|
||||||
|
toml = "0.9.11"
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
|
|||||||
34
src/config.rs
Normal file
34
src/config.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use std::{fs, io};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
error::{Error, Result},
|
||||||
|
storage::fs::base_path,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub sync: Sync,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Sync {
|
||||||
|
pub fs_dir: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn new() -> Result<Self> {
|
||||||
|
let path = base_path().join("config.toml");
|
||||||
|
let bytes = match fs::read(&path) {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => match e.kind() {
|
||||||
|
io::ErrorKind::NotFound => Vec::new(),
|
||||||
|
_ => return Err(Error::read_config(e, &path)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let config =
|
||||||
|
toml::from_slice::<Config>(&bytes).map_err(|e| Error::parse_config(e, &path))?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/error.rs
12
src/error.rs
@@ -34,6 +34,18 @@ pub enum ErrorKind {
|
|||||||
#[source]
|
#[source]
|
||||||
source: tempfile::PersistError,
|
source: tempfile::PersistError,
|
||||||
},
|
},
|
||||||
|
#[error("error parsing configuration at {path}")]
|
||||||
|
ParseConfig {
|
||||||
|
path: PathBuf,
|
||||||
|
#[source]
|
||||||
|
source: toml::de::Error,
|
||||||
|
},
|
||||||
|
#[error("error reading configuration at {path}")]
|
||||||
|
ReadConfig {
|
||||||
|
path: PathBuf,
|
||||||
|
#[source]
|
||||||
|
source: std::io::Error,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Error>;
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
|||||||
22
src/main.rs
22
src/main.rs
@@ -1,4 +1,5 @@
|
|||||||
mod archive;
|
mod archive;
|
||||||
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
mod reporter;
|
mod reporter;
|
||||||
mod storage;
|
mod storage;
|
||||||
@@ -6,6 +7,7 @@ mod storage;
|
|||||||
use std::{ops::Deref, sync::Arc};
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use clap::{CommandFactory, Parser, Subcommand};
|
use clap::{CommandFactory, Parser, Subcommand};
|
||||||
|
use console::style;
|
||||||
use indicatif::MultiProgress;
|
use indicatif::MultiProgress;
|
||||||
use thiserror_ext::AsReport;
|
use thiserror_ext::AsReport;
|
||||||
use tracing::level_filters::LevelFilter;
|
use tracing::level_filters::LevelFilter;
|
||||||
@@ -14,6 +16,7 @@ use tracing_subscriber::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config::Config,
|
||||||
reporter::Reporter,
|
reporter::Reporter,
|
||||||
storage::{Storage, StorageImpl, get_storage_from_env},
|
storage::{Storage, StorageImpl, get_storage_from_env},
|
||||||
};
|
};
|
||||||
@@ -34,15 +37,7 @@ enum Commands {
|
|||||||
struct AppState {
|
struct AppState {
|
||||||
multi: MultiProgress,
|
multi: MultiProgress,
|
||||||
storage: Storage,
|
storage: Storage,
|
||||||
}
|
config: Config,
|
||||||
|
|
||||||
impl AppState {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
multi: MultiProgress::new(),
|
|
||||||
storage: get_storage_from_env(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -63,7 +58,12 @@ impl Data {
|
|||||||
|
|
||||||
fn run() -> crate::error::Result<()> {
|
fn run() -> crate::error::Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let app_state = Data::new(AppState::new());
|
let config = Config::new()?;
|
||||||
|
let app_state = Data::new(AppState {
|
||||||
|
multi: MultiProgress::new(),
|
||||||
|
storage: get_storage_from_env(),
|
||||||
|
config,
|
||||||
|
});
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Some(Commands::Push) => {
|
Some(Commands::Push) => {
|
||||||
@@ -88,7 +88,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
)
|
)
|
||||||
.init();
|
.init();
|
||||||
if let Err(e) = run() {
|
if let Err(e) = run() {
|
||||||
eprintln!("Error: {}", e.as_report());
|
eprintln!("{}: {}", style("Error").red(), e.as_report());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -31,8 +31,12 @@ impl StorageImpl for FSStorage {
|
|||||||
let revision = self.get_revision()?;
|
let revision = self.get_revision()?;
|
||||||
let new_revision = revision + 1;
|
let new_revision = revision + 1;
|
||||||
let reporter = Reporter::new(app_state.clone());
|
let reporter = Reporter::new(app_state.clone());
|
||||||
let result = create_archive(app_state, &reporter)?;
|
let result = create_archive(app_state.clone(), &reporter)?;
|
||||||
let archive_path = base_path().join(&format!("revision_{new_revision}.tar.gz"));
|
let archive_path = match &app_state.config.sync.fs_dir {
|
||||||
|
Some(dir) => PathBuf::from(shellexpand::tilde(&dir).as_ref())
|
||||||
|
.join(&format!("revision_{new_revision}.tar.gz")),
|
||||||
|
_ => base_path().join(&format!("revision_{new_revision}.tar.gz")),
|
||||||
|
};
|
||||||
|
|
||||||
result
|
result
|
||||||
.temp_file
|
.temp_file
|
||||||
|
|||||||
Reference in New Issue
Block a user