public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* Re: [pbs-devel] [PATCH proxmox-backup] fix #3613: catalog_shell: include matched dir's contents on restore
@ 2022-04-06  8:26 Dietmar Maurer
  2022-04-06  9:15 ` Dylan Whyte
  0 siblings, 1 reply; 6+ messages in thread
From: Dietmar Maurer @ 2022-04-06  8:26 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Dylan Whyte


> On 04/04/2022 6:19 PM Dylan Whyte <d.whyte@proxmox.com> wrote:
> 
>  
> Prior to this, during an interactive restore, if a directory was matched
> via a pattern match or selection, only the empty directory would be
> restored, and not its contents. 

Why not simply use "**" if you want to restore a whole tree?




^ permalink raw reply	[flat|nested] 6+ messages in thread
* [pbs-devel] [PATCH proxmox-backup] fix #3613: catalog_shell: include matched dir's contents on restore
@ 2022-04-04 16:19 Dylan Whyte
  0 siblings, 0 replies; 6+ messages in thread
From: Dylan Whyte @ 2022-04-04 16:19 UTC (permalink / raw)
  To: pbs-devel

Prior to this, during an interactive restore, if a directory was matched
via a pattern match or selection, only the empty directory would be
restored, and not its contents. Now the entire contents is restored on
directory match

Signed-off-by: Dylan Whyte <d.whyte@proxmox.com>
---
 pbs-client/src/catalog_shell.rs | 56 ++++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 19 deletions(-)

diff --git a/pbs-client/src/catalog_shell.rs b/pbs-client/src/catalog_shell.rs
index c9c9da67..d0658def 100644
--- a/pbs-client/src/catalog_shell.rs
+++ b/pbs-client/src/catalog_shell.rs
@@ -997,6 +997,9 @@ impl Shell {
             &self.accessor,
         )?;
 
+        // Clear match list following restore
+        self.selected.clear();
+
         extractor.extract().await
     }
 }
@@ -1007,9 +1010,7 @@ struct ExtractorState<'a> {
     path_len_stack: Vec<usize>,
 
     dir_stack: Vec<PathStackEntry>,
-
-    matches: bool,
-    matches_stack: Vec<bool>,
+    match_pos: Option<usize>,
 
     read_dir: <Vec<catalog::DirEntry> as IntoIterator>::IntoIter,
     read_dir_stack: Vec<<Vec<catalog::DirEntry> as IntoIterator>::IntoIter>,
@@ -1029,6 +1030,7 @@ impl<'a> ExtractorState<'a> {
         match_list: &'a [MatchEntry],
         accessor: &'a Accessor,
     ) -> Result<Self, Error> {
+        let match_pos = None;
         let read_dir = catalog
             .read_dir(&dir_stack.last().unwrap().catalog)?
             .into_iter();
@@ -1038,9 +1040,7 @@ impl<'a> ExtractorState<'a> {
             path_len_stack: Vec::new(),
 
             dir_stack,
-
-            matches: match_list.is_empty(),
-            matches_stack: Vec::new(),
+            match_pos,
 
             read_dir,
             read_dir_stack: Vec::new(),
@@ -1084,11 +1084,6 @@ impl<'a> ExtractorState<'a> {
             None => return Ok(ControlFlow::Break(())), // out of root directory
         };
 
-        self.matches = self
-            .matches_stack
-            .pop()
-            .ok_or_else(|| format_err!("internal iterator error (matches_stack)"))?;
-
         self.dir_stack
             .pop()
             .ok_or_else(|| format_err!("internal iterator error (dir_stack)"))?;
@@ -1106,14 +1101,14 @@ impl<'a> ExtractorState<'a> {
     async fn handle_new_directory(
         &mut self,
         entry: catalog::DirEntry,
-        match_result: Option<MatchType>,
+        create_dir: bool,
     ) -> Result<(), Error> {
         // enter a new directory:
         self.read_dir_stack.push(mem::replace(
             &mut self.read_dir,
             self.catalog.read_dir(&entry)?.into_iter(),
         ));
-        self.matches_stack.push(self.matches);
+
         self.dir_stack.push(PathStackEntry::new(entry));
         self.path_len_stack.push(self.path_len);
         self.path_len = self.path.len();
@@ -1121,23 +1116,46 @@ impl<'a> ExtractorState<'a> {
         Shell::walk_pxar_archive(self.accessor, &mut self.dir_stack).await?;
         let dir_pxar = self.dir_stack.last().unwrap().pxar.as_ref().unwrap();
         let dir_meta = dir_pxar.entry().metadata().clone();
-        let create = self.matches && match_result != Some(MatchType::Exclude);
-        self.extractor.enter_directory(dir_pxar.file_name().to_os_string(), dir_meta, create)?;
+        self.extractor.enter_directory(dir_pxar.file_name().to_os_string(), dir_meta, create_dir)?;
 
         Ok(())
     }
 
     pub async fn handle_entry(&mut self, entry: catalog::DirEntry) -> Result<(), Error> {
         let match_result = self.match_list.matches(&self.path, entry.get_file_mode());
+
+        let current_pos = self.dir_stack.len();
+
         let did_match = match match_result {
-            Some(MatchType::Include) => true,
-            Some(MatchType::Exclude) => false,
-            None => self.matches,
+            Some(MatchType::Include) => {
+                // Only update match position for items lower in the directory stack
+                if let Some(match_pos) = self.match_pos {
+                    self.match_pos = Some(usize::min(current_pos, match_pos));
+                } else {
+                    self.match_pos = Some(current_pos)
+                }
+                true
+            },
+            Some(MatchType::Exclude) => return Ok(()), // no need to continue for excluded item
+            None => {
+                // Restore items contained within a matched directory
+                if let Some(match_pos) = self.match_pos {
+                    if current_pos > match_pos {
+                        true
+                    } else {
+                        self.match_pos = None;
+                        false
+                    }
+                } else {
+                    // Restore everything if no matches were specified
+                    self.match_list.is_empty()
+                }
+            }
         };
 
         match (did_match, &entry.attr) {
             (_, DirEntryAttribute::Directory { .. }) => {
-                self.handle_new_directory(entry, match_result).await?;
+                self.handle_new_directory(entry, did_match).await?;
             }
             (true, DirEntryAttribute::File { .. }) => {
                 self.dir_stack.push(PathStackEntry::new(entry));
-- 
2.30.2





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-04-06 12:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-06  8:26 [pbs-devel] [PATCH proxmox-backup] fix #3613: catalog_shell: include matched dir's contents on restore Dietmar Maurer
2022-04-06  9:15 ` Dylan Whyte
2022-04-06  9:30   ` Wolfgang Bumiller
2022-04-06 10:09     ` Dylan Whyte
2022-04-06 12:20       ` Wolfgang Bumiller
  -- strict thread matches above, loose matches on Subject: below --
2022-04-04 16:19 Dylan Whyte

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal