Skip to content

Commit

Permalink
add util::GlobMatcherExt
Browse files Browse the repository at this point in the history
  • Loading branch information
aawsome committed Jan 12, 2025
1 parent 799e2a8 commit af6ae1c
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 21 deletions.
2 changes: 1 addition & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ enum-map = { workspace = true }
enum-map-derive = "0.17.0"
enumset = { version = "1.1.5", features = ["serde"] }
gethostname = "0.5.0"
globset = "0.4.15"
humantime = "2.1.0"
itertools = "0.13.0"
quick_cache = "0.6.9"
Expand All @@ -124,7 +125,6 @@ xattr = "1"
anyhow = { workspace = true }
expect-test = "1.5.0"
flate2 = "1.0.35"
globset = "0.4.15"
insta = { version = "1.41.1", features = ["redactions", "ron"] }
mockall = "0.13"
pretty_assertions = "1.4.1"
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub(crate) mod progress;
/// Structs which are saved in JSON or binary format in the repository
pub mod repofile;
pub(crate) mod repository;
pub mod util;

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking x86_64-pc-windows-msvc on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking x86_64-pc-windows-gnu on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking x86_64-apple-darwin on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking aarch64-apple-darwin on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking x86_64-unknown-linux-gnu on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking x86_64-unknown-linux-musl on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking aarch64-unknown-linux-gnu on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking aarch64-unknown-linux-musl on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking i686-unknown-linux-gnu on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking x86_64-unknown-netbsd on stable

missing documentation for a module

Check warning on line 118 in crates/core/src/lib.rs

View workflow job for this annotation

GitHub Actions / Cross checking armv7-unknown-linux-gnueabihf on stable

missing documentation for a module
/// Virtual File System support - allows to act on the repository like on a file system
pub mod vfs;

Expand Down
29 changes: 29 additions & 0 deletions crates/core/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use globset::GlobMatcher;

/// Extend `globset::GlobMatcher` to allow mathing on unix paths (on every platform)
pub trait GlobMatcherExt {
/// Match on unix paths, i.e. paths which are available as `&[u8]`
fn is_unix_match(&self, path: impl AsRef<[u8]>) -> bool;
}

impl GlobMatcherExt for GlobMatcher {
// This is a hacky implementation, espeically for windows where we convert lossily
// into an utf8 string and match on the windows path given by that string.
// Note: `GlobMatcher` internally converts into a `&[u8]` to perform the matching
// TODO: Use https://github.com/BurntSushi/ripgrep/pull/2955 once it is available.
#[cfg(not(windows))]
fn is_unix_match(&self, path: impl AsRef<[u8]>) -> bool {
use std::{ffi::OsStr, os::unix::ffi::OsStrExt, path::PathBuf};

let path = PathBuf::from(OsStr::from_bytes(path.as_ref()));
self.is_match(&path)
}
#[cfg(windows)]
fn is_unix_match(&self, path: impl AsRef<[u8]>) -> bool {
use std::{ffi::OsStr, path::Path};

let string: &str = &String::from_utf8_lossy(path.as_ref());
let path = Path::new(OsStr::new(string));
self.is_match(path)
}
}
21 changes: 6 additions & 15 deletions crates/core/tests/integration/find.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// don't warn about try_from paths conversion on unix
#![allow(clippy::unnecessary_fallible_conversions)]

use std::{
path::{Path, PathBuf},
str::FromStr,
};
use std::{path::PathBuf, str::FromStr};

use anyhow::Result;
use globset::Glob;
Expand All @@ -13,6 +10,7 @@ use rstest::rstest;

use rustic_core::{
repofile::{Node, SnapshotFile},
util::GlobMatcherExt,
BackupOptions, FindMatches, FindNode,
};
use typed_path::UnixPath;
Expand All @@ -39,9 +37,8 @@ fn test_find(tar_gz_testdata: Result<TestSource>, set_up_repo: Result<RepoOpen>)
assert_with_win("find-nodes-not-found", not_found);
// test non-existing match
let glob = Glob::new("not_existing")?.compile_matcher();
let not_found = repo.find_matching_nodes(vec![snapshot.tree], &|path, _| {
glob.is_match(PathBuf::try_from(path).unwrap())
})?;
let not_found =
repo.find_matching_nodes(vec![snapshot.tree], &|path, _| glob.is_unix_match(path))?;
assert_debug_snapshot!("find-matching-nodes-not-found", not_found);

// test existing path
Expand All @@ -51,21 +48,15 @@ fn test_find(tar_gz_testdata: Result<TestSource>, set_up_repo: Result<RepoOpen>)
// test existing match
let glob = Glob::new("testfile")?.compile_matcher();
let match_func = |path: &UnixPath, _: &Node| {
glob.is_match(PathBuf::try_from(path).unwrap())
|| path
.file_name()
.is_some_and(|f| glob.is_match(Path::new(&String::from_utf8(f.to_vec()).unwrap())))
glob.is_unix_match(path) || path.file_name().is_some_and(|f| glob.is_unix_match(f))
};
let FindMatches { paths, matches, .. } =
repo.find_matching_nodes(vec![snapshot.tree], &match_func)?;
assert_debug_snapshot!("find-matching-existing", (paths, matches));
// test existing match
let glob = Glob::new("testfile*")?.compile_matcher();
let match_func = |path: &UnixPath, _: &Node| {
glob.is_match(PathBuf::try_from(path).unwrap())
|| path
.file_name()
.is_some_and(|f| glob.is_match(Path::new(&String::from_utf8(f.to_vec()).unwrap())))
glob.is_unix_match(path) || path.file_name().is_some_and(|f| glob.is_unix_match(f))
};
let FindMatches { paths, matches, .. } =
repo.find_matching_nodes(vec![snapshot.tree], &match_func)?;
Expand Down
8 changes: 3 additions & 5 deletions examples/find/examples/find.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! `ls` example
use globset::Glob;
use rustic_backend::BackendOptions;
use rustic_core::{FindMatches, Repository, RepositoryOptions};
use rustic_core::{util::GlobMatcherExt, FindMatches, Repository, RepositoryOptions};
use simplelog::{Config, LevelFilter, SimpleLogger};
use std::{error::Error, path::PathBuf};
use std::error::Error;

// don't warn about try_from paths conversion on unix
#[allow(clippy::unnecessary_fallible_conversions)]
Expand Down Expand Up @@ -32,9 +32,7 @@ fn main() -> Result<(), Box<dyn Error>> {
paths,
nodes,
matches,
} = repo.find_matching_nodes(tree_ids, &|path, _| {
glob.is_match(PathBuf::try_from(path).unwrap())
})?;
} = repo.find_matching_nodes(tree_ids, &|path, _| glob.is_unix_match(path))?;
for (snap, matches) in snapshots.iter().zip(matches) {
println!("results in {snap:?}");
for (path_idx, node_idx) in matches {
Expand Down

0 comments on commit af6ae1c

Please sign in to comment.