def get_required_repository_package_env_sh_path(self, package_name, package_version, required_repository): """Return path to env.sh file in required repository if the required repository has been installed.""" env_sh_file_dir = \ tool_dependency_util.get_tool_dependency_install_dir(app=self.app, repository_name=required_repository.name, repository_owner=required_repository.owner, repository_changeset_revision=required_repository.installed_changeset_revision, tool_dependency_type='package', tool_dependency_name=package_name, tool_dependency_version=package_version) env_sh_file_path = os.path.join(env_sh_file_dir, 'env.sh') return env_sh_file_path
def set_environment(self, elem, tool_shed_repository, attr_tups_of_dependencies_for_install): """ Create a ToolDependency to set an environment variable. This is different from the process used to set an environment variable that is associated with a package. An example entry in a tool_dependencies.xml file is:: <set_environment version="1.0"> <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable> </set_environment> This method must also handle the sub-element tag:: <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable> """ # TODO: Add support for a repository dependency definition within this tool dependency type's tag set. This should look something like # the following. See the implementation of support for this in the tool dependency package type's method above. # This function is only called for set environment actions as defined below, not within an <install version="1.0"> tool # dependency type. Here is an example of the tag set this function does handle: # <action type="set_environment"> # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR</environment_variable> # </action> # Here is an example of the tag set this function does not handle: # <set_environment version="1.0"> # <repository toolshed="<tool shed>" name="<repository name>" owner="<repository owner>" changeset_revision="<changeset revision>" /> # </set_environment> env_manager = EnvManager(self.app) tool_dependencies = [] env_var_version = elem.get('version', '1.0') tool_shed_repository_install_dir = os.path.abspath( tool_shed_repository.repo_files_directory(self.app)) if elem.tag == 'environment_variable': # <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable> elems = [elem] else: # <set_environment version="1.0"> # <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable> # </set_environment> elems = [env_var_elem for env_var_elem in elem] for env_var_elem in elems: env_var_name = env_var_elem.get('name') if not env_var_name: raise Exception( 'The <environment_variable> tag must have a name attribute' ) # The value of env_var_name must match the text value of at least 1 <requirement> tag in the # tool config's <requirements> tag set whose "type" attribute is "set_environment" (e.g., # <requirement type="set_environment">R_SCRIPT_PATH</requirement>). env_var_action = env_var_elem.get('action') if not env_var_action: raise Exception( 'The <environment_variable> tag must have an action attribute' ) # Tool dependencies of type "set_environment" always have the version attribute set to None. attr_tup = (env_var_name, None, 'set_environment') if attr_tup in attr_tups_of_dependencies_for_install: install_dir = \ tool_dependency_util.get_tool_dependency_install_dir(app=self.app, repository_name=tool_shed_repository.name, repository_owner=tool_shed_repository.owner, repository_changeset_revision=tool_shed_repository.installed_changeset_revision, tool_dependency_type='set_environment', tool_dependency_name=env_var_name, tool_dependency_version=None) install_environment = InstallEnvironment( app=self.app, tool_shed_repository_install_dir= tool_shed_repository_install_dir, install_dir=install_dir) env_var_dict = env_manager.create_env_var_dict( elem=env_var_elem, install_environment=install_environment) if not os.path.exists(install_dir): os.makedirs(install_dir) status = self.app.install_model.ToolDependency.installation_status.INSTALLING tool_dependency = \ tool_dependency_util.create_or_update_tool_dependency(app=self.app, tool_shed_repository=tool_shed_repository, name=env_var_name, version=None, type='set_environment', status=status, set_status=True) if env_var_version == '1.0': # Create this tool dependency's env.sh file. env_file_builder = EnvFileBuilder(install_dir) return_code = env_file_builder.append_line( make_executable=True, **env_var_dict) if return_code: error_message = 'Error creating env.sh file for tool dependency %s, return_code: %s' % \ (str(tool_dependency.name), str(return_code)) log.debug(error_message) status = self.app.install_model.ToolDependency.installation_status.ERROR tool_dependency = \ tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=status, error_message=error_message) else: if tool_dependency.status not in [ self.app.install_model.ToolDependency. installation_status.ERROR, self.app.install_model.ToolDependency. installation_status.INSTALLED ]: status = self.app.install_model.ToolDependency.installation_status.INSTALLED tool_dependency = \ tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=status) log.debug( 'Environment variable %s set in %s for tool dependency %s.' % (str(env_var_name), str(install_dir), str(tool_dependency.name))) else: error_message = 'Only set_environment version 1.0 is currently supported (i.e., change your tag to be <set_environment version="1.0">).' status = self.app.install_model.ToolDependency.installation_status.ERROR tool_dependency = \ tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=status, error_message=error_message) tool_dependencies.append(tool_dependency) return tool_dependencies
def handle_complex_repository_dependency_for_package( self, elem, package_name, package_version, tool_shed_repository, from_tool_migration_manager=False): """ Inspect the repository defined by a complex repository dependency definition and take certain steps to enable installation of the received package name and version to proceed. The received elem is the <repository> tag set which defines the complex repository dependency. The received tool_shed_repository is the installed tool shed repository for which the tool dependency defined by the received package_name and package_version is being installed. """ handled_tool_dependencies = [] tool_shed_url = elem.attrib['toolshed'] required_repository_name = elem.attrib['name'] required_repository_owner = elem.attrib['owner'] default_required_repository_changeset_revision = elem.attrib[ 'changeset_revision'] required_repository = get_repository_for_dependency_relationship( self.app, tool_shed_url, required_repository_name, required_repository_owner, default_required_repository_changeset_revision) tool_shed = remove_protocol_from_tool_shed_url(tool_shed_url) tmp_filename = None if required_repository: required_repository_changeset_revision = required_repository.installed_changeset_revision # Define the installation directory for the required tool dependency package in the required repository. required_repository_package_install_dir = \ tool_dependency_util.get_tool_dependency_install_dir(app=self.app, repository_name=required_repository_name, repository_owner=required_repository_owner, repository_changeset_revision=required_repository_changeset_revision, tool_dependency_type='package', tool_dependency_name=package_name, tool_dependency_version=package_version) # Define this dependent repository's tool dependency installation directory that will contain # the env.sh file with a path to the required repository's installed tool dependency package. dependent_install_dir = \ tool_dependency_util.get_tool_dependency_install_dir(app=self.app, repository_name=tool_shed_repository.name, repository_owner=tool_shed_repository.owner, repository_changeset_revision=tool_shed_repository.installed_changeset_revision, tool_dependency_type='package', tool_dependency_name=package_name, tool_dependency_version=package_version) if os.path.exists(dependent_install_dir): # The install manager handles tool migration stages and the sync_database_with_file_system() # method handles two scenarios: (1) where a Galaxy file system environment related to installed # Tool Shed repositories and tool dependencies has somehow gotten out of sync with the Galaxy # database tables associated with these installed items, and (2) the Tool Shed's install and test # framework which installs repositories in 2 stages, those of type tool_dependency_definition # followed by those containing valid tools and tool functional test components. Neither of these # scenarios apply when the install manager is running. if from_tool_migration_manager: can_install_tool_dependency = True else: # Notice that we'll throw away the following tool_dependency if it can be installed. tool_dependency, can_install_tool_dependency = self.sync_database_with_file_system( self.app, tool_shed_repository, package_name, package_version, dependent_install_dir, tool_dependency_type='package') if not can_install_tool_dependency: log.debug( "Tool dependency %s version %s cannot be installed (it was probably previously installed), " "so appending it to the list of handled tool dependencies.", str(tool_dependency.name), str(tool_dependency.version)) handled_tool_dependencies.append(tool_dependency) else: can_install_tool_dependency = True if can_install_tool_dependency: # Set this dependent repository's tool dependency env.sh file with a path to the required repository's # installed tool dependency package. We can get everything we need from the discovered installed # required_repository. if required_repository.is_deactivated_or_installed: if not os.path.exists( required_repository_package_install_dir): log.error( f'Missing required tool dependency directory {str(required_repository_package_install_dir)}' ) repo_files_dir = required_repository.repo_files_directory( self.app) if not repo_files_dir: message = "Unable to locate the repository directory for revision %s of installed repository %s owned by %s." % \ (str(required_repository.changeset_revision), str(required_repository.name), str(required_repository.owner)) raise Exception(message) tool_dependencies_config = get_absolute_path_to_file_in_repository( repo_files_dir, 'tool_dependencies.xml') if tool_dependencies_config: config_to_use = tool_dependencies_config else: message = "Unable to locate required tool_dependencies.xml file for revision %s of installed repository %s owned by %s." % \ (str(required_repository.changeset_revision), str(required_repository.name), str(required_repository.owner)) raise Exception(message) else: # Make a call to the tool shed to get the changeset revision to which the current value of required_repository_changeset_revision # should be updated if it's not current. text = get_updated_changeset_revisions_from_tool_shed( app=self.app, tool_shed_url=tool_shed, name=required_repository_name, owner=required_repository_owner, changeset_revision= required_repository_changeset_revision) if text: updated_changeset_revisions = listify(text) # The list of changeset revisions is in reverse order, so the newest will be first. required_repository_changeset_revision = updated_changeset_revisions[ 0] # Make a call to the tool shed to get the required repository's tool_dependencies.xml file. tmp_filename = self.create_temporary_tool_dependencies_config( tool_shed, required_repository_name, required_repository_owner, required_repository_changeset_revision) config_to_use = tmp_filename handled_tool_dependencies = \ self.create_tool_dependency_with_initialized_env_sh_file(dependent_install_dir=dependent_install_dir, tool_shed_repository=tool_shed_repository, required_repository=required_repository, package_name=package_name, package_version=package_version, tool_dependencies_config=config_to_use) self.remove_file(tmp_filename) else: message = "Unable to locate required tool shed repository named %s owned by %s with revision %s." % \ (str(required_repository_name), str(required_repository_owner), str(default_required_repository_changeset_revision)) raise Exception(message) return handled_tool_dependencies
def process_tag_set(self, tool_shed_repository, tool_dependency, package_elem, package_name, package_version, from_tool_migration_manager=False, tool_dependency_db_records=None): # <install version="1.0"> # Get the installation directory for tool dependencies that will be installed for the received tool_shed_repository. actions_elem_tuples = [] proceed_with_install = False install_dir = \ tool_dependency_util.get_tool_dependency_install_dir(app=self.app, repository_name=tool_shed_repository.name, repository_owner=tool_shed_repository.owner, repository_changeset_revision=tool_shed_repository.installed_changeset_revision, tool_dependency_type='package', tool_dependency_name=package_name, tool_dependency_version=package_version) if os.path.exists(install_dir): # The tool_migration_manager handles tool migration stages and the sync_database_with_file_system() # method handles two scenarios: (1) where a Galaxy file system environment related to installed # Tool Shed repositories and tool dependencies has somehow gotten out of sync with the Galaxy # database tables associated with these installed items, and (2) the Tool Shed's install and test # framework which installs repositories in 2 stages, those of type tool_dependency_definition # followed by those containing valid tools and tool functional test components. Neither of these # scenarios apply when the install manager is running. if from_tool_migration_manager: proceed_with_install = True else: # Notice that we'll throw away the following tool_dependency if it can be installed. tool_dependency, proceed_with_install = self.sync_database_with_file_system( self.app, tool_shed_repository, package_name, package_version, install_dir, tool_dependency_type='package') if not proceed_with_install: log.debug( "Tool dependency %s version %s cannot be installed (it was probably previously installed), so returning it." % (str(tool_dependency.name), str(tool_dependency.version))) return tool_dependency, proceed_with_install, actions_elem_tuples else: proceed_with_install = True if proceed_with_install: package_install_version = package_elem.get('version', '1.0') status = self.app.install_model.ToolDependency.installation_status.INSTALLING tool_dependency = \ tool_dependency_util.create_or_update_tool_dependency(app=self.app, tool_shed_repository=tool_shed_repository, name=package_name, version=package_version, type='package', status=status, set_status=True) # Get the information about the current platform in case the tool dependency definition includes tag sets # for installing compiled binaries. platform_info_dict = tool_dependency_util.get_platform_info_dict() if package_install_version == '1.0': # Handle tool dependency installation using a fabric method included in the Galaxy framework. actions_elem_tuples = tool_dependency_util.parse_package_elem( package_elem, platform_info_dict=platform_info_dict, include_after_install_actions=True) if not actions_elem_tuples: proceed_with_install = False error_message = f'Version {str(package_version)} of the {str(package_name)} package cannot be installed because ' error_message += 'the recipe for installing the package is missing either an <actions> tag set or an <actions_group> ' error_message += 'tag set.' # Since there was an installation error, update the tool dependency status to Error. # The remove_installation_path option must be left False here. tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app, tool_dependency=tool_dependency, status=self.app.install_model.ToolDependency. installation_status.ERROR, error_message=error_message) else: raise NotImplementedError( 'Only install version 1.0 is currently supported (i.e., change your tag to be <install version="1.0">).' ) return tool_dependency, proceed_with_install, actions_elem_tuples