mirror of
https://github.com/Dummi26/rembackup.git
synced 2025-12-21 06:06:31 +01:00
detect file/directory removal and replacing a file with a directory or a directory with a file
also change changes/actions print style for brevity
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::{fs, io, path::Path};
|
||||
use std::{collections::HashMap, fs, io, path::Path};
|
||||
|
||||
use crate::{indexchanges::IndexChange, indexfile::IndexFile};
|
||||
|
||||
@@ -14,10 +14,15 @@ pub fn perform_index_diff(source: &Path, index: &Path) -> io::Result<Vec<IndexCh
|
||||
Ok(changes)
|
||||
}
|
||||
fn rec(
|
||||
// location of source files
|
||||
source: &Path,
|
||||
// relative path used on this iteration
|
||||
rel_path: &Path,
|
||||
// location of the index
|
||||
index_files: &Path,
|
||||
// list of changes to be made
|
||||
changes: &mut Vec<IndexChange>,
|
||||
// if the index is part of `source`, where exactly is it?
|
||||
inner_index: Option<&Path>,
|
||||
) -> Result<(), io::Error> {
|
||||
if let Some(ii) = &inner_index {
|
||||
@@ -27,13 +32,31 @@ fn rec(
|
||||
}
|
||||
}
|
||||
|
||||
if !index_files.join(rel_path).try_exists()? {
|
||||
changes.push(IndexChange::AddDir(rel_path.to_path_buf()));
|
||||
}
|
||||
for entry in fs::read_dir(source.join(rel_path))? {
|
||||
// used to find removals
|
||||
let index_rel_path = index_files.join(rel_path);
|
||||
let mut index_entries = match fs::read_dir(&index_rel_path) {
|
||||
Err(_) => {
|
||||
changes.push(IndexChange::AddDir(rel_path.to_path_buf()));
|
||||
HashMap::new()
|
||||
}
|
||||
Ok(e) => e
|
||||
.into_iter()
|
||||
.filter_map(|v| v.ok())
|
||||
.map(|v| Ok((v.file_name(), v.file_type()?.is_dir())))
|
||||
.collect::<Result<_, io::Error>>()?,
|
||||
};
|
||||
// compare source files with index
|
||||
let source_files = fs::read_dir(source.join(rel_path))?.collect::<Vec<_>>();
|
||||
// find changes/adds
|
||||
for entry in source_files {
|
||||
let entry = entry?;
|
||||
let metadata = entry.metadata()?;
|
||||
let in_index_and_is_dir = index_entries.remove(&entry.file_name());
|
||||
if metadata.is_dir() {
|
||||
if let Some(false) = in_index_and_is_dir {
|
||||
// is dir, but was file -> remove file
|
||||
changes.push(IndexChange::RemoveFile(rel_path.join(entry.file_name())));
|
||||
}
|
||||
rec(
|
||||
source,
|
||||
&rel_path.join(entry.file_name()),
|
||||
@@ -42,6 +65,10 @@ fn rec(
|
||||
inner_index,
|
||||
)?;
|
||||
} else {
|
||||
if let Some(true) = in_index_and_is_dir {
|
||||
// is file, but was dir -> remove dir
|
||||
changes.push(IndexChange::RemoveDir(rel_path.join(entry.file_name())));
|
||||
}
|
||||
let newif = IndexFile::new_from_metadata(&metadata);
|
||||
let oldif = IndexFile::from_path(&index_files.join(rel_path).join(entry.file_name()));
|
||||
match oldif {
|
||||
@@ -53,5 +80,13 @@ fn rec(
|
||||
}
|
||||
}
|
||||
}
|
||||
// removals
|
||||
for (removed_file, is_dir) in index_entries {
|
||||
changes.push(if is_dir {
|
||||
IndexChange::RemoveDir(rel_path.join(removed_file))
|
||||
} else {
|
||||
IndexChange::RemoveFile(rel_path.join(removed_file))
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user