feat: implement unpacking
This commit is contained in:
@@ -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");
|
||||||
|
|||||||
@@ -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()?,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user