all lists on 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal