diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index b145363460..bc667db4b4 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -222,6 +222,20 @@ namespace O3DE::ProjectManager m_gemModel->AddGem(gemInfo); } + AZ::Outcome, AZStd::string> allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); + if (allRepoGemInfosResult.IsSuccess()) + { + const QVector allRepoGemInfos = allRepoGemInfosResult.GetValue(); + for (const GemInfo& gemInfo : allRepoGemInfos) + { + m_gemModel->AddGem(gemInfo); + } + } + else + { + QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve gems from repos.

Error:
%1").arg(allRepoGemInfosResult.GetError().c_str())); + } + m_gemModel->UpdateGemDependencies(); m_notificationsEnabled = false; @@ -248,14 +262,14 @@ namespace O3DE::ProjectManager } else { - QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve enabled gems for project %1.\n\nError:\n%2").arg(projectPath, enabledGemNamesResult.GetError().c_str())); + QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve enabled gems for project %1.

Error:
%2").arg(projectPath, enabledGemNamesResult.GetError().c_str())); } m_notificationsEnabled = true; } else { - QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve gems for %1.\n\nError:\n%2").arg(projectPath, allGemInfosResult.GetError().c_str())); + QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve gems for %1.

Error:
%2").arg(projectPath, allGemInfosResult.GetError().c_str())); } } diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 6a67c60ddf..740393fec0 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -1201,4 +1201,31 @@ namespace O3DE::ProjectManager { m_requestCancelDownload = true; } + + AZ::Outcome, AZStd::string> PythonBindings::GetAllGemRepoGemsInfos() + { + QVector gemInfos; + AZ::Outcome result = ExecuteWithLockErrorHandling( + [&] + { + auto gemPaths = m_repo.attr("get_gem_json_paths_from_all_cached_repos")(); + + if (pybind11::isinstance(gemPaths)) + { + for (auto path : gemPaths) + { + GemInfo gemInfo = GemInfoFromPath(path, pybind11::none()); + gemInfo.m_downloadStatus = GemInfo::DownloadStatus::NotDownloaded; + gemInfos.push_back(gemInfo); + } + } + }); + + if (!result.IsSuccess()) + { + return AZ::Failure(result.GetError()); + } + + return AZ::Success(AZStd::move(gemInfos)); + } } diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 6d3642ba35..4375d56d02 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -66,6 +66,7 @@ namespace O3DE::ProjectManager AZ::Outcome, AZStd::string> GetAllGemRepoInfos() override; AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) override; void CancelDownload() override; + AZ::Outcome, AZStd::string> GetAllGemRepoGemsInfos() override; private: AZ_DISABLE_COPY_MOVE(PythonBindings); diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index 0013cf3acf..1134804f1f 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -221,6 +221,12 @@ namespace O3DE::ProjectManager * Cancels the current download. */ virtual void CancelDownload() = 0; + + /** + * Gathers all gem infos for all gems registered from repos. + * @return A list of gem infos. + */ + virtual AZ::Outcome, AZStd::string> GetAllGemRepoGemsInfos() = 0; }; using PythonBindingsInterface = AZ::Interface; diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index fc778591c4..297d8e39d2 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -502,7 +502,10 @@ def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None if gem_name and not gem_path: gem_path = get_registered(gem_name=gem_name, project_path=project_path) - return get_json_data('gem', gem_path, validation.valid_o3de_gem_json) + if pathlib.Path(gem_path).is_file(): + return get_json_data_file(gem_path, 'gem', validation.valid_o3de_gem_json) + else: + return get_json_data('gem', gem_path, validation.valid_o3de_gem_json) def get_template_json_data(template_name: str = None, template_path: str or pathlib.Path = None, diff --git a/scripts/o3de/o3de/repo.py b/scripts/o3de/o3de/repo.py index 0629277a42..9c26658a30 100644 --- a/scripts/o3de/o3de/repo.py +++ b/scripts/o3de/o3de/repo.py @@ -104,13 +104,13 @@ def process_add_o3de_repo(file_name: str or pathlib.Path, return 0 -def get_gem_json_paths_from_cached_repo(repo_uri: str) -> list: +def get_gem_json_paths_from_cached_repo(repo_uri: str) -> set: url = f'{repo_uri}/repo.json' repo_sha256 = hashlib.sha256(url.encode()) cache_folder = manifest.get_o3de_cache_folder() cache_filename = cache_folder / str(repo_sha256.hexdigest() + '.json') - gem_list = [] + gem_set = set() file_name = pathlib.Path(cache_filename).resolve() if not file_name.is_file(): @@ -137,10 +137,21 @@ def get_gem_json_paths_from_cached_repo(repo_uri: str) -> list: manifest_json_sha256 = hashlib.sha256(manifest_json_uri.encode()) cache_gem_json_filepath = cache_folder / str(manifest_json_sha256.hexdigest() + '.json') if cache_gem_json_filepath.is_file(): - logger.warn(f'Could not find cached gem json file for {o3de_object_uri} in repo {repo_uri}') - gem_list.append(cache_gem_json_filepath) + gem_set.add(cache_gem_json_filepath) + else: + logger.warn(f'Could not find cached gem json file {cache_gem_json_filepath} for {o3de_object_uri} in repo {repo_uri}') - return gem_list + return gem_set + +def get_gem_json_paths_from_all_cached_repos() -> set: + json_data = manifest.load_o3de_manifest() + gem_set = set() + + for repo_uri in json_data['repos']: + gem_set.update(get_gem_json_paths_from_cached_repo(repo_uri)) + + return gem_set + def refresh_repo(repo_uri: str, cache_folder: str = None,