Skip to content

git-glob windows support #383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,16 @@ Follow linked crate name for detailed status. Please note that all crates follow
Crates that seem feature complete and need to see some more use before they can be released as 1.0.

* [git-mailmap](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-mailmap)
* [git-chunk](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-chunk)

### Initial Development
* **usable**
* [git-actor](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-actor)
* [git-hash](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-hash)
* [git-chunk](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-chunk)
* [git-object](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-object)
* [git-validate](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-validate)
* [git-url](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-url)
* [git-glob](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-glob)
* [git-packetline](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-packetline)
* [git-transport](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-transport)
* [git-protocol](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-protocol)
Expand All @@ -119,7 +120,6 @@ Crates that seem feature complete and need to see some more use before they can
* [git-revision](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-revision)
* [git-attributes](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-attributes)
* [git-quote](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-quote)
* [git-glob](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-glob)
* **idea**
* [git-note](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-note)
* [git-pathspec](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-pathspec)
Expand Down
8 changes: 4 additions & 4 deletions crate-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
* [ ] Some examples

### git-chunk
* [ ] decode the chunk file table of contents and provide convenient API
* [ ] write the table of contents
* [x] decode the chunk file table of contents and provide convenient API
* [x] write the table of contents

### git-object
* *decode (zero-copy)* borrowed objects
Expand Down Expand Up @@ -232,8 +232,8 @@ A mechanism to associate metadata with any object, and keep revisions of it usin
* [ ] CRUD for git notes

### git-glob
* [ ] parse pattern
* [ ] a type for pattern matching
* [x] parse pattern
* [x] a type for pattern matching of paths and non-paths, optionally case-insensitively.

### git-worktree
* handle the working tree/checkout
Expand Down
3 changes: 2 additions & 1 deletion git-glob/src/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bitflags! {
/// Describes whether to match a path case sensitively or not.
///
/// Used in [Pattern::matches_repo_relative_path()].
#[derive(Debug, PartialOrd, PartialEq, Copy, Clone, Hash, Ord, Eq)]
pub enum Case {
/// The case affects the match
Sensitive,
Expand Down Expand Up @@ -84,7 +85,7 @@ impl Pattern {
return false;
}

let flags = wildmatch::Mode::SLASH_IS_LITERAL
let flags = wildmatch::Mode::NO_MATCH_SLASH_LITERAL
| match case {
Case::Fold => wildmatch::Mode::IGNORE_CASE,
Case::Sensitive => wildmatch::Mode::empty(),
Expand Down
15 changes: 9 additions & 6 deletions git-glob/src/wildmatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ bitflags! {
/// The match mode employed in [`Pattern::matches()`][crate::Pattern::matches()].
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Mode: u8 {
/// Let globs not match the slash `/` literal.
const SLASH_IS_LITERAL = 1 << 0;
/// Let globs like `*` and `?` not match the slash `/` literal, which is useful when matching paths.
const NO_MATCH_SLASH_LITERAL = 1 << 0;
/// Match case insensitively for ascii characters only.
const IGNORE_CASE = 1 << 1;
}
Expand Down Expand Up @@ -65,22 +65,25 @@ pub(crate) mod function {
}
match p_ch {
b'?' => {
if mode.contains(Mode::SLASH_IS_LITERAL) && t_ch == SLASH {
if mode.contains(Mode::NO_MATCH_SLASH_LITERAL) && t_ch == SLASH {
return NoMatch;
} else {
continue;
}
}
STAR => {
let mut match_slash = mode.contains(Mode::SLASH_IS_LITERAL).then(|| false).unwrap_or(true);
let mut match_slash = mode
.contains(Mode::NO_MATCH_SLASH_LITERAL)
.then(|| false)
.unwrap_or(true);
match p.next() {
Some((next_p_idx, next_p_ch)) => {
let next;
if next_p_ch == STAR {
let leading_slash_idx = p_idx.checked_sub(1);
while p.next_if(|(_, c)| *c == STAR).is_some() {}
next = p.next();
if !mode.contains(Mode::SLASH_IS_LITERAL) {
if !mode.contains(Mode::NO_MATCH_SLASH_LITERAL) {
match_slash = true;
} else if leading_slash_idx.map_or(true, |idx| pattern[idx] == SLASH)
&& next.map_or(true, |(_, c)| {
Expand Down Expand Up @@ -318,7 +321,7 @@ pub(crate) mod function {
break;
}
}
if matched == negated || mode.contains(Mode::SLASH_IS_LITERAL) && t_ch == SLASH {
if matched == negated || mode.contains(Mode::NO_MATCH_SLASH_LITERAL) && t_ch == SLASH {
return NoMatch;
}
continue;
Expand Down
55 changes: 16 additions & 39 deletions git-glob/tests/fixtures/make_baseline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ git config commit.gpgsign false
git config core.autocrlf false
git config core.ignorecase false

while read -r pattern nomatch; do
echo "$pattern" "$nomatch"
while read -r pattern value; do
echo "$pattern" "$value"
echo "$pattern" > .gitignore
git check-ignore -vn "$nomatch" 2>&1 || :
done <<EOF >>git-baseline.nmatch
echo "$value" | git check-ignore -vn --stdin 2>&1 || :
done <<EOF >git-baseline.nmatch
*/\ XXX/\
*/\\ XXX/\
/*foo bar/foo
Expand Down Expand Up @@ -68,11 +68,15 @@ foo/** foo
abc[/]def abc/def
EOF

while read -r pattern match; do
echo "$pattern" "$match"
while read -r pattern value; do
echo "$pattern" "$value"
echo "$pattern" > .gitignore
git check-ignore -vn "$match" 2>&1 || :
done <<EOF >>git-baseline.match
echo "$value" | git check-ignore -vn --stdin 2>&1 || :
done <<EOF >git-baseline.match
\a a
\\\[a-z] \a
\\\? \a
\\\* \\
/*foo.txt barfoo.txt
*foo.txt bar/foo.txt
*.c mozilla-sha1/sha1.c
Expand Down Expand Up @@ -141,40 +145,13 @@ abc/def abc/def
EOF

git config core.ignorecase true
while read -r pattern match; do
echo "$pattern" "$match"
while read -r pattern value; do
echo "$pattern" "$value"
echo "$pattern" > .gitignore
git check-ignore -vn "$match" 2>&1 || :
done <<EOF >>git-baseline.match-icase
echo "$value" | git check-ignore -vn --stdin 2>&1 || :
done <<EOF >git-baseline.match-icase
aBcDeFg aBcDeFg
aBcDeFg abcdefg
aBcDeFg ABCDEFG
aBcDeFg AbCdEfG
EOF

# nmatches OS specific
# windows
# "abc?def" "abc\\def"
# unix
# "abc\\def" "abc/def"


# matches OS specific

# unix only
# "\\a" "a"
#"abc\\def" "abc/def"
#"abc?def" "abc/def"
# \[a-z] \a
# \? \a
# \* \\

# windows only
# "abc[/]def" "abc/def"
# "abc\\def" "abc/def"
#"abc?def" "abc\\def"

# empty string is not a valid path-spec
#** " "
#{} " "
#{,} " "
13 changes: 11 additions & 2 deletions git-glob/tests/matching/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ fn compare_baseline_with_ours() {
let dir = git_testtools::scripted_fixture_repo_read_only("make_baseline.sh").unwrap();
let (mut total_matches, mut total_correct, mut panics) = (0, 0, 0);
let mut mismatches = Vec::new();
for (input_file, expected_matches) in &[("git-baseline.match", true), ("git-baseline.nmatch", false)] {
for (input_file, expected_matches, case) in &[
("git-baseline.match", true, pattern::Case::Sensitive),
("git-baseline.nmatch", false, pattern::Case::Sensitive),
("git-baseline.match-icase", true, pattern::Case::Fold),
] {
let input = std::fs::read(dir.join(*input_file)).unwrap();
let mut seen = BTreeSet::default();

Expand All @@ -58,13 +62,18 @@ fn compare_baseline_with_ours() {
{
total_matches += 1;
assert!(seen.insert(m), "duplicate match entry: {:?}", m);
assert_eq!(
is_match, *expected_matches,
"baseline for matches must be {} - check baseline and git version: {:?}",
expected_matches, m
);
match std::panic::catch_unwind(|| {
let pattern = pat(pattern);
pattern.matches_repo_relative_path(
value,
basename_start_pos(value),
false, // TODO: does it make sense to pretend it is a dir and see what happens?
pattern::Case::Sensitive,
*case,
)
}) {
Ok(actual_match) => {
Expand Down