From 3f21193bc4f316affdaf68d6cb15a468c473c7d9 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Mon, 5 Aug 2024 11:06:14 -0400 Subject: [PATCH 1/2] Improve tool shed API error messages for repo path bug. --- lib/galaxy/exceptions/__init__.py | 5 +++++ lib/galaxy/exceptions/error_codes.json | 5 +++++ lib/tool_shed/managers/tools.py | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/lib/galaxy/exceptions/__init__.py b/lib/galaxy/exceptions/__init__.py index 8deab77bc17b..82f66efdbe7d 100644 --- a/lib/galaxy/exceptions/__init__.py +++ b/lib/galaxy/exceptions/__init__.py @@ -250,6 +250,11 @@ class InconsistentDatabase(MessageException): err_code = error_codes_by_name["INCONSISTENT_DATABASE"] +class InconsistentApplicationState(MessageException): + status_code = 500 + err_code = error_codes_by_name["INCONSISTENT_APPLICATION_STATE"] + + class InternalServerError(MessageException): status_code = 500 err_code = error_codes_by_name["INTERNAL_SERVER_ERROR"] diff --git a/lib/galaxy/exceptions/error_codes.json b/lib/galaxy/exceptions/error_codes.json index 99464306acb6..e148b102b786 100644 --- a/lib/galaxy/exceptions/error_codes.json +++ b/lib/galaxy/exceptions/error_codes.json @@ -189,6 +189,11 @@ "code": 500006, "message": "Reference data required for program execution failed to load." }, + { + "name": "INCONSISTENT_APPLICATION_STATE", + "code": 500007, + "message": "Inconsistent application state (likely not dbms related) prevented fulfilling the request." + }, { "name": "NOT_IMPLEMENTED", "code": 501001, diff --git a/lib/tool_shed/managers/tools.py b/lib/tool_shed/managers/tools.py index b9dc6209e1b3..6a6872b77ec4 100644 --- a/lib/tool_shed/managers/tools.py +++ b/lib/tool_shed/managers/tools.py @@ -10,6 +10,7 @@ from galaxy import exceptions from galaxy.exceptions import ( + InconsistentApplicationState, InternalServerError, ObjectNotFound, RequestParameterInvalidException, @@ -149,8 +150,16 @@ def _shed_tool_source_for( if error_message: raise InternalServerError("Failed to materialize target repository revision") repo_files_dir = repository_metadata.repository.repo_path(trans.app) + if not repo_files_dir: + raise InconsistentApplicationState( + f"Failed to resolve repository path from hgweb_config_manager for [{trs_tool_id}], inconsistent repository state or application configuration" + ) repo_rel_tool_path = relpath(tool_config, repo_files_dir) path_to_tool = os.path.join(work_dir, repo_rel_tool_path) + if not os.path.exists(path_to_tool): + raise InconsistentApplicationState( + f"Target tool expected at [{path_to_tool}] and not found, inconsistent repository state or application configuration" + ) tool_source = get_tool_source(path_to_tool) return tool_source finally: From efe76b53e0aa363f790c4a05c46c51835ec2dfab Mon Sep 17 00:00:00 2001 From: John Chilton Date: Mon, 5 Aug 2024 11:15:22 -0400 Subject: [PATCH 2/2] Skip buggy hgweb_config_manager to find tool sources. --- lib/tool_shed/managers/tools.py | 2 +- lib/tool_shed/util/repository_util.py | 7 +------ lib/tool_shed/webapp/model/__init__.py | 13 +++++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/tool_shed/managers/tools.py b/lib/tool_shed/managers/tools.py index 6a6872b77ec4..0768758fc9bb 100644 --- a/lib/tool_shed/managers/tools.py +++ b/lib/tool_shed/managers/tools.py @@ -149,7 +149,7 @@ def _shed_tool_source_for( cloned_ok, error_message = clone_repository(repository_clone_url, work_dir, str(ctx.rev())) if error_message: raise InternalServerError("Failed to materialize target repository revision") - repo_files_dir = repository_metadata.repository.repo_path(trans.app) + repo_files_dir = repository_metadata.repository.hg_repository_path(trans.app.config.file_path) if not repo_files_dir: raise InconsistentApplicationState( f"Failed to resolve repository path from hgweb_config_manager for [{trs_tool_id}], inconsistent repository state or application configuration" diff --git a/lib/tool_shed/util/repository_util.py b/lib/tool_shed/util/repository_util.py index 9c9545c2e7f1..32829078f661 100644 --- a/lib/tool_shed/util/repository_util.py +++ b/lib/tool_shed/util/repository_util.py @@ -231,12 +231,7 @@ def create_repository( session = sa_session() with transaction(session): session.commit() - dir = os.path.join(app.config.file_path, *util.directory_hash_id(repository.id)) - # Define repo name inside hashed directory. - final_repository_path = os.path.join(dir, "repo_%d" % repository.id) - # Create final repository directory. - if not os.path.exists(final_repository_path): - os.makedirs(final_repository_path) + final_repository_path = repository.ensure_hg_repository_path(app.config.file_path) os.rename(repository_path, final_repository_path) app.hgweb_config_manager.add_entry(lhs, final_repository_path) # Update the repository registry. diff --git a/lib/tool_shed/webapp/model/__init__.py b/lib/tool_shed/webapp/model/__init__.py index a31ab4861f4a..6edd97d4511a 100644 --- a/lib/tool_shed/webapp/model/__init__.py +++ b/lib/tool_shed/webapp/model/__init__.py @@ -524,6 +524,19 @@ def repo_path(self, app=None): os.path.join(hgweb_config_manager.hgweb_repo_prefix, self.user.username, self.name) ) + def hg_repository_path(self, repositories_directory: str) -> str: + if self.id is None: + raise Exception("Attempting to call hg_repository_path before id has been set on repository object") + dir = os.path.join(repositories_directory, *util.directory_hash_id(self.id)) + final_repository_path = os.path.join(dir, "repo_%d" % self.id) + return final_repository_path + + def ensure_hg_repository_path(self, repositories_directory: str) -> str: + final_repository_path = self.hg_repository_path(repositories_directory) + if not os.path.exists(final_repository_path): + os.makedirs(final_repository_path) + return final_repository_path + def revision(self): repo = self.hg_repo tip_ctx = repo[repo.changelog.tip()]