pxar: cleanup: refactor and rename exclude pattern

The original name PxarExcludePattern makes no sense anymore as the patterns are
also used to match filenames during restore of the archive.

Therefore, exclude_pattern.rs is moved to match_pattern.rs and PxarExcludePattern
rename to MatchPattern.
Further, since it makes more sense the MatchTypes are now declared as None,
Positive, Negative, PartialPositive or PartialNegative, as this makes more sense
and seems more readable.
Positive matches are those without '!' prefix, Negatives with '!' prefix.

This makes also the filename matching in the encoder/decoder more intuitive and
the logic was adapted accordingly.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner
2019-08-02 17:02:24 +02:00
committed by Dietmar Maurer
parent fe076c8259
commit 4d142ea79e
5 changed files with 93 additions and 92 deletions

View File

@ -7,7 +7,7 @@ use endian_trait::Endian;
use super::flags;
use super::format_definition::*;
use super::exclude_pattern::*;
use super::match_pattern::*;
use super::dir_stack::*;
use std::io::{Read, Write};
@ -630,14 +630,14 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
entry: PxarEntry,
filename: &OsStr,
matched: MatchType,
match_pattern: &Vec<PxarExcludePattern>,
match_pattern: &Vec<MatchPattern>,
) -> Result<(), Error> {
let (mut head, attr) = self.read_attributes()
.map_err(|err| format_err!("Reading of directory attributes failed - {}", err))?;
let dir = PxarDir::new(filename, entry, attr);
dirs.push(dir);
if matched == MatchType::Include {
if matched == MatchType::Positive {
dirs.create_all_dirs(!self.allow_existing_dirs)?;
}
@ -674,7 +674,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
pub fn restore(
&mut self,
path: &Path,
match_pattern: &Vec<PxarExcludePattern>
match_pattern: &Vec<MatchPattern>
) -> Result<(), Error> {
let _ = std::fs::create_dir(path);
@ -685,7 +685,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
let mut dirs = PxarDirStack::new(fd);
// An empty match pattern list indicates to restore the full archive.
let matched = if match_pattern.len() == 0 {
MatchType::Include
MatchType::Positive
} else {
MatchType::None
};
@ -725,7 +725,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
dirs: &mut PxarDirStack,
filename: &OsStr,
parent_matched: MatchType,
match_pattern: &Vec<PxarExcludePattern>,
match_pattern: &Vec<MatchPattern>,
) -> Result<(), Error> {
let relative_path = dirs.as_path_buf();
let full_path = base_path.join(&relative_path).join(filename);
@ -751,24 +751,16 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
let mut matched = parent_matched;
if match_pattern.len() > 0 {
match match_filename(filename, entry.mode as u32 & libc::S_IFMT == libc::S_IFDIR, match_pattern) {
(MatchType::Include, pattern) => {
matched = MatchType::Include;
child_pattern = pattern;
},
(MatchType::None, _) => matched = MatchType::None,
(MatchType::Exclude, _) => matched = MatchType::Exclude,
(MatchType::PartialExclude, pattern) => {
matched = MatchType::PartialExclude;
child_pattern = pattern;
},
(MatchType::PartialInclude, pattern) => {
matched = MatchType::PartialInclude;
(MatchType::Negative, _) => matched = MatchType::Negative,
(match_type, pattern) => {
matched = match_type;
child_pattern = pattern;
},
}
}
let fd = if matched == MatchType::Include {
let fd = if matched == MatchType::Positive {
Some(dirs.create_all_dirs(!self.allow_existing_dirs)?)
} else {
None
@ -1037,8 +1029,8 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
fn match_filename(
filename: &OsStr,
is_dir: bool,
match_pattern: &Vec<PxarExcludePattern>
) -> (MatchType, Vec<PxarExcludePattern>) {
match_pattern: &Vec<MatchPattern>
) -> (MatchType, Vec<MatchPattern>) {
let mut child_pattern = Vec::new();
let mut match_state = MatchType::None;
// read_filename() checks for nul bytes, so it is save to unwrap here
@ -1047,22 +1039,21 @@ fn match_filename(
for pattern in match_pattern {
match pattern.matches_filename(&name, is_dir) {
MatchType::None => {},
// The logic is inverted here, since PxarExcludePattern assumes excludes not includes
MatchType::Exclude => {
match_state = MatchType::Include;
let incl_pattern = PxarExcludePattern::from_line(b"**/*").unwrap().unwrap();
MatchType::Positive => {
match_state = MatchType::Positive;
let incl_pattern = MatchPattern::from_line(b"**/*").unwrap().unwrap();
child_pattern.push(incl_pattern.get_rest_pattern());
},
MatchType::Include => match_state = MatchType::Exclude,
MatchType::PartialExclude => {
if match_state != MatchType::Include && match_state != MatchType::Exclude {
match_state = MatchType::PartialInclude;
MatchType::Negative => match_state = MatchType::Negative,
MatchType::PartialPositive => {
if match_state != MatchType::Negative && match_state != MatchType::Positive {
match_state = MatchType::PartialPositive;
}
child_pattern.push(pattern.get_rest_pattern());
},
MatchType::PartialInclude => {
if match_state == MatchType::PartialInclude {
match_state = MatchType::PartialExclude;
MatchType::PartialNegative => {
if match_state == MatchType::PartialPositive {
match_state = MatchType::PartialNegative;
}
child_pattern.push(pattern.get_rest_pattern());
},