fn delete_existing_version()

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(())
}