Extract restore_path
This commit is contained in:
parent
e1a3df5954
commit
f3d6b07650
1 changed files with 117 additions and 98 deletions
|
@ -15,6 +15,7 @@ use crate::{
|
|||
XATTR_HEAD,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum NewFileHandling {
|
||||
Keep,
|
||||
Delete,
|
||||
|
@ -28,6 +29,121 @@ pub enum RestoreErr {
|
|||
PathNotContainedByTable(PathBuf),
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a path to its state as of the commit with uuid specified in `commit`
|
||||
*/
|
||||
pub fn reset_path(
|
||||
path: &PathBuf,
|
||||
commit: &str,
|
||||
recursive: bool,
|
||||
verbose: bool,
|
||||
new_file_handling: NewFileHandling,
|
||||
) -> Result<()> {
|
||||
let max_depth = if recursive { usize::MAX } else { 0 };
|
||||
|
||||
let info =
|
||||
containing_table_info(path)?.ok_or(RestoreErr::PathNotContainedByTable(path.clone()))?;
|
||||
let table_path = info.path_abs();
|
||||
|
||||
let snapshot_path = table_snapshot_path(table_path, commit);
|
||||
|
||||
for entry in WalkDir::new(path)
|
||||
.max_depth(max_depth)
|
||||
.into_iter()
|
||||
.filter_entry(|e| !is_hidden(e))
|
||||
{
|
||||
let entry = entry?;
|
||||
|
||||
let path = entry.path().to_path_buf();
|
||||
|
||||
let abs_path = path.absolutize().unwrap().to_path_buf();
|
||||
|
||||
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();
|
||||
|
||||
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)?;
|
||||
|
||||
let working_dest_dir = &abs_path;
|
||||
|
||||
for entry in WalkDir::new(&snapshot_file_path).into_iter() {
|
||||
let entry = entry?;
|
||||
|
||||
let snapshot_rel = entry
|
||||
.path()
|
||||
.to_path_buf()
|
||||
.relativize(&snapshot_file_path)
|
||||
.unwrap();
|
||||
let working = snapshot_rel.resolve_curdir(working_dest_dir).unwrap();
|
||||
|
||||
reflink_or_copy(entry.path(), &working)?;
|
||||
}
|
||||
|
||||
if verbose {
|
||||
println!("r{}", path.display());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Snapshot is file
|
||||
// Copy over working either way
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
* Return files to their state as of the most recent commit.
|
||||
*/
|
||||
|
@ -37,7 +153,6 @@ pub fn restore(
|
|||
verbose: bool,
|
||||
new_file_handling: NewFileHandling,
|
||||
) -> Result<()> {
|
||||
let max_depth = if recursive { usize::MAX } else { 0 };
|
||||
for path in paths {
|
||||
let info = containing_table_info(path)?
|
||||
.ok_or(RestoreErr::PathNotContainedByTable(path.clone()))?;
|
||||
|
@ -48,103 +163,7 @@ pub fn restore(
|
|||
|
||||
let uuid = String::from_utf8(uuid_bytes)?;
|
||||
|
||||
let snapshot_path = table_snapshot_path(table_path, uuid);
|
||||
|
||||
for entry in WalkDir::new(path)
|
||||
.max_depth(max_depth)
|
||||
.into_iter()
|
||||
.filter_entry(|e| !is_hidden(e))
|
||||
{
|
||||
let entry = entry?;
|
||||
|
||||
let path = entry.path().to_path_buf();
|
||||
|
||||
let abs_path = path.absolutize().unwrap().to_path_buf();
|
||||
|
||||
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();
|
||||
|
||||
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)?;
|
||||
|
||||
let working_dest_dir = &abs_path;
|
||||
|
||||
for entry in WalkDir::new(&snapshot_file_path).into_iter() {
|
||||
let entry = entry?;
|
||||
|
||||
let snapshot_rel = entry
|
||||
.path()
|
||||
.to_path_buf()
|
||||
.relativize(&snapshot_file_path)
|
||||
.unwrap();
|
||||
let working =
|
||||
snapshot_rel.resolve_curdir(working_dest_dir).unwrap();
|
||||
|
||||
reflink_or_copy(entry.path(), &working)?;
|
||||
}
|
||||
|
||||
if verbose {
|
||||
println!("r{}", path.display());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Snapshot is file
|
||||
// Copy over working either way
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
reset_path(path, uuid.as_str(), recursive, verbose, new_file_handling)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue