diff --git a/src/server/backups.rs b/src/server/backups.rs index 37e6021..e5fd4de 100644 --- a/src/server/backups.rs +++ b/src/server/backups.rs @@ -18,6 +18,7 @@ pub struct BackupManager { world_dir: PathBuf, max_backups: u64, start_time: Option>, + files: Vec<(PathBuf, PathBuf)> } impl BackupManager { @@ -33,9 +34,40 @@ impl BackupManager { world_dir, max_backups, start_time: None, + files: Vec::new() } } + fn set_files_to_backup(&mut self) -> io::Result<()> { + let mut dirs = vec![ + (PathBuf::from("worlds"), self.world_dir.clone()), + (PathBuf::from("config"), self.config_dir.clone()), + ]; + self.files.clear(); + + while let Some((path_in_tar, path)) = dirs.pop() { + for res in path.read_dir()? { + let entry = res?; + + if entry.file_name() == "cache" { + continue; + } + + let new_path_in_tar = path_in_tar.join(entry.file_name()); + + // All dirs get expanded recursively, while all files get returned as output + // NOTE: does this remove empty directories from backups? Is this a problem? + if entry.file_type()?.is_dir() { + dirs.push((new_path_in_tar, entry.path())); + } else { + self.files.push((new_path_in_tar, entry.path())); + } + } + } + + Ok(()) + } + pub fn create_archive(&mut self) -> io::Result<()> { let start_time = chrono::offset::Local::now(); self.start_time = Some(start_time); @@ -46,22 +78,10 @@ impl BackupManager { let enc = GzEncoder::new(tar_gz, Compression::default()); let mut tar = tar::Builder::new(enc); - tar.append_dir_all("worlds", &self.world_dir)?; + self.set_files_to_backup()?; - // Add all files from the config directory that aren't the cache - for entry in self - .config_dir - .read_dir()? - .filter_map(|e| e.ok()) - .filter(|e| e.file_name() != "cache") - { - let tar_path = Path::new("config").join(entry.file_name()); - - if entry.file_type()?.is_dir() { - tar.append_dir_all(tar_path, entry.path())?; - } else { - tar.append_path_with_name(entry.path(), tar_path)?; - } + for (path_in_tar, path) in &self.files { + tar.append_path_with_name(path, path_in_tar)?; } // TODO re-add this info file in some way