in src/main.rs [91:206]
fn delete_existing_version(
log: &slog::Logger,
root_path: &Path,
update_folder_name: &str,
) -> Result<(), Box<dyn error::Error>> {
let mut directories: LinkedList<PathBuf> = LinkedList::new();
let mut top_directories: LinkedList<PathBuf> = LinkedList::new();
let mut file_handles: LinkedList<FileHandle> = LinkedList::new();
let root = PathBuf::from(root_path);
directories.push_back(root);
while directories.len() > 0 {
let dir = directories.pop_front().unwrap();
info!(log, "Reading directory: {:?}", dir);
for entry in fs::read_dir(&dir)? {
let entry = entry?;
let entry_name = entry.file_name();
let entry_name = entry_name.to_str().ok_or(io::Error::new(
io::ErrorKind::Other,
"Could not get entry name",
))?;
if dir == root_path {
// don't delete the update folder
if entry_name == update_folder_name {
continue;
}
// don't delete ourselves
if entry_name == "tools" {
continue;
}
// don't delete any of the unins* files
if entry_name.starts_with("unins") {
continue;
}
}
let entry_file_type = entry.file_type()?;
let entry_path = entry.path();
if entry_file_type.is_dir() {
if dir == root_path {
top_directories.push_back(entry_path.to_owned());
}
directories.push_back(entry_path);
} else if entry_file_type.is_file() {
// attempt to get exclusive file handle
let msg = format!("Opening file handle: {:?}", entry_path);
let file_handle = util::retry(
&msg,
|attempt| -> Result<FileHandle, Box<dyn error::Error>> {
info!(
log,
"Get file handle: {:?} (attempt {})", entry_path, attempt
);
FileHandle::new(&entry_path)
},
Some(16),
)?;
file_handles.push_back(file_handle);
}
}
}
info!(log, "Collected all directories and file handles");
for file_handle in &file_handles {
util::retry(
"marking a file for deletion",
|_| -> Result<(), Box<dyn error::Error>> { file_handle.mark_for_deletion() },
None,
)?;
}
info!(log, "All file handles marked for deletion");
for file_handle in &file_handles {
util::retry(
"closing a file handle",
|_| -> Result<(), Box<dyn error::Error>> { file_handle.close() },
None,
)?;
}
info!(log, "All files deleted");
for dir in top_directories {
let msg = format!("Deleting a directory: {:?}", dir);
util::retry(
&msg,
|attempt| -> Result<(), Box<dyn error::Error>> {
if !dir.exists() {
return Ok(());
}
info!(
log,
"Delete directory recursively: {:?} (attempt {})", dir, attempt
);
fs::remove_dir_all(&dir)?;
Ok(())
},
None,
)?;
}
Ok(())
}