@@ -43,96 +43,17 @@ pub fn for_file(run_config: &RunConfig, file_path: &str, from_codeowners: bool)
4343 for_file_optimized ( run_config, file_path)
4444}
4545
46- fn for_file_codeowners_only ( run_config : & RunConfig , file_path : & str ) -> RunResult {
47- match team_for_file_from_codeowners ( run_config, file_path) {
48- Ok ( Some ( team) ) => {
49- let relative_team_path = team
50- . path
51- . strip_prefix ( & run_config. project_root )
52- . unwrap_or ( team. path . as_path ( ) )
53- . to_string_lossy ( )
54- . to_string ( ) ;
55- RunResult {
56- info_messages : vec ! [ format!(
57- "Team: {}\n Github Team: {}\n Team YML: {}\n Description:\n - Owner inferred from codeowners file" ,
58- team. name, team. github_team, relative_team_path
59- ) ] ,
60- ..Default :: default ( )
61- }
62- }
63- Ok ( None ) => RunResult :: default ( ) ,
64- Err ( err) => RunResult {
65- io_errors : vec ! [ err. to_string( ) ] ,
66- ..Default :: default ( )
67- } ,
68- }
69- }
70- pub fn team_for_file_from_codeowners ( run_config : & RunConfig , file_path : & str ) -> Result < Option < Team > , Error > {
71- let config = config_from_path ( & run_config. config_path ) ?;
72- let relative_file_path = Path :: new ( file_path)
73- . strip_prefix ( & run_config. project_root )
74- . unwrap_or ( Path :: new ( file_path) ) ;
75-
76- let parser = crate :: ownership:: parser:: Parser {
77- project_root : run_config. project_root . clone ( ) ,
78- codeowners_file_path : run_config. codeowners_file_path . clone ( ) ,
79- team_file_globs : config. team_file_glob . clone ( ) ,
80- } ;
81- Ok ( parser
82- . team_from_file_path ( Path :: new ( relative_file_path) )
83- . map_err ( |e| Error :: Io ( e. to_string ( ) ) ) ?)
84- }
85-
86- pub fn team_for_file ( run_config : & RunConfig , file_path : & str ) -> Result < Option < Team > , Error > {
46+ pub fn file_owners_for_file ( run_config : & RunConfig , file_path : & str ) -> Result < Vec < FileOwner > , Error > {
8747 let config = config_from_path ( & run_config. config_path ) ?;
8848 use crate :: ownership:: for_file_fast:: find_file_owners;
8949 let owners = find_file_owners ( & run_config. project_root , & config, std:: path:: Path :: new ( file_path) ) . map_err ( Error :: Io ) ?;
9050
91- Ok ( owners. first ( ) . map ( |fo| fo . team . clone ( ) ) )
51+ Ok ( owners)
9252}
9353
94- // (imports below intentionally trimmed after refactor)
95-
96- fn for_file_optimized ( run_config : & RunConfig , file_path : & str ) -> RunResult {
97- let config = match config_from_path ( & run_config. config_path ) {
98- Ok ( c) => c,
99- Err ( err) => {
100- return RunResult {
101- io_errors : vec ! [ err. to_string( ) ] ,
102- ..Default :: default ( )
103- } ;
104- }
105- } ;
106-
107- use crate :: ownership:: for_file_fast:: find_file_owners;
108- let file_owners = match find_file_owners ( & run_config. project_root , & config, std:: path:: Path :: new ( file_path) ) {
109- Ok ( v) => v,
110- Err ( err) => {
111- return RunResult {
112- io_errors : vec ! [ err] ,
113- ..Default :: default ( )
114- } ;
115- }
116- } ;
117-
118- let info_messages: Vec < String > = match file_owners. len ( ) {
119- 0 => vec ! [ format!( "{}" , FileOwner :: default ( ) ) ] ,
120- 1 => vec ! [ format!( "{}" , file_owners[ 0 ] ) ] ,
121- _ => {
122- let mut error_messages = vec ! [ "Error: file is owned by multiple teams!" . to_string( ) ] ;
123- for file_owner in file_owners {
124- error_messages. push ( format ! ( "\n {}" , file_owner) ) ;
125- }
126- return RunResult {
127- validation_errors : error_messages,
128- ..Default :: default ( )
129- } ;
130- }
131- } ;
132- RunResult {
133- info_messages,
134- ..Default :: default ( )
135- }
54+ pub fn team_for_file ( run_config : & RunConfig , file_path : & str ) -> Result < Option < Team > , Error > {
55+ let owners = file_owners_for_file ( run_config, file_path) ?;
56+ Ok ( owners. first ( ) . map ( |fo| fo. team . clone ( ) ) )
13657}
13758
13859pub fn version ( ) -> String {
@@ -336,12 +257,144 @@ impl Runner {
336257 }
337258}
338259
260+ fn for_file_codeowners_only ( run_config : & RunConfig , file_path : & str ) -> RunResult {
261+ match team_for_file_from_codeowners ( run_config, file_path) {
262+ Ok ( Some ( team) ) => {
263+ let relative_team_path = team
264+ . path
265+ . strip_prefix ( & run_config. project_root )
266+ . unwrap_or ( team. path . as_path ( ) )
267+ . to_string_lossy ( )
268+ . to_string ( ) ;
269+ RunResult {
270+ info_messages : vec ! [ format!(
271+ "Team: {}\n Github Team: {}\n Team YML: {}\n Description:\n - Owner inferred from codeowners file" ,
272+ team. name, team. github_team, relative_team_path
273+ ) ] ,
274+ ..Default :: default ( )
275+ }
276+ }
277+ Ok ( None ) => RunResult :: default ( ) ,
278+ Err ( err) => RunResult {
279+ io_errors : vec ! [ err. to_string( ) ] ,
280+ ..Default :: default ( )
281+ } ,
282+ }
283+ }
284+ pub fn team_for_file_from_codeowners ( run_config : & RunConfig , file_path : & str ) -> Result < Option < Team > , Error > {
285+ let config = config_from_path ( & run_config. config_path ) ?;
286+ let relative_file_path = Path :: new ( file_path)
287+ . strip_prefix ( & run_config. project_root )
288+ . unwrap_or ( Path :: new ( file_path) ) ;
289+
290+ let parser = crate :: ownership:: parser:: Parser {
291+ project_root : run_config. project_root . clone ( ) ,
292+ codeowners_file_path : run_config. codeowners_file_path . clone ( ) ,
293+ team_file_globs : config. team_file_glob . clone ( ) ,
294+ } ;
295+ Ok ( parser
296+ . team_from_file_path ( Path :: new ( relative_file_path) )
297+ . map_err ( |e| Error :: Io ( e. to_string ( ) ) ) ?)
298+ }
299+
300+ fn for_file_optimized ( run_config : & RunConfig , file_path : & str ) -> RunResult {
301+ let config = match config_from_path ( & run_config. config_path ) {
302+ Ok ( c) => c,
303+ Err ( err) => {
304+ return RunResult {
305+ io_errors : vec ! [ err. to_string( ) ] ,
306+ ..Default :: default ( )
307+ } ;
308+ }
309+ } ;
310+
311+ use crate :: ownership:: for_file_fast:: find_file_owners;
312+ let file_owners = match find_file_owners ( & run_config. project_root , & config, std:: path:: Path :: new ( file_path) ) {
313+ Ok ( v) => v,
314+ Err ( err) => {
315+ return RunResult {
316+ io_errors : vec ! [ err] ,
317+ ..Default :: default ( )
318+ } ;
319+ }
320+ } ;
321+
322+ let info_messages: Vec < String > = match file_owners. len ( ) {
323+ 0 => vec ! [ format!( "{}" , FileOwner :: default ( ) ) ] ,
324+ 1 => vec ! [ format!( "{}" , file_owners[ 0 ] ) ] ,
325+ _ => {
326+ let mut error_messages = vec ! [ "Error: file is owned by multiple teams!" . to_string( ) ] ;
327+ for file_owner in file_owners {
328+ error_messages. push ( format ! ( "\n {}" , file_owner) ) ;
329+ }
330+ return RunResult {
331+ validation_errors : error_messages,
332+ ..Default :: default ( )
333+ } ;
334+ }
335+ } ;
336+ RunResult {
337+ info_messages,
338+ ..Default :: default ( )
339+ }
340+ }
341+
339342#[ cfg( test) ]
340343mod tests {
344+ use tempfile:: tempdir;
345+
346+ use crate :: { common_test, ownership:: mapper:: Source } ;
347+
341348 use super :: * ;
342349
343350 #[ test]
344351 fn test_version ( ) {
345352 assert_eq ! ( version( ) , env!( "CARGO_PKG_VERSION" ) . to_string( ) ) ;
346353 }
354+ fn write_file ( temp_dir : & Path , file_path : & str , content : & str ) {
355+ let file_path = temp_dir. join ( file_path) ;
356+ let _ = std:: fs:: create_dir_all ( file_path. parent ( ) . unwrap ( ) ) ;
357+ std:: fs:: write ( file_path, content) . unwrap ( ) ;
358+ }
359+
360+ #[ test]
361+ fn test_file_owners_for_file ( ) {
362+ let temp_dir = tempdir ( ) . unwrap ( ) ;
363+ write_file (
364+ temp_dir. path ( ) ,
365+ "config/code_ownership.yml" ,
366+ common_test:: tests:: DEFAULT_CODE_OWNERSHIP_YML ,
367+ ) ;
368+ [ "a" , "b" , "c" ] . iter ( ) . for_each ( |name| {
369+ let team_yml = format ! ( "name: {}\n github:\n team: \" @{}\" \n members:\n - {}member\n " , name, name, name) ;
370+ write_file ( temp_dir. path ( ) , & format ! ( "config/teams/{}.yml" , name) , & team_yml) ;
371+ } ) ;
372+ write_file (
373+ temp_dir. path ( ) ,
374+ "app/consumers/deep/nesting/nestdir/deep_file.rb" ,
375+ "# @team b\n class DeepFile end;" ,
376+ ) ;
377+
378+ let run_config = RunConfig {
379+ project_root : temp_dir. path ( ) . to_path_buf ( ) ,
380+ codeowners_file_path : temp_dir. path ( ) . join ( ".github/CODEOWNERS" ) . to_path_buf ( ) ,
381+ config_path : temp_dir. path ( ) . join ( "config/code_ownership.yml" ) . to_path_buf ( ) ,
382+ no_cache : false ,
383+ } ;
384+
385+ let file_owners = file_owners_for_file ( & run_config, "app/consumers/deep/nesting/nestdir/deep_file.rb" ) . unwrap ( ) ;
386+ assert_eq ! ( file_owners. len( ) , 1 ) ;
387+ assert_eq ! ( file_owners[ 0 ] . team. name, "b" ) ;
388+ assert_eq ! ( file_owners[ 0 ] . team. github_team, "@b" ) ;
389+ assert ! ( file_owners[ 0 ] . team. path. to_string_lossy( ) . ends_with( "config/teams/b.yml" ) ) ;
390+ assert_eq ! ( file_owners[ 0 ] . sources. len( ) , 1 ) ;
391+ assert_eq ! ( file_owners[ 0 ] . sources, vec![ Source :: AnnotatedFile ] ) ;
392+
393+ let team = team_for_file ( & run_config, "app/consumers/deep/nesting/nestdir/deep_file.rb" )
394+ . unwrap ( )
395+ . unwrap ( ) ;
396+ assert_eq ! ( team. name, "b" ) ;
397+ assert_eq ! ( team. github_team, "@b" ) ;
398+ assert ! ( team. path. to_string_lossy( ) . ends_with( "config/teams/b.yml" ) ) ;
399+ }
347400}
0 commit comments