From 31903b0cab97d7fb5d0dfd9bdc96fb2e33dd651b Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Mon, 25 Jul 2022 05:53:03 +0200 Subject: [PATCH] restore: restore metadata of dir after its contents --- src/commands/restore.rs | 51 ++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 8b6ce6f..d38e79e 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -157,27 +157,52 @@ async fn restore_metadata( ) -> Result<()> { // walk over tree in repository and compare with tree in dest let mut node_streamer = NodeStreamer::new(index, tree).await?; + let mut dir_stack = Vec::new(); while let Some((path, node)) = node_streamer.try_next().await? { if !opts.dry_run { - dest.create_special(&path, &node) - .unwrap_or_else(|_| eprintln!("restore {:?}: creating special file failed.", path)); - if opts.numeric_id { - dest.set_uid_gid(&path, node.meta()) - .unwrap_or_else(|_| eprintln!("restore {:?}: setting UID/GID failed.", path)); - } else { - dest.set_user_group(&path, node.meta()).unwrap_or_else(|_| { - eprintln!("restore {:?}: setting User/Group failed.", path) - }); + match node.node_type() { + NodeType::Dir => { + // set metadata for all non-parent paths in stack + while let Some((stackpath, _)) = dir_stack.last() { + if !path.starts_with(stackpath) { + let (path, node) = dir_stack.pop().unwrap(); + set_metadata(dest, &path, &node, opts); + } else { + break; + } + } + // push current path to the stack + dir_stack.push((path, node)); + } + _ => set_metadata(dest, &path, &node, opts), } - dest.set_permission(&path, node.meta()) - .unwrap_or_else(|_| eprintln!("restore {:?}: chmod failed.", path)); - dest.set_times(&path, node.meta()) - .unwrap_or_else(|_| eprintln!("restore {:?}: setting file times failed.", path)); } } + // empty dir stack and set metadata + for (path, node) in dir_stack.into_iter().rev() { + set_metadata(dest, &path, &node, opts); + } + Ok(()) } + +fn set_metadata(dest: &LocalBackend, path: &PathBuf, node: &Node, opts: &Opts) { + dest.create_special(path, node) + .unwrap_or_else(|_| eprintln!("restore {:?}: creating special file failed.", path)); + if opts.numeric_id { + dest.set_uid_gid(path, node.meta()) + .unwrap_or_else(|_| eprintln!("restore {:?}: setting UID/GID failed.", path)); + } else { + dest.set_user_group(path, node.meta()) + .unwrap_or_else(|_| eprintln!("restore {:?}: setting User/Group failed.", path)); + } + dest.set_permission(path, node.meta()) + .unwrap_or_else(|_| eprintln!("restore {:?}: chmod failed.", path)); + dest.set_times(path, node.meta()) + .unwrap_or_else(|_| eprintln!("restore {:?}: setting file times failed.", path)); +} + /// struct that contains information of file contents grouped by /// 1) pack ID, /// 2) blob within this pack