Skip to content

Commit 177306c

Browse files
committed
reorg main
1 parent 3df204c commit 177306c

File tree

5 files changed

+119
-79
lines changed

5 files changed

+119
-79
lines changed

src/cli.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clap::{Parser, Subcommand};
2-
use codeowners::runner::Error as RunnerError;
2+
use codeowners::runner::{Error as RunnerError, RunResult};
33
use codeowners::runner::{RunConfig, Runner};
44
use error_stack::{Result, ResultExt};
55
use path_clean::PathClean;
@@ -73,7 +73,7 @@ impl Args {
7373
}
7474
}
7575

76-
pub fn cli() -> Result<(), RunnerError> {
76+
pub fn cli() -> Result<RunResult, RunnerError> {
7777
let args = Args::parse();
7878

7979
let config_path = args.absolute_config_path()?;
@@ -89,19 +89,14 @@ pub fn cli() -> Result<(), RunnerError> {
8989

9090
let runner = Runner::new(run_config).change_context(RunnerError::Io)?;
9191

92-
match args.command {
93-
Command::Validate => runner.validate()?,
94-
Command::Generate => runner.generate()?,
95-
Command::GenerateAndValidate => {
96-
runner.generate()?;
97-
runner.validate()?;
98-
}
99-
Command::ForFile { name } => {
100-
runner.for_file(&name)?;
101-
}
102-
Command::ForTeam { name } => runner.for_team(&name)?,
103-
Command::DeleteCache => runner.delete_cache()?,
104-
}
92+
let runner_result = match args.command {
93+
Command::Validate => runner.validate(),
94+
Command::Generate => runner.generate(),
95+
Command::GenerateAndValidate => runner.generate_and_validate(),
96+
Command::ForFile { name } => runner.for_file(&name),
97+
Command::ForTeam { name } => runner.for_team(&name),
98+
Command::DeleteCache => runner.delete_cache(),
99+
};
105100

106-
Ok(())
101+
Ok(runner_result)
107102
}

src/main.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
mod cli;
22
use std::process;
33

4-
use codeowners::{ownership::ValidatorErrors, runner::Error as RunnerError};
4+
use codeowners::runner::{Error as RunnerError, RunResult};
55
use error_stack::Result;
66

77
use crate::cli::cli;
88

99
fn main() -> Result<(), RunnerError> {
1010
install_logger();
11-
maybe_print_errors(cli())?;
11+
maybe_print_errors(cli()?)?;
1212

1313
Ok(())
1414
}
1515

16-
fn maybe_print_errors(result: Result<(), RunnerError>) -> Result<(), RunnerError> {
17-
if let Err(error) = result {
18-
if let Some(validation_errors) = error.downcast_ref::<ValidatorErrors>() {
19-
println!("{}", validation_errors);
20-
process::exit(-1);
21-
} else {
22-
Err(error)?
16+
fn maybe_print_errors(result: RunResult) -> Result<(), RunnerError> {
17+
dbg!(&result);
18+
if !result.info_messages.is_empty() {
19+
for msg in result.info_messages {
20+
println!("{}", msg);
2321
}
2422
}
23+
if !result.io_errors.is_empty() || !result.validation_errors.is_empty() {
24+
for msg in result.io_errors {
25+
println!("{}", msg);
26+
}
27+
for msg in result.validation_errors {
28+
println!("{}", msg);
29+
}
30+
process::exit(-1);
31+
}
2532

2633
Ok(())
2734
}

src/runner.rs

Lines changed: 90 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,24 @@ use crate::{
1212
};
1313

1414
pub fn validate(run_config: &RunConfig, _file_paths: Vec<String>) -> RunResult {
15-
let runner = match Runner::new(run_config.clone()) {
16-
Ok(runner) => runner,
17-
Err(err) => {
18-
return RunResult {
19-
io_errors: vec![err.to_string()],
20-
..Default::default()
21-
};
22-
}
23-
};
24-
match runner.validate() {
25-
Ok(_) => RunResult::default(),
26-
Err(err) => RunResult {
27-
validate_errors: vec![err.to_string()],
28-
..Default::default()
29-
},
30-
}
15+
run_with_runner(run_config, |runner| runner.validate())
16+
}
17+
18+
pub fn generate(run_config: &RunConfig) -> RunResult {
19+
run_with_runner(run_config, |runner| runner.generate())
3120
}
3221

3322
pub fn generate_and_validate(run_config: &RunConfig) -> RunResult {
23+
run_with_runner(run_config, |runner| runner.generate_and_validate())
24+
}
25+
26+
pub fn delete_cache(run_config: &RunConfig) -> RunResult {
27+
run_with_runner(run_config, |runner| runner.delete_cache())
28+
}
29+
30+
pub type Runnable = fn(Runner) -> RunResult;
31+
32+
pub fn run_with_runner(run_config: &RunConfig, runnable: Runnable) -> RunResult {
3433
let runner = match Runner::new(run_config.clone()) {
3534
Ok(runner) => runner,
3635
Err(err) => {
@@ -40,17 +39,12 @@ pub fn generate_and_validate(run_config: &RunConfig) -> RunResult {
4039
};
4140
}
4241
};
43-
match runner.generate_and_validate() {
44-
Ok(_) => RunResult::default(),
45-
Err(err) => RunResult {
46-
validate_errors: vec![err.to_string()],
47-
..Default::default()
48-
},
49-
}
42+
runnable(runner)
5043
}
44+
5145
#[derive(Debug, Default, Serialize, Deserialize)]
5246
pub struct RunResult {
53-
pub validate_errors: Vec<String>,
47+
pub validation_errors: Vec<String>,
5448
pub io_errors: Vec<String>,
5549
pub info_messages: Vec<String>,
5650
}
@@ -68,6 +62,12 @@ pub struct Runner {
6862
cache: Cache,
6963
}
7064

65+
impl RunResult {
66+
pub fn has_errors(&self) -> bool {
67+
!self.validation_errors.is_empty() || !self.io_errors.is_empty()
68+
}
69+
}
70+
7171
#[derive(Debug)]
7272
pub enum Error {
7373
Io,
@@ -117,56 +117,94 @@ impl Runner {
117117
})
118118
}
119119

120-
pub fn validate(&self) -> Result<(), Error> {
121-
self.ownership.validate().change_context(Error::ValidationFailed)?;
122-
Ok(())
120+
pub fn validate(&self) -> RunResult {
121+
match self.ownership.validate() {
122+
Ok(_) => RunResult::default(),
123+
Err(err) => RunResult {
124+
validation_errors: vec![format!("{}", err)],
125+
..Default::default()
126+
},
127+
}
123128
}
124129

125-
pub fn generate(&self) -> Result<(), Error> {
126-
std::fs::write(&self.run_config.codeowners_file_path, self.ownership.generate_file()).change_context(Error::Io)?;
127-
Ok(())
130+
pub fn generate(&self) -> RunResult {
131+
match std::fs::write(&self.run_config.codeowners_file_path, self.ownership.generate_file()) {
132+
Ok(_) => RunResult::default(),
133+
Err(err) => RunResult {
134+
io_errors: vec![err.to_string()],
135+
..Default::default()
136+
},
137+
}
128138
}
129139

130-
pub fn generate_and_validate(&self) -> Result<(), Error> {
131-
self.generate().change_context(Error::Io)?;
132-
self.validate().change_context(Error::ValidationFailed)?;
133-
Ok(())
140+
pub fn generate_and_validate(&self) -> RunResult {
141+
let run_result = self.generate();
142+
if run_result.has_errors() {
143+
return run_result;
144+
}
145+
self.validate()
134146
}
135147

136-
pub fn for_file(&self, file_path: &str) -> Result<(), Error> {
137-
let file_owners = self.ownership.for_file(file_path).change_context(Error::Io)?;
138-
match file_owners.len() {
139-
0 => println!("{}", FileOwner::default()),
140-
1 => println!("{}", file_owners[0]),
148+
pub fn for_file(&self, file_path: &str) -> RunResult {
149+
let file_owners = match self.ownership.for_file(file_path) {
150+
Ok(file_owners) => file_owners,
151+
Err(err) => {
152+
return RunResult {
153+
io_errors: vec![err.to_string()],
154+
..Default::default()
155+
};
156+
}
157+
};
158+
let info_messages: Vec<String> = match file_owners.len() {
159+
0 => vec![format!("{}", FileOwner::default())],
160+
1 => vec![format!("{}", file_owners[0])],
141161
_ => {
142-
println!("Error: file is owned by multiple teams!");
162+
let mut error_messages = vec!["Error: file is owned by multiple teams!".to_string()];
143163
for file_owner in file_owners {
144-
println!("\n{}", file_owner);
164+
error_messages.push(format!("\n{}", file_owner));
145165
}
166+
return RunResult {
167+
validation_errors: error_messages,
168+
..Default::default()
169+
};
146170
}
171+
};
172+
RunResult {
173+
info_messages,
174+
..Default::default()
147175
}
148-
Ok(())
149176
}
150177

151-
pub fn for_team(&self, team_name: &str) -> Result<(), Error> {
178+
pub fn for_team(&self, team_name: &str) -> RunResult {
179+
let mut info_messages = vec![];
180+
let mut io_errors = vec![];
152181
match self.ownership.for_team(team_name) {
153182
Ok(team_ownerships) => {
154-
println!("# Code Ownership Report for `{}` Team", team_name);
183+
info_messages.push(format!("# Code Ownership Report for `{}` Team", team_name));
155184
for team_ownership in team_ownerships {
156-
println!("\n#{}", team_ownership.heading);
185+
info_messages.push(format!("\n#{}", team_ownership.heading));
157186
match team_ownership.globs.len() {
158-
0 => println!("This team owns nothing in this category."),
159-
_ => println!("{}", team_ownership.globs.join("\n")),
187+
0 => info_messages.push("This team owns nothing in this category.".to_string()),
188+
_ => info_messages.push(team_ownership.globs.join("\n")),
160189
}
161190
}
162191
}
163-
Err(err) => println!("{}", err),
192+
Err(err) => io_errors.push(format!("{}", err)),
193+
}
194+
RunResult {
195+
info_messages,
196+
io_errors,
197+
..Default::default()
164198
}
165-
Ok(())
166199
}
167200

168-
pub fn delete_cache(&self) -> Result<(), Error> {
169-
self.cache.delete_cache().change_context(Error::Io)?;
170-
Ok(())
201+
pub fn delete_cache(&self) -> RunResult {
202+
match self.cache.delete_cache().change_context(Error::Io) {
203+
Ok(_) => RunResult::default(),
204+
Err(err) => RunResult {
205+
io_errors: vec![err.to_string()],
206+
..Default::default()
207+
},
208+
}
171209
}
172210
}

tests/invalid_project_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn test_for_file_multiple_owners() -> Result<(), Box<dyn Error>> {
7070
.arg("for-file")
7171
.arg("ruby/app/services/multi_owned.rb")
7272
.assert()
73-
.success()
73+
.failure()
7474
.stdout(predicate::eq(indoc! {"
7575
Error: file is owned by multiple teams!
7676

tests/valid_project_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ fn test_for_missing_team() -> Result<(), Box<dyn Error>> {
147147
.arg("for-team")
148148
.arg("Nope")
149149
.assert()
150-
.success()
150+
.failure()
151151
.stdout(predicate::eq(indoc! {"
152152
Team not found
153153
"}));

0 commit comments

Comments
 (0)