all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
To: Gabriel Goller <g.goller@proxmox.com>
Cc: pbs-devel@lists.proxmox.com
Subject: Re: [pbs-devel] [PATCH pathpatterns] match_list: added `matches_path()` function, which matches only the path
Date: Fri, 11 Aug 2023 10:32:58 +0200	[thread overview]
Message-ID: <lzyydypfobw2xbo3han7gdcge4al2fctauj6snyn3kksngzj4w@gmb4dtwwi6sm> (raw)
In-Reply-To: <c7waqbj7iysa2qjmumsqtajd6sfh6fliknryy4njorg65t2tf7@nt3hanxfqw3u>

On Fri, Aug 11, 2023 at 10:26:22AM +0200, Wolfgang Bumiller wrote:
> On Wed, Aug 09, 2023 at 12:19:12PM +0200, Gabriel Goller wrote:
> > Added `matches_path()` function, which only matches against the path and returns
> > an error if a file_mode pattern is found/needed in the matching list. This is
> > useful when we want to check if a file is excluded before running `stat()` on
> > the file to get the file_mode (which could fail).
> > 
> > Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
> > ---
> >  src/match_list.rs | 159 +++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 158 insertions(+), 1 deletion(-)
> > 
> > diff --git a/src/match_list.rs b/src/match_list.rs
> > index c5b14e0..acad328 100644
> > --- a/src/match_list.rs
> > +++ b/src/match_list.rs
> > @@ -1,6 +1,6 @@
> >  //! Helpers for include/exclude lists.
> > -
> >  use bitflags::bitflags;
> > +use std::fmt;
> >  
> >  use crate::PatternFlag;
> >  
> > @@ -39,6 +39,17 @@ impl Default for MatchFlag {
> >      }
> >  }
> >  
> > +#[derive(Debug, PartialEq)]
> > +pub struct FileModeRequiredForMatching;
> 
> Let's shorten this to just `FileModeRequired` ;-)
> 
> > +
> > +impl fmt::Display for FileModeRequiredForMatching {
> > +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> > +        write!(f, "File mode is required for matching")
> > +    }
> > +}
> > +
> > +impl std::error::Error for FileModeRequiredForMatching {}
> > +
> >  /// A pattern entry. (Glob patterns or literal patterns.)
> >  // Note:
> >  // For regex we'd likely use the POSIX extended REs via `regexec(3)`, since we're targetting
> > @@ -304,12 +315,32 @@ impl MatchEntry {
> >  
> >          self.matches_path_exact(path)
> >      }
> > +
> > +    /// Check whether the path contains a matching suffix. Returns an error if a file mode is required.
> > +    pub fn matches_path<T: AsRef<[u8]>>(
> > +        &self,
> > +        path: T,
> > +    ) -> Result<bool, FileModeRequiredForMatching> {
> > +        self.matches_path_do(path.as_ref())
> > +    }
> > +
> > +    fn matches_path_do(&self, path: &[u8]) -> Result<bool, FileModeRequiredForMatching> {
> > +        if !self.flags.contains(MatchFlag::ANY_FILE_TYPE) {
> > +            return Err(FileModeRequiredForMatching);
> > +        }
> > +
> > +        Ok(self.matches_path_suffix_do(path))
> > +    }
> >  }
> >  
> >  #[doc(hidden)]
> >  pub trait MatchListEntry {
> >      fn entry_matches(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>;
> >      fn entry_matches_exact(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>;
> > +    fn entry_matches_path(
> > +        &self,
> > +        path: &[u8],
> > +    ) -> Result<Option<MatchType>, FileModeRequiredForMatching>;
> 
> >  }
> >  
> >  impl MatchListEntry for &'_ MatchEntry {
> > @@ -328,6 +359,21 @@ impl MatchListEntry for &'_ MatchEntry {
> >              None
> >          }
> >      }
> > +
> > +    fn entry_matches_path(
> > +        &self,
> > +        path: &[u8],
> > +    ) -> Result<Option<MatchType>, FileModeRequiredForMatching> {
> > +        if let Ok(b) = self.matches_path(path) {
> 
> This can just use `?`, it's the exact same error type after all.
> (Also `if let Ok` is generally best avoided since the 'else' branch
> discards the error, and if not, it's often a case like this where it can
> juse use '?' ;-) ).
> 
> Effectively this could be as short as
> 
>     Ok(self.matches_path(path)?.then(|| self.match_type()))
> 
> > +            if b {
> 
> As an additional hint: when you nest ifs around things you can match,
> you can just include both cases in the patterns:
>     match self.matches_path(path) {
>         Ok(true) => Ok(Some(self.match_type())),
>         Ok(false) => Ok(None),
>         Err(err) => Err(err),
>         // where this Err() case already tells you that you can use '?' instead
>     }
> 
> > +                Ok(Some(self.match_type()))
> > +            } else {
> > +                Ok(None)
> > +            }
> > +        } else {
> > +            Err(FileModeRequiredForMatching)
> > +        }
> > +    }
> >  }
> >  
> >  impl MatchListEntry for &'_ &'_ MatchEntry {
> > @@ -346,6 +392,21 @@ impl MatchListEntry for &'_ &'_ MatchEntry {
> >              None
> >          }
> >      }
> > +
> > +    fn entry_matches_path(
> > +        &self,
> > +        path: &[u8],
> > +    ) -> Result<Option<MatchType>, FileModeRequiredForMatching> {
> 
> same
> 
> > +        if let Ok(b) = self.matches_path(path) {
> > +            if b {
> > +                Ok(Some(self.match_type()))
> > +            } else {
> > +                Ok(None)
> > +            }
> > +        } else {
> > +            Err(FileModeRequiredForMatching)
> > +        }
> > +    }
> >  }
> >  
> >  /// This provides [`matches`](MatchList::matches) and [`matches_exact`](MatchList::matches_exact)
> > @@ -374,6 +435,20 @@ pub trait MatchList {
> >      }
> >  
> >      fn matches_exact_do(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>;
> > +
> > +    /// Check whether this list contains anything exactly matching the path, returns error if
> > +    /// `file_mode` is required for exact matching.
> > +    fn matches_path<T: AsRef<[u8]>>(
> > +        &self,
> > +        path: T,
> > +    ) -> Result<Option<MatchType>, FileModeRequiredForMatching> {
> > +        self.matches_path_do(path.as_ref())
> > +    }
> > +
> > +    fn matches_path_do(
> > +        &self,
> > +        path: &[u8],
> > +    ) -> Result<Option<MatchType>, FileModeRequiredForMatching>;
> >  }
> >  
> >  impl<'a, T> MatchList for T
> > @@ -408,6 +483,24 @@ where
> >  
> >          None
> >      }
> > +
> > +    fn matches_path_do(
> > +        &self,
> > +        path: &[u8],
> > +    ) -> Result<Option<MatchType>, FileModeRequiredForMatching> {
> 
> Given the amount of tiny match helpers we run through with those 2
> traits already I wonder if we should just make a breaking change here
> instead and only have the versions with the `Result` while users (or
> defaulted helpers in the trait) just pass `file_mode.unwrap_or(!0)`
> (since a mode of 0 should match anything ;-) ).

(of s/of 0/of !0/` of course)




  reply	other threads:[~2023-08-11  8:33 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-09 10:19 Gabriel Goller
2023-08-09 10:19 ` [pbs-devel] [PATCH proxmox-backup v3 1/1] fix #4380: check if file is excluded before running `stat()` Gabriel Goller
2023-08-11  8:51   ` Wolfgang Bumiller
2023-08-14  7:41     ` Gabriel Goller
2023-08-11  8:26 ` [pbs-devel] [PATCH pathpatterns] match_list: added `matches_path()` function, which matches only the path Wolfgang Bumiller
2023-08-11  8:32   ` Wolfgang Bumiller [this message]
2023-08-11  8:38     ` Wolfgang Bumiller
2023-08-14  9:32   ` Gabriel Goller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=lzyydypfobw2xbo3han7gdcge4al2fctauj6snyn3kksngzj4w@gmb4dtwwi6sm \
    --to=w.bumiller@proxmox.com \
    --cc=g.goller@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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