1 new changeset in galaxy-central: http://bitbucket.org/galaxy/galaxy-central/changeset/8b97f197b759/ changeset: 8b97f197b759 user: greg date: 2011-07-08 22:11:28 summary: First pass implementation for tool shed repository metadata. This implementation currently provides a baseline metadata collection for tools in a tool shed repository. This change set also includes the implementation for displaying a tool UI for each valid tool config in the tool shed repository. Fixes issue # 565. affected #: 16 files (14.8 KB) --- a/lib/galaxy/webapps/community/app.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/app.py Fri Jul 08 16:11:28 2011 -0400 @@ -1,4 +1,6 @@ import sys, config +import galaxy.tools.data +import galaxy.datatypes.registry import galaxy.webapps.community.model from galaxy.web import security from galaxy.tags.tag_handler import CommunityTagHandler @@ -11,6 +13,8 @@ self.config = config.Configuration( **kwargs ) self.config.check() config.configure_logging( self.config ) + # Set up datatypes registry + self.datatypes_registry = galaxy.datatypes.registry.Registry( self.config.root, self.config.datatypes_config ) # Determine the database url if self.config.database_connection: db_url = self.config.database_connection @@ -28,6 +32,8 @@ self.security = security.SecurityHelper( id_secret=self.config.id_secret ) # Tag handler self.tag_handler = CommunityTagHandler() + # Tool data tables + self.tool_data_tables = galaxy.tools.data.ToolDataTableManager( self.config.tool_data_table_config_path ) # Load security policy self.security_agent = self.model.security_agent def shutdown( self ): --- a/lib/galaxy/webapps/community/config.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/config.py Fri Jul 08 16:11:28 2011 -0400 @@ -41,6 +41,9 @@ self.cookie_path = kwargs.get( "cookie_path", "/" ) self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root ) self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" ) + self.tool_secret = kwargs.get( "tool_secret", "" ) + self.tool_data_path = resolve_path( kwargs.get( "tool_data_path", "tool-data" ), os.getcwd() ) + self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root ) self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) ) self.remote_user_maildomain = kwargs.get( "remote_user_maildomain", None ) self.remote_user_logout_href = kwargs.get( "remote_user_logout_href", None ) @@ -56,7 +59,9 @@ self.smtp_server = kwargs.get( 'smtp_server', None ) self.smtp_username = kwargs.get( 'smtp_username', None ) self.smtp_password = kwargs.get( 'smtp_password', None ) + self.start_job_runners = kwargs.get( 'start_job_runners', None ) self.email_alerts_from = kwargs.get( 'email_alerts_from', None ) + self.nginx_upload_path = kwargs.get( 'nginx_upload_path', False ) self.log_actions = string_as_bool( kwargs.get( 'log_actions', 'False' ) ) self.brand = kwargs.get( 'brand', None ) self.wiki_url = kwargs.get( 'wiki_url', 'http://bitbucket.org/galaxy/galaxy-central/wiki/Home' ) @@ -65,7 +70,7 @@ self.screencasts_url = kwargs.get( 'screencasts_url', None ) self.log_events = False self.cloud_controller_instance = False - self.datatypes_config = kwargs.get( 'datatypes_config_file', 'community_datatypes_conf.xml' ) + self.datatypes_config = kwargs.get( 'datatypes_config_file', 'datatypes_conf.xml' ) # Proxy features self.apache_xsendfile = kwargs.get( 'apache_xsendfile', False ) self.nginx_x_accel_redirect_base = kwargs.get( 'nginx_x_accel_redirect_base', False ) --- a/lib/galaxy/webapps/community/controllers/common.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/controllers/common.py Fri Jul 08 16:11:28 2011 -0400 @@ -1,12 +1,13 @@ import os, string, socket, logging from time import strftime from datetime import * +from galaxy.tools import * from galaxy.util.json import from_json_string, to_json_string from galaxy.web.base.controller import * from galaxy.webapps.community import model from galaxy.model.orm import * from galaxy.model.item_attrs import UsesItemRatings -from mercurial import hg, ui +from mercurial import hg, ui, commands log = logging.getLogger( __name__ ) @@ -68,14 +69,15 @@ def get_repository( trans, id ): """Get a repository from the database via id""" return trans.sa_session.query( trans.model.Repository ).get( trans.security.decode_id( id ) ) +def get_repository_metadata( trans, id, changeset_revision ): + """Get metadata for a specified repository change set from the database""" + 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_by_name( trans, name ): """Get a repository from the database via name""" return trans.sa_session.query( app.model.Repository ).filter_by( name=name ).one() -def get_repository_tip( repository ): - # The received repository must be a mercurial repository, not a db record. - tip_changeset = repository.changelog.tip() - tip_ctx = repository.changectx( tip_changeset ) - return "%s:%s" % ( str( tip_ctx.rev() ), tip_ctx.parents()[0] ) def get_user( trans, id ): """Get a user from the database""" return trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( id ) ) @@ -121,19 +123,138 @@ def update_for_browsing( repository, current_working_dir ): # Make a copy of a repository's files for browsing. repo_dir = repository.repo_path + repo = hg.repository( ui.ui(), repo_dir ) + # The following will delete the disk copy of only the files in the repository. + #os.system( 'hg update -r null > /dev/null 2>&1' ) + repo.ui.pushbuffer() + commands.status( repo.ui, repo, all=True ) + status_and_file_names = repo.ui.popbuffer().strip().split( "\n" ) + # status_and_file_names looks something like: + # ['? MY_README_AGAIN', '? galaxy_tmap_tool/tmap-0.0.9.tar.gz', '? dna_filtering.py', 'C filtering.py', 'C filtering.xml'] + # The codes used to show the status of files are: + # M = modified + # A = added + # R = removed + # C = clean + # ! = deleted, but still tracked + # ? = not tracked + # I = ignored + # We'll remove all files that are not tracked or ignored. + files_to_remove_from_disk = [] + for status_and_file_name in status_and_file_names: + if status_and_file_name.startswith( '?' ) or status_and_file_name.startswith( 'I' ): + files_to_remove_from_disk.append( os.path.abspath( os.path.join( repo_dir, status_and_file_name.split()[1] ) ) ) + for full_path in files_to_remove_from_disk: + if os.path.isdir( full_path ): + try: + os.rmdir( full_path ) + except OSError, e: + # The directory is not empty + pass + elif os.path.isfile( full_path ): + os.remove( full_path ) + dir = os.path.split( full_path )[0] + try: + os.rmdir( dir ) + except OSError, e: + # The directory is not empty + pass os.chdir( repo_dir ) os.system( 'hg update > /dev/null 2>&1' ) os.chdir( current_working_dir ) +def load_tool( trans, config_file ): """ - # TODO: the following is useful if the repository files somehow include missing or - # untracked files. If this happens, we can enhance the following to clean things up. - # We're not currently doing any cleanup though since so far none of the repositories - # have problematic files for browsing. - # Get the tip change set. + Load a single tool from the file named by `config_file` and return + an instance of `Tool`. + """ + # Parse XML configuration file and get the root element + tree = util.parse_xml( config_file ) + root = tree.getroot() + if root.tag == 'tool': + # Allow specifying a different tool subclass to instantiate + if root.find( "type" ) is not None: + type_elem = root.find( "type" ) + module = type_elem.get( 'module', 'galaxy.tools' ) + cls = type_elem.get( 'class' ) + mod = __import__( module, globals(), locals(), [cls]) + ToolClass = getattr( mod, cls ) + elif root.get( 'tool_type', None ) is not None: + ToolClass = tool_types.get( root.get( 'tool_type' ) ) + else: + ToolClass = Tool + return ToolClass( config_file, root, trans.app ) + return None +def set_repository_metadata( trans, id, ctx_str, **kwd ): + """Set repository metadata""" + message = '' + status = 'done' + repository = get_repository( trans, id ) + repo_dir = repository.repo_path repo = hg.repository( ui.ui(), repo_dir ) + found = False + invalid_tool_configs = [] for changeset in repo.changelog: ctx = repo.changectx( changeset ) - ctx_parent = ctx.parents()[0] - break - modified, added, removed, deleted, unknown, ignored, clean = repo.status( node1=ctx_parent.node(), node2=ctx.node() ) - """ + if str( ctx ) == ctx_str: + found = True + break + if found: + for root, dirs, files in os.walk( repo_dir ): + if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0: + if '.hg' in dirs: + # Don't visit .hg directories - should be impossible since we don't + # allow uploaded archives that contain .hg dirs, but just in case... + dirs.remove( '.hg' ) + if 'hgrc' in files: + # Don't include hgrc files in commit. + files.remove( 'hgrc' ) + for name in files: + # Find all tool configs. + if name.endswith( '.xml' ): + try: + full_path = os.path.abspath( os.path.join( root, name ) ) + tool = load_tool( trans, full_path ) + if tool is not None: + repository_metadata = get_repository_metadata( trans, id, repository.tip ) + # TODO: add more stuff, like requirements + tool_dict = dict( id = tool.id, + name = tool.name, + version = tool.version, + description = tool.description, + tool_config = full_path ) + if repository_metadata: + metadata = repository_metadata.metadata + if metadata and 'tools' in metadata: + metadata_tools = metadata[ 'tools' ] + found = False + for tool_metadata_dict in metadata_tools: + if 'id' in tool_metadata_dict and tool_metadata_dict[ 'id' ] == tool.id and \ + 'version' in tool_metadata_dict and tool_metadata_dict[ 'version' ] == tool.version: + found = True + tool_metadata_dict[ 'name' ] = tool.name + tool_metadata_dict[ 'description' ] = tool.description + tool_metadata_dict[ 'tool_config' ] = os.path.join( root, name ) + # TODO: add more stuff, like tool requirements, code files, etc + if not found: + metadata_tools.append( tool_dict ) + else: + if metadata is None: + repository_metadata.metadata = {} + repository_metadata.metadata[ 'tools' ] = [ tool_dict ] + trans.sa_session.add( repository_metadata ) + else: + metadata_dict = dict( tools = [ tool_dict ] ) + repository_metadata = trans.model.RepositoryMetadata( repository.id, repository.tip, metadata_dict ) + trans.sa_session.add( repository_metadata ) + trans.sa_session.flush() + except Exception, e: + invalid_tool_configs.append( ( name, str( e ) ) ) + else: + message = "Repository does not include changeset revision '%s'." % str( ctx_str ) + status = 'error' + if invalid_tool_configs: + message = "The following tool configs are invalid and were not added to the repository metadata:<br/>" + for itc_tup in invalid_tool_configs: + message += "<b>%s</b> - %s<br/>" % ( itc_tup[0], itc_tup[1] ) + status = 'error' + return message, status --- a/lib/galaxy/webapps/community/controllers/repository.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/controllers/repository.py Fri Jul 08 16:11:28 2011 -0400 @@ -76,8 +76,7 @@ return repository.name class VersionColumn( grids.TextColumn ): def get_value( self, trans, grid, repository ): - repo = hg.repository( ui.ui(), repository.repo_path ) - return get_repository_tip( repo ) + return repository.version class DescriptionColumn( grids.TextColumn ): def get_value( self, trans, grid, repository ): return repository.description @@ -124,7 +123,7 @@ key="name", link=( lambda item: dict( operation="view_or_manage_repository", id=item.id, webapp="community" ) ), attach_popup=False ), - DescriptionColumn( "Description", + DescriptionColumn( "Synopsis", key="description", attach_popup=False ), VersionColumn( "Version", @@ -420,7 +419,7 @@ selected_files_to_delete = selected_files_to_delete.split( ',' ) current_working_dir = os.getcwd() # Get the current repository tip. - tip = repo[ 'tip' ] + tip = repository.tip for selected_file in selected_files_to_delete: repo_file = os.path.abspath( selected_file ) commands.remove( repo.ui, repo, repo_file ) @@ -434,10 +433,19 @@ update_for_browsing( repository, current_working_dir ) # Get the new repository tip. repo = hg.repository( ui.ui(), repo_dir ) - if tip != repo[ 'tip' ]: + if tip != repository.tip: message = "The selected files were deleted from the repository." else: message = 'No changes to repository.' + # Set metadata on the repository tip + error_message, status = set_repository_metadata( trans, id, repository.tip, **kwd ) + if error_message: + message = '%s<br/>%s' % ( message, error_message ) + return trans.response.send_redirect( web.url_for( controller='repository', + action='manage_repository', + id=id, + message=message, + status=status ) ) else: message = "Select at least 1 file to delete from the repository before clicking <b>Delete selected files</b>." status = "error" @@ -454,7 +462,6 @@ status = params.get( 'status', 'done' ) repository = get_repository( trans, id ) repo = hg.repository( ui.ui(), repository.repo_path ) - tip = get_repository_tip( repo ) avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, repository, webapp_model=trans.model ) display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) ) alerts = params.get( 'alerts', '' ) @@ -481,10 +488,15 @@ trans.sa_session.flush() checked = alerts_checked or ( user and user.email in email_alerts ) alerts_check_box = CheckboxField( 'alerts', checked=checked ) + repository_metadata = get_repository_metadata( trans, id, repository.tip ) + if repository_metadata: + metadata = repository_metadata.metadata + else: + metadata = None return trans.fill_template( '/webapps/community/repository/view_repository.mako', repo=repo, repository=repository, - tip=tip, + metadata=metadata, avg_rating=avg_rating, display_reviews=display_reviews, num_ratings=num_ratings, @@ -499,7 +511,6 @@ status = params.get( 'status', 'done' ) repository = get_repository( trans, id ) repo = hg.repository( ui.ui(), repository.repo_path ) - tip = get_repository_tip( repo ) repo_name = util.restore_text( params.get( 'repo_name', repository.name ) ) description = util.restore_text( params.get( 'description', repository.description ) ) long_description = util.restore_text( params.get( 'long_description', repository.long_description ) ) @@ -577,6 +588,11 @@ allow_push_select_field = self.__build_allow_push_select_field( trans, current_allow_push_list ) checked = alerts_checked or user.email in email_alerts alerts_check_box = CheckboxField( 'alerts', checked=checked ) + repository_metadata = get_repository_metadata( trans, id, repository.tip ) + if repository_metadata: + metadata = repository_metadata.metadata + else: + metadata = None return trans.fill_template( '/webapps/community/repository/manage_repository.mako', repo_name=repo_name, description=description, @@ -585,7 +601,7 @@ allow_push_select_field=allow_push_select_field, repo=repo, repository=repository, - tip=tip, + metadata=metadata, avg_rating=avg_rating, display_reviews=display_reviews, num_ratings=num_ratings, @@ -676,7 +692,6 @@ status='error' ) ) repository = get_repository( trans, id ) repo = hg.repository( ui.ui(), repository.repo_path ) - tip = get_repository_tip( repo ) if repository.user == trans.user: return trans.response.send_redirect( web.url_for( controller='repository', action='browse_repositories', @@ -691,7 +706,6 @@ rra = self.get_user_item_rating( trans.sa_session, trans.user, repository, webapp_model=trans.model ) return trans.fill_template( '/webapps/community/repository/rate_repository.mako', repository=repository, - tip=tip, avg_rating=avg_rating, display_reviews=display_reviews, num_ratings=num_ratings, @@ -736,6 +750,40 @@ action='browse_repositories', **kwd ) ) @web.expose + @web.require_login( "set repository metadata" ) + def set_metadata( self, trans, id, ctx_str, **kwd ): + message, status = set_repository_metadata( trans, id, ctx_str, **kwd ) + return trans.response.send_redirect( web.url_for( controller='repository', + action='manage_repository', + id=id, + message=message, + status=status ) ) + @web.expose + def display_tool( self, trans, repository_id, tool_config, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + repository = get_repository( trans, repository_id ) + tool = load_tool( trans, os.path.abspath( tool_config ) ) + tool_state = self.__new_state( trans ) + return trans.fill_template( "/webapps/community/repository/tool_form.mako", + repository=repository, + tool=tool, + tool_state=tool_state, + message=message, + status=status ) + def __new_state( self, trans, all_pages=False ): + """ + Create a new `DefaultToolState` for this tool. It will not be initialized + with default values for inputs. + + Only inputs on the first page will be initialized unless `all_pages` is + True, in which case all inputs regardless of page are initialized. + """ + state = DefaultToolState() + state.inputs = {} + return state + @web.expose def download( self, trans, repository_id, file_type, **kwd ): # Download an archive of the repository files compressed as zip, gz or bz2. params = util.Params( kwd ) --- a/lib/galaxy/webapps/community/controllers/upload.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/controllers/upload.py Fri Jul 08 16:11:28 2011 -0400 @@ -33,7 +33,7 @@ uploaded_file = None upload_point = self.__get_upload_point( repository, **kwd ) # Get the current repository tip. - tip = repo[ 'tip' ] + tip = repository.tip if params.get( 'upload_button', False ): current_working_dir = os.getcwd() file_data = params.get( 'file_data', '' ) @@ -89,8 +89,7 @@ # is eliminating unwanted files from the repository directory. update_for_browsing( repository, current_working_dir ) # Get the new repository tip. - repo = hg.repository( ui.ui(), repo_dir ) - if tip != repo[ 'tip' ]: + if tip != repository.tip: if ( isgzip or isbz2 ) and uncompress_file: uncompress_str = ' uncompressed and ' else: @@ -102,12 +101,22 @@ else: message += " %d files were removed from the repository root." % len( files_to_remove ) else: - message = 'No changes to repository.' + message = 'No changes to repository.' + # Set metadata on the repository tip + error_message, status = set_repository_metadata( trans, repository_id, repository.tip, **kwd ) + if error_message: + message = '%s<br/>%s' % ( message, error_message ) + return trans.response.send_redirect( web.url_for( controller='repository', + action='manage_repository', + id=repository_id, + message=message, + status=status ) ) trans.response.send_redirect( web.url_for( controller='repository', action='browse_repository', + id=repository_id, commit_message='Deleted selected files', message=message, - id=trans.security.encode_id( repository.id ) ) ) + status=status ) ) else: status = 'error' selected_categories = [ trans.security.decode_id( id ) for id in category_ids ] --- a/lib/galaxy/webapps/community/model/__init__.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/model/__init__.py Fri Jul 08 16:11:28 2011 -0400 @@ -114,6 +114,15 @@ return config.get( "paths", option ) raise Exception( "Entry for repository %s missing in %s/hgweb.config file." % ( lhs, os.getcwd() ) ) @property + def version( self ): + repo = hg.repository( ui.ui(), self.repo_path ) + tip_ctx = repo.changectx( repo.changelog.tip() ) + return "%s:%s" % ( str( tip_ctx.rev() ), str( repo.changectx( repo.changelog.tip() ) ) ) + @property + def tip( self ): + repo = hg.repository( ui.ui(), self.repo_path ) + return str( repo.changectx( repo.changelog.tip() ) ) + @property def is_new( self ): repo = hg.repository( ui.ui(), self.repo_path ) tip_ctx = repo.changectx( repo.changelog.tip() ) @@ -143,6 +152,12 @@ fp.write( line ) fp.close() +class RepositoryMetadata( object ): + def __init__( self, repository_id=None, changeset_revision=None, metadata=None ): + self.repository_id = repository_id + self.changeset_revision = changeset_revision + self.metadata = metadata or dict() + class ItemRatingAssociation( object ): def __init__( self, id=None, user=None, item=None, rating=0, comment='' ): self.id = id --- a/lib/galaxy/webapps/community/model/mapping.py Fri Jul 08 09:09:02 2011 -0400 +++ b/lib/galaxy/webapps/community/model/mapping.py Fri Jul 08 16:11:28 2011 -0400 @@ -111,6 +111,14 @@ Column( "email_alerts", JSONType, nullable=True ), Column( "times_downloaded", Integer ) ) +RepositoryMetadata.table = Table( "repository_metadata", metadata, + Column( "id", Integer, primary_key=True ), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "repository_id", Integer, ForeignKey( "repository.id" ), index=True ), + Column( "changeset_revision", TrimmedString( 255 ), index=True ), + Column( "metadata", JSONType, nullable=True ) ) + RepositoryRatingAssociation.table = Table( "repository_rating_association", metadata, Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), @@ -186,6 +194,9 @@ ratings=relation( RepositoryRatingAssociation, order_by=desc( RepositoryRatingAssociation.table.c.update_time ), backref="repositories" ), user=relation( User.mapper ) ) ) +assign_mapper( context, RepositoryMetadata, RepositoryMetadata.table, + properties=dict( repository=relation( Repository ) ) ) + assign_mapper( context, RepositoryRatingAssociation, RepositoryRatingAssociation.table, properties=dict( repository=relation( Repository ), user=relation( User ) ) ) --- a/templates/webapps/community/repository/browse_repository.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/browse_repository.mako Fri Jul 08 16:11:28 2011 -0400 @@ -5,12 +5,13 @@ <% from galaxy.web.framework.helpers import time_ago + is_admin = trans.user_is_admin() is_new = repository.is_new can_push = trans.app.security_agent.can_push( trans.user, repository ) can_upload = can_push can_browse_contents = not is_new can_rate = trans.user and repository.user != trans.user - can_manage = repository.user == trans.user + can_manage = is_admin or repository.user == trans.user can_view_change_log = not is_new %> --- a/templates/webapps/community/repository/manage_repository.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/manage_repository.mako Fri Jul 08 16:11:28 2011 -0400 @@ -121,9 +121,9 @@ <div class="form-row"><label>Version:</label> %if can_view_change_log: - <a href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">${tip}</a> + <a href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">${repository.version}</a> %else: - ${tip} + ${repository.version} %endif </div><div class="form-row"> @@ -150,6 +150,40 @@ </form></div></div> +<p/> +<div class="toolForm"> + <div class="toolFormTitle">Repository metadata</div> + <div class="toolFormBody"> + %if metadata: + %if 'tools' in metadata: + <div class="form-row"> + <label>Tools:</label> + <% tool_dicts = metadata[ 'tools' ] %> + <table class="grid"> + %for tool_dict in tool_dicts: + <tr> + <td><a href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ] )}">${tool_dict[ 'name' ]}</a></td> + <td>${tool_dict[ 'description' ]}</td> + <td>version: ${tool_dict[ 'version' ]}</td> + </tr> + %endfor + </table> + </div> + <div style="clear: both"></div> + %endif + %endif + <form name="set_metadata" action="${h.url_for( controller='repository', action='set_metadata', id=trans.security.encode_id( repository.id ), ctx_str=repository.tip )}" method="post"> + <div class="form-row"> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="submit" name="set_metadata_button" value="Reset metadata"/> + </div> + <div class="toolParamHelp" style="clear: both;"> + Inspect the repository and reset the above attributes for the repository tip. + </div> + </div> + </form> + </div> +</div> %if trans.app.config.smtp_server: <p/><div class="toolForm"> --- a/templates/webapps/community/repository/rate_repository.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/rate_repository.mako Fri Jul 08 16:11:28 2011 -0400 @@ -4,12 +4,13 @@ <% from galaxy.web.framework.helpers import time_ago from urllib import quote_plus + is_admin = trans.user_is_admin() is_new = repository.is_new can_push = trans.app.security_agent.can_push( trans.user, repository ) can_upload = can_push can_browse_contents = not is_new can_rate = repository.user != trans.user - can_manage = repository.user == trans.user + can_manage = is_admin or repository.user == trans.user can_view_change_log = not is_new if can_push: browse_label = 'Browse or delete repository files' @@ -103,7 +104,7 @@ </div><div class="form-row"><label>Version:</label> - ${tip} + ${repository.version} <div style="clear: both"></div></div><div class="form-row"> --- a/templates/webapps/community/repository/upload.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/upload.mako Fri Jul 08 16:11:28 2011 -0400 @@ -2,11 +2,12 @@ <%namespace file="/webapps/community/repository/common.mako" import="*" /><% + is_admin = trans.user_is_admin() is_new = repository.is_new can_browse_contents = not is_new can_browse_contents = not is_new can_rate = repository.user != trans.user - can_manage = repository.user == trans.user + can_manage = is_admin or repository.user == trans.user can_view_change_log = not is_new %> --- a/templates/webapps/community/repository/view_changelog.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/view_changelog.mako Fri Jul 08 16:11:28 2011 -0400 @@ -5,9 +5,10 @@ <% from galaxy.web.framework.helpers import time_ago + is_admin = trans.user_is_admin() is_new = repository.is_new can_browse_contents = not is_new - can_manage = trans.user == repository.user + can_manage = is_admin or trans.user == repository.user can_push = trans.app.security_agent.can_push( trans.user, repository ) can_rate = trans.user and repository.user != trans.user can_upload = can_push --- a/templates/webapps/community/repository/view_changeset.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/view_changeset.mako Fri Jul 08 16:11:28 2011 -0400 @@ -5,10 +5,11 @@ <% from galaxy.web.framework.helpers import time_ago + is_admin = trans.user_is_admin() is_new = repository.is_new can_browse_contents = not is_new can_rate = trans.user and repository.user != trans.user - can_manage = trans.user == repository.user + can_manage = is_admin or trans.user == repository.user can_push = trans.app.security_agent.can_push( trans.user, repository ) can_view_change_log = not is_new can_upload = can_push --- a/templates/webapps/community/repository/view_repository.mako Fri Jul 08 09:09:02 2011 -0400 +++ b/templates/webapps/community/repository/view_repository.mako Fri Jul 08 16:11:28 2011 -0400 @@ -120,9 +120,9 @@ <div class="form-row"><label>Version:</label> %if can_view_change_log: - <a href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">${tip}</a> + <a href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">${repository.version}</a> %else: - ${tip} + ${repository.version} %endif </div><div class="form-row"> @@ -145,6 +145,30 @@ %endif </div></div> +%if metadata: + <p/> + <div class="toolForm"> + <div class="toolFormTitle">Repository metadata</div> + <div class="toolFormBody"> + %if 'tools' in metadata: + <div class="form-row"> + <label>Tools:</label> + <% tool_dicts = metadata[ 'tools' ] %> + <table class="grid"> + %for tool_dict in tool_dicts: + <tr> + <td><a href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ] )}">${tool_dict[ 'name' ]}</a></td> + <td>${tool_dict[ 'description' ]}</td> + <td>version: ${tool_dict[ 'version' ]}</td> + </tr> + %endfor + </table> + </div> + <div style="clear: both"></div> + %endif + </div> + </div> +%endif %if trans.user and trans.app.config.smtp_server: <p/><div class="toolForm"> 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.