Skip to content

Commit b90ed08

Browse files
committed
fallback error
1 parent 1c71490 commit b90ed08

File tree

2 files changed

+78
-12
lines changed

2 files changed

+78
-12
lines changed

src/runner.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ impl RunResult {
304304
pub fn json_info(result: ForFileResult) -> Self {
305305
let json = match serde_json::to_string_pretty(&result) {
306306
Ok(json) => json,
307-
Err(e) => return Self::json_io_error(Error::Io(e.to_string())),
307+
Err(e) => return Self::fallback_io_error(&e.to_string()),
308308
};
309309
Self {
310310
info_messages: vec![json],
@@ -317,9 +317,9 @@ impl RunResult {
317317
Error::Io(msg) => msg,
318318
Error::ValidationFailed => "Error::ValidationFailed".to_string(),
319319
};
320-
let json = match serde_json::to_string(&serde_json::json!({"error": message})).map_err(|e| Error::Io(e.to_string())) {
320+
let json = match serde_json::to_string(&serde_json::json!({"error": message})) {
321321
Ok(json) => json,
322-
Err(e) => return Self::json_io_error(Error::Io(e.to_string())),
322+
Err(e) => return Self::fallback_io_error(&format!("JSON serialization failed: {}", e)),
323323
};
324324
Self {
325325
io_errors: vec![json],
@@ -331,13 +331,20 @@ impl RunResult {
331331
let json_obj = serde_json::json!({"validation_errors": validation_errors});
332332
let json = match serde_json::to_string_pretty(&json_obj) {
333333
Ok(json) => json,
334-
Err(e) => return Self::json_io_error(Error::Io(e.to_string())),
334+
Err(e) => return Self::fallback_io_error(&format!("JSON serialization failed: {}", e)),
335335
};
336336
Self {
337337
validation_errors: vec![json],
338338
..Default::default()
339339
}
340340
}
341+
342+
fn fallback_io_error(message: &str) -> Self {
343+
Self {
344+
io_errors: vec![format!("{{\"error\": \"{}\"}}", message.replace('"', "\\\""))],
345+
..Default::default()
346+
}
347+
}
341348
}
342349

343350
#[cfg(test)]

src/runner/api.rs

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@ use std::path::Path;
44
use crate::ownership::FileOwner;
55
use crate::project::Team;
66

7-
use super::{Error, RunConfig, RunResult, Runner, config_from_path, run};
7+
use super::{Error, ForFileResult, RunConfig, RunResult, Runner, config_from_path, run};
88

99
pub fn for_file(run_config: &RunConfig, file_path: &str, from_codeowners: bool, json: bool) -> RunResult {
10-
run(run_config, |runner| {
11-
if from_codeowners {
12-
runner.for_file_codeowners_only(file_path, json)
13-
} else {
14-
runner.for_file_derived(file_path, json)
15-
}
16-
})
10+
if from_codeowners {
11+
return for_file_codeowners_only_fast(run_config, file_path, json);
12+
}
13+
for_file_optimized(run_config, file_path, json)
1714
}
1815

1916
pub fn for_team(run_config: &RunConfig, team_name: &str) -> RunResult {
@@ -81,3 +78,65 @@ pub fn team_for_file_from_codeowners(run_config: &RunConfig, file_path: &str) ->
8178
.map_err(Error::Io)?;
8279
Ok(res)
8380
}
81+
82+
// Fast path that avoids creating a full Runner for single file queries
83+
fn for_file_optimized(run_config: &RunConfig, file_path: &str, json: bool) -> RunResult {
84+
let config = match config_from_path(&run_config.config_path) {
85+
Ok(c) => c,
86+
Err(err) => {
87+
return RunResult::from_io_error(Error::Io(err.to_string()), json);
88+
}
89+
};
90+
91+
use crate::ownership::file_owner_resolver::find_file_owners;
92+
let file_owners = match find_file_owners(&run_config.project_root, &config, std::path::Path::new(file_path)) {
93+
Ok(v) => v,
94+
Err(err) => {
95+
return RunResult::from_io_error(Error::Io(err), json);
96+
}
97+
};
98+
99+
match file_owners.as_slice() {
100+
[] => RunResult::from_file_owner(&crate::ownership::FileOwner::default(), json),
101+
[owner] => RunResult::from_file_owner(owner, json),
102+
many => {
103+
let mut error_messages = vec!["Error: file is owned by multiple teams!".to_string()];
104+
for owner in many {
105+
error_messages.push(format!("\n{}", owner));
106+
}
107+
RunResult::from_validation_errors(error_messages, json)
108+
}
109+
}
110+
}
111+
112+
fn for_file_codeowners_only_fast(run_config: &RunConfig, file_path: &str, json: bool) -> RunResult {
113+
match team_for_file_from_codeowners(run_config, file_path) {
114+
Ok(Some(team)) => {
115+
let team_yml = crate::path_utils::relative_to(&run_config.project_root, team.path.as_path())
116+
.to_string_lossy()
117+
.to_string();
118+
let result = ForFileResult {
119+
team_name: team.name.clone(),
120+
github_team: team.github_team.clone(),
121+
team_yml,
122+
description: vec!["Owner inferred from codeowners file".to_string()],
123+
};
124+
if json {
125+
RunResult::json_info(result)
126+
} else {
127+
RunResult {
128+
info_messages: vec![format!(
129+
"Team: {}\nGithub Team: {}\nTeam YML: {}\nDescription:\n- {}",
130+
result.team_name,
131+
result.github_team,
132+
result.team_yml,
133+
result.description.join("\n- ")
134+
)],
135+
..Default::default()
136+
}
137+
}
138+
}
139+
Ok(None) => RunResult::from_file_owner(&crate::ownership::FileOwner::default(), json),
140+
Err(err) => RunResult::from_io_error(Error::Io(format!("{}", err)), json),
141+
}
142+
}

0 commit comments

Comments
 (0)