Skip to content
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

[ignore] Add extensive test for gitignore matching #551

Merged
merged 5 commits into from
Jul 13, 2017
Merged
Show file tree
Hide file tree
Changes from 4 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
40 changes: 37 additions & 3 deletions ignore/src/gitignore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ impl Gitignore {
self.num_whitelists
}

/// Returns whether the given file path matched a pattern in this gitignore
/// matcher.
/// Returns whether the given path (file or directory) matched a pattern in
/// this gitignore matcher.
///
/// `is_dir` should be true if the path refers to a directory and false
/// otherwise.
Expand All @@ -191,6 +191,40 @@ impl Gitignore {
self.matched_stripped(self.strip(path.as_ref()), is_dir)
}

/// Returns whether the given path (file or directory) or any of its parent
/// directories matched a pattern in this gitignore matcher.
///
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the initial description, I think we should briefly explain what we mean by parent. That is, it is a transformation on the path itself and doesn't try to walk up the file system. I'm not sure how to say that succinctly and clearly though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know what you mean. Added some more text here. Please see how that look?

/// NOTE: This method is more expensive than walking the directory hierarchy
/// top-to-bottom and matching the entries. But, it is useful in cases when
/// a list of paths are available without a hierarchy.
///
/// `is_dir` should be true if the path refers to a directory and false
/// otherwise.
///
/// The given path is matched relative to the path given when building
/// the matcher. Specifically, before matching `path`, its prefix (as
/// determined by a common suffix of the directory containing this
/// gitignore) is stripped. If there is no common suffix/prefix overlap,
/// then `path` is assumed to be relative to this matcher.
pub fn matched_recursive<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match<&Glob> {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we think of another name? I feel like matched_recursive doesn't really signal to the user what this is actually doing. But this is a super subtle method, so I'm not sure what to call it either. Maybe matched_any_parent or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Renamed to matched_path_or_any_parents(). What do you think?

if self.is_empty() {
return Match::None;
}
let mut current_path = self.strip(path.as_ref());
match self.matched_stripped(current_path, is_dir) {
Match::None => {
while let Some(parent) = current_path.parent() {
match self.matched_stripped(parent, is_dir) {
Match::None => current_path = parent,
a_match => return a_match,
}
}
}
a_match => return a_match,
}
Match::None
}

/// Like matched, but takes a path that has already been stripped.
fn matched_stripped<P: AsRef<Path>>(
&self,
Expand Down Expand Up @@ -440,7 +474,7 @@ impl GitignoreBuilder {
}

/// Toggle whether the globs should be matched case insensitively or not.
///
///
/// This is disabled by default.
pub fn case_insensitive(
&mut self, yes: bool
Expand Down
216 changes: 216 additions & 0 deletions ignore/tests/gitignore_recursive_tests.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Based on https://github.com/behnam/gitignore-test/blob/master/.gitignore

### file in root

# MATCH /file_root_1
file_root_00

# NO_MATCH
file_root_01/

# NO_MATCH
file_root_02/*

# NO_MATCH
file_root_03/**


# MATCH /file_root_10
/file_root_10

# NO_MATCH
/file_root_11/

# NO_MATCH
/file_root_12/*

# NO_MATCH
/file_root_13/**


# NO_MATCH
*/file_root_20

# NO_MATCH
*/file_root_21/

# NO_MATCH
*/file_root_22/*

# NO_MATCH
*/file_root_23/**


# MATCH /file_root_30
**/file_root_30

# NO_MATCH
**/file_root_31/

# NO_MATCH
**/file_root_32/*

# NO_MATCH
**/file_root_33/**


### file in sub-dir

# MATCH /parent_dir/file_deep_1
file_deep_00

# NO_MATCH
file_deep_01/

# NO_MATCH
file_deep_02/*

# NO_MATCH
file_deep_03/**


# NO_MATCH
/file_deep_10

# NO_MATCH
/file_deep_11/

# NO_MATCH
/file_deep_12/*

# NO_MATCH
/file_deep_13/**


# MATCH /parent_dir/file_deep_20
*/file_deep_20

# NO_MATCH
*/file_deep_21/

# NO_MATCH
*/file_deep_22/*

# NO_MATCH
*/file_deep_23/**


# MATCH /parent_dir/file_deep_30
**/file_deep_30

# NO_MATCH
**/file_deep_31/

# NO_MATCH
**/file_deep_32/*

# NO_MATCH
**/file_deep_33/**


### dir in root

# MATCH /dir_root_00
dir_root_00

# MATCH /dir_root_01
dir_root_01/

# MATCH /dir_root_02
dir_root_02/*

# MATCH /dir_root_03
dir_root_03/**


# MATCH /dir_root_10
/dir_root_10

# MATCH /dir_root_11
/dir_root_11/

# MATCH /dir_root_12
/dir_root_12/*

# MATCH /dir_root_13
/dir_root_13/**


# NO_MATCH
*/dir_root_20

# NO_MATCH
*/dir_root_21/

# NO_MATCH
*/dir_root_22/*

# NO_MATCH
*/dir_root_23/**


# MATCH /dir_root_30
**/dir_root_30

# MATCH /dir_root_31
**/dir_root_31/

# MATCH /dir_root_32
**/dir_root_32/*

# MATCH /dir_root_33
**/dir_root_33/**


### dir in sub-dir

# MATCH /parent_dir/dir_deep_00
dir_deep_00

# MATCH /parent_dir/dir_deep_01
dir_deep_01/

# NO_MATCH
dir_deep_02/*

# NO_MATCH
dir_deep_03/**


# NO_MATCH
/dir_deep_10

# NO_MATCH
/dir_deep_11/

# NO_MATCH
/dir_deep_12/*

# NO_MATCH
/dir_deep_13/**


# MATCH /parent_dir/dir_deep_20
*/dir_deep_20

# MATCH /parent_dir/dir_deep_21
*/dir_deep_21/

# MATCH /parent_dir/dir_deep_22
*/dir_deep_22/*

# MATCH /parent_dir/dir_deep_23
*/dir_deep_23/**


# MATCH /parent_dir/dir_deep_30
**/dir_deep_30

# MATCH /parent_dir/dir_deep_31
**/dir_deep_31/

# MATCH /parent_dir/dir_deep_32
**/dir_deep_32/*

# MATCH /parent_dir/dir_deep_33
**/dir_deep_33/**
Loading