| 84 | } |
| 85 | |
| 86 | pub async fn glob_up<P: AsRef<Path>>(pattern: &str, start: P, stop: Option<P>) -> Vec<PathBuf> { |
| 87 | let mut current = start.as_ref().to_path_buf(); |
| 88 | let stop = stop.map(|s| s.as_ref().to_path_buf()); |
| 89 | let mut result = Vec::new(); |
| 90 | |
| 91 | loop { |
| 92 | let glob = match glob::Pattern::new(pattern) { |
| 93 | Ok(g) => g, |
| 94 | Err(_) => { |
| 95 | if let Some(ref s) = stop { |
| 96 | if ¤t == s { |
| 97 | break; |
| 98 | } |
| 99 | } |
| 100 | if let Some(parent) = current.parent() { |
| 101 | if parent == current { |
| 102 | break; |
| 103 | } |
| 104 | current = parent.to_path_buf(); |
| 105 | } |
| 106 | continue; |
| 107 | } |
| 108 | }; |
| 109 | |
| 110 | for entry in WalkDir::new(¤t) |
| 111 | .max_depth(1) |
| 112 | .follow_links(true) |
| 113 | .into_iter() |
| 114 | .filter_map(|e| e.ok()) |
| 115 | { |
| 116 | let path = entry.path(); |
| 117 | if path.is_file() { |
| 118 | if let Ok(rel) = path.strip_prefix(¤t) { |
| 119 | if glob.matches(&rel.to_string_lossy()) { |
| 120 | result.push(path.to_path_buf()); |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | if stop.as_ref() == Some(¤t) { |
| 127 | break; |
| 128 | } |
| 129 | if let Some(parent) = current.parent() { |
| 130 | if parent == current { |
| 131 | break; |
| 132 | } |
| 133 | current = parent.to_path_buf(); |
| 134 | } else { |
| 135 | break; |
| 136 | } |
| 137 | } |
| 138 | result |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | #[cfg(test)] |