GlobPattern: support trailing slash and globstar (eg. **/*.egg)

This commit is contained in:
rdb 2017-02-12 17:21:53 +01:00
parent ec3c2c5681
commit 29edf55069

View File

@ -99,7 +99,7 @@ match_files(vector_string &results, const Filename &cwd) const {
pattern = source; pattern = source;
} else { } else {
pattern = source.substr(0, slash); pattern = source.substr(0, slash);
suffix = source.substr(slash + 1); suffix = source.substr(slash);
} }
GlobPattern glob(pattern); GlobPattern glob(pattern);
@ -118,11 +118,21 @@ r_match_files(const Filename &prefix, const string &suffix,
size_t slash = suffix.find('/'); size_t slash = suffix.find('/');
if (slash == string::npos) { if (slash == string::npos) {
next_pattern = suffix; next_pattern = suffix;
} else if (slash + 1 == suffix.size()) {
// If the slash is at the end, we need to keep it, since it indicates that
// we only want to match directories.
next_pattern = suffix.substr(0, slash);
next_suffix = "/";
} else { } else {
next_pattern = suffix.substr(0, slash); next_pattern = suffix.substr(0, slash);
next_suffix = suffix.substr(slash + 1); next_suffix = suffix.substr(slash + 1);
} }
if (_pattern == "**" && next_pattern == "**") {
// Collapse consecutive globstar patterns.
return r_match_files(prefix, next_suffix, results, cwd);
}
Filename parent_dir; Filename parent_dir;
if (prefix.is_local() && !cwd.empty()) { if (prefix.is_local() && !cwd.empty()) {
parent_dir = Filename(cwd, prefix); parent_dir = Filename(cwd, prefix);
@ -136,19 +146,24 @@ r_match_files(const Filename &prefix, const string &suffix,
if (!has_glob_characters()) { if (!has_glob_characters()) {
// If there are no special characters in the pattern, it's a literal // If there are no special characters in the pattern, it's a literal
// match. // match.
Filename fn(parent_dir, _pattern);
if (suffix.empty()) { if (suffix.empty()) {
// Time to stop. // Time to stop.
Filename single_filename(parent_dir, _pattern); if (fn.exists()) {
if (single_filename.exists()) {
results.push_back(Filename(prefix, _pattern)); results.push_back(Filename(prefix, _pattern));
return 1; return 1;
} }
return 0; return 0;
} else if (fn.is_directory()) {
// If the pattern ends with a slash, match a directory only.
if (suffix == "/") {
results.push_back(Filename(prefix, _pattern + "/"));
return 1;
} else {
return next_glob.r_match_files(Filename(prefix, _pattern),
next_suffix, results, cwd);
}
} }
return next_glob.r_match_files(Filename(prefix, _pattern),
next_suffix, results, cwd);
} }
// If there *are* special glob characters, we must attempt to match the // If there *are* special glob characters, we must attempt to match the
@ -164,18 +179,44 @@ r_match_files(const Filename &prefix, const string &suffix,
// the pattern. // the pattern.
int num_matched = 0; int num_matched = 0;
// A globstar pattern matches zero or more directories.
if (_pattern == "**") {
// Try to match this directory (as if the globstar wasn't there)
if (suffix.empty()) {
// This is a directory. Add it.
results.push_back(Filename(prefix));
num_matched++;
} else if (suffix == "/") {
// Keep the trailing slash, but be sure not to duplicate it.
results.push_back(Filename(prefix, ""));
num_matched++;
} else {
num_matched += next_glob.r_match_files(prefix, next_suffix, results, cwd);
}
next_suffix = suffix;
next_glob = *this;
}
vector_string::const_iterator fi; vector_string::const_iterator fi;
for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) { for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
const string &local_file = (*fi); const string &local_file = (*fi);
if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) { if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) {
if (matches(local_file)) { if (matches(local_file)) {
// We have a match; continue. // We have a match; continue.
if (suffix.empty()) { if (Filename(parent_dir, local_file).is_directory()) {
if (suffix.empty() && _pattern != "**") {
results.push_back(Filename(prefix, local_file));
num_matched++;
} else if (suffix == "/" && _pattern != "**") {
results.push_back(Filename(prefix, local_file + "/"));
num_matched++;
} else {
num_matched += next_glob.r_match_files(Filename(prefix, local_file),
next_suffix, results, cwd);
}
} else if (suffix.empty()) {
results.push_back(Filename(prefix, local_file)); results.push_back(Filename(prefix, local_file));
num_matched++; num_matched++;
} else {
num_matched += next_glob.r_match_files(Filename(prefix, local_file),
next_suffix, results, cwd);
} }
} }
} }