feat: implement unpacking

This commit is contained in:
2026-02-06 23:49:14 -08:00
parent a562005f6c
commit 0036b7007e
5 changed files with 46 additions and 22 deletions

View File

@@ -9,6 +9,7 @@ use crate::{
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Config { pub struct Config {
#[serde(default)]
pub sync: Sync, pub sync: Sync,
} }
@@ -17,6 +18,14 @@ pub struct Sync {
pub fs_dir: Option<String>, pub fs_dir: Option<String>,
} }
impl Default for Sync {
fn default() -> Self {
Self {
fs_dir: Some(base_path_local().to_string_lossy().into_owned()),
}
}
}
impl Config { impl Config {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let path = base_path_local().join("config.toml"); let path = base_path_local().join("config.toml");

View File

@@ -31,6 +31,8 @@ struct Cli {
enum Commands { enum Commands {
/// push current state to storage /// push current state to storage
Push, Push,
/// update state with latest revision
Pull,
} }
struct AppState { struct AppState {
@@ -68,6 +70,9 @@ fn run() -> crate::error::Result<()> {
Some(Commands::Push) => { Some(Commands::Push) => {
app_state.storage.store_revision(app_state.clone())?; app_state.storage.store_revision(app_state.clone())?;
} }
Some(Commands::Pull) => {
app_state.storage.unpack_revision(app_state.clone())?;
}
_ => Cli::command().print_long_help()?, _ => Cli::command().print_long_help()?,
} }

View File

@@ -1,4 +1,4 @@
use std::borrow::Cow; use std::{borrow::Cow, time::Duration};
use indicatif::{HumanBytes, ProgressBar, ProgressDrawTarget, ProgressStyle}; use indicatif::{HumanBytes, ProgressBar, ProgressDrawTarget, ProgressStyle};
@@ -19,7 +19,7 @@ impl Reporter {
.unwrap() .unwrap()
.tick_chars(TICK_CHARS), .tick_chars(TICK_CHARS),
); );
spinner.enable_steady_tick(std::time::Duration::from_millis(100)); spinner.enable_steady_tick(Duration::from_millis(100));
spinner.set_draw_target(ProgressDrawTarget::stderr_with_hz(20)); spinner.set_draw_target(ProgressDrawTarget::stderr_with_hz(20));
Self { app_state, spinner } Self { app_state, spinner }
} }
@@ -57,6 +57,25 @@ impl Reporter {
self.spinner.finish_with_message(msg); self.spinner.finish_with_message(msg);
} }
pub fn start_extract_progress(&self, operation: impl Into<Cow<'static, str>>) -> ProgressBar {
let bar = self.app_state.multi.add(ProgressBar::new_spinner());
bar.set_style(
ProgressStyle::with_template("{msg:8.214/yellow} {spinner} [{elapsed_precise}]")
.unwrap()
.tick_chars(TICK_CHARS),
);
bar.enable_steady_tick(Duration::from_millis(100));
bar.set_message(operation);
bar
}
pub fn finish_extract_progress(bar: &ProgressBar, msg: impl Into<Cow<'static, str>>) {
bar.set_style(
ProgressStyle::with_template("{msg:>12.green} ✓ [{elapsed_precise}]").unwrap(),
);
bar.finish_with_message(msg);
}
pub fn start_bytes_progress( pub fn start_bytes_progress(
&self, &self,
total_bytes: u64, total_bytes: u64,

View File

@@ -9,7 +9,7 @@ use crate::Data;
use crate::archive::create_archive; use crate::archive::create_archive;
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::reporter::Reporter; use crate::reporter::Reporter;
use crate::storage::StorageImpl; use crate::storage::{StorageImpl, base_path_prism};
pub struct FSStorage; pub struct FSStorage;
@@ -61,7 +61,7 @@ impl StorageImpl for FSStorage {
let reporter = Reporter::new(app_state.clone()); let reporter = Reporter::new(app_state.clone());
let result = create_archive(app_state.clone(), &reporter)?; let result = create_archive(app_state.clone(), &reporter)?;
let archive_path = let archive_path =
base_path(app_state.clone()).join(&format!("revision_{revision}.tar.gz")); base_path(app_state.clone()).join(&format!("revision_{new_revision}.tar.gz"));
match result.temp_file.persist(&archive_path) { match result.temp_file.persist(&archive_path) {
Ok(_) => {} Ok(_) => {}
@@ -111,17 +111,13 @@ impl StorageImpl for FSStorage {
Ok(archive) Ok(archive)
} }
fn unpack_revision( fn unpack_revision(&self, app_state: Data) -> Result<()> {
&self, let revision = self.get_revision_metadata(app_state.clone())?;
app_state: Data,
destination: PathBuf,
revision: usize,
) -> Result<()> {
let mut archive = self.retrieve_revision(app_state.clone(), revision)?; let mut archive = self.retrieve_revision(app_state.clone(), revision)?;
let entries = archive.entries()?; let entries = archive.entries()?;
let reporter = Reporter::new(app_state); let reporter =
let total_files = entries.progress_with_style Reporter::new(app_state.clone()).start_extract_progress("extracting revision");
reporter.start_archive_progress(total); let destination = base_path_prism();
for entry in entries { for entry in entries {
let mut entry = entry?; let mut entry = entry?;
@@ -129,6 +125,7 @@ impl StorageImpl for FSStorage {
.unpack_in(&destination) .unpack_in(&destination)
.map_err(|e| Error::unpack_error(e))?; .map_err(|e| Error::unpack_error(e))?;
} }
Reporter::finish_extract_progress(&reporter, "extracted revision");
Ok(()) Ok(())
} }

View File

@@ -14,8 +14,7 @@ pub trait StorageImpl {
app_state: Data, app_state: Data,
revision: usize, revision: usize,
) -> Result<tar::Archive<GzDecoder<BufReader<std::fs::File>>>>; ) -> Result<tar::Archive<GzDecoder<BufReader<std::fs::File>>>>;
fn unpack_revision(&self, app_state: Data, destination: PathBuf, revision: usize) fn unpack_revision(&self, app_state: Data) -> Result<()>;
-> Result<()>;
} }
pub enum Storage { pub enum Storage {
@@ -47,14 +46,9 @@ impl StorageImpl for Storage {
} }
} }
fn unpack_revision( fn unpack_revision(&self, app_state: Data) -> Result<()> {
&self,
app_state: Data,
destination: PathBuf,
revision: usize,
) -> Result<()> {
match self { match self {
Self::FS(storage) => storage.unpack_revision(app_state, destination, revision), Self::FS(storage) => storage.unpack_revision(app_state),
} }
} }
} }