commit/galaxy-central: greg: Enhancements related to displaying tool shed repository contents and dependencies in both Galaxy and the tool shed
1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/14589278b02d/ changeset: 14589278b02d user: greg date: 2012-11-30 21:14:26 summary: Enhancements related to displaying tool shed repository contents and dependencies in both Galaxy and the tool shed affected #: 35 files diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -3111,8 +3111,6 @@ if os.path.exists( relative_path ): self.shed_config_filename = shed_tool_conf_dict[ 'config_filename' ] return shed_tool_conf_dict - #if self.dist_to_shed: - # #return ./migrated_tools.xml return default def get_shed_config_dict( self, app, default=None ): """ @@ -3154,8 +3152,8 @@ def in_error_state( self ): return self.status == self.installation_status.ERROR @property - def has_readme( self ): - return self.metadata and 'readme' in self.metadata + def has_readme_files( self ): + return self.metadata and 'readme_files' in self.metadata @property def installed_tool_dependencies( self ): """Return the repository's tool dependencies that are currently installed.""" diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/tool_shed/install_manager.py --- a/lib/galaxy/tool_shed/install_manager.py +++ b/lib/galaxy/tool_shed/install_manager.py @@ -6,7 +6,6 @@ from galaxy.tools import ToolSection from galaxy.util.json import from_json_string, to_json_string from galaxy.util.shed_util import * -from galaxy.util.shed_util_common import * from galaxy.util.odict import odict from galaxy.tool_shed.common_util import * diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/tool_shed/update_manager.py --- a/lib/galaxy/tool_shed/update_manager.py +++ b/lib/galaxy/tool_shed/update_manager.py @@ -4,7 +4,6 @@ import threading, urllib2, logging from galaxy.util import string_as_bool from galaxy.util.shed_util import * -from galaxy.util.shed_util_common import * log = logging.getLogger( __name__ ) diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -33,7 +33,6 @@ from galaxy.util.hash_util import * from galaxy.util import listify from galaxy.util.shed_util import * -from galaxy.util.shed_util_common import * from galaxy.web import url_for from galaxy.visualization.genome.visual_analytics import TracksterConfig diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/util/shed_util_common.py --- a/lib/galaxy/util/shed_util_common.py +++ b/lib/galaxy/util/shed_util_common.py @@ -1,10 +1,11 @@ -import os, shutil, tempfile, logging, string +import os, shutil, tempfile, logging, string, threading from galaxy import util from galaxy.tools import parameters from galaxy.util import inflector from galaxy.util.json import * from galaxy.web import url_for from galaxy.web.form_builder import SelectField +from galaxy.webapps.community.util.container_util import * from galaxy.datatypes.checkers import * from galaxy.model.orm import * @@ -33,6 +34,133 @@ TOOL_SHED_ADMIN_CONTROLLER = 'TOOL_SHED_ADMIN_CONTROLLER' VALID_CHARS = set( string.letters + string.digits + "'\"-=_.()/+*^,:?!#[]%\\$@;{}" ) +def add_installation_directories_to_tool_dependencies( trans, repository_name, repository_owner, changeset_revision, tool_dependencies ): + for dependency_key, requirements_dict in tool_dependencies.items(): + if dependency_key not in [ 'set_environment' ]: + dependency_name = requirements_dict[ 'name' ] + version = requirements_dict[ 'version' ] + type = requirements_dict[ 'type' ] + install_dir = os.path.join( trans.app.config.tool_dependency_dir, + dependency_name, + version, + repository_owner, + repository_name, + changeset_revision ) + requirements_dict[ 'install_dir' ] = install_dir + tool_dependencies[ dependency_key ] = requirements_dict + return tool_dependencies +def build_readme_files_dict( repository_metadata ): + """Return a dictionary of valid readme file name <-> readme file content pairs for all readme files contained in the received repository_metadata.""" + readme_files_dict = {} + if repository_metadata: + metadata = repository_metadata.metadata + if metadata and 'readme_files' in metadata: + for relative_path_to_readme_file in metadata[ 'readme_files' ]: + readme_file_name = os.path.split( relative_path_to_readme_file )[ 1 ] + full_path_to_readme_file = os.path.abspath( relative_path_to_readme_file ) + try: + f = open( full_path_to_readme_file, 'r' ) + text = f.read() + f.close() + readme_files_dict[ readme_file_name ] = str( text ) + except Exception, e: + log.debug( "Error reading README file '%s' defined in metadata for repository '%s', revision '%s': %s" % \ + ( str( relative_path_to_readme_file ), str( repository_name ), str( changeset_revision ), str( e ) ) ) + return readme_files_dict +def build_repository_containers_for_galaxy( trans, toolshed_base_url, repository_name, repository_owner, changeset_revision, + readme_files_dict, repository_dependencies, tool_dependencies ): + """Return a dictionary of containers for the received repository's dependencies and readme files for display during installation to Galaxy.""" + containers_dict = dict( readme_files=None, repository_dependencies=None, tool_dependencies=None ) + if readme_files_dict or repository_dependencies or tool_dependencies: + lock = threading.Lock() + lock.acquire( True ) + if tool_dependencies: + # Add the install_dir attribute to the tool_dependencies. + tool_dependencies = add_installation_directories_to_tool_dependencies( trans, repository_name, repository_owner, changeset_revision, tool_dependencies ) + try: + folder_id = 0 + if readme_files_dict: + folder_id, readme_files_root_folder = build_readme_files_folder( folder_id, readme_files_dict ) + containers_dict[ 'readme_files' ] = readme_files_root_folder + if repository_dependencies: + folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( toolshed_base_url=toolshed_base_url, + repository_name=repository_name, + repository_owner=repository_owner, + changeset_revision=changeset_revision, + folder_id=folder_id, + repository_dependencies=repository_dependencies ) + containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder + if tool_dependencies: + folder_id, tool_dependencies_root_folder = build_tool_dependencies_folder( folder_id, tool_dependencies, for_galaxy=True ) + containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder + except Exception, e: + log.debug( "Exception in build_repository_containers_for_galaxy: %s" % str( e ) ) + finally: + lock.release() + return containers_dict +def build_repository_containers_for_tool_shed( repository, changeset_revision, repository_dependencies, repository_metadata ): + """Return a dictionary of containers for the received repository's dependencies and contents for display in the tool shed.""" + containers_dict = dict( datatypes=None, + invalid_tools=None, + readme_files=None, + repository_dependencies=None, + tool_dependencies=None, + valid_tools=None, + workflows=None ) + if repository_metadata: + metadata = repository_metadata.metadata + lock = threading.Lock() + lock.acquire( True ) + try: + folder_id = 0 + # Datatypes container. + if metadata and 'datatypes' in metadata: + datatypes = metadata[ 'datatypes' ] + folder_id, datatypes_root_folder = build_datatypes_folder( folder_id, datatypes ) + containers_dict[ 'datatypes' ] = datatypes_root_folder + # Invalid tools container. + if metadata and 'invalid_tools' in metadata: + invalid_tool_configs = metadata[ 'invalid_tools' ] + folder_id, invalid_tools_root_folder = build_invalid_tools_folder( folder_id, + invalid_tool_configs, + changeset_revision, + repository=repository, + label='Invalid tools' ) + containers_dict[ 'invalid_tools' ] = invalid_tools_root_folder + # Readme files container. + readme_files_dict = build_readme_files_dict( repository_metadata ) + folder_id, readme_files_root_folder = build_readme_files_folder( folder_id, readme_files_dict ) + containers_dict[ 'readme_files' ] = readme_files_root_folder + # Repository dependencies container. + toolshed_base_url = str( url_for( '/', qualified=True ) ).rstrip( '/' ) + folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( toolshed_base_url=toolshed_base_url, + repository_name=repository.name, + repository_owner=repository.user.username, + changeset_revision=changeset_revision, + folder_id=folder_id, + repository_dependencies=repository_dependencies ) + if repository_dependencies_root_folder: + containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder + # Tool dependencies container. + if metadata and 'tool_dependencies' in metadata: + tool_dependencies = metadata[ 'tool_dependencies' ] + folder_id, tool_dependencies_root_folder = build_tool_dependencies_folder( folder_id, tool_dependencies, for_galaxy=False ) + containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder + # Valid tools container. + if metadata and 'tools' in metadata: + valid_tools = metadata[ 'tools' ] + folder_id, valid_tools_root_folder = build_tools_folder( folder_id, valid_tools, repository, changeset_revision, label='Valid tools' ) + containers_dict[ 'valid_tools' ] = valid_tools_root_folder + # Workflows container. + if metadata and 'workflows' in metadata: + workflows = metadata[ 'workflows' ] + folder_id, workflows_root_folder = build_workflows_folder( folder_id, workflows, repository_metadata, label='Workflows' ) + containers_dict[ 'workflows' ] = workflows_root_folder + except Exception, e: + log.debug( "Exception in build_repository_containers_for_tool_shed: %s" % str( e ) ) + finally: + lock.release() + return containers_dict def build_repository_ids_select_field( trans, cntrller, name='repository_ids', multiple=True, display='checkboxes' ): """Method called from both Galaxy and the Tool Shed to generate the current list of repositories for resetting metadata.""" repositories_select_field = SelectField( name=name, multiple=multiple, display=display ) @@ -336,14 +464,40 @@ trans.sa_session.add( repository_metadata ) trans.sa_session.flush() return repository_metadata -def create_repo_info_dict( repository, owner, repository_clone_url, changeset_revision, ctx_rev, metadata ): +def create_repo_info_dict( trans, repo, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None, + repository=None, repository_metadata=None ): + """ + Return a dictionary that includes all of the information needed to install a repository into a local Galaxy instance. The dictionary will also contain + the recursive list of repository dependencies defined for the repository, as well as the defined tool dependencies. This method is called during the + tool shed repository installation process from Galaxy. In this case both the received repository and repository_metadata will be objects, but repository_name + sill be None. This method is also called when a tool shed repository that was uninstalled from a Galaxy instance is being re-installed. In this case, both + repository and repository_metadata will be None, but repository_name will have a value. + """ repo_info_dict = {} - repo_info_dict[ repository.name ] = ( repository.description, - repository_clone_url, - changeset_revision, - ctx_rev, - owner, - metadata.get( 'tool_dependencies', None ) ) + if repository is None and repository_metadata is None: + # The repository associated with the received repository_clone_url is being re-installed into a Galaxy instance, so we need to retrieve the + # appropriate repository from the tool shed using the received information. + repository = get_repository_by_name_and_owner( trans, repository_name, repository_owner ) + repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) + if repository_metadata: + metadata = repository_metadata.metadata + if metadata: + # Get a dictionary of all repositories upon which the contents of the received repository depends. + repository_dependencies = get_repository_dependencies_for_changeset_revision( trans, + repo, + repository, + repository_metadata, + str( url_for( '/', qualified=True ) ).rstrip( '/' ), + repository_dependencies=None, + all_repository_dependencies=None ) + # Cast unicode to string. + repo_info_dict[ str( repository.name ) ] = ( str( repository.description ), + str( repository_clone_url ), + str( changeset_revision ), + str( ctx_rev ), + str( repository_owner ), + repository_dependencies, + metadata.get( 'tool_dependencies', None ) ) return repo_info_dict def generate_clone_url_for_repository_in_tool_shed( trans, repository ): """Generate the URL for cloning a repository that is in the tool shed.""" @@ -464,7 +618,8 @@ else: original_repository_metadata = None readme_file_names = get_readme_file_names( repository.name ) - metadata_dict = { 'shed_config_filename': shed_config_dict.get( 'config_filename' ) } + metadata_dict = { 'shed_config_filename' : shed_config_dict.get( 'config_filename' ) } + readme_files = [] invalid_file_tups = [] invalid_tool_configs = [] tool_dependencies_config = None @@ -524,7 +679,7 @@ shed_config_dict, resetting_all_metadata_on_repository ) metadata_dict = generate_repository_dependency_metadata( relative_path_to_repository_dependencies, metadata_dict ) - # See if we have a READ_ME file. + # See if we have one or more READ_ME files. elif name.lower() in readme_file_names: relative_path_to_readme = get_relative_path_to_repository_file( root, name, @@ -532,7 +687,7 @@ work_dir, shed_config_dict, resetting_all_metadata_on_repository ) - metadata_dict[ 'readme' ] = relative_path_to_readme + readme_files.append( relative_path_to_readme ) # See if we have a tool config. elif name not in NOT_TOOL_CONFIGS and name.endswith( '.xml' ): full_path = str( os.path.abspath( os.path.join( root, name ) ) ) @@ -583,6 +738,8 @@ exported_workflow_dict = from_json_string( workflow_text ) if 'a_galaxy_workflow' in exported_workflow_dict and exported_workflow_dict[ 'a_galaxy_workflow' ] == 'true': metadata_dict = generate_workflow_metadata( relative_path, exported_workflow_dict, metadata_dict ) + if readme_files: + metadata_dict[ 'readme_files' ] = readme_files if 'tools' in metadata_dict: # This step must be done after metadata for tools has been defined. tool_dependencies_config = get_config_from_disk( 'tool_dependencies.xml', files_dir ) @@ -864,6 +1021,80 @@ valid_filenames.append( '%s.txt' % r ) valid_filenames.append( '%s.txt' % repository_name ) return valid_filenames +def get_repository_by_name_and_owner( trans, name, owner ): + """Get a repository from the database via name and owner""" + user = get_user_by_username( trans, owner ) + return trans.sa_session.query( trans.model.Repository ) \ + .filter( and_( trans.model.Repository.table.c.name == name, + trans.model.Repository.table.c.user_id == user.id ) ) \ + .first() +def get_repository_dependencies_for_changeset_revision( trans, repo, repository, repository_metadata, toolshed_base_url, repository_dependencies=None, + all_repository_dependencies=None ): + """ + Return a dictionary of all repositories upon which the contents of the received repository_metadata record depend. The dictionary keys + are name-spaced values consisting of toolshed_base_url/repository_name/repository_owner/changeset_revision and the values are lists of + repository_dependency tuples consisting of ( toolshed_base_url, repository_name, repository_owner, changeset_revision ). This method + ensures that all required repositories to the nth degree are returned. + """ + if all_repository_dependencies is None: + all_repository_dependencies = {} + if repository_dependencies is None: + repository_dependencies = [] + metadata = repository_metadata.metadata + if metadata and 'repository_dependencies' in metadata: + repository_dependencies_root_key = generate_repository_dependencies_key_for_repository( toolshed_base_url=toolshed_base_url, + repository_name=repository.name, + repository_owner=repository.user.username, + changeset_revision=repository_metadata.changeset_revision ) + for repository_dependency in metadata[ 'repository_dependencies' ]: + if repository_dependency not in repository_dependencies: + repository_dependencies.append( repository_dependency ) + else: + repository_dependencies_root_key = None + if repository_dependencies: + repository_dependency = repository_dependencies.pop( 0 ) + # Cast unicode to string. + repository_dependency = [ str( item ) for item in repository_dependency ] + tool_shed, name, owner, changeset_revision = repository_dependency + if repository_dependencies_root_key: + if repository_dependencies_root_key in all_repository_dependencies: + # See if this repository_dependency is contained in the list associated with the repository_dependencies_root_key. + all_repository_dependencies_val = all_repository_dependencies[ repository_dependencies_root_key ] + if repository_dependency not in all_repository_dependencies_val: + all_repository_dependencies_val.append( repository_dependency ) + all_repository_dependencies[ repository_dependencies_root_key ] = all_repository_dependencies_val + else: + # Insert this repository_dependency. + all_repository_dependencies[ repository_dependencies_root_key ] = [ repository_dependency ] + if tool_shed_is_this_tool_shed( tool_shed ): + # The repository is in the current tool shed. + required_repository = get_repository_by_name_and_owner( trans, name, owner ) + required_repository_metadata = get_repository_metadata_by_repository_id_changset_revision( trans, + trans.security.encode_id( required_repository.id ), + changeset_revision ) + if required_repository_metadata: + required_repo_dir = required_repository.repo_path( trans.app ) + required_repo = hg.repository( get_configured_ui(), required_repo_dir ) + else: + # The repository changeset_revision is no longer installable, so see if there's been an update. + required_repo_dir = required_repository.repo_path( trans.app ) + required_repo = hg.repository( get_configured_ui(), required_repo_dir ) + required_repository_metadata = get_next_downloadable_changeset_revision( required_repository, required_repo, changeset_revision ) + if required_repository_metadata: + # The required_repository_metadata changeset_revision is installable. + required_metadata = required_repository_metadata.metadata + if required_metadata: + return get_repository_dependencies_for_changeset_revision( trans=trans, + repo=required_repo, + repository=required_repository, + repository_metadata=required_repository_metadata, + toolshed_base_url=tool_shed, + repository_dependencies=repository_dependencies, + all_repository_dependencies=all_repository_dependencies ) + else: + # The repository is in a different tool shed, so build an url and send a request. + raise Exception( "Repository dependencies that refer to repositories in other tool sheds is not yet supported." ) + return all_repository_dependencies def get_repository_file_contents( file_path ): if is_gzip( file_path ): to_html = to_html_str( '\ngzip compressed file\n' ) @@ -917,6 +1148,12 @@ elif all_metadata_records: return all_metadata_records[ 0 ] return None +def get_repository_metadata_by_repository_id_changset_revision( trans, id, changeset_revision ): + """Get a specified metadata record for a specified repository.""" + return trans.sa_session.query( trans.model.RepositoryMetadata ) \ + .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ), + trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \ + .first() def get_relative_path_to_repository_file( root, name, relative_install_dir, work_dir, shed_config_dict, resetting_all_metadata_on_repository ): if resetting_all_metadata_on_repository: full_path_to_file = os.path.join( root, name ) @@ -959,6 +1196,11 @@ relative_path_to_sample_file = relative_path_to_sample_file[ len( tool_path ) + 1 :] sample_file_metadata_paths.append( relative_path_to_sample_file ) return sample_file_metadata_paths, sample_file_copy_paths +def get_user_by_username( trans, username ): + """Get a user from the database by username""" + return trans.sa_session.query( trans.model.User ) \ + .filter( trans.model.User.table.c.username == username ) \ + .one() def handle_existing_tool_dependencies_that_changed_in_update( app, repository, original_dependency_dict, new_dependency_dict ): """ This method is called when a Galaxy admin is getting updates for an installed tool shed repository in order to cover the case where an @@ -1348,6 +1590,8 @@ elif c not in [ '\r' ]: translated.append( '' ) return ''.join( translated ) +def tool_shed_is_this_tool_shed( toolshed_base_url ): + return toolshed_base_url.rstrip( '/' ) == str( url_for( '/', qualified=True ) ).rstrip( '/' ) def update_existing_tool_dependency( app, repository, original_dependency_dict, new_dependencies_dict ): """ Update an exsiting tool dependency whose definition was updated in a change set pulled by a Galaxy administrator when getting updates diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/webapps/community/controllers/common.py --- a/lib/galaxy/webapps/community/controllers/common.py +++ b/lib/galaxy/webapps/community/controllers/common.py @@ -1,4 +1,4 @@ -import os, string, socket, logging, simplejson, binascii, tempfile, filecmp, threading +import os, string, socket, logging, simplejson, binascii, tempfile, filecmp from time import strftime from datetime import * from galaxy.datatypes.checkers import * @@ -7,7 +7,6 @@ from galaxy.util.json import from_json_string, to_json_string from galaxy.util.hash_util import * from galaxy.util.shed_util_common import * -from galaxy.webapps.community.util.container_util import * from galaxy.web.base.controller import * from galaxy.web.base.controllers.admin import * from galaxy.webapps.community import model @@ -21,11 +20,11 @@ log = logging.getLogger( __name__ ) new_repo_email_alert_template = """ +Repository name: ${repository_name} Revision: ${revision} Change description: ${description} -Repository name: ${repository_name} Uploaded by: ${username} Date content uploaded: ${display_date} @@ -41,24 +40,23 @@ """ email_alert_template = """ -GALAXY TOOL SHED REPOSITORY UPDATE ALERT ------------------------------------------------------------------------------ -You received this alert because you registered to receive email whenever -changes were made to the repository named "${repository_name}". ------------------------------------------------------------------------------ - -Date of change: ${display_date} -Changed by: ${username} - +Repository name: ${repository_name} Revision: ${revision} Change description: ${description} +Changed by: ${username} +Date of change: ${display_date} + ${content_alert_str} ----------------------------------------------------------------------------- This change alert was sent from the Galaxy tool shed hosted on the server "${host}" +----------------------------------------------------------------------------- +You received this alert because you registered to receive email whenever +changes were made to the repository named "${repository_name}". +----------------------------------------------------------------------------- """ contact_owner_template = """ @@ -104,62 +102,6 @@ trans.sa_session.flush() return item_rating -def build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ): - containers_dict = dict( datatypes=None, - invalid_tools=None, - repository_dependencies=None, - tool_dependencies=None, - valid_tools=None, - workflows=None ) - if repository_metadata: - metadata = repository_metadata.metadata - lock = threading.Lock() - lock.acquire( True ) - try: - folder_id = 0 - # Datatypes container. - if metadata and 'datatypes' in metadata: - datatypes = metadata[ 'datatypes' ] - folder_id, datatypes_root_folder = build_datatypes_folder( folder_id, datatypes ) - containers_dict[ 'datatypes' ] = datatypes_root_folder - # Invalid tools container. - if metadata and 'invalid_tools' in metadata: - invalid_tool_configs = metadata[ 'invalid_tools' ] - folder_id, invalid_tools_root_folder = build_invalid_tools_folder( folder_id, - invalid_tool_configs, - repository, - changeset_revision, - label='Invalid tools' ) - containers_dict[ 'invalid_tools' ] = invalid_tools_root_folder - # Repository dependencies container. - folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( repository, - changeset_revision, - folder_id, - repository_dependencies ) - if repository_dependencies_root_folder: - containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder - # Tool dependencies container. - if metadata and 'tool_dependencies' in metadata: - tool_dependencies = metadata[ 'tool_dependencies' ] - folder_id, tool_dependencies_root_folder = build_tool_dependencies_folder( folder_id, tool_dependencies ) - containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder - # Valid tools container. - if metadata and 'tools' in metadata: - valid_tools = metadata[ 'tools' ] - folder_id, valid_tools_root_folder = build_tools_folder( folder_id, valid_tools, repository, changeset_revision, label='Valid tools' ) - containers_dict[ 'valid_tools' ] = valid_tools_root_folder - # Workflows container. - if metadata and 'workflows' in metadata: - workflows = metadata[ 'workflows' ] - folder_id, workflows_root_folder = build_workflows_folder( folder_id, workflows, repository_metadata, label='Workflows' ) - containers_dict[ 'workflows' ] = workflows_root_folder - except Exception, e: - repository_dependencies_root_folder = None - tool_dependencies_root_folder = None - log.debug( "Exception in build_repository_containers: %s" % str( e ) ) - finally: - lock.release() - return containers_dict def add_tool_versions( trans, id, repository_metadata, changeset_revisions ): # Build a dictionary of { 'tool id' : 'parent tool id' } pairs for each tool in repository_metadata. metadata = repository_metadata.metadata @@ -401,75 +343,6 @@ def get_repository_by_name( trans, name ): """Get a repository from the database via name""" return trans.sa_session.query( trans.model.Repository ).filter_by( name=name ).one() -def get_repository_by_name_and_owner( trans, name, owner ): - """Get a repository from the database via name and owner""" - user = get_user_by_username( trans, owner ) - return trans.sa_session.query( trans.model.Repository ) \ - .filter( and_( trans.model.Repository.table.c.name == name, - trans.model.Repository.table.c.user_id == user.id ) ) \ - .first() -def get_repository_dependencies_for_changeset_revision( trans, repo, repository, repository_metadata, toolshed_base_url, repository_dependencies=None, - all_repository_dependencies=None ): - """ - Return a dictionary of all repositories upon which the contents of the received repository_metadata record depend. The dictionary keys - are name-spaced values consisting of tool_shed_base_url/repository_name/repository_owner/changeset_revision and the values are lists of - repository_dependency tuples consisting of ( tool_shed_base_url, repository_name, repository_owner, changeset_revision ). This is a - recursive method, so it ensures that all required repositories to the nth degree are returned. - """ - if all_repository_dependencies is None: - all_repository_dependencies = odict() - if repository_dependencies is None: - repository_dependencies = [] - metadata = repository_metadata.metadata - if metadata and 'repository_dependencies' in metadata: - repository_dependencies_root_key = generate_repository_dependencies_key_for_repository( repository, repository_metadata.changeset_revision ) - for repository_dependency in metadata[ 'repository_dependencies' ]: - if repository_dependency not in repository_dependencies: - repository_dependencies.append( repository_dependency ) - else: - repository_dependencies_root_key = None - if repository_dependencies: - repository_dependency = repository_dependencies.pop( 0 ) - tool_shed, name, owner, changeset_revision = repository_dependency - if repository_dependencies_root_key: - if repository_dependencies_root_key in all_repository_dependencies: - # See if this repository_dependency is contained in the list associated with the repository_dependencies_root_key. - all_repository_dependencies_val = all_repository_dependencies[ repository_dependencies_root_key ] - if repository_dependency not in all_repository_dependencies_val: - all_repository_dependencies_val.append( repository_dependency ) - all_repository_dependencies[ repository_dependencies_root_key ] = all_repository_dependencies_val - else: - # Insert this repository_dependency. - all_repository_dependencies[ repository_dependencies_root_key ] = [ repository_dependency ] - if tool_shed_is_this_tool_shed( tool_shed ): - # The repository is in the current tool shed. - required_repository = get_repository_by_name_and_owner( trans, name, owner ) - required_repository_metadata = get_repository_metadata_by_repository_id_changset_revision( trans, - trans.security.encode_id( required_repository.id ), - changeset_revision ) - if required_repository_metadata: - required_repo_dir = required_repository.repo_path( trans.app ) - required_repo = hg.repository( get_configured_ui(), required_repo_dir ) - else: - # The repository changeset_revision is no longer installable, so see if there's been an update. - required_repo_dir = required_repository.repo_path( trans.app ) - required_repo = hg.repository( get_configured_ui(), required_repo_dir ) - required_repository_metadata = get_next_downloadable_changeset_revision( required_repository, required_repo, changeset_revision ) - if required_repository_metadata: - # The required_repository_metadata changeset_revision is installable. - required_metadata = required_repository_metadata.metadata - if required_metadata: - return get_repository_dependencies_for_changeset_revision( trans=trans, - repo=required_repo, - repository=required_repository, - repository_metadata=required_repository_metadata, - toolshed_base_url=tool_shed, - repository_dependencies=repository_dependencies, - all_repository_dependencies=all_repository_dependencies ) - else: - # The repository is in a different tool shed, so build an url and send a request. - raise Exception( "Repository dependencies that refer to repositories in other tool sheds is not yet supported." ) - return all_repository_dependencies def get_repository_metadata_by_id( trans, id ): """Get repository metadata from the database""" return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) ) @@ -477,12 +350,6 @@ """Get all metadata records for a specified repository.""" return trans.sa_session.query( trans.model.RepositoryMetadata ) \ .filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) ) -def get_repository_metadata_by_repository_id_changset_revision( trans, id, changeset_revision ): - """Get a specified metadata record for a specified repository.""" - return trans.sa_session.query( trans.model.RepositoryMetadata ) \ - .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ), - trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \ - .first() def get_repository_metadata_revisions_for_review( repository, reviewed=True ): repository_metadata_revisions = [] metadata_changeset_revision_hashes = [] @@ -635,7 +502,7 @@ else: email_alerts.append( user.email ) else: - subject = "Galaxy tool shed repository update alert" + subject = "Galaxy tool shed update alert for repository named %s" % str( repository.name ) email_alerts = from_json_string( repository.email_alerts ) for email in email_alerts: to = email.strip() @@ -827,8 +694,6 @@ id=trans.security.encode_id( repository.id ), message=error_message, status='error' ) ) -def tool_shed_is_this_tool_shed( toolshed_base_url ): - return toolshed_base_url.rstrip( '/' ) == str( url_for( '/', qualified=True ) ).rstrip( '/' ) def update_for_browsing( trans, repository, current_working_dir, commit_message='' ): # This method id deprecated, but we'll keep it around for a while in case we need it. The problem is that hg purge # is not supported by the mercurial API. diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/webapps/community/controllers/hg.py --- a/lib/galaxy/webapps/community/controllers/hg.py +++ b/lib/galaxy/webapps/community/controllers/hg.py @@ -1,6 +1,7 @@ import os, logging from galaxy.web.base.controller import * -from galaxy.webapps.community.controllers.common import * +from galaxy.util.shed_util_common import get_repository_by_name_and_owner +from galaxy.webapps.community.controllers.common import set_repository_metadata from galaxy import eggs eggs.require('mercurial') diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/webapps/community/controllers/repository.py --- a/lib/galaxy/webapps/community/controllers/repository.py +++ b/lib/galaxy/webapps/community/controllers/repository.py @@ -1278,6 +1278,7 @@ it into a local Galaxy instance. """ includes_tools = False + includes_repository_dependencies = False includes_tool_dependencies = False repo_info_dicts = [] for tup in zip( util.listify( repository_ids ), util.listify( changeset_revisions ) ): @@ -1288,33 +1289,39 @@ metadata = repository_metadata.metadata if not includes_tools and 'tools' in metadata: includes_tools = True + if not includes_repository_dependencies and 'repository_dependencies' in metadata: + includes_repository_dependencies = True if not includes_tool_dependencies and 'tool_dependencies' in metadata: includes_tool_dependencies = True repo_dir = repository.repo_path( trans.app ) repo = hg.repository( get_configured_ui(), repo_dir ) ctx = get_changectx_for_changeset( repo, changeset_revision ) - repo_info_dict = create_repo_info_dict( repository, repository.user.username, repository_clone_url, changeset_revision, str( ctx.rev() ), metadata ) + repo_info_dict = create_repo_info_dict( trans=trans, + repo=repo, + repository_clone_url=repository_clone_url, + changeset_revision=changeset_revision, + ctx_rev=str( ctx.rev() ), + repository_owner=repository.user.username, + repository_name=None, + repository=repository, + repository_metadata=repository_metadata ) repo_info_dicts.append( tool_shed_encode( repo_info_dict ) ) - return dict( includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies, repo_info_dicts=repo_info_dicts ) - @web.expose - def get_readme( self, trans, **kwd ): - """If the received changeset_revision includes a readme file, return it's contents.""" + return dict( includes_tools=includes_tools, + includes_repository_dependencies=includes_repository_dependencies, + includes_tool_dependencies=includes_tool_dependencies, + repo_info_dicts=repo_info_dicts ) + @web.json + def get_readme_files( self, trans, **kwd ): + """ + This method is called when installing or re-installing a single repository into a Galaxy instance. If the received changeset_revision + includes one or more readme files, return them in a dictionary. + """ repository_name = kwd[ 'name' ] repository_owner = kwd[ 'owner' ] changeset_revision = kwd[ 'changeset_revision' ] repository = get_repository_by_name_and_owner( trans, repository_name, repository_owner ) - repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) - metadata = repository_metadata.metadata - if metadata and 'readme' in metadata: - try: - f = open( metadata[ 'readme' ], 'r' ) - text = f.read() - f.close() - return str( text ) - except Exception, e: - log.debug( "Error attempting to read README file '%s' defined in metadata for repository '%s', revision '%s': %s" % \ - ( str( metadata[ 'readme' ] ), str( repository_name ), str( changeset_revision ), str( e ) ) ) - return '' + repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) + return build_readme_files_dict( repository_metadata ) @web.expose def get_tool_dependencies( self, trans, **kwd ): """Handle a request from a local Galaxy instance.""" @@ -1799,7 +1806,7 @@ review_id = trans.security.encode_id( review.id ) else: review_id = None - containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ) + containers_dict = build_repository_containers_for_tool_shed( repository, changeset_revision, repository_dependencies, repository_metadata ) return trans.fill_template( '/webapps/community/repository/manage_repository.mako', cntrller=cntrller, repo_name=repo_name, @@ -1867,8 +1874,6 @@ return state @web.json def open_folder( self, trans, folder_path ): - # The tool shed includes a repository source file browser, which currently depends upon - # copies of the hg repository file store in the repo_path for browsing. # Avoid caching trans.response.headers['Pragma'] = 'no-cache' trans.response.headers['Expires'] = '0' @@ -1904,7 +1909,7 @@ selected_value=changeset_revision, add_id_to_name=False, downloadable=False ) - containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ) + containers_dict = build_repository_containers_for_tool_shed( repository, changeset_revision, repository_dependencies, repository_metadata ) return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako', repository=repository, containers_dict=containers_dict, @@ -2373,52 +2378,6 @@ action='view_repository', **kwd ) ) @web.expose - def view_readme( self, trans, id, changeset_revision, **kwd ): - params = util.Params( kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - cntrller = params.get( 'cntrller', 'repository' ) - repository = get_repository_in_tool_shed( trans, id ) - repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) - if repository_metadata: - metadata = repository_metadata.metadata - else: - metadata = None - if metadata and 'readme' in metadata: - readme_file = str( metadata[ 'readme' ] ) - repo_files_dir = repository.repo_path( trans.app ) - try: - f = open( readme_file, 'r' ) - raw_text = f.read() - f.close() - except IOError: - work_dir = tempfile.mkdtemp() - try: - manifest_readme_file = self.get_file_from_changeset_revision( repo_files_dir, changeset_revision, readme_file, work_dir ) - f = open( manifest_readme_file, 'r' ) - raw_text = f.read() - f.close() - remove_dir( work_dir ) - except Exception, e: - raw_text = "Error locating and reading this repository's README file '%s': %s" % ( readme_file, str( e ) ) - log.debug( raw_text ) - remove_dir( work_dir ) - except Exception, e: - raw_text = "Error locating and reading this repository's README file '%s': %s" % ( readme_file, str( e ) ) - log.debug( raw_text ) - readme_text = raw_text - else: - readme_text = '' - is_malicious = changeset_is_malicious( trans, id, changeset_revision ) - return trans.fill_template( '/webapps/community/common/view_readme.mako', - cntrller=cntrller, - repository=repository, - changeset_revision=changeset_revision, - readme_text=readme_text, - is_malicious=is_malicious, - message=message, - status=status ) - @web.expose def view_repository( self, trans, id, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) @@ -2492,7 +2451,7 @@ review_id = trans.security.encode_id( review.id ) else: review_id = None - containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ) + containers_dict = build_repository_containers_for_tool_shed( repository, changeset_revision, repository_dependencies, repository_metadata ) return trans.fill_template( '/webapps/community/repository/view_repository.mako', cntrller=cntrller, repo=repo, diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 lib/galaxy/webapps/community/util/container_util.py --- a/lib/galaxy/webapps/community/util/container_util.py +++ b/lib/galaxy/webapps/community/util/container_util.py @@ -1,4 +1,4 @@ -import logging +import os, logging from galaxy.web import url_for log = logging.getLogger( __name__ ) @@ -18,6 +18,7 @@ self.valid_tools = [] self.tool_dependencies = [] self.repository_dependencies = [] + self.readme_files = [] self.workflows = [] def contains_folder( self, folder ): for index, contained_folder in enumerate( self.folders ): @@ -42,6 +43,13 @@ self.repository_id = repository_id self.changeset_revision = changeset_revision +class ReadMe( object ): + """Readme text object""" + def __init__( self, id=None, name=None, text=None ): + self.id = id + self.name = name + self.text = text + class RepositoryDependency( object ): """Repository dependency object""" def __init__( self, id=None, toolshed=None, repository_name=None, repository_owner=None, changeset_revision=None ): @@ -67,11 +75,13 @@ class ToolDependency( object ): """Tool dependency object""" - def __init__( self, id=None, name=None, version=None, type=None ): + def __init__( self, id=None, name=None, version=None, type=None, install_dir=None, readme=None ): self.id = id self.name = name self.version = version self.type = type + self.install_dir = install_dir + self.readme = readme class Workflow( object ): """Workflow object""" @@ -111,8 +121,9 @@ else: datatypes_root_folder = None return folder_id, datatypes_root_folder -def build_invalid_tools_folder( folder_id, invalid_tool_configs, repository, changeset_revision, label='Invalid tools' ): +def build_invalid_tools_folder( folder_id, invalid_tool_configs, changeset_revision, repository=None, label='Invalid tools' ): """Return a folder hierarchy containing invalid tools.""" + # TODO: Should we display invalid tools on the tool panel selection page when installing the repository into Galaxy? if invalid_tool_configs: invalid_tool_id = 0 folder_id += 1 @@ -122,15 +133,41 @@ invalid_tools_root_folder.folders.append( folder ) for invalid_tool_config in invalid_tool_configs: invalid_tool_id += 1 + if repository: + repository_id = repository.id + else: + repository_id = None invalid_tool = InvalidTool( id=invalid_tool_id, tool_config=invalid_tool_config, - repository_id=repository.id, + repository_id=repository_id, changeset_revision=changeset_revision ) folder.invalid_tools.append( invalid_tool ) else: invalid_tools_root_folder = None return folder_id, invalid_tools_root_folder -def build_repository_dependencies_folder( repository, changeset_revision, folder_id, repository_dependencies, label='Repository dependencies' ): +def build_readme_files_folder( folder_id, readme_files_dict, label='Readme files' ): + """Return a folder hierarchy containing readme text files.""" + if readme_files_dict: + readme_id = 0 + folder_id += 1 + readme_files_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + readme_files_folder = Folder( id=folder_id, key='readme_files', label=label ) + readme_files_root_folder.folders.append( readme_files_folder ) + for readme_file_name, readme_file_text in readme_files_dict.items(): + readme_id += 1 + readme = ReadMe( id=readme_id, + name=readme_file_name, + text=readme_file_text ) + folder_id += 1 + folder = Folder( id=folder_id, key=readme.name, label=readme.name ) + folder.readme_files.append( readme ) + readme_files_folder.folders.append( folder ) + else: + readme_files_root_folder = None + return folder_id, readme_files_root_folder +def build_repository_dependencies_folder( toolshed_base_url, repository_name, repository_owner, changeset_revision, folder_id, repository_dependencies, + label='Repository dependencies' ): """Return a folder hierarchy containing repository dependencies.""" if repository_dependencies: repository_dependency_id = 0 @@ -139,7 +176,7 @@ repository_dependencies_root_folder = Folder( id=folder_id, key='root', label='root' ) folder_id += 1 # Create the Repository dependencies folder and add it to the root folder. - key = generate_repository_dependencies_key_for_repository( repository, changeset_revision ) + key = generate_repository_dependencies_key_for_repository( toolshed_base_url, repository_name, repository_owner, changeset_revision ) repository_dependencies_folder = Folder( id=folder_id, key=key, label=label ) repository_dependencies_root_folder.folders.append( repository_dependencies_folder ) # Process the repository dependencies. @@ -149,7 +186,7 @@ if not folder: # Create a new folder. folder_id += 1 - label = generate_repository_dependencies_folder_label_from_key( repository, changeset_revision, key ) + label = generate_repository_dependencies_folder_label_from_key( repository_name, repository_owner, changeset_revision, key ) folder = Folder( id=folder_id, key=key, label=label ) for repository_dependency_tup in val: toolshed, name, owner, changeset_revision = repository_dependency_tup @@ -213,7 +250,7 @@ else: tools_root_folder = None return folder_id, tools_root_folder -def build_tool_dependencies_folder( folder_id, tool_dependencies, label='Tool dependencies' ): +def build_tool_dependencies_folder( folder_id, tool_dependencies, label='Tool dependencies', for_galaxy=False ): """Return a folder hierarchy containing tool dependencies.""" if tool_dependencies: tool_dependency_id = 0 @@ -224,22 +261,40 @@ tool_dependencies_root_folder.folders.append( folder ) # Insert a header row. tool_dependency_id += 1 - tool_dependency = ToolDependency( id=tool_dependency_id, - name='Name', - version='Version', - type='Type' ) + if for_galaxy: + # Include the installation directory. + tool_dependency = ToolDependency( id=tool_dependency_id, + name='Name', + version='Version', + type='Type', + install_dir='Install directory' ) + else: + tool_dependency = ToolDependency( id=tool_dependency_id, + name='Name', + version='Version', + type='Type' ) folder.tool_dependencies.append( tool_dependency ) for dependency_key, requirements_dict in tool_dependencies.items(): tool_dependency_id += 1 if dependency_key == 'set_environment': - version = None + for set_environment_dict in requirements_dict: + name = set_environment_dict[ 'name' ] + type = set_environment_dict[ 'type' ] + tool_dependency = ToolDependency( id=tool_dependency_id, + name=name, + type=type ) + folder.tool_dependencies.append( tool_dependency ) else: + name = requirements_dict[ 'name' ] version = requirements_dict[ 'version' ] - tool_dependency = ToolDependency( id=tool_dependency_id, - name=requirements_dict[ 'name' ], - version=version, - type=requirements_dict[ 'type' ] ) - folder.tool_dependencies.append( tool_dependency ) + type = requirements_dict[ 'type' ] + install_dir = requirements_dict.get( 'install_dir', None ) + tool_dependency = ToolDependency( id=tool_dependency_id, + name=name, + version=version, + type=type, + install_dir=install_dir ) + folder.tool_dependencies.append( tool_dependency ) else: tool_dependencies_root_folder = None return folder_id, tool_dependencies_root_folder @@ -279,18 +334,23 @@ else: workflows_root_folder = None return folder_id, workflows_root_folder -def generate_repository_dependencies_folder_label_from_key( repository, changeset_revision, key ): +def generate_repository_dependencies_folder_label_from_key( repository_name, repository_owner, changeset_revision, key ): """Return a repository dependency label based on the repository dependency key.""" - if key_is_current_repositorys_key( repository, changeset_revision, key ): + if key_is_current_repositorys_key( repository_name, repository_owner, changeset_revision, key ): label = 'Repository dependencies' else: toolshed_base_url, name, owner, revision = get_components_from_key( key ) label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( name, revision, owner ) return label -def generate_repository_dependencies_key_for_repository( repository, changeset_revision ): +def generate_repository_dependencies_key_for_repository( toolshed_base_url, repository_name, repository_owner, changeset_revision ): # FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported. - toolshed_base_url = str( url_for( '/', qualified=True ) ).rstrip( '/' ) - return '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository.name, STRSEP, repository.user.username, STRSEP, changeset_revision ) + return '%s%s%s%s%s%s%s' % ( str( toolshed_base_url ).rstrip( '/' ), + STRSEP, + str( repository_name ), + STRSEP, + str( repository_owner ), + STRSEP, + str( changeset_revision ) ) def get_folder( folder, key ): if folder and folder.key == key: return folder @@ -308,7 +368,7 @@ def is_folder( folder_keys, toolshed_base_url, repository_name, repository_owner, changeset_revision ): key = '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository_name, STRSEP, repository_owner, STRSEP, changeset_revision ) return key in folder_keys -def key_is_current_repositorys_key( repository, changeset_revision, key ): - toolshed_base_url, repository_name, repository_owner, changeset_revision = get_components_from_key( key ) - return repository_name == repository.name and repository_owner == repository.user.username and repository_changeset_revision == changeset_revision +def key_is_current_repositorys_key( repository_name, repository_owner, changeset_revision, key ): + toolshed_base_url, key_name, key_owner, key_changeset_revision = get_components_from_key( key ) + return repository_name == key_name and repository_owner == key_owner and changeset_revision == key_changeset_revision \ No newline at end of file diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 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 @@ -2,7 +2,6 @@ from admin import * from galaxy.util.json import from_json_string, to_json_string from galaxy.util.shed_util import * -from galaxy.util.shed_util_common import * from galaxy.tool_shed.encoding_util import * from galaxy import eggs, tools @@ -961,12 +960,6 @@ url_args=dict( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( tool_shed_repository.id ) ) ) ] - if tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata: - view_readme_action = grids.GridAction( label='View README', - url_args=dict( controller='admin_toolshed', - action='view_readme', - id=trans.security.encode_id( tool_shed_repository.id ) ) ) - self.tool_dependency_grid.global_actions.insert( 1, view_readme_action ) if 'operation' in kwd: operation = kwd[ 'operation' ].lower() if not tool_dependency_ids: @@ -1050,6 +1043,9 @@ status = kwd.get( 'status', 'done' ) includes_tools = util.string_as_bool( kwd.get( 'includes_tools', False ) ) tool_shed_url = kwd[ 'tool_shed_url' ] + # Handle repository dependencies. + includes_repository_dependencies = util.string_as_bool( kwd.get( 'includes_repository_dependencies', False ) ) + install_repository_dependencies = kwd.get( 'install_repository_dependencies', '' ) # Every repository will be installed into the same tool panel section or all will be installed outside of any sections. new_tool_panel_section = kwd.get( 'new_tool_panel_section', '' ) tool_panel_section = kwd.get( 'tool_panel_section', '' ) @@ -1071,10 +1067,13 @@ response.close() repo_information_dict = from_json_string( raw_text ) includes_tools = util.string_as_bool( repo_information_dict[ 'includes_tools' ] ) + includes_repository_dependencies = util.string_as_bool( repo_information_dict[ 'includes_repository_dependencies' ] ) includes_tool_dependencies = util.string_as_bool( repo_information_dict[ 'includes_tool_dependencies' ] ) encoded_repo_info_dicts = util.listify( repo_information_dict[ 'repo_info_dicts' ] ) repo_info_dicts = [ tool_shed_decode( encoded_repo_info_dict ) for encoded_repo_info_dict in encoded_repo_info_dicts ] - if not includes_tools or ( includes_tools and kwd.get( 'select_tool_panel_section_button', False ) ): + if ( not includes_tools and not includes_repository_dependencies ) or \ + ( ( includes_tools or includes_repository_dependencies ) and kwd.get( 'select_tool_panel_section_button', False ) ): + install_repository_dependencies = CheckboxField.is_checked( install_repository_dependencies ) if includes_tools: install_tool_dependencies = CheckboxField.is_checked( install_tool_dependencies ) shed_tool_conf = kwd[ 'shed_tool_conf' ] @@ -1100,10 +1099,9 @@ filtered_repo_info_dicts = [] for repo_info_dict in repo_info_dicts: for name, repo_info_tuple in repo_info_dict.items(): - description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple + description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = repo_info_tuple clone_dir = os.path.join( tool_path, self.generate_tool_path( repository_clone_url, changeset_revision ) ) relative_install_dir = os.path.join( clone_dir, name ) - owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) ) # Make sure the repository was not already installed. installed_tool_shed_repository, installed_changeset_revision = self.repository_was_previously_installed( trans, tool_shed_url, @@ -1111,7 +1109,7 @@ repo_info_tuple, clone_dir ) if installed_tool_shed_repository: - message += "The tool shed repository <b>%s</b> with owner <b>%s</b> and changeset revision <b>%s</b> " % ( name, owner, changeset_revision ) + message += "Revision <b>%s</b> of tool shed repository <b>%s</b> owned by <b>%s</b> " % ( changeset_revision, name, repository_owner ) if installed_changeset_revision != changeset_revision: message += "was previously installed using changeset revision <b>%s</b>. " % installed_changeset_revision else: @@ -1123,7 +1121,8 @@ if installed_changeset_revision != changeset_revision: message += "You can get the latest updates for the repository using the <b>Get updates</b> option from the repository's " message += "<b>Repository Actions</b> pop-up menu. " - message+= 'Click <a href="%s">here</a> to manage the repository. ' % ( web.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( installed_tool_shed_repository.id ) ) ) + message+= 'Click <a href="%s">here</a> to manage the repository. ' % \ + ( web.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( installed_tool_shed_repository.id ) ) ) status = 'error' if len( repo_info_dicts ) == 1: new_kwd = dict( message=message, status=status ) @@ -1131,7 +1130,7 @@ action='browse_repositories', **new_kwd ) ) else: - print "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % name + log.debug( "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % name ) tool_shed_repository = create_or_update_tool_shed_repository( app=trans.app, name=name, description=description, @@ -1141,7 +1140,7 @@ metadata_dict={}, status=trans.model.ToolShedRepository.installation_status.NEW, current_changeset_revision=changeset_revision, - owner=owner, + owner=repository_owner, dist_to_shed=False ) created_or_updated_tool_shed_repositories.append( tool_shed_repository ) filtered_repo_info_dicts.append( tool_shed_encode( repo_info_dict ) ) @@ -1171,6 +1170,7 @@ tool_section = None tsrids_list = [ trans.security.encode_id( tsr.id ) for tsr in created_or_updated_tool_shed_repositories ] new_kwd = dict( includes_tools=includes_tools, + includes_repository_dependencies=includes_repository_dependencies, includes_tool_dependencies=includes_tool_dependencies, install_tool_dependencies=install_tool_dependencies, message=message, @@ -1203,42 +1203,53 @@ shed_tool_conf = shed_tool_conf.replace( './', '', 1 ) shed_tool_conf_select_field = None tool_panel_section_select_field = build_tool_panel_section_select_field( trans ) - if includes_tools and len( repo_info_dicts ) == 1: - # If we're installing a single repository, see if it contains a readme file tha twe can display. + if len( repo_info_dicts ) == 1: + # If we're installing a single repository, see if it contains a readme or dependencies that we can display. repo_info_dict = repo_info_dicts[ 0 ] name = repo_info_dict.keys()[ 0 ] repo_info_tuple = repo_info_dict[ name ] - description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple + description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = repo_info_tuple url = url_join( tool_shed_url, - 'repository/get_readme?name=%s&owner=%s&changeset_revision=%s' % \ + 'repository/get_readme_files?name=%s&owner=%s&changeset_revision=%s' % \ ( name, repository_owner, changeset_revision ) ) response = urllib2.urlopen( url ) raw_text = response.read() response.close() - readme_text = raw_text + readme_files_dict = from_json_string( raw_text ) + containers_dict = build_repository_containers_for_galaxy( trans=trans, + toolshed_base_url=tool_shed_url, + repository_name=name, + repository_owner=repository_owner, + changeset_revision=changeset_revision, + readme_files_dict=readme_files_dict, + repository_dependencies=repository_dependencies, + tool_dependencies=tool_dependencies ) else: - readme_text = '' + containers_dict = dict( readme_files_dict=None, repository_dependencies=None, tool_dependencies=None ) + # Handle tool dependencies chack box. if trans.app.config.tool_dependency_dir is None: if includes_tool_dependencies: - message = "Tool dependencies defined in this repository can be automatically installed if you set the value of your <b>tool_dependency_dir</b>" - message += " setting in your Galaxy config file (universe_wsgi.ini) and restart your Galaxy server before installing the repository." + message = "Tool dependencies defined in this repository can be automatically installed if you set the value of your <b>tool_dependency_dir</b> " + message += "setting in your Galaxy config file (universe_wsgi.ini) and restart your Galaxy server before installing the repository." status = "warning" - checked = False + install_tool_dependencies_check_box_checked = False else: - checked = True - install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=checked ) + install_tool_dependencies_check_box_checked = True + install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=install_tool_dependencies_check_box_checked ) + # Handle repository dependencies check box. + install_repository_dependencies_check_box = CheckboxField( 'install_repository_dependencies', checked=True ) return trans.fill_template( '/admin/tool_shed_repository/select_tool_panel_section.mako', encoded_repo_info_dicts=encoded_repo_info_dicts, includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies, + install_repository_dependencies_check_box=install_repository_dependencies_check_box, install_tool_dependencies_check_box=install_tool_dependencies_check_box, new_tool_panel_section=new_tool_panel_section, - repo_info_dicts=repo_info_dicts, + containers_dict=containers_dict, shed_tool_conf=shed_tool_conf, shed_tool_conf_select_field=shed_tool_conf_select_field, tool_panel_section_select_field=tool_panel_section_select_field, tool_shed_url=kwd[ 'tool_shed_url' ], - readme_text=readme_text, message=message, status=status ) @web.expose @@ -1269,8 +1280,8 @@ tool_panel_dict = generate_tool_panel_dict_for_new_install( metadata[ 'tools' ] ) else: tool_panel_dict = generate_tool_panel_dict_for_new_install( metadata[ 'tools' ] ) - # TODO: Fix this to handle the case where the tools are distributed across in more than 1 ToolSection. The - # following assumes everything was loaded into 1 section (or no section) in the tool panel. + # Fix this to handle the case where the tools are distributed across in more than 1 ToolSection - this assumes everything was loaded into 1 + # section (or no section) in the tool panel. tool_section_dicts = tool_panel_dict[ tool_panel_dict.keys()[ 0 ] ] tool_section_dict = tool_section_dicts[ 0 ] original_section_id = tool_section_dict[ 'id' ] @@ -1328,12 +1339,16 @@ # The repo_info_dict should be encoded. if not repo_info_dict: # This should only happen if the tool_shed_repository does not include any valid tools. - repo_info_dict = create_repo_info_dict( tool_shed_repository, - tool_shed_repository.owner, - repository_clone_url, - tool_shed_repository.installed_changeset_revision, - ctx_rev, - metadata ) + repo = hg.repository( get_configured_ui(), path=os.path.abspath( tool_shed_repository.repo_path( trans.app ) ) ) + repo_info_dict = create_repo_info_dict( trans=trans, + repo=repo, + repository_clone_url=repository_clone_url, + changeset_revision=tool_shed_repository.installed_changeset_revision, + ctx_rev=ctx_rev, + repository_owner=tool_shed_repository.owner, + repository_name=tool_shed_repository.name, + repository=None, + repository_metadata=None ) repo_info_dict = tool_shed_encode( repo_info_dict ) new_kwd = dict( includes_tool_dependencies=tool_shed_repository.includes_tool_dependencies, includes_tools=tool_shed_repository.includes_tools, @@ -1410,12 +1425,16 @@ tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository ) ctx_rev = get_ctx_rev( tool_shed_url, repository.name, repository.owner, repository.installed_changeset_revision ) repository_clone_url = generate_clone_url_for_installed_repository( trans, repository ) - repo_info_dict = create_repo_info_dict( repository, - repository.owner, - repository_clone_url, - repository.installed_changeset_revision, - ctx_rev, - metadata ) + repo = hg.repository( get_configured_ui(), path=os.path.abspath( tool_shed_repository.repo_path( trans.app ) ) ) + repo_info_dict = create_repo_info_dict( trans=trans, + repo=repo, + repository_clone_url=repository_clone_url, + changeset_revision=repository.installed_changeset_revision, + ctx_rev=ctx_rev, + repository_owner=repository.owner, + repository_name=repository.name, + repository=None, + repository_metadata=None ) # Get the location in the tool panel in which the tool was originally loaded. if 'tool_panel_section' in metadata: tool_panel_dict = metadata[ 'tool_panel_section' ] @@ -1444,28 +1463,46 @@ message = "The tools contained in your <b>%s</b> repository were last loaded into the tool panel outside of any sections. " % repository.name message += "Uncheck the <b>No changes</b> check box and select a tool panel section to load the tools into that section." status = 'warning' - includes_tool_dependencies = 'tool_dependencies' in metadata - install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=True ) - if metadata and 'readme' in metadata: + if metadata and 'readme_files' in metadata: url = url_join( tool_shed_url, - 'repository/get_readme?name=%s&owner=%s&changeset_revision=%s' % \ + 'repository/get_readme_files?name=%s&owner=%s&changeset_revision=%s' % \ ( repository.name, repository.owner, repository.installed_changeset_revision ) ) response = urllib2.urlopen( url ) raw_text = response.read() response.close() - readme_text = raw_text + readme_files_dict = from_json_string( raw_text ) + containers_dict = build_repository_containers_for_galaxy( trans=trans, + toolshed_base_url=tool_shed_url, + repository_name=name, + repository_owner=repository_owner, + changeset_revision=changeset_revision, + readme_files_dict=readme_files_dict, + repository_dependencies=repository_dependencies, + tool_dependencies=tool_dependencies ) else: - readme_text = '' + containers_dict = dict( readme_files_dict=None, repository_dependencies=None, tool_dependencies=None ) + # Handle repository dependencies check box. + install_repository_dependencies_check_box = CheckboxField( 'install_repository_dependencies', checked=True ) + # Handle tool dependencies check box. + if trans.app.config.tool_dependency_dir is None: + if includes_tool_dependencies: + message = "Tool dependencies defined in this repository can be automatically installed if you set the value of your <b>tool_dependency_dir</b> " + message += "setting in your Galaxy config file (universe_wsgi.ini) and restart your Galaxy server before installing the repository." + status = "warning" + install_tool_dependencies_check_box_checked = False + else: + install_tool_dependencies_check_box_checked = True + install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=install_tool_dependencies_check_box_checked ) return trans.fill_template( '/admin/tool_shed_repository/reselect_tool_panel_section.mako', repository=repository, - readme_text=readme_text, no_changes_check_box=no_changes_check_box, original_section_name=original_section_name, + install_repository_dependencies_check_box=install_repository_dependencies_check_box, install_tool_dependencies_check_box=install_tool_dependencies_check_box, + containers_dict=containers_dict, tool_panel_section_select_field=tool_panel_section_select_field, encoded_repo_info_dict=tool_shed_encode( repo_info_dict ), repo_info_dict=repo_info_dict, - includes_tool_dependencies=includes_tool_dependencies, message=message, status=status ) @web.expose @@ -1714,41 +1751,6 @@ status=status ) ) @web.expose @web.require_admin - def view_readme( self, trans, id, **kwd ): - params = util.Params( kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - cntrller = params.get( 'cntrller', 'admin_toolshed' ) - status = params.get( 'status', 'done' ) - repository = get_installed_tool_shed_repository( trans, id ) - metadata = repository.metadata - shed_config_dict = repository.get_shed_config_dict( trans.app ) - tool_path = shed_config_dict.get( 'tool_path', None ) - if metadata and 'readme' in metadata: - readme_filename = metadata[ 'readme' ] - if tool_path: - readme_filename = os.path.join( tool_path, readme_filename ) - try: - f = open( readme_filename, 'r' ) - raw_text = f.read() - f.close() - readme_text = raw_text - except Exception, e: - log.debug( "Error attempting to read README file '%s' defined in metadata for repository '%s', revision '%s': %s" % \ - ( str( readme_filename ), str( repository.name ), str( repository.changeset_revision ), str( e ) ) ) - readme_text = '' - else: - readme_text = '' - is_malicious = False - return trans.fill_template( '/webapps/community/common/view_readme.mako', - cntrller=cntrller, - repository=repository, - changeset_revision=repository.changeset_revision, - readme_text=readme_text, - is_malicious=is_malicious, - message=message, - status=status ) - @web.expose - @web.require_admin def view_tool_metadata( self, trans, repository_id, tool_id, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/browse_repository.mako --- a/templates/admin/tool_shed_repository/browse_repository.mako +++ b/templates/admin/tool_shed_repository/browse_repository.mako @@ -18,9 +18,6 @@ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> - %if repository.has_readme: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> - %endif <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> %if repository.can_reset_metadata: <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='reset_repository_metadata', id=trans.security.encode_id( repository.id ) )}">Reset repository metadata</a> diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/browse_tool_dependency.mako --- a/templates/admin/tool_shed_repository/browse_tool_dependency.mako +++ b/templates/admin/tool_shed_repository/browse_tool_dependency.mako @@ -20,9 +20,6 @@ <li><a class="action-button" id="tool_dependency-${tool_dependency.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="tool_dependency-${tool_dependency.id}-popup"><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> - %if repository.has_readme: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> - %endif <a class="action-button" 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" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> %if repository.can_reset_metadata: diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/common.mako --- a/templates/admin/tool_shed_repository/common.mako +++ b/templates/admin/tool_shed_repository/common.mako @@ -1,3 +1,5 @@ +<%namespace file="/webapps/community/repository/common.mako" import="*" /> + <%def name="browse_files(title_text, directory_path)"><script type="text/javascript"> $(function(){ @@ -67,146 +69,107 @@ </script></%def> -<%def name="render_tool_dependency_section( install_tool_dependencies_check_box, repo_info_dicts )"> - <% import os %> +<%def name="render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )"> + <style type="text/css"> + #dependency_table{ table-layout:fixed; + width:100%; + overflow-wrap:normal; + overflow:hidden; + border:0px; + word-break:keep-all; + word-wrap:break-word; + line-break:strict; } + </style> + <% + class RowCounter( object ): + def __init__( self ): + self.count = 0 + def increment( self ): + self.count += 1 + def __str__( self ): + return str( self.count ) + + repository_dependencies_root_folder = containers_dict[ 'repository_dependencies' ] + tool_dependencies_root_folder = containers_dict[ 'tool_dependencies' ] + env_settings_heaader_row_displayed = False + package_header_row_displayed = False + %><div class="form-row"><div class="toolParamHelp" style="clear: both;"><p> - These tool dependencies can be automatically handled with the installed repository, providing significant benefits, and + These dependencies can be automatically handled with the installed repository, providing significant benefits, and Galaxy includes various features to manage them. </p></div></div> - <div class="form-row"> - <label>Handle tool dependencies?</label> - <% disabled = trans.app.config.tool_dependency_dir is None %> - ${install_tool_dependencies_check_box.get_html( disabled=disabled )} - <div class="toolParamHelp" style="clear: both;"> - %if disabled: - Set the tool_dependency_dir configuration value in your universe_wsgi.ini to automatically handle tool dependencies. - %else: - Un-check to skip automatic handling of these tool dependencies. + %if repository_dependencies_root_folder: + <div class="form-row"> + <label>Handle repository dependencies?</label> + ${install_repository_dependencies_check_box.get_html()} + <div class="toolParamHelp" style="clear: both;"> + Un-check to skip automatic installation of these additional repositories required by this repository. + </div> + </div> + <div style="clear: both"></div> + <div class="form-row"> + %if repository_dependencies_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table"> + ${render_folder( repository_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> %endif + <div style="clear: both"></div></div> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <style type="text/css"> - #dependency_table{ table-layout:fixed; - width:100%; - overflow-wrap:normal; - overflow:hidden; - border:0px; - word-break:keep-all; - word-wrap:break-word; - line-break:strict; } - </style> - <table class="grid" id="dependency_table"> - <tr><td colspan="4" bgcolor="#D8D8D8"><b>Tool dependencies</b></td></tr> - <% - env_settings_heaader_row_displayed = False - package_header_row_displayed = False - %> - %for repo_info_dict in repo_info_dicts: - %for repository_name, repo_info_tuple in repo_info_dict.items(): - <% description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple %> - %if tool_dependencies: - <% - # See if tool dependencies are packages, environment settings or both. - contains_packages = False - for k in tool_dependencies.keys(): - if k != 'set_environment': - contains_packages = True - break - contains_env_settings = 'set_environment' in tool_dependencies.keys() - %> - %if contains_packages: - %if not package_header_row_displayed: - <% - info_str = "Each of these packages may require their own build requirements (e.g., CMake, g++, etc). " - info_str += "Galaxy will not attempt to install these build requirements, so tool dependency installation " - info_str += "may partially fail if any are missing from your environment, but the repository and all of it's " - info_str += "contents will be installed. You can install the missing build requirements and have Galaxy attempt " - info_str += "to install the packages again if tool dependency installation fails in any way." - %> - </tr><td bgcolor="#FFFFCC" colspan="4">${info_str}</td></tr> - <tr> - <th>Name</th> - <th>Version</th> - <th>Type</th> - <th>Install directory</th> - </tr> - <% package_header_row_displayed = True %> - %endif - %for dependency_key, requirements_dict in tool_dependencies.items(): - %if dependency_key not in [ 'set_environment' ]: - <% - name = requirements_dict[ 'name' ] - version = requirements_dict[ 'version' ] - type = requirements_dict[ 'type' ] - install_dir = os.path.join( trans.app.config.tool_dependency_dir, - name, - version, - repository_owner, - repository_name, - changeset_revision ) - tool_dependency_readme_text = requirements_dict.get( 'readme', None ) - %> - %if not os.path.exists( install_dir ): - <tr> - <td>${name}</td> - <td>${version}</td> - <td>${type}</td> - <td>${install_dir}</td> - </tr> - %if tool_dependency_readme_text: - <tr><td colspan="4" bgcolor="#FFFFCC">${name} ${version} requirements and installation information</td></tr> - <tr><td colspan="4"><pre>${tool_dependency_readme_text}</pre></td></tr> - %endif - %endif - %endif - %endfor - %endif - %if contains_env_settings: - <% environment_settings = tool_dependencies[ 'set_environment' ] %> - %if not env_settings_heaader_row_displayed: - <% - info_str = "Each of these environment settings will be defined in a file named env.sh in the installation directory." - %> - </tr><td bgcolor="#FFFFCC" colspan="4">${info_str}</td></tr> - <tr> - <th>Name</th> - <th>Type</th> - <th colspan="2">Install directory for environment shell file</th> - </tr> - <% env_settings_heaader_row_displayed = True %> - %endif - %for environment_setting_dict in environment_settings: - <% - name = environment_setting_dict[ 'name' ] - type = environment_setting_dict[ 'type' ] - install_dir = os.path.join( trans.app.config.tool_dependency_dir, - 'environment_settings', - name, - repository_owner, - repository_name, - changeset_revision ) - %> - %if not os.path.exists( install_dir ): - <tr> - <td>${name}</td> - <td>${type}</td> - <td colspan="2">${install_dir}</td> - </tr> - %endif - %endfor - %endif - %endif - %endfor - %endfor - </table> + %endif + %if tool_dependencies_root_folder: + <div class="form-row"> + <label>Handle tool dependencies?</label> + <% disabled = trans.app.config.tool_dependency_dir is None %> + ${install_tool_dependencies_check_box.get_html( disabled=disabled )} + <div class="toolParamHelp" style="clear: both;"> + %if disabled: + Set the tool_dependency_dir configuration value in your Galaxy config to automatically handle tool dependencies. + %else: + Un-check to skip automatic handling of these tool dependencies. + %endif + </div> + </div><div style="clear: both"></div> - </div> + <div class="form-row"> + %if tool_dependencies_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="dependency_table"> + ${render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + %endif + <div style="clear: both"></div> + </div> + %endif +</%def> + +<%def name="render_readme_section( containers_dict )"> + <% + class RowCounter( object ): + def __init__( self ): + self.count = 0 + def increment( self ): + self.count += 1 + def __str__( self ): + return str( self.count ) + + readme_files_root_folder = containers_dict[ 'readme_files' ] + %> + %if readme_files_root_folder: + <p/> + <div class="form-row"> + <% row_counter = RowCounter() %> + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table"> + ${render_folder( readme_files_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + </div> + %endif </%def><%def name="dependency_status_updater()"> diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 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 @@ -7,9 +7,6 @@ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> - %if repository.has_readme: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> - %endif <a class="action-button" 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" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> %if repository.can_reset_metadata: diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/manage_repository.mako --- a/templates/admin/tool_shed_repository/manage_repository.mako +++ b/templates/admin/tool_shed_repository/manage_repository.mako @@ -14,9 +14,6 @@ %elif repository.can_install: <a class="action-button" 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: - %if repository.has_readme: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> - %endif <a class="action-button" 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" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> %if repository.can_reset_metadata: diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/reselect_tool_panel_section.mako --- a/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako +++ b/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako @@ -1,19 +1,33 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/admin/tool_shed_repository/common.mako" import="render_tool_dependency_section" /> -<%namespace file="/webapps/community/common/common.mako" import="render_readme" /> +<%namespace file="/admin/tool_shed_repository/common.mako" import="render_dependencies_section" /> +<%namespace file="/admin/tool_shed_repository/common.mako" import="render_readme_section" /> %if message: ${render_msg( message, status )} %endif <div class="toolForm"> - <div class="toolFormTitle">Choose the tool panel section to contain the installed tools (optional)</div><div class="toolFormBody"><form name="reselect_tool_panel_section" id="reselect_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='reinstall_repository', id=trans.security.encode_id( repository.id ), repo_info_dict=encoded_repo_info_dict )}" method="post" ><div style="clear: both"></div> - %if includes_tool_dependencies: - ${render_tool_dependency_section( install_tool_dependencies_check_box, [ repo_info_dict ] )} + <% readme_files_dict = containers_dict[ 'readme_files' ] %> + %if readme_files_dict: + <div class="form-row"> + <table class="colored" width="100%"> + <th bgcolor="#EBD9B2">Repository README file (may contain important installation or license information)</th> + </table> + </div> + ${render_readme_section( containers_dict )} + <div style="clear: both"></div> + %endif + %if includes_repository_dependencies or includes_tool_dependencies: + <div class="form-row"> + <table class="colored" width="100%"> + <th bgcolor="#EBD9B2">Confirm dependency installation</th> + </table> + </div> + ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )} %endif <div style="clear: both"></div><div class="form-row"> @@ -43,6 +57,3 @@ </form></div></div> -%if readme_text: - ${render_readme( readme_text )} -%endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/select_tool_panel_section.mako --- a/templates/admin/tool_shed_repository/select_tool_panel_section.mako +++ b/templates/admin/tool_shed_repository/select_tool_panel_section.mako @@ -1,7 +1,19 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/admin/tool_shed_repository/common.mako" import="render_tool_dependency_section" /> -<%namespace file="/webapps/community/common/common.mako" import="render_readme" /> +<%namespace file="/admin/tool_shed_repository/common.mako" import="render_dependencies_section" /> +<%namespace file="/admin/tool_shed_repository/common.mako" import="render_readme_section" /> +<%namespace file="/webapps/community/repository/common.mako" import="*" /> + +<%def name="stylesheets()"> + ${parent.stylesheets()} + ${h.css( "library" )} +</%def> + +<%def name="javascripts()"> + ${parent.javascripts()} + ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} + ${container_javascripts()} +</%def> %if message: ${render_msg( message, status )} @@ -21,26 +33,34 @@ general questions or concerns. </p></div> -<br/> - <div class="toolForm"> - %if includes_tool_dependencies and trans.app.config.use_tool_dependencies: - <div class="toolFormTitle">Confirm tool dependency installation</div> - %else: - <div class="toolFormTitle">Choose the tool panel section to contain the installed tools (optional)</div> - %endif <div class="toolFormBody"><form name="select_tool_panel_section" id="select_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='prepare_for_install', tool_shed_url=tool_shed_url, encoded_repo_info_dicts=encoded_repo_info_dicts, includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies )}" method="post" ><div style="clear: both"></div> - %if includes_tool_dependencies and trans.app.config.use_tool_dependencies: - ${render_tool_dependency_section( install_tool_dependencies_check_box, repo_info_dicts )} - <div style="clear: both"></div> + <% readme_files_dict = containers_dict[ 'readme_files' ] %> + %if readme_files_dict: <div class="form-row"><table class="colored" width="100%"> - <th bgcolor="#EBD9B2">Choose the tool panel section to contain the installed tools (optional)</th> + <th bgcolor="#EBD9B2">Repository README file (may contain important installation or license information)</th></table></div> + ${render_readme_section( containers_dict )} + <div style="clear: both"></div> %endif + %if includes_repository_dependencies or ( includes_tool_dependencies and trans.app.config.use_tool_dependencies ): + <div class="form-row"> + <table class="colored" width="100%"> + <th bgcolor="#EBD9B2">Confirm dependency installation</th> + </table> + </div> + ${render_dependencies_section( install_repository_dependencies_check_box, install_tool_dependencies_check_box, containers_dict )} + <div style="clear: both"></div> + %endif + <div class="form-row"> + <table class="colored" width="100%"> + <th bgcolor="#EBD9B2">Choose the tool panel section to contain the installed tools (optional)</th> + </table> + </div> %if shed_tool_conf_select_field: <div class="form-row"><label>Shed tool configuration file:</label> @@ -77,6 +97,3 @@ </form></div></div> -%if readme_text: - ${render_readme( readme_text )} -%endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako --- a/templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako +++ b/templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako @@ -7,9 +7,6 @@ <ul class="manage-table-actions"><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"> - %if repository.has_readme: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> - %endif <a class="action-button" 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" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/admin/tool_shed_repository/view_tool_metadata.mako --- a/templates/admin/tool_shed_repository/view_tool_metadata.mako +++ b/templates/admin/tool_shed_repository/view_tool_metadata.mako @@ -5,9 +5,6 @@ <ul class="manage-table-actions"><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"> - %if repository_metadata and 'readme' in repository_metadata: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> - %endif <a class="action-button" 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" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/common/common.mako --- a/templates/webapps/community/common/common.mako +++ b/templates/webapps/community/common/common.mako @@ -57,29 +57,6 @@ ${html} </%def> -<%def name="render_readme( readme_text )"> - <style type="text/css"> - #readme_table{ table-layout:fixed; - width:100%; - overflow-wrap:normal; - overflow:hidden; - border:0px; - word-break:keep-all; - word-wrap:break-word; - line-break:strict; } - </style> - <div class="toolForm"> - <div class="toolFormTitle">Repository README file (may contain important installation or license information)</div> - <div class="toolFormBody"> - <div class="form-row"> - <table id="readme_table"> - <tr><td>${ escape_html_add_breaks( readme_text ) }</td></tr> - </table> - </div> - </div> - </div> -</%def> - <%def name="render_long_description( description_text )"><style type="text/css"> #description_table{ table-layout:fixed; diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/common/view_readme.mako --- a/templates/webapps/community/common/view_readme.mako +++ /dev/null @@ -1,88 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/webapps/community/common/common.mako" import="render_readme" /> - -<% - if trans.webapp.name == 'community': - is_admin = trans.user_is_admin() - is_new = repository.is_new( trans.app ) - can_contact_owner = trans.user and trans.user != repository.user - can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository ) - can_rate = not is_new and trans.user and repository.user != trans.user - can_upload = can_push - can_download = not is_new and ( not is_malicious or can_push ) - can_browse_contents = not is_new - can_view_change_log = not is_new - can_manage = is_admin or repository.user == trans.user - if can_push: - browse_label = 'Browse or delete repository tip files' - else: - browse_label = 'Browse repository tip files' -%> - -<br/><br/> -<ul class="manage-table-actions"> - %if trans.webapp.name == 'community': - <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li> - <div popupmenu="repository-${repository.id}-popup"> - %if can_manage: - <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a> - %else: - <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a> - %endif - %if can_upload: - <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> - %endif - %if can_view_change_log: - <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> - %endif - %if can_rate: - <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a> - %endif - %if can_browse_contents: - <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label | h}</a> - %endif - %if can_contact_owner: - <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a> - %endif - %if can_download: - <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a> - <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a> - <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a> - %endif - </div> - %else: - %if cntrller=='repository': - <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', operation='preview_tools_in_changeset', id=trans.security.encode_id( repository.id ) )}">Preview tools for install</a></li> - <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li> - <div popupmenu="repository-${repository.id}-popup"> - <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a> - <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a> - <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a> - </div> - %else: - <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li> - <div popupmenu="repository-${repository.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> - <a class="action-button" 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" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> - %if repository.includes_tools: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='set_tool_versions', id=trans.security.encode_id( repository.id ) )}">Set tool versions</a> - %endif - %if repository.tool_dependencies: - <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a> - %endif - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a> - </div> - %endif - %endif -</ul> - -%if message: - ${render_msg( message, status )} -%endif - -%if readme_text: - ${render_readme( readme_text )} -%endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/browse_repository.mako --- a/templates/webapps/community/repository/browse_repository.mako +++ b/templates/webapps/community/repository/browse_repository.mako @@ -77,9 +77,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/common.mako --- a/templates/webapps/community/repository/common.mako +++ b/templates/webapps/community/repository/common.mako @@ -1,3 +1,5 @@ +<%namespace file="/webapps/community/common/common.mako" import="escape_html_add_breaks" /> + <%def name="common_javascripts(repository)"><script type="text/javascript"> $(function(){ @@ -75,7 +77,7 @@ </script></%def> -<%def name="dependency_javascripts()"> +<%def name="container_javascripts()"><script type="text/javascript"> var init_dependencies = function() { var storage_id = "library-expand-state-${trans.security.encode_id(10000)}"; @@ -199,30 +201,29 @@ ><% col_span_str = '' + folder_label = str( folder.label ) if folder.datatypes: - label = folder.label col_span_str = 'colspan="4"' elif folder.label == 'Repository dependencies': - label = "%s<i> - this repository requires installation of these additional repositories</i>" % folder.label - elif folder.repository_dependencies: - label = folder.label + folder_label = "%s<i> - this repository requires installation of these additional repositories</i>" % folder_label + elif folder.key == 'readme_files': + folder_label = "%s<i> - may contain important installation or license information</i>" % folder_label elif folder.invalid_tools: - label = "%s<i> - click the tool config file name to see why the tool is invalid</i>" % folder.label + folder_label = "%s<i> - click the tool config file name to see why the tool is invalid</i>" % folder_label elif folder.tool_dependencies: - label = "%s<i> - this repository's tools require installation of these dependencies</i>" % folder.label + folder_label = "%s<i> - this repository's tools require handling of these dependencies</i>" % folder_label col_span_str = 'colspan="3"' elif folder.valid_tools: - label = "%s<i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i>" % folder.label + folder_label = "%s<i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i>" % folder_label col_span_str = 'colspan="3"' elif folder.workflows: - label = folder.label col_span_str = 'colspan="4"' %><td ${col_span_str} style="padding-left: ${folder_pad}px;"><span class="expandLink folder-${encoded_id}-click"><div style="float: left; margin-left: 2px;" class="expandLink folder-${encoded_id}-click"><a class="folder-${encoded_id}-click" href="javascript:void(0);"> - ${label} + ${folder_label} </a></div></span> @@ -236,6 +237,9 @@ %for sub_folder in folder.folders: ${render_folder( sub_folder, pad, parent=my_row, row_counter=row_counter, is_root_folder=False )} %endfor + %for readme in folder.readme_files: + ${render_readme( readme, pad, my_row, row_counter )} + %endfor %for repository_dependency in folder.repository_dependencies: ${render_repository_dependency( repository_dependency, pad, my_row, row_counter )} %endfor @@ -298,9 +302,30 @@ %endif id="libraryItem-${encoded_id}"><td style="padding-left: ${pad+20}px;"> - <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( invalid_tool.repository_id ), tool_config=invalid_tool.tool_config, changeset_revision=invalid_tool.changeset_revision )}"> + %if invalid_tool.repository_id and invalid_tool.tool_config and invalid_tool.changeset_revision: + <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( invalid_tool.repository_id ), tool_config=invalid_tool.tool_config, changeset_revision=invalid_tool.changeset_revision )}"> + ${invalid_tool.tool_config | h} + </a> + %else: ${invalid_tool.tool_config | h} - </a> + %endif + </td> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_readme( readme, pad, parent, row_counter )"> + <% encoded_id = trans.security.encode_id( readme.id ) %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + <td style="padding-left: ${pad+20}px;"> + ${escape_html_add_breaks( readme.text )} </td></tr><% @@ -311,14 +336,19 @@ <%def name="render_repository_dependency( repository_dependency, pad, parent, row_counter )"> - <% encoded_id = trans.security.encode_id( repository_dependency.id ) %> + <% + encoded_id = trans.security.encode_id( repository_dependency.id ) + repository_name = str( repository_dependency.repository_name ) + changeset_revision = str( repository_dependency.changeset_revision ) + repository_owner = str( repository_dependency.repository_owner ) + %><tr class="datasetRow" %if parent is not None: parent="${parent}" %endif id="libraryItem-${encoded_id}"> ##<td style="padding-left: ${pad+20}px;">${repository_dependency.toolshed | h}</td> - <td style="padding-left: ${pad+20}px;">Repository <b>${repository_dependency.repository_name | h}</b> revision <b>${repository_dependency.changeset_revision | h}</b> owned by <b>${repository_dependency.repository_owner | h}</b></td> + <td style="padding-left: ${pad+20}px;">Repository <b>${repository_name | h}</b> revision <b>${changeset_revision | h}</b> owned by <b>${repository_owner | h}</b></td></tr><% my_row = row_counter.count @@ -385,6 +415,9 @@ ${version_str | h} </${cell_type}><${cell_type}>${tool_dependency.type | h}</${cell_type}> + %if tool_dependency.install_dir: + <${cell_type}>${tool_dependency.install_dir | h}</${cell_type}> + %endif </tr><% my_row = row_counter.count @@ -428,17 +461,18 @@ from galaxy.tool_shed.encoding_util import tool_shed_encode has_datatypes = metadata and 'datatypes' in metadata - has_readme = metadata and 'readme' in metadata + has_readme_files = metadata and 'readme_files' in metadata has_workflows = metadata and 'workflows' in metadata datatypes_root_folder = containers_dict[ 'datatypes' ] invalid_tools_root_folder = containers_dict[ 'invalid_tools' ] + readme_files_root_folder = containers_dict[ 'readme_files' ] repository_dependencies_root_folder = containers_dict[ 'repository_dependencies' ] tool_dependencies_root_folder = containers_dict[ 'tool_dependencies' ] valid_tools_root_folder = containers_dict[ 'valid_tools' ] workflows_root_folder = containers_dict[ 'workflows' ] - has_contents = datatypes_root_folder, invalid_tools_root_folder or valid_tools_root_folder or workflows_root_folder + has_contents = datatypes_root_folder or invalid_tools_root_folder or valid_tools_root_folder or workflows_root_folder class RowCounter( object ): def __init__( self ): @@ -448,6 +482,18 @@ def __str__( self ): return str( self.count ) %> + %if readme_files_root_folder: + <div class="toolForm"> + <div class="toolFormTitle">Repository README files (may contain important installation or license information)</div> + <div class="toolFormBody"> + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="readme_files"> + ${render_folder( readme_files_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + </div> + </div> + %endif %if repository_dependencies_root_folder or tool_dependencies_root_folder: <div class="toolForm"><div class="toolFormTitle">Dependencies of this repository</div> @@ -455,15 +501,15 @@ %if repository_dependencies_root_folder: <p/><% row_counter = RowCounter() %> - <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="repository_dependencies"> - ${self.render_folder( repository_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="repository_dependencies"> + ${render_folder( repository_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} </table> %endif %if tool_dependencies_root_folder: <p/><% row_counter = RowCounter() %> - <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="tool_dependencies"> - ${self.render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="tool_dependencies"> + ${render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} </table> %endif </div> @@ -477,29 +523,29 @@ %if valid_tools_root_folder: <p/><% row_counter = RowCounter() %> - <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="valid_tools"> - ${self.render_folder( valid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="valid_tools"> + ${render_folder( valid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} </table> %endif %if invalid_tools_root_folder: <p/><% row_counter = RowCounter() %> - <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="invalid_tools"> - ${self.render_folder( invalid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="invalid_tools"> + ${render_folder( invalid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} </table> %endif %if workflows_root_folder: <p/><% row_counter = RowCounter() %> - <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="workflows"> - ${self.render_folder( workflows_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="workflows"> + ${render_folder( workflows_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} </table> %endif %if datatypes_root_folder: <p/><% row_counter = RowCounter() %> - <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="datatypes"> - ${self.render_folder( datatypes_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="datatypes"> + ${render_folder( datatypes_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} </table> %endif </div> diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/contact_owner.mako --- a/templates/webapps/community/repository/contact_owner.mako +++ b/templates/webapps/community/repository/contact_owner.mako @@ -43,9 +43,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/manage_repository.mako --- a/templates/webapps/community/repository/manage_repository.mako +++ b/templates/webapps/community/repository/manage_repository.mako @@ -5,23 +5,26 @@ <% from galaxy.web.framework.helpers import time_ago + + has_metadata = repository.metadata_revisions + has_readme = metadata and 'readme' in metadata is_admin = trans.user_is_admin() is_new = repository.is_new( trans.app ) is_deprecated = repository.deprecated + + can_browse_contents = not is_new can_contact_owner = trans.user and trans.user != repository.user + can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository ) + can_download = not is_deprecated and not is_new and ( not is_malicious or can_push ) + can_rate = not is_new and not is_deprecated and trans.user and repository.user != trans.user + can_reset_all_metadata = not is_deprecated and is_admin and len( repo ) > 0 + can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) + can_set_metadata = not is_new and not is_deprecated + can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip( trans.app ) + can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated can_upload = can_push - can_download = not is_deprecated and not is_new and ( not is_malicious or can_push ) - can_browse_contents = not is_new - can_set_metadata = not is_new and not is_deprecated - can_rate = not is_new and not is_deprecated and trans.user and repository.user != trans.user can_view_change_log = not is_new - can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip( trans.app ) - can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated - can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated - can_reset_all_metadata = not is_deprecated and is_admin and len( repo ) > 0 - has_readme = metadata and 'readme' in metadata - can_review_repository = not is_new and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) reviewing_repository = cntrller and cntrller == 'repository_review' if can_push: @@ -51,7 +54,7 @@ <%def name="javascripts()"> ${parent.javascripts()} ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} - ${dependency_javascripts()} + ${container_javascripts()} </%def><br/><br/> @@ -78,9 +81,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/preview_tools_in_changeset.mako --- a/templates/webapps/community/repository/preview_tools_in_changeset.mako +++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako @@ -36,7 +36,7 @@ <%def name="javascripts()"> ${parent.javascripts()} ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} - ${dependency_javascripts()} + ${container_javascripts()} </%def><br/><br/> @@ -44,9 +44,6 @@ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to local Galaxy</a></li><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li><div popupmenu="repository-${repository.id}-popup"> - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a> - %endif <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a><a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a> diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/rate_repository.mako --- a/templates/webapps/community/repository/rate_repository.mako +++ b/templates/webapps/community/repository/rate_repository.mako @@ -84,9 +84,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/tool_form.mako --- a/templates/webapps/community/repository/tool_form.mako +++ b/templates/webapps/community/repository/tool_form.mako @@ -147,9 +147,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/view_changelog.mako --- a/templates/webapps/community/repository/view_changelog.mako +++ b/templates/webapps/community/repository/view_changelog.mako @@ -52,9 +52,6 @@ %else: <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View README</a> - %endif %if can_rate: <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/view_changeset.mako --- a/templates/webapps/community/repository/view_changeset.mako +++ b/templates/webapps/community/repository/view_changeset.mako @@ -53,9 +53,6 @@ %else: <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/view_repository.mako --- a/templates/webapps/community/repository/view_repository.mako +++ b/templates/webapps/community/repository/view_repository.mako @@ -5,22 +5,26 @@ <% from galaxy.web.framework.helpers import time_ago + + has_readme = metadata and 'readme' in metadata + has_metadata = repository.metadata_revisions is_new = repository.is_new( trans.app ) is_deprecated = repository.deprecated + + can_browse_contents = trans.webapp.name == 'community' and not is_new can_contact_owner = trans.user and trans.user != repository.user + can_download = not is_deprecated and not is_new and ( not is_malicious or can_push ) can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository ) can_rate = not is_deprecated and not is_new and trans.user and repository.user != trans.user + can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) can_upload = can_push - can_download = not is_deprecated and not is_new and ( not is_malicious or can_push ) - can_browse_contents = trans.webapp.name == 'community' and not is_new can_view_change_log = trans.webapp.name == 'community' and not is_new + reviewing_repository = cntrller and cntrller == 'repository_review' + if can_push: browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' - has_readme = metadata and 'readme' in metadata - reviewing_repository = cntrller and cntrller == 'repository_review' - can_review_repository = not is_new and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) %><%! @@ -40,7 +44,7 @@ <%def name="javascripts()"> ${parent.javascripts()} ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} - ${dependency_javascripts()} + ${container_javascripts()} </%def><br/><br/> @@ -68,9 +72,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/view_tool_metadata.mako --- a/templates/webapps/community/repository/view_tool_metadata.mako +++ b/templates/webapps/community/repository/view_tool_metadata.mako @@ -6,23 +6,27 @@ <% from galaxy.web.framework.helpers import time_ago from urllib import quote_plus + + has_metadata = repository.metadata_revisions + has_readme = metadata and 'readme' in metadata is_admin = trans.user_is_admin() is_new = repository.is_new( trans.app ) is_deprecated = repository.deprecated + + can_browse_contents = trans.webapp.name == 'community' and not is_new can_contact_owner = trans.user and trans.user != repository.user + can_download = not is_new and ( not is_malicious or can_push ) + can_manage = is_admin or repository.user == trans.user can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository ) + can_rate = repository.user != trans.user + can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) can_upload = can_push - can_download = not is_new and ( not is_malicious or can_push ) - can_browse_contents = trans.webapp.name == 'community' and not is_new - can_rate = repository.user != trans.user - can_manage = is_admin or repository.user == trans.user can_view_change_log = trans.webapp.name == 'community' and not is_new + if can_push: browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' - has_readme = metadata and 'readme' in metadata - can_review_repository = not is_new and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) %><%! @@ -69,9 +73,6 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 templates/webapps/community/repository/view_workflow.mako --- a/templates/webapps/community/repository/view_workflow.mako +++ b/templates/webapps/community/repository/view_workflow.mako @@ -55,9 +55,6 @@ %else: <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a> %endif - %if has_readme: - <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a> - %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a> %endif diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 test/tool_shed/base/twilltestcase.py --- a/test/tool_shed/base/twilltestcase.py +++ b/test/tool_shed/base/twilltestcase.py @@ -134,12 +134,6 @@ tc.fv( "1", "selected_files_to_delete", ','.join( files_to_delete ) ) tc.submit( 'select_files_to_delete_button' ) self.check_for_strings( strings_displayed, strings_not_displayed ) - def display_readme_file( self, repository, changeset_revision=None, strings_displayed=[], strings_not_displayed=[] ): - if changeset_revision is None: - changeset_revision = self.get_repository_tip( repository ) - repository_id = self.security.encode_id( repository.id ) - self.visit_url( '/repository/view_readme?changeset_revision=%s&id=%s' % ( changeset_revision, repository_id ) ) - self.check_for_strings( strings_displayed, strings_not_displayed ) def display_repository_clone_page( self, owner_name, repository_name, strings_displayed=[], strings_not_displayed=[] ): url = '/repos/%s/%s' % ( owner_name, repository_name ) self.visit_url( url ) diff -r 88aba66bb81351cbd625ca7fb9ed39874016b36a -r 14589278b02d0dea916319811ddebf17ecca0747 test/tool_shed/functional/test_0000_basic_repository_features.py --- a/test/tool_shed/functional/test_0000_basic_repository_features.py +++ b/test/tool_shed/functional/test_0000_basic_repository_features.py @@ -105,7 +105,7 @@ commit_message="Uploaded filtering.txt", uncompress_file='No', remove_repo_files_not_in_tar='No' ) - self.display_readme_file( repository, strings_displayed=[ 'Readme file for filtering 1.1.0' ] ) + self.manage_repository( repository, strings_displayed=[ 'Readme file for filtering 1.1.0' ] ) def test_0055_upload_filtering_test_data( self ): '''Upload filtering test data.''' repository = get_repository_by_name_and_owner( repository_name, admin_username ) @@ -137,22 +137,16 @@ '''Upload readme.txt file associated with tool version 2.2.0.''' repository = get_repository_by_name_and_owner( repository_name, admin_username ) self.upload_file( repository, 'readme.txt', commit_message="Uploaded readme.txt" ) - self.display_readme_file( repository, strings_displayed=[ 'This is a readme file.' ] ) + self.manage_repository( repository, strings_displayed=[ 'This is a readme file.' ] ) # Verify that there is a different readme file for each metadata revision. metadata_revisions = self.get_repository_metadata_revisions( repository ) - strings_to_check = [ 'Readme file for filtering 1.1.0', 'This is a readme file.' ] - for key, metadata_revision in enumerate( metadata_revisions ): - # Metadata revisions are in order newest to oldest at this point. - self.display_readme_file( repository, metadata_revision, strings_not_displayed=[ strings_to_check[ key ] ] ) + self.manage_repository( repository, strings_displayed=[ 'Readme file for filtering 1.1.0', 'This is a readme file.' ] ) def test_0075_delete_readme_txt_file( self ): '''Delete the readme.txt file.''' repository = get_repository_by_name_and_owner( repository_name, admin_username ) self.delete_files_from_repository( repository, filenames=[ 'readme.txt' ] ) self.check_count_of_metadata_revisions_associated_with_repository( repository, metadata_count=2 ) - # Deleting a readme file for a specific revision should make the repository fall back - # to a previous revision's readme file, if one exists. - # TODO: All readme files should be displayed. - self.display_readme_file( repository, strings_displayed=[ 'Readme file for filtering 1.1.0' ] ) + self.manage_repository( repository, strings_displayed=[ 'Readme file for filtering 1.1.0' ] ) def test_0080_search_for_valid_filter_tool( self ): '''Verify that the "search for valid tool" feature finds the filtering tool.''' repository = get_repository_by_name_and_owner( repository_name, admin_username ) 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.
participants (1)
-
Bitbucket