feat(storage): add configuration format, accept custom fs dir

This commit is contained in:
2026-02-03 22:30:51 -08:00
parent 9b2c1d0624
commit 1d05bb8944
6 changed files with 186 additions and 13 deletions

119
Cargo.lock generated
View File

@@ -224,6 +224,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.14"
@@ -284,12 +290,28 @@ dependencies = [
"wasip2",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "indicatif"
version = "0.18.3"
@@ -374,14 +396,18 @@ name = "minecraft-sync"
version = "0.1.0"
dependencies = [
"clap",
"console",
"ctrlc",
"dirs",
"flate2",
"indicatif",
"serde",
"shellexpand",
"tar",
"tempfile",
"thiserror",
"thiserror-ext",
"toml",
"tracing",
"tracing-subscriber",
"walkdir",
@@ -552,6 +578,45 @@ dependencies = [
"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]]
name = "sharded-slab"
version = "0.1.7"
@@ -561,6 +626,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "shellexpand"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb"
dependencies = [
"dirs",
]
[[package]]
name = "simd-adler32"
version = "0.3.8"
@@ -665,6 +739,45 @@ dependencies = [
"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]]
name = "tracing"
version = "0.1.44"
@@ -860,6 +973,12 @@ dependencies = [
"windows-link",
]
[[package]]
name = "winnow"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
[[package]]
name = "wit-bindgen"
version = "0.51.0"

View File

@@ -5,14 +5,18 @@ edition = "2024"
[dependencies]
clap = { version = "4.5.56", features = ["derive"] }
console = "0.16.2"
ctrlc = "3.5.1"
dirs = "6.0.0"
flate2 = "1.1.8"
indicatif = "0.18.3"
serde = { version = "1.0.228", features = ["derive"] }
shellexpand = "3.1.1"
tar = "0.4.44"
tempfile = "3.24.0"
thiserror = "2.0.18"
thiserror-ext = "0.3.0"
toml = "0.9.11"
tracing = "0.1.44"
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
walkdir = "2.5.0"

34
src/config.rs Normal file
View 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)
}
}

View File

@@ -34,6 +34,18 @@ pub enum ErrorKind {
#[source]
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>;

View File

@@ -1,4 +1,5 @@
mod archive;
mod config;
mod error;
mod reporter;
mod storage;
@@ -6,6 +7,7 @@ mod storage;
use std::{ops::Deref, sync::Arc};
use clap::{CommandFactory, Parser, Subcommand};
use console::style;
use indicatif::MultiProgress;
use thiserror_ext::AsReport;
use tracing::level_filters::LevelFilter;
@@ -14,6 +16,7 @@ use tracing_subscriber::{
};
use crate::{
config::Config,
reporter::Reporter,
storage::{Storage, StorageImpl, get_storage_from_env},
};
@@ -34,15 +37,7 @@ enum Commands {
struct AppState {
multi: MultiProgress,
storage: Storage,
}
impl AppState {
pub fn new() -> Self {
Self {
multi: MultiProgress::new(),
storage: get_storage_from_env(),
}
}
config: Config,
}
#[derive(Clone)]
@@ -63,7 +58,12 @@ impl Data {
fn run() -> crate::error::Result<()> {
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 {
Some(Commands::Push) => {
@@ -88,7 +88,7 @@ fn main() -> std::io::Result<()> {
)
.init();
if let Err(e) = run() {
eprintln!("Error: {}", e.as_report());
eprintln!("{}: {}", style("Error").red(), e.as_report());
}
Ok(())

View File

@@ -31,8 +31,12 @@ impl StorageImpl for FSStorage {
let revision = self.get_revision()?;
let new_revision = revision + 1;
let reporter = Reporter::new(app_state.clone());
let result = create_archive(app_state, &reporter)?;
let archive_path = base_path().join(&format!("revision_{new_revision}.tar.gz"));
let result = create_archive(app_state.clone(), &reporter)?;
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
.temp_file