@@ -115,6 +115,7 @@ def _write_json_file(path: str, updated_content: Dict):
115115 json .dump (updated_content , f , indent = 2 )
116116 f .write ("\n " )
117117
118+
118119def _add_new_library_source_roots (library_config : Dict , library_id : str ) -> None :
119120 """Adds the default source_roots to the library configuration if not present.
120121
@@ -320,13 +321,22 @@ def _copy_files_needed_for_post_processing(output: str, input: str, library_id:
320321 """
321322
322323 path_to_library = f"packages/{ library_id } "
324+ repo_metadata_path = f"{ input } /{ path_to_library } /.repo-metadata.json"
323325
324326 # We need to create these directories so that we can copy files necessary for post-processing.
325- os .makedirs (f"{ output } /{ path_to_library } /scripts/client-post-processing" , exist_ok = True )
326- shutil .copy (
327- f"{ input } /{ path_to_library } /.repo-metadata.json" ,
328- f"{ output } /{ path_to_library } /.repo-metadata.json" ,
327+ os .makedirs (
328+ f"{ output } /{ path_to_library } /scripts/client-post-processing" , exist_ok = True
329329 )
330+ # TODO(https://github.com/googleapis/librarian/issues/2334):
331+ # if `.repo-metadata.json` for a library exists in
332+ # `.librarian/generator-input`, then we override the generated `.repo-metadata.json`
333+ # with what we have in `generator-input`. Remove this logic once the
334+ # generated `.repo-metadata.json` file is completely backfilled.
335+ if os .path .exists (repo_metadata_path ):
336+ shutil .copy (
337+ repo_metadata_path ,
338+ f"{ output } /{ path_to_library } /.repo-metadata.json" ,
339+ )
330340
331341 # copy post-procesing files
332342 for post_processing_file in glob .glob (
@@ -373,6 +383,78 @@ def _clean_up_files_after_post_processing(output: str, library_id: str):
373383 os .remove (gapic_version_file )
374384
375385
386+ def _create_repo_metadata_from_service_config (
387+ service_config_name : str , api_path : str , source : str , library_id : str
388+ ) -> Dict :
389+ """Creates the .repo-metadata.json content from the service config.
390+
391+ Args:
392+ service_config_name (str): The name of the service config file.
393+ api_path (str): The path to the API.
394+ source (str): The path to the source directory.
395+ library_id (str): The ID of the library.
396+
397+ Returns:
398+ Dict: The content of the .repo-metadata.json file.
399+ """
400+ full_service_config_path = f"{ source } /{ api_path } /{ service_config_name } "
401+
402+ # TODO(https://github.com/googleapis/librarian/issues/2332): Read the api
403+ # service config to backfill `.repo-metadata.json`.
404+ return {
405+ "api_shortname" : "" ,
406+ "name_pretty" : "" ,
407+ "product_documentation" : "" ,
408+ "api_description" : "" ,
409+ "client_documentation" : "" ,
410+ "issue_tracker" : "" ,
411+ "release_level" : "" ,
412+ "language" : "python" ,
413+ "library_type" : "GAPIC_AUTO" ,
414+ "repo" : "googleapis/google-cloud-python" ,
415+ "distribution_name" : "" ,
416+ "api_id" : "" ,
417+ }
418+
419+
420+ def _generate_repo_metadata_file (
421+ output : str , library_id : str , source : str , apis : List [Dict ]
422+ ):
423+ """Generates the .repo-metadata.json file from the primary API service config.
424+
425+ Args:
426+ output (str): The path to the output directory.
427+ library_id (str): The ID of the library.
428+ source (str): The path to the source directory.
429+ apis (List[Dict]): A list of APIs to generate.
430+ """
431+ path_to_library = f"packages/{ library_id } "
432+ output_repo_metadata = f"{ output } /{ path_to_library } /.repo-metadata.json"
433+
434+ # TODO(https://github.com/googleapis/librarian/issues/2334)): If `.repo-metadata.json`
435+ # already exists in the `output` dir, then this means that it has been successfully copied
436+ # over from the `input` dir and we can skip the logic here. Remove the following logic
437+ # once we clean up all the `.repo-metadata.json` files from `.librarian/generator-input`.
438+ if os .path .exists (output_repo_metadata ):
439+ return
440+
441+ os .makedirs (f"{ output } /{ path_to_library } " , exist_ok = True )
442+
443+ # TODO(https://github.com/googleapis/librarian/issues/2333): Programatically
444+ # determine the primary api to be used to
445+ # to determine the information for metadata. For now, let's use the first
446+ # api in the list.
447+ primary_api = apis [0 ]
448+
449+ metadata_content = _create_repo_metadata_from_service_config (
450+ primary_api .get ("service_config" ),
451+ primary_api .get ("path" ),
452+ source ,
453+ library_id ,
454+ )
455+ _write_json_file (output_repo_metadata , metadata_content )
456+
457+
376458def handle_generate (
377459 librarian : str = LIBRARIAN_DIR ,
378460 source : str = SOURCE_DIR ,
@@ -411,6 +493,7 @@ def handle_generate(
411493 if api_path :
412494 _generate_api (api_path , library_id , source , output )
413495 _copy_files_needed_for_post_processing (output , input , library_id )
496+ _generate_repo_metadata_file (output , library_id , source , apis_to_generate )
414497 _run_post_processor (output , library_id )
415498 _clean_up_files_after_post_processing (output , library_id )
416499 except Exception as e :
@@ -961,7 +1044,9 @@ def _process_changelog(
9611044 entry_parts .append (f"\n \n ### { change_type_map [adjusted_change_type ]} \n " )
9621045 for change in library_changes :
9631046 commit_link = f"([{ change [source_commit_hash_key ]} ]({ _REPO_URL } /commit/{ change [source_commit_hash_key ]} ))"
964- entry_parts .append (f"* { change [subject_key ]} { change [body_key ]} { commit_link } " )
1047+ entry_parts .append (
1048+ f"* { change [subject_key ]} { change [body_key ]} { commit_link } "
1049+ )
9651050
9661051 new_entry_text = "\n " .join (entry_parts )
9671052 anchor_pattern = re .compile (
0 commit comments