@@ -309,7 +309,19 @@ fn ruby_package_owner(path: &Path) -> Result<Option<String>, Error> {
309309 let file = File :: open ( path) . change_context ( Error :: Io ) ?;
310310 let deserializer: deserializers:: RubyPackage = serde_yaml:: from_reader ( file) . change_context ( Error :: SerdeYaml ) ?;
311311
312- Ok ( deserializer. owner )
312+ let top_level_owner = deserializer. owner ;
313+ let metadata_owner = deserializer. metadata . and_then ( |metadata| metadata. owner ) ;
314+
315+ // Error if both are present to avoid ambiguity
316+ match ( top_level_owner. as_ref ( ) , metadata_owner. as_ref ( ) ) {
317+ ( Some ( _) , Some ( _) ) => {
318+ Err ( error_stack:: report!( Error :: Io ) . attach_printable ( format ! (
319+ "Package at {} has both 'owner' and 'metadata.owner' defined. Please use only one." ,
320+ path. display( )
321+ ) ) )
322+ }
323+ _ => Ok ( top_level_owner. or ( metadata_owner) ) ,
324+ }
313325}
314326
315327fn javascript_package_owner ( path : & Path ) -> Result < Option < String > , Error > {
@@ -334,4 +346,44 @@ mod tests {
334346 fn test_glob_match ( ) {
335347 assert ! ( glob_match( OWNED_GLOB , "script/.eslintrc.js" ) ) ;
336348 }
349+
350+ #[ test]
351+ fn test_ruby_package_owner_top_level ( ) {
352+ let yaml = "owner: TeamA\n " ;
353+ let temp_file = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
354+ std:: fs:: write ( temp_file. path ( ) , yaml) . unwrap ( ) ;
355+
356+ let owner = ruby_package_owner ( temp_file. path ( ) ) . unwrap ( ) ;
357+ assert_eq ! ( owner, Some ( "TeamA" . to_string( ) ) ) ;
358+ }
359+
360+ #[ test]
361+ fn test_ruby_package_owner_metadata ( ) {
362+ let yaml = "metadata:\n owner: TeamB\n " ;
363+ let temp_file = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
364+ std:: fs:: write ( temp_file. path ( ) , yaml) . unwrap ( ) ;
365+
366+ let owner = ruby_package_owner ( temp_file. path ( ) ) . unwrap ( ) ;
367+ assert_eq ! ( owner, Some ( "TeamB" . to_string( ) ) ) ;
368+ }
369+
370+ #[ test]
371+ fn test_ruby_package_owner_errors_when_both_present ( ) {
372+ let yaml = "owner: TeamA\n metadata:\n owner: TeamB\n " ;
373+ let temp_file = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
374+ std:: fs:: write ( temp_file. path ( ) , yaml) . unwrap ( ) ;
375+
376+ let result = ruby_package_owner ( temp_file. path ( ) ) ;
377+ assert ! ( result. is_err( ) ) ;
378+ }
379+
380+ #[ test]
381+ fn test_ruby_package_owner_no_owner ( ) {
382+ let yaml = "name: my_package\n " ;
383+ let temp_file = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
384+ std:: fs:: write ( temp_file. path ( ) , yaml) . unwrap ( ) ;
385+
386+ let owner = ruby_package_owner ( temp_file. path ( ) ) . unwrap ( ) ;
387+ assert_eq ! ( owner, None ) ;
388+ }
337389}
0 commit comments