Skip to content

Commit ef521e3

Browse files
committed
idiomatic improvements
1 parent 11d9506 commit ef521e3

File tree

2 files changed

+66
-59
lines changed

2 files changed

+66
-59
lines changed

src/ownership/for_file_fast.rs

Lines changed: 58 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use std::{
66

77
use fast_glob::glob_match;
88
use glob::glob;
9-
use lazy_static::lazy_static;
10-
use regex::Regex;
119

1210
use crate::{config::Config, project::Team};
1311

@@ -106,7 +104,7 @@ pub fn find_file_owners(project_root: &Path, config: &Config, file_path: &Path)
106104
}
107105

108106
fn build_teams_by_name_map(teams: &[Team]) -> HashMap<String, Team> {
109-
let mut map = HashMap::new();
107+
let mut map = HashMap::with_capacity(teams.len() * 2);
110108
for team in teams {
111109
map.insert(team.name.clone(), team.clone());
112110
map.insert(team.github_team.clone(), team.clone());
@@ -117,7 +115,7 @@ fn build_teams_by_name_map(teams: &[Team]) -> HashMap<String, Team> {
117115
fn load_teams(project_root: &Path, team_file_globs: &[String]) -> std::result::Result<Vec<Team>, String> {
118116
let mut teams: Vec<Team> = Vec::new();
119117
for glob_str in team_file_globs {
120-
let absolute_glob = format!("{}/{}", project_root.display(), glob_str);
118+
let absolute_glob = project_root.join(glob_str).to_string_lossy().into_owned();
121119
let paths = glob(&absolute_glob).map_err(|e| e.to_string())?;
122120
for path in paths.flatten() {
123121
match Team::from_team_file_path(path.clone()) {
@@ -132,30 +130,48 @@ fn load_teams(project_root: &Path, team_file_globs: &[String]) -> std::result::R
132130
Ok(teams)
133131
}
134132

135-
lazy_static! {
136-
// Allow optional leading whitespace before the comment marker
137-
static ref TOP_OF_FILE_TEAM_AT_REGEX: Option<Regex> = Regex::new(r#"^\s*(?:#|//)\s*@team\s+(.+)$"#).ok();
138-
static ref TOP_OF_FILE_TEAM_COLON_REGEX: Option<Regex> = Regex::new(r#"(?i)^\s*(?:#|//)\s*team\s*:\s*(.+)$"#).ok();
139-
}
133+
// no regex: parse cheaply with ASCII-aware checks
140134

141135
fn read_top_of_file_team(path: &Path) -> Option<String> {
142-
let content = fs::read_to_string(path).ok()?;
143-
let line = content.lines().next()?;
136+
use std::io::{BufRead, BufReader};
137+
138+
let file = std::fs::File::open(path).ok()?;
139+
let mut reader = BufReader::new(file);
140+
let mut line = String::new();
141+
reader.read_line(&mut line).ok()?;
142+
143+
// trim trailing newlines
144+
let mut s: &str = line.trim_end_matches(['\r', '\n']);
145+
// allow optional leading whitespace
146+
s = s.trim_start();
147+
148+
// strip comment leader
149+
if let Some(rest) = s.strip_prefix("//") {
150+
s = rest;
151+
} else if let Some(rest) = s.strip_prefix('#') {
152+
s = rest;
153+
} else {
154+
return None;
155+
}
144156

145-
if let Some(re) = &*TOP_OF_FILE_TEAM_AT_REGEX {
146-
if let Some(cap) = re.captures(line) {
147-
if let Some(m) = cap.get(1) {
148-
return Some(m.as_str().to_string());
149-
}
150-
}
157+
// optional spaces after comment leader
158+
s = s.trim_start();
159+
160+
// @team <Name>
161+
if let Some(rest) = s.strip_prefix("@team") {
162+
return Some(rest.trim_start().to_string());
151163
}
152-
if let Some(re) = &*TOP_OF_FILE_TEAM_COLON_REGEX {
153-
if let Some(cap) = re.captures(line) {
154-
if let Some(m) = cap.get(1) {
155-
return Some(m.as_str().to_string());
156-
}
164+
165+
// team: <Name> (case-insensitive label, optional spaces around ':')
166+
let prefix = "team";
167+
if s.len() >= prefix.len() && s[..prefix.len()].eq_ignore_ascii_case(prefix) {
168+
let mut rest = &s[prefix.len()..];
169+
rest = rest.trim_start();
170+
if let Some(after_colon) = rest.strip_prefix(':') {
171+
return Some(after_colon.trim_start().to_string());
157172
}
158173
}
174+
159175
None
160176
}
161177

@@ -167,34 +183,32 @@ fn most_specific_directory_owner(
167183
let mut current = project_root.join(relative_file_path);
168184
let mut best: Option<(String, Source)> = None;
169185
loop {
170-
let parent_opt = current.parent().map(|p| p.to_path_buf());
171-
let Some(parent) = parent_opt else { break };
172-
let codeowner_path = parent.join(".codeowner");
186+
if !current.pop() {
187+
break;
188+
}
189+
let codeowner_path = current.join(".codeowner");
173190
if let Ok(owner_str) = fs::read_to_string(&codeowner_path) {
174191
let owner = owner_str.trim();
175192
if let Some(team) = teams_by_name.get(owner) {
176-
let relative_dir = parent
193+
let relative_dir = current
177194
.strip_prefix(project_root)
178-
.unwrap_or(parent.as_path())
195+
.unwrap_or(current.as_path())
179196
.to_string_lossy()
180197
.to_string();
181198
let candidate = (team.name.clone(), Source::Directory(relative_dir));
182199
match &best {
183200
None => best = Some(candidate),
184201
Some((_, existing_source)) => {
185-
let existing_len = source_directory_depth(existing_source);
186-
let candidate_len = source_directory_depth(&candidate.1);
187-
if candidate_len > existing_len {
202+
if candidate.1.len() > existing_source.len() {
188203
best = Some(candidate);
189204
}
190205
}
191206
}
192207
}
193208
}
194-
if parent == project_root {
209+
if current == project_root {
195210
break;
196211
}
197-
current = parent.clone();
198212
}
199213
best
200214
}
@@ -207,17 +221,18 @@ fn nearest_package_owner(
207221
) -> Option<(String, Source)> {
208222
let mut current = project_root.join(relative_file_path);
209223
loop {
210-
let parent_opt = current.parent().map(|p| p.to_path_buf());
211-
let Some(parent) = parent_opt else { break };
212-
let parent_rel = parent.strip_prefix(project_root).unwrap_or(parent.as_path());
224+
if !current.pop() {
225+
break;
226+
}
227+
let parent_rel = current.strip_prefix(project_root).unwrap_or(current.as_path());
213228
if let Some(rel_str) = parent_rel.to_str() {
214229
if glob_list_matches(rel_str, &config.ruby_package_paths) {
215-
let pkg_yml = parent.join("package.yml");
230+
let pkg_yml = current.join("package.yml");
216231
if pkg_yml.exists() {
217232
if let Ok(owner) = read_ruby_package_owner(&pkg_yml) {
218233
if let Some(team) = teams_by_name.get(&owner) {
219234
let package_path = parent_rel.join("package.yml");
220-
let package_glob = format!("{}/**/**", rel_str);
235+
let package_glob = format!("{rel_str}/**/**");
221236
return Some((
222237
team.name.clone(),
223238
Source::Package(package_path.to_string_lossy().to_string(), package_glob),
@@ -227,12 +242,12 @@ fn nearest_package_owner(
227242
}
228243
}
229244
if glob_list_matches(rel_str, &config.javascript_package_paths) {
230-
let pkg_json = parent.join("package.json");
245+
let pkg_json = current.join("package.json");
231246
if pkg_json.exists() {
232247
if let Ok(owner) = read_js_package_owner(&pkg_json) {
233248
if let Some(team) = teams_by_name.get(&owner) {
234249
let package_path = parent_rel.join("package.json");
235-
let package_glob = format!("{}/**/**", rel_str);
250+
let package_glob = format!("{rel_str}/**/**");
236251
return Some((
237252
team.name.clone(),
238253
Source::Package(package_path.to_string_lossy().to_string(), package_glob),
@@ -242,20 +257,14 @@ fn nearest_package_owner(
242257
}
243258
}
244259
}
245-
if parent == project_root {
260+
if current == project_root {
246261
break;
247262
}
248-
current = parent;
249263
}
250264
None
251265
}
252266

253-
fn source_directory_depth(source: &Source) -> usize {
254-
match source {
255-
Source::Directory(path) => path.matches('/').count(),
256-
_ => 0,
257-
}
258-
}
267+
// removed: use `Source::len()` instead
259268

260269
fn glob_list_matches(path: &str, globs: &[String]) -> bool {
261270
globs.iter().any(|g| glob_match(g, path))
@@ -401,20 +410,12 @@ mod tests {
401410
// Ruby package
402411
let ruby_pkg = project_root.join("packs/payroll");
403412
std::fs::create_dir_all(&ruby_pkg).unwrap();
404-
std::fs::write(
405-
ruby_pkg.join("package.yml"),
406-
"---\nowner: Payroll\n",
407-
)
408-
.unwrap();
413+
std::fs::write(ruby_pkg.join("package.yml"), "---\nowner: Payroll\n").unwrap();
409414

410415
// JS package
411416
let js_pkg = project_root.join("frontend/flow");
412417
std::fs::create_dir_all(&js_pkg).unwrap();
413-
std::fs::write(
414-
js_pkg.join("package.json"),
415-
r#"{"metadata": {"owner": "UX"}}"#,
416-
)
417-
.unwrap();
418+
std::fs::write(js_pkg.join("package.json"), r#"{"metadata": {"owner": "UX"}}"#).unwrap();
418419

419420
// Teams map
420421
let mut tbn: HashMap<String, Team> = HashMap::new();

src/project.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,14 @@ mod tests {
202202

203203
#[test]
204204
fn test_vendored_gem_by_name_maps_all_gems() {
205-
let vg1 = VendoredGem { path: PathBuf::from("vendored/a"), name: "a".to_string() };
206-
let vg2 = VendoredGem { path: PathBuf::from("vendored/b"), name: "b".to_string() };
205+
let vg1 = VendoredGem {
206+
path: PathBuf::from("vendored/a"),
207+
name: "a".to_string(),
208+
};
209+
let vg2 = VendoredGem {
210+
path: PathBuf::from("vendored/b"),
211+
name: "b".to_string(),
212+
};
207213
let project = Project {
208214
base_path: PathBuf::from("."),
209215
files: vec![],

0 commit comments

Comments
 (0)