Almost fully implement restore
This commit is contained in:
parent
b99f8d50fc
commit
75eab354c8
5 changed files with 117 additions and 37 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -427,6 +427,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"nom",
|
||||
"path-absolutize",
|
||||
"reflink",
|
||||
"rustyline",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -741,6 +742,16 @@ dependencies = [
|
|||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reflink"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc585ec28b565b4c28977ce8363a6636cedc280351ba25a7915f6c9f37f68cbe"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.5"
|
||||
|
|
|
@ -22,6 +22,7 @@ ghee-lang = { path = "lang" }
|
|||
lazy_static = "1.4.0"
|
||||
nom = "7.1.3"
|
||||
path-absolutize = "3.1.1"
|
||||
reflink = "0.1.3"
|
||||
rustyline = "12.0.0"
|
||||
serde = { version = "1.0.163", features = ["derive"] }
|
||||
serde_json = "1.0.96"
|
||||
|
|
|
@ -229,16 +229,16 @@ pub enum Commands {
|
|||
},
|
||||
|
||||
Restore {
|
||||
#[arg(help = "Paths to get restore", required = true)]
|
||||
#[arg(help = "Paths to restore", required = true)]
|
||||
paths: Vec<PathBuf>,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Delete paths not present in most recent commit; defaults to true",
|
||||
default_value_t = true
|
||||
help = "Keep paths not present in most recent commit; defaults to false",
|
||||
default_value_t = false
|
||||
)]
|
||||
delete: bool,
|
||||
keep: bool,
|
||||
|
||||
#[arg(long, help = "Process paths nonrecursively; defaults to false")]
|
||||
flat: bool,
|
||||
|
|
|
@ -247,14 +247,14 @@ fn run_command(cmd: &Commands) {
|
|||
|
||||
Commands::Restore {
|
||||
paths,
|
||||
delete,
|
||||
keep,
|
||||
flat,
|
||||
verbose,
|
||||
} => {
|
||||
let new_file_handling = if *delete {
|
||||
NewFileHandling::Delete
|
||||
let new_file_handling = if *keep {
|
||||
NewFileHandling::Keep
|
||||
} else {
|
||||
NewFileHandling::Ignore
|
||||
NewFileHandling::Delete
|
||||
};
|
||||
restore(paths, !*flat, *verbose, new_file_handling)
|
||||
.unwrap_or_else(|e| panic!("Error restoring paths {:?}: {}", paths, e));
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
use std::{env::current_dir, path::PathBuf};
|
||||
use std::{
|
||||
env::current_dir,
|
||||
fs::{remove_dir, remove_file},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use path_absolutize::Absolutize;
|
||||
use reflink::reflink_or_copy;
|
||||
use thiserror::Error;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::{
|
||||
containing_table_info,
|
||||
|
@ -11,7 +17,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub enum NewFileHandling {
|
||||
Ignore,
|
||||
Keep,
|
||||
Delete,
|
||||
}
|
||||
|
||||
|
@ -45,37 +51,99 @@ pub fn restore(
|
|||
|
||||
let snapshot_path = table_snapshot_path(table_path, uuid);
|
||||
|
||||
let max_depth = if recursive { usize::MAX } else { 0 };
|
||||
for path in paths {
|
||||
let abs_path = path.absolutize().unwrap().to_path_buf();
|
||||
for entry in WalkDir::new(path).max_depth(max_depth).into_iter() {
|
||||
let entry = entry?;
|
||||
|
||||
if !abs_path
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.starts_with(table_path.to_str().unwrap())
|
||||
{
|
||||
return Err(RestoreErr::PathNotContainedByTable {
|
||||
path: path.clone(),
|
||||
table_path: table_path.clone(),
|
||||
let path = entry.path().to_path_buf();
|
||||
|
||||
println!("path: {}", path.display());
|
||||
|
||||
let abs_path = path.absolutize().unwrap().to_path_buf();
|
||||
|
||||
if !abs_path
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.starts_with(table_path.to_str().unwrap())
|
||||
{
|
||||
return Err(RestoreErr::PathNotContainedByTable {
|
||||
path: path.clone(),
|
||||
table_path: table_path.clone(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
let rel_path = abs_path.relativize(table_path)?;
|
||||
|
||||
let snapshot_file_path = {
|
||||
let mut p = snapshot_path.clone();
|
||||
p.push(&rel_path);
|
||||
p
|
||||
}
|
||||
.absolutize()
|
||||
.unwrap()
|
||||
.to_path_buf();
|
||||
|
||||
println!("snapshot_file_path: {}", snapshot_file_path.display());
|
||||
|
||||
if abs_path.exists() {
|
||||
if snapshot_file_path.exists() {
|
||||
// Both paths exist
|
||||
// Now handle files vs directories
|
||||
if snapshot_file_path.is_dir() {
|
||||
if abs_path.is_dir() {
|
||||
// do nothing - both paths are directories
|
||||
} else {
|
||||
// Replace file with directory
|
||||
remove_file(&abs_path)?;
|
||||
copy_dir(&snapshot_file_path, &abs_path)?;
|
||||
//TODO copy entire tree of snapshot_file_path to abs_path
|
||||
// create_dir(&abs_path)?;
|
||||
}
|
||||
} else {
|
||||
// Snapshot is file
|
||||
// Copy over working either way
|
||||
//TODO Do we need to remove before `reflink_or_copy`ing over?
|
||||
if abs_path.is_dir() {
|
||||
remove_dir(&abs_path)?;
|
||||
} else {
|
||||
remove_file(&abs_path)?;
|
||||
}
|
||||
|
||||
reflink_or_copy(&snapshot_file_path, abs_path)?;
|
||||
if verbose {
|
||||
println!("r{}", path.display());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// working exists; snapshot doesn't
|
||||
match new_file_handling {
|
||||
NewFileHandling::Delete => {
|
||||
remove_file(abs_path)?;
|
||||
if verbose {
|
||||
println!("-{}", path.display());
|
||||
}
|
||||
}
|
||||
NewFileHandling::Keep => { /* do nothing, obvvvvvsly */ }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if snapshot_file_path.exists() {
|
||||
// snapshot exists; working doesn't
|
||||
reflink_or_copy(&snapshot_file_path, abs_path)?;
|
||||
if verbose {
|
||||
println!("r{}", path.display());
|
||||
}
|
||||
} else {
|
||||
// neither working nor snapshot exists
|
||||
eprintln!(
|
||||
"WTF? {} exists neither in working directory nor in most recent commit",
|
||||
rel_path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
let rel_path = abs_path.relativize(table_path)?;
|
||||
|
||||
let snapshot_file_path = {
|
||||
let mut p = snapshot_path.clone();
|
||||
p.push(rel_path);
|
||||
p
|
||||
}
|
||||
.absolutize()
|
||||
.unwrap()
|
||||
.to_path_buf();
|
||||
|
||||
println!(
|
||||
"Comparing {} to {}",
|
||||
path.display(),
|
||||
snapshot_file_path.display()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue