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', None )
            # 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', None )
            if env_var_name and env_var_action:
                # 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 env_var_dict:
                        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 = repository_util.get_repository_for_dependency_relationship( self.app, tool_shed_url,
                                                                                       required_repository_name,
                                                                                       required_repository_owner,
                                                                                       default_required_repository_changeset_revision )
     tool_shed = common_util.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( 'Missing required tool dependency directory %s' % 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 = repository_util.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 = metadata_util.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 = 'Version %s of the %s package cannot be installed because ' % ( str( package_version ), str( package_name ) )
                 error_message += 'the recipe for installing the package is missing either an &lt;actions&gt; tag set or an &lt;actions_group&gt; '
                 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