Skip to content

Commit 390eb73

Browse files
committed
introducing runner for reuse
1 parent 231bcab commit 390eb73

File tree

4 files changed

+155
-89
lines changed

4 files changed

+155
-89
lines changed

src/cli.rs

Lines changed: 23 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
use clap::{Parser, Subcommand};
2-
use codeowners::{
3-
cache::{Cache, Caching, file::GlobalCache, noop::NoopCache},
4-
config::Config,
5-
ownership::{FileOwner, Ownership},
6-
project_builder::ProjectBuilder,
7-
};
8-
use core::fmt;
9-
use error_stack::{Context, Result, ResultExt};
2+
use codeowners::runner::Error as RunnerError;
3+
use codeowners::runner::{RunConfig, Runner};
4+
use error_stack::{Result, ResultExt};
105
use path_clean::PathClean;
11-
use std::{
12-
fs::File,
13-
path::{Path, PathBuf},
14-
};
6+
use std::path::{Path, PathBuf};
157

168
#[derive(Subcommand, Debug)]
179
enum Command {
@@ -64,105 +56,52 @@ struct Args {
6456
}
6557

6658
impl Args {
67-
fn absolute_project_root(&self) -> Result<PathBuf, Error> {
68-
self.project_root.canonicalize().change_context(Error::Io)
59+
fn absolute_project_root(&self) -> Result<PathBuf, RunnerError> {
60+
self.project_root.canonicalize().change_context(RunnerError::Io)
6961
}
7062

71-
fn absolute_config_path(&self) -> Result<PathBuf, Error> {
63+
fn absolute_config_path(&self) -> Result<PathBuf, RunnerError> {
7264
Ok(self.absolute_path(&self.config_path)?.clean())
7365
}
7466

75-
fn absolute_codeowners_path(&self) -> Result<PathBuf, Error> {
67+
fn absolute_codeowners_path(&self) -> Result<PathBuf, RunnerError> {
7668
Ok(self.absolute_path(&self.codeowners_file_path)?.clean())
7769
}
7870

79-
fn absolute_path(&self, path: &Path) -> Result<PathBuf, Error> {
71+
fn absolute_path(&self, path: &Path) -> Result<PathBuf, RunnerError> {
8072
Ok(self.absolute_project_root()?.join(path))
8173
}
8274
}
8375

84-
#[derive(Debug)]
85-
pub enum Error {
86-
Io,
87-
ValidationFailed,
88-
}
89-
90-
impl Context for Error {}
91-
92-
pub fn cli() -> Result<(), Error> {
76+
pub fn cli() -> Result<(), RunnerError> {
9377
let args = Args::parse();
9478

9579
let config_path = args.absolute_config_path()?;
9680
let codeowners_file_path = args.absolute_codeowners_path()?;
9781
let project_root = args.absolute_project_root()?;
9882

99-
let config_file = File::open(&config_path)
100-
.change_context(Error::Io)
101-
.attach_printable(format!("Can't open config file: {}", config_path.to_string_lossy()))?;
102-
103-
let config: Config = serde_yaml::from_reader(config_file).change_context(Error::Io)?;
104-
let cache: Cache = if args.no_cache {
105-
NoopCache::default().into()
106-
} else {
107-
GlobalCache::new(project_root.clone(), config.cache_directory.clone())
108-
.change_context(Error::Io)?
109-
.into()
83+
let run_config = RunConfig {
84+
config_path,
85+
codeowners_file_path,
86+
project_root,
87+
no_cache: args.no_cache,
11088
};
11189

112-
let mut project_builder = ProjectBuilder::new(&config, project_root.clone(), codeowners_file_path.clone(), &cache);
113-
let project = project_builder.build().change_context(Error::Io)?;
114-
let ownership = Ownership::build(project);
115-
116-
cache.persist_cache().change_context(Error::Io)?;
90+
let runner = Runner::new(run_config).change_context(RunnerError::Io)?;
11791

11892
match args.command {
119-
Command::Validate => ownership.validate().change_context(Error::ValidationFailed)?,
120-
Command::Generate => {
121-
std::fs::write(codeowners_file_path, ownership.generate_file()).change_context(Error::Io)?;
122-
}
93+
Command::Validate => runner.validate()?,
94+
Command::Generate => runner.generate()?,
12395
Command::GenerateAndValidate => {
124-
std::fs::write(codeowners_file_path, ownership.generate_file()).change_context(Error::Io)?;
125-
ownership.validate().change_context(Error::ValidationFailed)?
96+
runner.generate()?;
97+
runner.validate()?;
12698
}
12799
Command::ForFile { name } => {
128-
let file_owners = ownership.for_file(&name).change_context(Error::Io)?;
129-
match file_owners.len() {
130-
0 => println!("{}", FileOwner::default()),
131-
1 => println!("{}", file_owners[0]),
132-
_ => {
133-
println!("Error: file is owned by multiple teams!");
134-
for file_owner in file_owners {
135-
println!("\n{}", file_owner);
136-
}
137-
}
138-
}
139-
}
140-
Command::ForTeam { name } => match ownership.for_team(&name) {
141-
Ok(team_ownerships) => {
142-
println!("# Code Ownership Report for `{}` Team", name);
143-
for team_ownership in team_ownerships {
144-
println!("\n#{}", team_ownership.heading);
145-
match team_ownership.globs.len() {
146-
0 => println!("This team owns nothing in this category."),
147-
_ => println!("{}", team_ownership.globs.join("\n")),
148-
}
149-
}
150-
}
151-
Err(err) => println!("{}", err),
152-
},
153-
Command::DeleteCache => {
154-
cache.delete_cache().change_context(Error::Io)?;
100+
runner.for_file(&name)?;
155101
}
102+
Command::ForTeam { name } => runner.for_team(&name)?,
103+
Command::DeleteCache => runner.delete_cache()?,
156104
}
157105

158106
Ok(())
159107
}
160-
161-
impl fmt::Display for Error {
162-
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
163-
match self {
164-
Error::Io => fmt.write_str("Error::Io"),
165-
Error::ValidationFailed => fmt.write_str("Error::ValidationFailed"),
166-
}
167-
}
168-
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ pub mod ownership;
55
pub(crate) mod project;
66
pub mod project_builder;
77
pub mod project_file_builder;
8+
pub mod runner;

src/main.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
mod cli;
22
use std::process;
33

4-
use cli::Error;
5-
use codeowners::ownership;
4+
use codeowners::{ownership::ValidatorErrors, runner::Error as RunnerError};
65
use error_stack::Result;
76

87
use crate::cli::cli;
98

10-
fn main() -> Result<(), Error> {
9+
fn main() -> Result<(), RunnerError> {
1110
install_logger();
1211
maybe_print_errors(cli())?;
1312

1413
Ok(())
1514
}
1615

17-
fn maybe_print_errors(result: Result<(), Error>) -> Result<(), Error> {
16+
fn maybe_print_errors(result: Result<(), RunnerError>) -> Result<(), RunnerError> {
1817
if let Err(error) = result {
19-
if let Some(validation_errors) = error.downcast_ref::<ownership::ValidatorErrors>() {
18+
if let Some(validation_errors) = error.downcast_ref::<ValidatorErrors>() {
2019
println!("{}", validation_errors);
2120
process::exit(-1);
2221
} else {

src/runner.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use core::fmt;
2+
use std::{fs::File, path::PathBuf};
3+
4+
use error_stack::{Context, Result, ResultExt};
5+
6+
use crate::{
7+
cache::{Cache, Caching, file::GlobalCache, noop::NoopCache},
8+
config::Config,
9+
ownership::{FileOwner, Ownership},
10+
project_builder::ProjectBuilder,
11+
};
12+
13+
pub struct RunConfig {
14+
pub project_root: PathBuf,
15+
pub codeowners_file_path: PathBuf,
16+
pub config_path: PathBuf,
17+
pub no_cache: bool,
18+
}
19+
20+
pub struct Runner {
21+
run_config: RunConfig,
22+
ownership: Ownership,
23+
cache: Cache,
24+
}
25+
26+
#[derive(Debug)]
27+
pub enum Error {
28+
Io,
29+
ValidationFailed,
30+
}
31+
32+
impl Context for Error {}
33+
impl fmt::Display for Error {
34+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
35+
match self {
36+
Error::Io => fmt.write_str("Error::Io"),
37+
Error::ValidationFailed => fmt.write_str("Error::ValidationFailed"),
38+
}
39+
}
40+
}
41+
42+
impl Runner {
43+
pub fn new(run_config: RunConfig) -> Result<Self, Error> {
44+
let config_file = File::open(&run_config.config_path)
45+
.change_context(Error::Io)
46+
.attach_printable(format!("Can't open config file: {}", &run_config.config_path.to_string_lossy()))?;
47+
48+
let config: Config = serde_yaml::from_reader(config_file).change_context(Error::Io)?;
49+
let cache: Cache = if run_config.no_cache {
50+
NoopCache::default().into()
51+
} else {
52+
GlobalCache::new(run_config.project_root.clone(), config.cache_directory.clone())
53+
.change_context(Error::Io)?
54+
.into()
55+
};
56+
57+
let mut project_builder = ProjectBuilder::new(
58+
&config,
59+
run_config.project_root.clone(),
60+
run_config.codeowners_file_path.clone(),
61+
&cache,
62+
);
63+
let project = project_builder.build().change_context(Error::Io)?;
64+
let ownership = Ownership::build(project);
65+
66+
cache.persist_cache().change_context(Error::Io)?;
67+
68+
Ok(Self {
69+
run_config,
70+
ownership,
71+
cache,
72+
})
73+
}
74+
75+
pub fn validate(&self) -> Result<(), Error> {
76+
self.ownership.validate().change_context(Error::ValidationFailed)?;
77+
Ok(())
78+
}
79+
80+
pub fn generate(&self) -> Result<(), Error> {
81+
std::fs::write(&self.run_config.codeowners_file_path, self.ownership.generate_file()).change_context(Error::Io)?;
82+
Ok(())
83+
}
84+
85+
pub fn generate_and_validate(&self) -> Result<(), Error> {
86+
self.generate().change_context(Error::Io)?;
87+
self.validate().change_context(Error::ValidationFailed)?;
88+
Ok(())
89+
}
90+
91+
pub fn for_file(&self, file_path: &str) -> Result<(), Error> {
92+
let file_owners = self.ownership.for_file(file_path).change_context(Error::Io)?;
93+
match file_owners.len() {
94+
0 => println!("{}", FileOwner::default()),
95+
1 => println!("{}", file_owners[0]),
96+
_ => {
97+
println!("Error: file is owned by multiple teams!");
98+
for file_owner in file_owners {
99+
println!("\n{}", file_owner);
100+
}
101+
}
102+
}
103+
Ok(())
104+
}
105+
106+
pub fn for_team(&self, team_name: &str) -> Result<(), Error> {
107+
match self.ownership.for_team(team_name) {
108+
Ok(team_ownerships) => {
109+
println!("# Code Ownership Report for `{}` Team", team_name);
110+
for team_ownership in team_ownerships {
111+
println!("\n#{}", team_ownership.heading);
112+
match team_ownership.globs.len() {
113+
0 => println!("This team owns nothing in this category."),
114+
_ => println!("{}", team_ownership.globs.join("\n")),
115+
}
116+
}
117+
}
118+
Err(err) => println!("{}", err),
119+
}
120+
Ok(())
121+
}
122+
123+
pub fn delete_cache(&self) -> Result<(), Error> {
124+
self.cache.delete_cache().change_context(Error::Io)?;
125+
Ok(())
126+
}
127+
}

0 commit comments

Comments
 (0)