1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/b56f6e027d2c/ Changeset: b56f6e027d2c User: greg Date: 2013-12-11 22:36:32 Summary: Allow a tool dependency to be uninstalled from Galaxy only if it is in an error state. Allow an installed repository to be uninstalled from Galaxy only if it has no dependent repositories and none of its contents are dependencies of other repository contents. Affected #: 13 files diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/galaxy/app.py --- a/lib/galaxy/app.py +++ b/lib/galaxy/app.py @@ -87,7 +87,8 @@ self.install_model = install_mapping.init( install_db_url, install_db_engine_options ) # Manage installed tool shed repositories. - self.installed_repository_manager = tool_shed.galaxy_install.InstalledRepositoryManager( self ) + from tool_shed.galaxy_install import installed_repository_manager + self.installed_repository_manager = installed_repository_manager.InstalledRepositoryManager( self ) # Create an empty datatypes registry. self.datatypes_registry = galaxy.datatypes.registry.Registry() # Load proprietary datatypes defined in datatypes_conf.xml files in all installed tool shed repositories. We diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/galaxy/model/tool_shed_install/__init__.py --- a/lib/galaxy/model/tool_shed_install/__init__.py +++ b/lib/galaxy/model/tool_shed_install/__init__.py @@ -1,10 +1,7 @@ import os - from galaxy.model.item_attrs import Dictifiable - from galaxy.util.bunch import Bunch from galaxy.util import asbool - from tool_shed.util import common_util @@ -61,9 +58,38 @@ def can_reset_metadata( self ): return self.status == self.installation_status.INSTALLED - @property - def can_uninstall( self ): - return self.status != self.installation_status.UNINSTALLED + def can_uninstall( self, app ): + # An installed repository cannot be uninstalled if other installed repositories or installed repository + # contents (i.e., tool dependencies) require it. + if self.status == self.installation_status.UNINSTALLED: + return False + irm = app.installed_repository_manager + # Find other installed repositories that require this repository. + for repository in irm.repository_dependencies_of_installed_repositories: + if repository.id == self.id: + installed_repository_dependencies = \ + irm.installed_repository_dependencies_of_installed_repositories[ repository ] + if installed_repository_dependencies: + # This repository cannot be uninstalled because other installed repositories require it. + return False + # Find installed tool dependencies that require this repository's installed tool dependencies. + installed_tool_dependencies = [] + for repository in irm.installed_tool_dependencies_of_installed_repositories: + if repository.id == self.id: + installed_tool_dependencies = \ + irm.installed_tool_dependencies_of_installed_repositories[ repository ] + break + for td in installed_tool_dependencies: + if td.id in irm.ids_of_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies_keys: + for installed_td in irm.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies: + if installed_td.id == td.id: + installed_dependent_tds = \ + irm.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies[ installed_td ] + if installed_dependent_tds: + # This repository cannot be uninstalled because it contains installed tool dependencies that + # are required at run time by other installed tool dependencies. + return False + return True @property def can_deactivate( self ): @@ -218,7 +244,7 @@ @property def installed_tool_dependencies( self ): - """Return the repository's tool dependencies that are currently installed.""" + """Return the repository's tool dependencies that are currently installed, but possibly in an error state.""" installed_dependencies = [] for tool_dependency in self.tool_dependencies: if tool_dependency.status in [ ToolDependency.installation_status.INSTALLED, @@ -313,9 +339,9 @@ required_repositories_missing_or_being_installed = [] for required_repository in self.repository_dependencies: if required_repository.status in [ self.installation_status.ERROR, - self.installation_status.INSTALLING, - self.installation_status.NEVER_INSTALLED, - self.installation_status.UNINSTALLED ]: + self.installation_status.INSTALLING, + self.installation_status.NEVER_INSTALLED, + self.installation_status.UNINSTALLED ]: required_repositories_missing_or_being_installed.append( required_repository ) return required_repositories_missing_or_being_installed @@ -507,7 +533,9 @@ @property def can_uninstall( self ): - return self.status in [ self.installation_status.ERROR, self.installation_status.INSTALLED ] + # A tool dependency can be uninstalled only if it is currently in an error state. Only the containing + # repository can be uninstalled if a tool dependency is properly installed. + return self.status in [ self.installation_status.ERROR ] @property def can_update( self ): @@ -516,6 +544,13 @@ self.installation_status.ERROR, self.installation_status.UNINSTALLED ] + def get_env_shell_file_path( self, app ): + installation_directory = self.installation_directory( app ) + file_path = os.path.join( installation_directory, 'env.sh' ) + if os.path.exists( file_path ): + return file_path + return None + @property def in_error_state( self ): return self.status == self.installation_status.ERROR @@ -536,6 +571,10 @@ self.tool_shed_repository.name, self.tool_shed_repository.installed_changeset_revision ) + @property + def is_installed( self ): + return self.status == self.installation_status.INSTALLED + class ToolVersion( object, Dictifiable ): dict_element_visible_keys = ( 'id', 'tool_shed_repository' ) @@ -549,23 +588,23 @@ def get_previous_version( self, app ): context = app.install_model.context tva = context.query( app.install_model.ToolVersionAssociation ) \ - .filter( app.install_model.ToolVersionAssociation.table.c.tool_id == self.id ) \ - .first() + .filter( app.install_model.ToolVersionAssociation.table.c.tool_id == self.id ) \ + .first() if tva: return context.query( app.install_model.ToolVersion ) \ - .filter( app.install_model.ToolVersion.table.c.id == tva.parent_id ) \ - .first() + .filter( app.install_model.ToolVersion.table.c.id == tva.parent_id ) \ + .first() return None def get_next_version( self, app ): context = app.install_model.context tva = context.query( app.install_model.ToolVersionAssociation ) \ - .filter( app.install_model.ToolVersionAssociation.table.c.parent_id == self.id ) \ - .first() + .filter( app.install_model.ToolVersionAssociation.table.c.parent_id == self.id ) \ + .first() if tva: return context.query( app.install_model.ToolVersion ) \ - .filter( app.install_model.ToolVersion.table.c.id == tva.tool_id ) \ - .first() + .filter( app.install_model.ToolVersion.table.c.id == tva.tool_id ) \ + .first() return None def get_versions( self, app ): diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/galaxy/model/tool_shed_install/mapping.py --- a/lib/galaxy/model/tool_shed_install/mapping.py +++ b/lib/galaxy/model/tool_shed_install/mapping.py @@ -7,10 +7,8 @@ from galaxy.model.base import ModelMapping from galaxy.model.orm.engine_factory import build_engine - metadata = MetaData() - install_model.ToolShedRepository.table = Table( "tool_shed_repository", metadata, Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), @@ -72,7 +70,6 @@ Column( "repository_path", TEXT ), Column( "version", Integer ) ) - mapper( install_model.ToolShedRepository, install_model.ToolShedRepository.table, properties=dict( tool_versions=relation( install_model.ToolVersion, primaryjoin=( install_model.ToolShedRepository.table.c.id == install_model.ToolVersion.table.c.tool_shed_repository_id ), @@ -112,17 +109,13 @@ """Connect mappings to the database""" # Load the appropriate db module engine = build_engine( url, engine_options ) - # Connect the metadata to the database. metadata.bind = engine - - result = ModelMapping([install_model], engine=engine) - + result = ModelMapping( [ install_model ], engine=engine ) # Create tables if needed if create_tables: metadata.create_all() # metadata.engine.commit() - result.create_tables = create_tables #load local galaxy security policy return result diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -265,6 +265,9 @@ if remove_from_disk_checked: tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.UNINSTALLED tool_shed_repository.error_message = None + # Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the + # installed_repository_manager. + trans.app.installed_repository_manager.handle_uninstall( tool_shed_repository ) else: tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.DEACTIVATED trans.install_model.context.add( tool_shed_repository ) @@ -1564,7 +1567,7 @@ tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository if kwd.get( 'uninstall_tool_dependencies_button', False ): errors = False - # Filter tool dependencies to only those that are installed. + # Filter tool dependencies to only those that are installed but in an error state. tool_dependencies_for_uninstallation = [] for tool_dependency in tool_dependencies: if tool_dependency.can_uninstall: diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/tool_shed/galaxy_install/__init__.py --- a/lib/tool_shed/galaxy_install/__init__.py +++ b/lib/tool_shed/galaxy_install/__init__.py @@ -1,54 +0,0 @@ -""" -Classes encapsulating the management of repositories installed from Galaxy tool sheds. -""" -import os, logging -import tool_shed.util.shed_util_common -import tool_shed.util.datatype_util -from galaxy.model.orm import and_ -from tool_shed.util import xml_util - -log = logging.getLogger( __name__ ) - -class InstalledRepositoryManager( object ): - def __init__( self, app ): - self.app = app - self.install_model = self.app.install_model - self.context = self.install_model.context - self.tool_configs = self.app.config.tool_configs - if self.app.config.migrated_tools_config not in self.tool_configs: - self.tool_configs.append( self.app.config.migrated_tools_config ) - self.installed_repository_dicts = [] - def get_repository_install_dir( self, tool_shed_repository ): - for tool_config in self.tool_configs: - tree, error_message = xml_util.parse_xml( tool_config ) - if tree is None: - return None - root = tree.getroot() - tool_path = root.get( 'tool_path', None ) - if tool_path: - ts = tool_shed.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed ) - relative_path = os.path.join( tool_path, - ts, - 'repos', - tool_shed_repository.owner, - tool_shed_repository.name, - tool_shed_repository.installed_changeset_revision ) - if os.path.exists( relative_path ): - return relative_path - return None - def load_proprietary_datatypes( self ): - for tool_shed_repository in self.context.query( self.install_model.ToolShedRepository ) \ - .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True, - self.install_model.ToolShedRepository.table.c.deleted==False ) ) \ - .order_by( self.install_model.ToolShedRepository.table.c.id ): - relative_install_dir = self.get_repository_install_dir( tool_shed_repository ) - if relative_install_dir: - installed_repository_dict = tool_shed.util.datatype_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir ) - if installed_repository_dict: - self.installed_repository_dicts.append( installed_repository_dict ) - def load_proprietary_converters_and_display_applications( self, deactivate=False ): - for installed_repository_dict in self.installed_repository_dicts: - if installed_repository_dict[ 'converter_path' ]: - tool_shed.util.datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate ) - if installed_repository_dict[ 'display_path' ]: - tool_shed.util.datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate ) diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/tool_shed/galaxy_install/installed_repository_manager.py --- /dev/null +++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py @@ -0,0 +1,340 @@ +""" +Class encapsulating the management of repositories installed from Galaxy tool sheds. +""" +import logging +import os +import tool_shed.util.shed_util_common as suc +from tool_shed.util import datatype_util +from tool_shed.util import repository_dependency_util +from tool_shed.util import tool_dependency_util +from tool_shed.util import xml_util +from galaxy.model.orm import and_ + +log = logging.getLogger( __name__ ) + + +class InstalledRepositoryManager( object ): + + def __init__( self, app ): + """ + Among other things, eep in in-memory set of installed repositories and tool dependencies along with the relationships + between each of them. This will allow for quick discovery of those repositories or components that can be uninstalled. + The feature allowing a Galaxy administrator to uninstall a repository should not be available to repositories or tool + dependency packages that are required by other repositories or their contents (packages). The uninstall feature should + be available only at the repository hierarchy level where every dependency will be uninstalled. The exception for this + is if an item (repository or tool dependency package) is not in an INSTALLED state - in these cases, the specific item + can be uninstalled in order to attempt re-installation. + """ + self.app = app + self.install_model = self.app.install_model + self.context = self.install_model.context + self.tool_configs = self.app.config.tool_configs + if self.app.config.migrated_tools_config not in self.tool_configs: + self.tool_configs.append( self.app.config.migrated_tools_config ) + self.installed_repository_dicts = [] + # Keep an in-memory dictionary whose keys are tool_shed_repository objects (whose status is 'Installed') and whose values + # are a list of tool_shed_repository objects (whose status can be anything) required by the key. The value defines the + # entire repository dependency tree. + self.repository_dependencies_of_installed_repositories = {} + # Keep an in-memory dictionary whose keys are tool_shed_repository objects (whose status is 'Installed') and whose values + # are a list of tool_shed_repository objects (whose status is 'Installed') required by the key. The value defines the + # entire repository dependency tree. + self.installed_repository_dependencies_of_installed_repositories = {} + # Keep an in-memory dictionary whose keys are tool_shed_repository objects (whose status is 'Installed') and whose values + # are a list of its immediate tool_dependency objects (whose status can be anything). The value defines only the immediate + # tool dependencies of the repository and does not include any dependencies of the tool dependencies. + self.tool_dependencies_of_installed_repositories = {} + # Keep an in-memory dictionary whose keys are tool_shed_repository objects (whose status is 'Installed') and whose values + # are a list of its immediate tool_dependency objects (whose status is 'Installed'). The value defines only the immediate + # tool dependencies of the repository and does not include any dependencies of the tool dependencies. + self.installed_tool_dependencies_of_installed_repositories = {} + # Keep an in-memory dictionary whose keys are tool_dependency objects (whose status is 'Installed') and whose values are + # a list of tool_dependency objects (whose status can be anything) required by the installed tool dependency at runtime. + # The value defines the entire tool dependency tree. + self.runtime_tool_dependencies_of_installed_tool_dependencies = {} + # Keep an in-memory dictionary whose keys are tool_dependency objects (whose status is 'Installed') and whose values are + # a list of tool_dependency objects (whose status is 'Installed') that require the key at runtime. The value defines the + # entire tool dependency tree. + self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies = {} + # Load defined dependency relationships for installed tool shed repositories and their contents. + self.load_dependency_relationships() + + def add_entry_to_installed_repository_dependencies_of_installed_repositories( self, repository ): + """Add an entry to self.installed_repository_dependencies_of_installed_repositories.""" + if repository.id not in self.ids_of_installed_repository_dependencies_of_installed_repositories_keys: + debug_msg = "Adding an entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "to installed_repository_dependencies_of_installed_repositories." + log.debug( debug_msg ) + status = self.install_model.ToolShedRepository.installation_status.INSTALLED + repository_dependency_tree = \ + repository_dependency_util.get_repository_dependency_tree_for_repository( self.app, + repository, + status=status ) + self.installed_repository_dependencies_of_installed_repositories[ repository ] = \ + repository_dependency_tree + + def add_entry_to_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( self, tool_dependency ): + """Add an entry to self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies.""" + if tool_dependency.id not in self.ids_of_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies_keys: + debug_msg = "Adding an entry for version %s of %s %s " % \ + ( str( tool_dependency.version ), str( tool_dependency.type ), str( tool_dependency.name ) ) + debug_msg += "to installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies." + log.debug( debug_msg ) + status = self.install_model.ToolDependency.installation_status.INSTALLED + installed_runtime_dependent_tool_dependencies = \ + tool_dependency_util.get_runtime_dependent_tool_dependencies( self.app, tool_dependency, status=status ) + self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies[ tool_dependency ] = \ + installed_runtime_dependent_tool_dependencies + + def add_entry_to_installed_tool_dependencies_of_installed_repositories( self, repository ): + """Add an entry to self.installed_tool_dependencies_of_installed_repositories.""" + if repository.id not in self.ids_of_installed_tool_dependencies_of_installed_repositories_keys: + debug_msg = "Adding an entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "to installed_tool_dependencies_of_installed_repositories." + log.debug( debug_msg ) + installed_tool_dependencies = [] + for td in repository.tool_dependencies: + if td.status == self.app.install_model.ToolDependency.installation_status.INSTALLED: + installed_tool_dependencies.append( td ) + self.installed_tool_dependencies_of_installed_repositories[ repository ] = installed_tool_dependencies + + def add_entry_to_repository_dependencies_of_installed_repositories( self, repository ): + """Add an entry to self.repository_dependencies_of_installed_repositories.""" + if repository.id not in self.ids_of_repository_dependencies_of_installed_repositories_keys: + debug_msg = "Adding an entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "to repository_dependencies_of_installed_repositories." + log.debug( debug_msg ) + repository_dependency_tree = \ + repository_dependency_util.get_repository_dependency_tree_for_repository( self.app, + repository, + status=None ) + self.repository_dependencies_of_installed_repositories[ repository ] = repository_dependency_tree + + def add_entry_to_runtime_tool_dependencies_of_installed_tool_dependencies( self, tool_dependency ): + """Add an entry to self.runtime_tool_dependencies_of_installed_tool_dependencies.""" + if tool_dependency.id not in self.ids_of_runtime_tool_dependencies_of_installed_tool_dependencies_keys: + debug_msg = "Adding an entry for version %s of %s %s " % \ + ( str( tool_dependency.version ), str( tool_dependency.type ), str( tool_dependency.name ) ) + debug_msg += "to runtime_tool_dependencies_of_installed_tool_dependencies." + log.debug( debug_msg ) + runtime_dependent_tool_dependencies = \ + tool_dependency_util.get_runtime_dependent_tool_dependencies( self.app, tool_dependency, status=None ) + self.runtime_tool_dependencies_of_installed_tool_dependencies[ tool_dependency ] = \ + runtime_dependent_tool_dependencies + + def add_entry_to_tool_dependencies_of_installed_repositories( self, repository ): + """Add an entry to self.tool_dependencies_of_installed_repositories.""" + if repository.id not in self.ids_of_tool_dependencies_of_installed_repositories_keys: + debug_msg = "Adding an entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "to tool_dependencies_of_installed_repositories." + log.debug( debug_msg ) + self.tool_dependencies_of_installed_repositories[ repository ] = repository.tool_dependencies + + def get_containing_repository_for_tool_dependency( self, tool_dependency ): + for installed_repository, tool_dependencies in self.tool_dependencies_of_installed_repositories.items(): + td_ids = [ td.id for td in tool_dependencies ] + if tool_dependency.id in td_ids: + return installed_repository + return None + + def get_repository_install_dir( self, tool_shed_repository ): + for tool_config in self.tool_configs: + tree, error_message = xml_util.parse_xml( tool_config ) + if tree is None: + return None + root = tree.getroot() + tool_path = root.get( 'tool_path', None ) + if tool_path: + ts = suc.clean_tool_shed_url( tool_shed_repository.tool_shed ) + relative_path = os.path.join( tool_path, + ts, + 'repos', + tool_shed_repository.owner, + tool_shed_repository.name, + tool_shed_repository.installed_changeset_revision ) + if os.path.exists( relative_path ): + return relative_path + return None + + def handle_install( self, repository ): + """Load the dependency relationships for a repository that was just installed or reinstalled.""" + # Populate self.repository_dependencies_of_installed_repositories. + self.add_entry_to_repository_dependencies_of_installed_repositories( repository ) + # Populate self.installed_repository_dependencies_of_installed_repositories. + self.add_entry_to_installed_repository_dependencies_of_installed_repositories( repository ) + # Populate self.tool_dependencies_of_installed_repositories. + self.add_entry_to_tool_dependencies_of_installed_repositories( repository ) + # Populate self.installed_tool_dependencies_of_installed_repositories. + self.add_entry_to_installed_tool_dependencies_of_installed_repositories( repository ) + for tool_dependency in repository.tool_dependencies: + # Populate self.runtime_tool_dependencies_of_installed_tool_dependencies. + self.add_entry_to_runtime_tool_dependencies_of_installed_tool_dependencies( tool_dependency ) + # Populate self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies. + self.add_entry_to_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( tool_dependency ) + + def handle_uninstall( self, repository ): + """Remove the dependency relationships for a repository that was just uninstalled.""" + for tool_dependency in repository.tool_dependencies: + # Remove all this tool_dependency from all values in + # self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies + altered_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies = {} + for td, installed_runtime_dependent_tool_dependencies in \ + self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies.items(): + irdtd_ids = [ irdtd.id for irdtd in installed_runtime_dependent_tool_dependencies ] + if td.id in irdtd_ids: + index = irdtd_ids[ td.id ] + # Remove the tool_dependency from the list. + del installed_runtime_dependent_tool_dependencies[ index ] + # Add the possibly altered list to the altered dictionary. + altered_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies[ td ] = \ + installed_runtime_dependent_tool_dependencies + self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies = \ + altered_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies + # Remove the entry for this tool_dependency from self.runtime_tool_dependencies_of_installed_tool_dependencies. + self.remove_entry_from_runtime_tool_dependencies_of_installed_tool_dependencies( tool_dependency ) + # Remove the entry for this tool_dependency from + # self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies. + self.remove_entry_from_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( tool_dependency ) + # Remove this repository's entry from self.installed_tool_dependencies_of_installed_repositories. + self.remove_entry_from_installed_tool_dependencies_of_installed_repositories( repository ) + # Remove this repository's entry from self.tool_dependencies_of_installed_repositories + self.remove_entry_from_tool_dependencies_of_installed_repositories( repository ) + # Remove this repository's entry from self.installed_repository_dependencies_of_installed_repositories. + self.remove_entry_from_installed_repository_dependencies_of_installed_repositories( repository ) + # Remove this repository's entry from self.repository_dependencies_of_installed_repositories. + self.remove_entry_from_repository_dependencies_of_installed_repositories( repository ) + + @property + def ids_of_installed_repository_dependencies_of_installed_repositories_keys( self ): + return [ r.id for r in self.installed_repository_dependencies_of_installed_repositories.keys() ] + + @property + def ids_of_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies_keys( self ): + return [ td.id for td in self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies.keys() ] + + @property + def ids_of_installed_tool_dependencies_of_installed_repositories_keys( self ): + return [ r.id for r in self.installed_tool_dependencies_of_installed_repositories.keys() ] + + @property + def ids_of_repository_dependencies_of_installed_repositories_keys( self ): + return [ r.id for r in self.repository_dependencies_of_installed_repositories.keys() ] + + @property + def ids_of_runtime_tool_dependencies_of_installed_tool_dependencies_keys( self ): + return [ td.id for td in self.runtime_tool_dependencies_of_installed_tool_dependencies.keys() ] + + @property + def ids_of_tool_dependencies_of_installed_repositories_keys( self ): + return [ r.id for r in self.tool_dependencies_of_installed_repositories.keys() ] + + def load_dependency_relationships( self ): + """Load relationships for all installed repositories and tool dependencies into in-memnory dictionaries.""" + # Get the list of installed tool shed repositories. + for repository in self.context.query( self.app.install_model.ToolShedRepository ) \ + .filter( self.app.install_model.ToolShedRepository.table.c.status == + self.app.install_model.ToolShedRepository.installation_status.INSTALLED ): + # Populate self.repository_dependencies_of_installed_repositories. + self.add_entry_to_repository_dependencies_of_installed_repositories( repository ) + # Populate self.installed_repository_dependencies_of_installed_repositories. + self.add_entry_to_installed_repository_dependencies_of_installed_repositories( repository ) + # Populate self.tool_dependencies_of_installed_repositories. + self.add_entry_to_tool_dependencies_of_installed_repositories( repository ) + # Populate self.installed_tool_dependencies_of_installed_repositories. + self.add_entry_to_installed_tool_dependencies_of_installed_repositories( repository ) + # Get the list of installed tool dependencies. + for tool_dependency in self.context.query( self.app.install_model.ToolDependency ) \ + .filter( self.app.install_model.ToolDependency.table.c.status == + self.app.install_model.ToolDependency.installation_status.INSTALLED ): + # Populate self.runtime_tool_dependencies_of_installed_tool_dependencies. + self.add_entry_to_runtime_tool_dependencies_of_installed_tool_dependencies( tool_dependency ) + # Populate self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies. + self.add_entry_to_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( tool_dependency ) + + def load_proprietary_datatypes( self ): + for tool_shed_repository in self.context.query( self.install_model.ToolShedRepository ) \ + .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True, + self.install_model.ToolShedRepository.table.c.deleted==False ) ) \ + .order_by( self.install_model.ToolShedRepository.table.c.id ): + relative_install_dir = self.get_repository_install_dir( tool_shed_repository ) + if relative_install_dir: + installed_repository_dict = datatype_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir ) + if installed_repository_dict: + self.installed_repository_dicts.append( installed_repository_dict ) + + def load_proprietary_converters_and_display_applications( self, deactivate=False ): + for installed_repository_dict in self.installed_repository_dicts: + if installed_repository_dict[ 'converter_path' ]: + datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate ) + if installed_repository_dict[ 'display_path' ]: + datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate ) + + def remove_entry_from_installed_repository_dependencies_of_installed_repositories( self, repository ): + """Remove an entry from self.installed_repository_dependencies_of_installed_repositories""" + for r in self.installed_repository_dependencies_of_installed_repositories: + if r.id == repository.id: + debug_msg = "Removing entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "from installed_repository_dependencies_of_installed_repositories." + log.debug( debug_msg ) + del self.installed_repository_dependencies_of_installed_repositories[ r ] + break + + def remove_entry_from_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( self, tool_dependency ): + """Remove an entry from self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies.""" + for td in self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies: + if td.id == tool_dependency.id: + debug_msg = "Removing entry for version %s of %s %s " % \ + ( str( tool_dependency.version ), str( tool_dependency.type ), str( tool_dependency.name ) ) + debug_msg += "from installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies." + log.debug( debug_msg ) + del self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies[ td ] + break + + def remove_entry_from_installed_tool_dependencies_of_installed_repositories( self, repository ): + """Remove an entry from self.installed_tool_dependencies_of_installed_repositories""" + for r in self.installed_tool_dependencies_of_installed_repositories: + if r.id == repository.id: + debug_msg = "Removing entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "from installed_tool_dependencies_of_installed_repositories." + log.debug( debug_msg ) + del self.installed_tool_dependencies_of_installed_repositories[ r ] + break + + def remove_entry_from_repository_dependencies_of_installed_repositories( self, repository ): + """Remove an entry from self.repository_dependencies_of_installed_repositories.""" + for r in self.repository_dependencies_of_installed_repositories: + if r.id == repository.id: + debug_msg = "Removing entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "from repository_dependencies_of_installed_repositories." + log.debug( debug_msg ) + del self.repository_dependencies_of_installed_repositories[ r ] + break + + def remove_entry_from_runtime_tool_dependencies_of_installed_tool_dependencies( self, tool_dependency ): + """Remove an entry from self.runtime_tool_dependencies_of_installed_tool_dependencies.""" + for td in self.runtime_tool_dependencies_of_installed_tool_dependencies: + if td.id == tool_dependency.id: + debug_msg = "Removing entry for version %s of %s %s " % \ + ( str( tool_dependency.version ), str( tool_dependency.type ), str( tool_dependency.name ) ) + debug_msg += "from runtime_tool_dependencies_of_installed_tool_dependencies." + log.debug( debug_msg ) + del self.runtime_tool_dependencies_of_installed_tool_dependencies[ td ] + break + + def remove_entry_from_tool_dependencies_of_installed_repositories( self, repository ): + """Remove an entry from self.tool_dependencies_of_installed_repositories.""" + for r in self.tool_dependencies_of_installed_repositories: + if r.id == repository.id: + debug_msg = "Removing entry for revision %s of repository %s owned by %s " % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) + debug_msg += "from tool_dependencies_of_installed_repositories." + log.debug( debug_msg ) + del self.tool_dependencies_of_installed_repositories[ r ] + break diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/tool_shed/galaxy_install/repository_util.py --- a/lib/tool_shed/galaxy_install/repository_util.py +++ b/lib/tool_shed/galaxy_install/repository_util.py @@ -504,8 +504,8 @@ query = trans.install_model.context.query( trans.install_model.ToolShedRepository ).filter( or_( *clause_list ) ) return encoded_kwd, query, tool_shed_repositories, encoded_repository_ids -def install_tool_shed_repository( trans, tool_shed_repository, repo_info_dict, tool_panel_section_key, shed_tool_conf, tool_path, install_tool_dependencies, - reinstalling=False ): +def install_tool_shed_repository( trans, tool_shed_repository, repo_info_dict, tool_panel_section_key, shed_tool_conf, tool_path, + install_tool_dependencies, reinstalling=False ): if tool_panel_section_key: try: tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ] @@ -579,7 +579,11 @@ tool_dependencies_config=tool_dependencies_config, tool_dependencies=tool_shed_repository.tool_dependencies ) suc.remove_dir( work_dir ) - suc.update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.install_model.ToolShedRepository.installation_status.INSTALLED ) + suc.update_tool_shed_repository_status( trans.app, + tool_shed_repository, + trans.install_model.ToolShedRepository.installation_status.INSTALLED ) + # Add the installed repository and any tool dependencies to the in-memory dictionaries in the installed_repository_manager. + trans.app.installed_repository_manager.handle_install( tool_shed_repository ) else: # An error occurred while cloning the repository, so reset everything necessary to enable another attempt. set_repository_attributes( trans, diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/tool_shed/galaxy_install/update_manager.py --- a/lib/tool_shed/galaxy_install/update_manager.py +++ b/lib/tool_shed/galaxy_install/update_manager.py @@ -30,7 +30,7 @@ # repository. This information includes items like newer installable repository revisions, current revision updates, whether # the repository revision is the latest installable revision, and whether the repository has been deprecated in the tool shed. for repository in self.context.query( self.app.install_model.ToolShedRepository ) \ - .filter( self.app.install_model.ToolShedRepository.table.c.deleted == False ): + .filter( self.app.install_model.ToolShedRepository.table.c.deleted == False ): tool_shed_status_dict = suc.get_tool_shed_status_for_installed_repository( self.app, repository ) if tool_shed_status_dict: if tool_shed_status_dict != repository.tool_shed_status: diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/tool_shed/util/repository_dependency_util.py --- a/lib/tool_shed/util/repository_dependency_util.py +++ b/lib/tool_shed/util/repository_dependency_util.py @@ -355,14 +355,43 @@ handled_key_rd_dicts, circular_repository_dependencies ) elif key_rd_dicts_to_be_processed: - handle_next_repository_dependency( trans, key_rd_dicts_to_be_processed, all_repository_dependencies, handled_key_rd_dicts, circular_repository_dependencies ) + handle_next_repository_dependency( trans, + key_rd_dicts_to_be_processed, + all_repository_dependencies, + handled_key_rd_dicts, + circular_repository_dependencies ) elif key_rd_dicts_to_be_processed: - handle_next_repository_dependency( trans, key_rd_dicts_to_be_processed, all_repository_dependencies, handled_key_rd_dicts, circular_repository_dependencies ) + handle_next_repository_dependency( trans, + key_rd_dicts_to_be_processed, + all_repository_dependencies, + handled_key_rd_dicts, + circular_repository_dependencies ) elif key_rd_dicts_to_be_processed: - handle_next_repository_dependency( trans, key_rd_dicts_to_be_processed, all_repository_dependencies, handled_key_rd_dicts, circular_repository_dependencies ) + handle_next_repository_dependency( trans, + key_rd_dicts_to_be_processed, + all_repository_dependencies, + handled_key_rd_dicts, + circular_repository_dependencies ) all_repository_dependencies = prune_invalid_repository_dependencies( all_repository_dependencies ) return all_repository_dependencies +def get_repository_dependency_tree_for_repository( app, repository, dependency_tree=None, status=None ): + """ + Return a list of of tool_shed_repository ids (whose status can be anything) required by the received repository. The + returned list defines the entire repository dependency tree. + """ + if dependency_tree is None: + dependency_tree = [] + tree_object_ids = [ r.id for r in dependency_tree ] + for rrda in repository.required_repositories: + repository_dependency = rrda.repository_dependency + required_repository = repository_dependency.repository + if status is None or required_repository.status == status: + if required_repository.id not in tree_object_ids: + dependency_tree.append( required_repository ) + return get_repository_dependency_tree_for_repository( app, required_repository, dependency_tree=dependency_tree ) + return dependency_tree + def get_updated_changeset_revisions_for_repository_dependencies( trans, key_rd_dicts ): updated_key_rd_dicts = [] for key_rd_dict in key_rd_dicts: diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc lib/tool_shed/util/tool_dependency_util.py --- a/lib/tool_shed/util/tool_dependency_util.py +++ b/lib/tool_shed/util/tool_dependency_util.py @@ -4,6 +4,7 @@ from galaxy import eggs from galaxy import util from galaxy.model.orm import and_ +from galaxy.model.orm import or_ import tool_shed.util.shed_util_common as suc import tool_shed.repository_types.util as rt_util from tool_shed.util import xml_util @@ -13,9 +14,10 @@ def add_installation_directories_to_tool_dependencies( trans, tool_dependencies ): """ - Determine the path to the installation directory for each of the received tool dependencies. This path will be displayed within the tool dependencies - container on the select_tool_panel_section or reselect_tool_panel_section pages when installing or reinstalling repositories that contain tools with the - defined tool dependencies. The list of tool dependencies may be associated with more than a single repository. + Determine the path to the installation directory for each of the received tool dependencies. This path will be + displayed within the tool dependencies container on the select_tool_panel_section or reselect_tool_panel_section + pages when installing or reinstalling repositories that contain tools with the defined tool dependencies. The + list of tool dependencies may be associated with more than a single repository. """ for dependency_key, requirements_dict in tool_dependencies.items(): if dependency_key in [ 'set_environment' ]: @@ -64,7 +66,10 @@ return tool_dependency def create_tool_dependency_objects( app, tool_shed_repository, relative_install_dir, set_status=True ): - """Create or update a ToolDependency for each entry in tool_dependencies_config. This method is called when installing a new tool_shed_repository.""" + """ + Create or update a ToolDependency for each entry in tool_dependencies_config. This method is called when + installing a new tool_shed_repository. + """ tool_dependency_objects = [] shed_config_dict = tool_shed_repository.get_shed_config_dict( app ) if shed_config_dict.get( 'tool_path' ): @@ -82,12 +87,13 @@ name = elem.get( 'name', None ) version = elem.get( 'version', None ) if name and version: + status = app.install_model.ToolDependency.installation_status.NEVER_INSTALLED tool_dependency = create_or_update_tool_dependency( app, tool_shed_repository, name=name, version=version, type=tool_dependency_type, - status=app.install_model.ToolDependency.installation_status.NEVER_INSTALLED, + status=status, set_status=set_status ) tool_dependency_objects.append( tool_dependency ) elif tool_dependency_type == 'set_environment': @@ -96,12 +102,13 @@ name = env_elem.get( 'name', None ) action = env_elem.get( 'action', None ) if name and action: + status = app.install_model.ToolDependency.installation_status.NEVER_INSTALLED tool_dependency = create_or_update_tool_dependency( app, tool_shed_repository, name=name, version=None, type=tool_dependency_type, - status=app.install_model.ToolDependency.installation_status.NEVER_INSTALLED, + status=status, set_status=set_status ) tool_dependency_objects.append( tool_dependency ) return tool_dependency_objects @@ -185,12 +192,38 @@ def generate_message_for_repository_type_change( trans, repository ): message = '' if repository.can_change_type_to( trans.app, rt_util.TOOL_DEPENDENCY_DEFINITION ): - tool_dependency_definition_type_class = trans.app.repository_types_registry.get_class_by_label( rt_util.TOOL_DEPENDENCY_DEFINITION ) - message += "This repository currently contains a single file named <b>%s</b>. If additional files will " % suc.TOOL_DEPENDENCY_DEFINITION_FILENAME - message += "not be added to this repository, then it's type should be set to <b>%s</b>.<br/>" % tool_dependency_definition_type_class.label + tool_dependency_definition_type_class = \ + trans.app.repository_types_registry.get_class_by_label( rt_util.TOOL_DEPENDENCY_DEFINITION ) + message += "This repository currently contains a single file named <b>%s</b>. If additional files will " % \ + suc.TOOL_DEPENDENCY_DEFINITION_FILENAME + message += "not be added to this repository, then it's type should be set to <b>%s</b>.<br/>" % \ + tool_dependency_definition_type_class.label return message - - + +def get_runtime_dependent_tool_dependencies( app, tool_dependency, status=None ): + """ + Return the list of tool dependency objects that require the received tool dependency at run time. The returned + list will be filtered by the received status if it is not None. This method is called only from Galaxy. + """ + runtime_dependent_tool_dependencies = [] + required_env_shell_file_path = tool_dependency.get_env_shell_file_path( app ) + if required_env_shell_file_path: + required_env_shell_file_path = os.path.abspath( required_env_shell_file_path ) + if required_env_shell_file_path is not None: + for td in app.install_model.context.query( app.install_model.ToolDependency ): + if status is None or td.status == status: + env_shell_file_path = td.get_env_shell_file_path( app ) + if env_shell_file_path is not None: + try: + contents = open( env_shell_file_path, 'r' ).read() + except Exception, e: + contents = None + log.debug( 'Error reading file %s, so cannot determine if package %s requires package %s at run time: %s' % \ + ( str( env_shell_file_path ), str( td.name ), str( tool_dependency.name ), str( e ) ) ) + if contents is not None and contents.find( required_env_shell_file_path ) >= 0: + runtime_dependent_tool_dependencies.append( td ) + return runtime_dependent_tool_dependencies + def get_download_url_for_platform( url_templates, platform_info_dict ): ''' Compare the dict returned by get_platform_info() with the values specified in the url_template element. Return diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako --- a/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako +++ b/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako @@ -36,12 +36,100 @@ ${repository.deleted} </div><div class="form-row"> - %if repository.can_deactivate: + <% + can_deactivate_repository = repository.can_deactivate + can_uninstall_repository = repository.can_uninstall( trans.app ) + %> + %if can_deactivate_repository and can_uninstall_repository: <% deactivate_uninstall_button_text = "Deactivate or Uninstall" %> ${remove_from_disk_check_box.get_html()} <label for="repository" style="display: inline;font-weight:normal;">Check to uninstall or leave blank to deactivate</label><br/><br/> - <label>Deactivating this repository will result in the following:</label> + %elif can_deactivate_repository: + <% deactivate_uninstall_button_text = "Deactivate" %> + %else: + <% deactivate_uninstall_button_text = "Uninstall" %> + ##hack to mimic check box + <input type="hidden" name="remove_from_disk" value="true"/><input type="hidden" name="remove_from_disk" value="true"/> + %endif + %if not can_uninstall_repository: + <% + irm = trans.app.installed_repository_manager + + # Get installed repositories that require this repository. + installed_repository_dependencies = [] + installed_runtime_dependent_tool_dependencies = [] + for r in irm.installed_repository_dependencies_of_installed_repositories: + if r.id == repository.id: + installed_repository_dependencies = irm.installed_repository_dependencies_of_installed_repositories[ r ] + break + + # Get this repository's installed tool dependencies. + installed_tool_dependencies = [] + for r in irm.installed_tool_dependencies_of_installed_repositories: + if r.id == repository.id: + installed_tool_dependencies = irm.installed_tool_dependencies_of_installed_repositories[ r ] + break + + # Get installed runtime dependent tool dependencies of this repository's installed tool dependencies. + installed_runtime_dependent_tool_dependencies = [] + for itd in installed_tool_dependencies: + for td in irm.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies: + if td.id == itd.id: + installed_dependent_tds = \ + irm.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies[ td ] + if installed_dependent_tds: + installed_runtime_dependent_tool_dependencies.extend( installed_dependent_tds ) + %> + %if installed_repository_dependencies or installed_runtime_dependent_tool_dependencies: + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td bgcolor="#D8D8D8"> + <label>This repository cannot be uninstalled because it is required by the following installed items:</label> + </td> + </tr> + </table> + %if installed_repository_dependencies: + <label>Dependent repositories:</label> + <ul> + %for installed_repository_dependency in installed_repository_dependencies: + <% + changeset_revision = installed_repository_dependency.changeset_revision + name = installed_repository_dependency.name + owner = installed_repository_dependency.owner + %> + <li>Revision <b>${ changeset_revision | h}</b> of repository <b>${name | h}</b> owned by <b>${owner | h}</b></li> + %endfor + </ul> + %endif + %if installed_runtime_dependent_tool_dependencies: + <label>Runtime dependent tool dependencies of this repository's tool dependencies:</label> + <ul> + %for td in installed_runtime_dependent_tool_dependencies: + <% + containing_repository = irm.get_containing_repository_for_tool_dependency( td ) + repository_name = containing_repository.name + changeset_revision = containing_repository.changeset_revision + owner = containing_repository.owner + %> + <li> + Version <b>${td.version}</b> of ${td.type} <b>${td.name}</b> contained in revision + <b>${changeset_revision | h}</b> of repository <b>${repository_name | h}</b> owned by <b>${owner}</b> + </li> + %endfor + </ul> + %endif + <br/> + %endif + %endif + %if can_deactivate_repository: + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td bgcolor="#D8D8D8"> + <label>Deactivating this repository will result in the following:</label> + </td> + </tr> + </table><div class="toolParamHelp" style="clear: both;"> * The repository and all of it's contents will remain on disk. </div> @@ -64,40 +152,45 @@ * The repository record's deleted column in the tool_shed_repository database table will be set to True. </div><br/> - %else: - <% deactivate_uninstall_button_text = "Uninstall" %> - ##hack to mimic check box - <input type="hidden" name="remove_from_disk" value="true"/><input type="hidden" name="remove_from_disk" value="true"/> %endif - <label>Uninstalling this repository will result in the following:</label> - <div class="toolParamHelp" style="clear: both;"> - * The repository and all of it's contents will be removed from disk. - </div> - %if repository.includes_tools_for_display_in_tool_panel: + %if can_uninstall_repository: + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td bgcolor="#D8D8D8"> + <label>Uninstalling this repository will result in the following:</label> + </td> + </tr> + </table><div class="toolParamHelp" style="clear: both;"> - * The repository's tool tag sets will be removed from the tool config file in which they are defined. + * The repository and all of it's contents will be removed from disk. </div> - %endif - %if repository.includes_tool_dependencies: + %if repository.includes_tools_for_display_in_tool_panel: + <div class="toolParamHelp" style="clear: both;"> + * The repository's tool tag sets will be removed from the tool config file in which they are defined. + </div> + %endif + %if repository.includes_tool_dependencies: + <div class="toolParamHelp" style="clear: both;"> + * The repository's installed tool dependencies will be removed from disk. + </div> + <div class="toolParamHelp" style="clear: both;"> + * Each associated tool dependency record's status column in the tool_dependency database table will be set to 'Uninstalled'. + </div> + %endif + %if repository.includes_datatypes: + <div class="toolParamHelp" style="clear: both;"> + * The repository's datatypes, datatype converters and display applications will be eliminated from the datatypes registry. + </div> + %endif <div class="toolParamHelp" style="clear: both;"> - * The repository's installed tool dependencies will be removed from disk. + * The repository record's deleted column in the tool_shed_repository database table will be set to True. </div><div class="toolParamHelp" style="clear: both;"> - * Each associated tool dependency record's status column in the tool_dependency database table will be set to 'Uninstalled'. + * The repository record's uninstalled column in the tool_shed_repository database table will be set to True. </div> + <div style="clear: both"></div> + <br/> %endif - %if repository.includes_datatypes: - <div class="toolParamHelp" style="clear: both;"> - * The repository's datatypes, datatype converters and display applications will be eliminated from the datatypes registry. - </div> - %endif - <div class="toolParamHelp" style="clear: both;"> - * The repository record's deleted column in the tool_shed_repository database table will be set to True. - </div> - <div class="toolParamHelp" style="clear: both;"> - * The repository record's uninstalled column in the tool_shed_repository database table will be set to True. - </div> - <div style="clear: both"></div></div><div class="form-row"><input type="submit" name="deactivate_or_uninstall_repository_button" value="${deactivate_uninstall_button_text}"/> diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc templates/admin/tool_shed_repository/manage_repository_tool_dependencies.mako --- a/templates/admin/tool_shed_repository/manage_repository_tool_dependencies.mako +++ b/templates/admin/tool_shed_repository/manage_repository_tool_dependencies.mako @@ -30,6 +30,8 @@ <tr><th bgcolor="#D8D8D8">Name</th><th bgcolor="#D8D8D8">Version</th><th bgcolor="#D8D8D8">Type</th><th bgcolor="#D8D8D8">Status</th><th bgcolor="#D8D8D8">Error</th></tr> %for tool_dependency in repository.tool_dependencies: <% + # Tool dependencies cannot be uninstalled if they have a status of 'Installed'. Only the containing repository + # can be uninstalled (only if it has no dependent repositories) if a tool dependency has been successfully installed. if tool_dependency.error_message: error_message = tool_dependency.error_message else: @@ -39,7 +41,8 @@ trans.install_model.ToolDependency.installation_status.UNINSTALLED ]: can_install = True if not can_uninstall: - if tool_dependency.status not in [ trans.install_model.ToolDependency.installation_status.NEVER_INSTALLED, + if tool_dependency.status not in [ trans.install_model.ToolDependency.installation_status.INSTALLED, + trans.install_model.ToolDependency.installation_status.NEVER_INSTALLED, trans.install_model.ToolDependency.installation_status.UNINSTALLED ]: can_uninstall = True %> diff -r 392469f092a67318ed25a4c675e72850e0a8f4b4 -r b56f6e027d2ca3e8cb5ef6f6514e085107ac5dfc templates/admin/tool_shed_repository/repository_actions_menu.mako --- a/templates/admin/tool_shed_repository/repository_actions_menu.mako +++ b/templates/admin/tool_shed_repository/repository_actions_menu.mako @@ -5,6 +5,12 @@ from tool_shed.util.encoding_util import tool_shed_encode in_error_state = repository.in_error_state tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] + if repository.status in [ trans.install_model.ToolShedRepository.installation_status.DEACTIVATED, + trans.install_model.ToolShedRepository.installation_status.ERROR, + trans.install_model.ToolShedRepository.installation_status.INSTALLED ]: + can_administer = True + else: + can_administer = False %><br/><br/><ul class="manage-table-actions"> @@ -20,7 +26,7 @@ <a class="action-button" target="galaxy_main" href="${h.url_for( controller='admin_toolshed', action='reset_to_install', id=trans.security.encode_id( repository.id ), reset_repository=True )}">Reset to install</a> %elif repository.can_install: <a class="action-button" target="galaxy_main" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ), operation='install' )}">Install</a> - %elif repository.can_uninstall: + %elif can_administer: <a class="action-button" target="galaxy_main" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" target="galaxy_main" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a><a class="action-button" target="galaxy_main" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.