diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index ceaec55474..e46b819a7c 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -108,75 +108,79 @@ def get_o3de_third_party_folder() -> pathlib.Path: # o3de manifest file methods +def get_default_o3de_manifest_json_data() -> dict: + """ + Returns dict with default values suitable for storing + in the o3de_manifests.json + """ + username = os.path.split(get_home_folder())[-1] + + o3de_folder = get_o3de_folder() + default_engines_folder = get_o3de_engines_folder() + default_projects_folder = get_o3de_projects_folder() + default_gems_folder = get_o3de_gems_folder() + default_templates_folder = get_o3de_templates_folder() + default_restricted_folder = get_o3de_restricted_folder() + default_third_party_folder = get_o3de_third_party_folder() + + default_projects_restricted_folder = default_projects_folder / 'Restricted' + default_projects_restricted_folder.mkdir(parents=True, exist_ok=True) + default_gems_restricted_folder = default_gems_folder / 'Restricted' + default_gems_restricted_folder.mkdir(parents=True, exist_ok=True) + default_templates_restricted_folder = default_templates_folder / 'Restricted' + default_templates_restricted_folder.mkdir(parents=True, exist_ok=True) + + json_data = {} + json_data.update({'o3de_manifest_name': f'{username}'}) + json_data.update({'origin': o3de_folder.as_posix()}) + json_data.update({'default_engines_folder': default_engines_folder.as_posix()}) + json_data.update({'default_projects_folder': default_projects_folder.as_posix()}) + json_data.update({'default_gems_folder': default_gems_folder.as_posix()}) + json_data.update({'default_templates_folder': default_templates_folder.as_posix()}) + json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()}) + json_data.update({'default_third_party_folder': default_third_party_folder.as_posix()}) + + json_data.update({'engines': []}) + json_data.update({'projects': []}) + json_data.update({'external_subdirectories': []}) + json_data.update({'templates': []}) + json_data.update({'restricted': []}) + json_data.update({'repos': []}) + + default_restricted_folder_json = default_restricted_folder / 'restricted.json' + if not default_restricted_folder_json.is_file(): + with default_restricted_folder_json.open('w') as s: + restricted_json_data = {} + restricted_json_data.update({'restricted_name': 'o3de'}) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') + + default_projects_restricted_folder_json = default_projects_restricted_folder / 'restricted.json' + if not default_projects_restricted_folder_json.is_file(): + with default_projects_restricted_folder_json.open('w') as s: + restricted_json_data = {} + restricted_json_data.update({'restricted_name': 'projects'}) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') + + default_gems_restricted_folder_json = default_gems_restricted_folder / 'restricted.json' + if not default_gems_restricted_folder_json.is_file(): + with default_gems_restricted_folder_json.open('w') as s: + restricted_json_data = {} + restricted_json_data.update({'restricted_name': 'gems'}) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') + + default_templates_restricted_folder_json = default_templates_restricted_folder / 'restricted.json' + if not default_templates_restricted_folder_json.is_file(): + with default_templates_restricted_folder_json.open('w') as s: + restricted_json_data = {} + restricted_json_data.update({'restricted_name': 'templates'}) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') + + return json_data + def get_o3de_manifest() -> pathlib.Path: manifest_path = get_o3de_folder() / 'o3de_manifest.json' if not manifest_path.is_file(): - username = os.path.split(get_home_folder())[-1] - - o3de_folder = get_o3de_folder() - default_registry_folder = get_o3de_registry_folder() - default_cache_folder = get_o3de_cache_folder() - default_downloads_folder = get_o3de_download_folder() - default_logs_folder = get_o3de_logs_folder() - default_engines_folder = get_o3de_engines_folder() - default_projects_folder = get_o3de_projects_folder() - default_gems_folder = get_o3de_gems_folder() - default_templates_folder = get_o3de_templates_folder() - default_restricted_folder = get_o3de_restricted_folder() - default_third_party_folder = get_o3de_third_party_folder() - - default_projects_restricted_folder = default_projects_folder / 'Restricted' - default_projects_restricted_folder.mkdir(parents=True, exist_ok=True) - default_gems_restricted_folder = default_gems_folder / 'Restricted' - default_gems_restricted_folder.mkdir(parents=True, exist_ok=True) - default_templates_restricted_folder = default_templates_folder / 'Restricted' - default_templates_restricted_folder.mkdir(parents=True, exist_ok=True) - - json_data = {} - json_data.update({'o3de_manifest_name': f'{username}'}) - json_data.update({'origin': o3de_folder.as_posix()}) - json_data.update({'default_engines_folder': default_engines_folder.as_posix()}) - json_data.update({'default_projects_folder': default_projects_folder.as_posix()}) - json_data.update({'default_gems_folder': default_gems_folder.as_posix()}) - json_data.update({'default_templates_folder': default_templates_folder.as_posix()}) - json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()}) - json_data.update({'default_third_party_folder': default_third_party_folder.as_posix()}) - - json_data.update({'engines': []}) - json_data.update({'projects': []}) - json_data.update({'external_subdirectories': []}) - json_data.update({'templates': []}) - json_data.update({'restricted': []}) - json_data.update({'repos': []}) - - default_restricted_folder_json = default_restricted_folder / 'restricted.json' - if not default_restricted_folder_json.is_file(): - with default_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'o3de'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()}) - - default_projects_restricted_folder_json = default_projects_restricted_folder / 'restricted.json' - if not default_projects_restricted_folder_json.is_file(): - with default_projects_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'projects'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - - default_gems_restricted_folder_json = default_gems_restricted_folder / 'restricted.json' - if not default_gems_restricted_folder_json.is_file(): - with default_gems_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'gems'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - - default_templates_restricted_folder_json = default_templates_restricted_folder / 'restricted.json' - if not default_templates_restricted_folder_json.is_file(): - with default_templates_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'templates'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') + json_data = get_default_o3de_manifest_json_data() with manifest_path.open('w') as s: s.write(json.dumps(json_data, indent=4) + '\n') @@ -188,6 +192,7 @@ def load_o3de_manifest(manifest_path: pathlib.Path = None) -> dict: """ Loads supplied manifest file or ~/.o3de/o3de_manifest.json if None + raises Json.JSONDecodeError if manifest data could not be decoded to JSON :param manifest_path: optional path to manifest file to load """ if not manifest_path: @@ -196,8 +201,10 @@ def load_o3de_manifest(manifest_path: pathlib.Path = None) -> dict: try: json_data = json.load(f) except json.JSONDecodeError as e: - logger.error(f'Manifest json failed to load: {str(e)}') - return {} + logger.error(f'Manifest json failed to load at path "{manifest_path}": {str(e)}') + # Re-raise the exception and let the caller + # determine if they can proceed + raise else: return json_data @@ -589,7 +596,7 @@ def get_registered(engine_name: str = None, if isinstance(engine, dict): engine_path = pathlib.Path(engine['path']).resolve() else: - engine_path = pathlib.Path(engine_object).resolve() + engine_path = pathlib.Path(engine).resolve() engine_json = engine_path / 'engine.json' with engine_json.open('r') as f: diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index de0934f2e5..2500df1568 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -560,6 +560,107 @@ def register_default_third_party_folder(json_data: dict, manifest.get_o3de_third_party_folder() if remove else default_third_party_folder, 'default_third_party_folder') + +def remove_invalid_o3de_projects(manifest_path: pathlib.Path = None) -> int: + if not manifest_path: + manifest_path = manifest.get_o3de_manifest() + + json_data = manifest.load_o3de_manifest(manifest_path) + + result = 0 + + for project in json_data.get('projects', []): + if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json'): + logger.warning(f"Project path {project} is invalid.") + # Attempt to unregister all invalid projects even if previous projects failed to unregister + # but combine the result codes of each command. + result = register(project_path=pathlib.Path(project), remove=True) or result + + return result + + +def remove_invalid_o3de_objects() -> None: + for engine_path in manifest.get_engines(): + if not validation.valid_o3de_engine_json(pathlib.Path(engine_path).resolve() / 'engine.json'): + logger.warning(f"Engine path {engine_path} is invalid.") + register(engine_path=engine_path, remove=True) + + remove_invalid_o3de_projects() + + for external in manifest.get_external_subdirectories(): + external = pathlib.Path(external).resolve() + if not external.is_dir(): + logger.warning(f"External subdirectory {external} is invalid.") + register(engine_path=engine_path, external_subdir_path=external, remove=True) + + for template in manifest.get_templates(): + if not validation.valid_o3de_template_json(pathlib.Path(template).resolve() / 'template.json'): + logger.warning(f"Template path {template} is invalid.") + register(template_path=template, remove=True) + + for restricted in manifest.get_restricted(): + if not validation.valid_o3de_restricted_json(pathlib.Path(restricted).resolve() / 'restricted.json'): + logger.warning(f"Restricted path {restricted} is invalid.") + register(restricted_path=restricted, remove=True) + + json_data = manifest.load_o3de_manifest() + default_engines_folder = pathlib.Path( + json_data.get('default_engines_folder', manifest.get_o3de_engines_folder())).resolve() + if not default_engines_folder.is_dir(): + new_default_engines_folder = manifest.get_o3de_folder() / 'Engines' + new_default_engines_folder.mkdir(parents=True, exist_ok=True) + logger.warning( + f"Default engines folder {default_engines_folder} is invalid. Set default {new_default_engines_folder}") + register(default_engines_folder=new_default_engines_folder.as_posix()) + + default_projects_folder = pathlib.Path( + json_data.get('default_projects_folder', manifest.get_o3de_projects_folder())).resolve() + if not default_projects_folder.is_dir(): + new_default_projects_folder = manifest.get_o3de_folder() / 'Projects' + new_default_projects_folder.mkdir(parents=True, exist_ok=True) + logger.warning( + f"Default projects folder {default_projects_folder} is invalid. Set default {new_default_projects_folder}") + register(default_projects_folder=new_default_projects_folder.as_posix()) + + default_gems_folder = pathlib.Path(json_data.get('default_gems_folder', manifest.get_o3de_gems_folder())).resolve() + if not default_gems_folder.is_dir(): + new_default_gems_folder = manifest.get_o3de_folder() / 'Gems' + new_default_gems_folder.mkdir(parents=True, exist_ok=True) + logger.warning(f"Default gems folder {default_gems_folder} is invalid." + f" Set default {new_default_gems_folder}") + register(default_gems_folder=new_default_gems_folder.as_posix()) + + default_templates_folder = pathlib.Path( + json_data.get('default_templates_folder', manifest.get_o3de_templates_folder())).resolve() + if not default_templates_folder.is_dir(): + new_default_templates_folder = manifest.get_o3de_folder() / 'Templates' + new_default_templates_folder.mkdir(parents=True, exist_ok=True) + logger.warning( + f"Default templates folder {default_templates_folder} is invalid." + f" Set default {new_default_templates_folder}") + register(default_templates_folder=new_default_templates_folder.as_posix()) + + default_restricted_folder = pathlib.Path( + json_data.get('default_restricted_folder', manifest.get_o3de_restricted_folder())).resolve() + if not default_restricted_folder.is_dir(): + default_restricted_folder = manifest.get_o3de_folder() / 'Restricted' + default_restricted_folder.mkdir(parents=True, exist_ok=True) + logger.warning( + f"Default restricted folder {default_restricted_folder} is invalid." + f" Set default {default_restricted_folder}") + register(default_restricted_folder=default_restricted_folder.as_posix()) + + default_third_party_folder = pathlib.Path( + json_data.get('default_third_party_folder', manifest.get_o3de_third_party_folder())).resolve() + if not default_third_party_folder.is_dir(): + default_third_party_folder = manifest.get_o3de_folder() / '3rdParty' + default_third_party_folder.mkdir(parents=True, exist_ok=True) + logger.warning( + f"Default 3rd Party folder {default_third_party_folder} is invalid." + f" Set default {default_third_party_folder}") + register(default_third_party_folder=default_third_party_folder.as_posix()) + + def register(engine_path: pathlib.Path = None, project_path: pathlib.Path = None, gem_path: pathlib.Path = None, @@ -604,7 +705,18 @@ def register(engine_path: pathlib.Path = None, :return: 0 for success or non 0 failure code """ - json_data = manifest.load_o3de_manifest() + try: + json_data = manifest.load_o3de_manifest() + except json.JSONDecodeError: + if not force: + logger.error('O3DE object registration has halted due to JSON Decode Error in manifest at path:' + f' "{manifest.get_o3de_manifest()}".' + '\n Registration can be forced using the --force option,' + ' but that will result in the manifest using default data') + return 1 + else: + # Use a default manifest data an proceed + json_data = manifest.get_default_o3de_manifest_json_data() result = 0 @@ -679,99 +791,6 @@ def register(engine_path: pathlib.Path = None, return result -def remove_invalid_o3de_projects(manifest_path: pathlib.Path = None) -> int: - if not manifest_path: - manifest_path = manifest.get_o3de_manifest() - - json_data = manifest.load_o3de_manifest(manifest_path) - - result = 0 - - for project in json_data.get('projects', []): - if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json'): - logger.warning(f"Project path {project} is invalid.") - # Attempt to unregister all invalid projects even if previous projects failed to unregister - # but combine the result codes of each command. - result = register(project_path=pathlib.Path(project), remove=True) or result - - return result - -def remove_invalid_o3de_objects() -> None: - for engine_path in manifest.get_engines(): - if not validation.valid_o3de_engine_json(pathlib.Path(engine_path).resolve() / 'engine.json'): - logger.warning(f"Engine path {engine_path} is invalid.") - register(engine_path=engine_path, remove=True) - - remove_invalid_o3de_projects() - - for external in manifest.get_external_subdirectories(): - external = pathlib.Path(external).resolve() - if not external.is_dir(): - logger.warning(f"External subdirectory {external} is invalid.") - register(engine_path=engine_path, external_subdir_path=external, remove=True) - - for template in manifest.get_templates(): - if not validation.valid_o3de_template_json(pathlib.Path(template).resolve() / 'template.json'): - logger.warning(f"Template path {template} is invalid.") - register(template_path=template, remove=True) - - for restricted in manifest.get_restricted(): - if not validation.valid_o3de_restricted_json(pathlib.Path(restricted).resolve() / 'restricted.json'): - logger.warning(f"Restricted path {restricted} is invalid.") - register(restricted_path=restricted, remove=True) - - json_data = manifest.load_o3de_manifest() - default_engines_folder = pathlib.Path(json_data.get('default_engines_folder', manifest.get_o3de_engines_folder())).resolve() - if not default_engines_folder.is_dir(): - new_default_engines_folder = manifest.get_o3de_folder() / 'Engines' - new_default_engines_folder.mkdir(parents=True, exist_ok=True) - logger.warning( - f"Default engines folder {default_engines_folder} is invalid. Set default {new_default_engines_folder}") - register(default_engines_folder=new_default_engines_folder.as_posix()) - - default_projects_folder = pathlib.Path(json_data.get('default_projects_folder', manifest.get_o3de_projects_folder())).resolve() - if not default_projects_folder.is_dir(): - new_default_projects_folder = manifest.get_o3de_folder() / 'Projects' - new_default_projects_folder.mkdir(parents=True, exist_ok=True) - logger.warning( - f"Default projects folder {default_projects_folder} is invalid. Set default {new_default_projects_folder}") - register(default_projects_folder=new_default_projects_folder.as_posix()) - - default_gems_folder = pathlib.Path(json_data.get('default_gems_folder', manifest.get_o3de_gems_folder())).resolve() - if not default_gems_folder.is_dir(): - new_default_gems_folder = manifest.get_o3de_folder() / 'Gems' - new_default_gems_folder.mkdir(parents=True, exist_ok=True) - logger.warning(f"Default gems folder {default_gems_folder} is invalid." - f" Set default {new_default_gems_folder}") - register(default_gems_folder=new_default_gems_folder.as_posix()) - - default_templates_folder = pathlib.Path(json_data.get('default_templates_folder', manifest.get_o3de_templates_folder())).resolve() - if not default_templates_folder.is_dir(): - new_default_templates_folder = manifest.get_o3de_folder() / 'Templates' - new_default_templates_folder.mkdir(parents=True, exist_ok=True) - logger.warning( - f"Default templates folder {default_templates_folder} is invalid." - f" Set default {new_default_templates_folder}") - register(default_templates_folder=new_default_templates_folder.as_posix()) - - default_restricted_folder = pathlib.Path(json_data.get('default_restricted_folder', manifest.get_o3de_restricted_folder())).resolve() - if not default_restricted_folder.is_dir(): - default_restricted_folder = manifest.get_o3de_folder() / 'Restricted' - default_restricted_folder.mkdir(parents=True, exist_ok=True) - logger.warning( - f"Default restricted folder {default_restricted_folder} is invalid." - f" Set default {default_restricted_folder}") - register(default_restricted_folder=default_restricted_folder.as_posix()) - - default_third_party_folder = pathlib.Path(json_data.get('default_third_party_folder', manifest.get_o3de_third_party_folder())).resolve() - if not default_third_party_folder.is_dir(): - default_third_party_folder = manifest.get_o3de_folder() / '3rdParty' - default_third_party_folder.mkdir(parents=True, exist_ok=True) - logger.warning( - f"Default 3rd Party folder {default_third_party_folder} is invalid." - f" Set default {default_third_party_folder}") - register(default_third_party_folder=default_third_party_folder.as_posix()) - def _run_register(args: argparse) -> int: if args.override_home_folder: