commit/galaxy-central: greg: Handle all Galaxy utilitiy types when reinstalling an uninstalled tool shed repository. The shed-related config file can now be selected when reinstalling repositories with any contents so that a differnt "tool_path" location can be selected for the location of the reinstalled repository.
1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/305680a482c3/ changeset: 305680a482c3 user: greg date: 2013-02-19 21:01:09 summary: Handle all Galaxy utilitiy types when reinstalling an uninstalled tool shed repository. The shed-related config file can now be selected when reinstalling repositories with any contents so that a differnt "tool_path" location can be selected for the location of the reinstalled repository. affected #: 5 files diff -r 32fc25b8900059f63b0d41d52aa582f06426928c -r 305680a482c3096b082daffa5ff665f5f60d1528 lib/galaxy/util/shed_util.py --- a/lib/galaxy/util/shed_util.py +++ b/lib/galaxy/util/shed_util.py @@ -951,6 +951,7 @@ .first() def get_update_to_changeset_revision_and_ctx_rev( trans, repository ): """Return the changeset revision hash to which the repository can be updated.""" + changeset_revision_dict = {} tool_shed_url = suc.get_url_from_repository_tool_shed( trans.app, repository ) url = suc.url_join( tool_shed_url, 'repository/get_changeset_revision_and_ctx_rev?name=%s&owner=%s&changeset_revision=%s' % \ ( repository.name, repository.owner, repository.installed_changeset_revision ) ) @@ -959,18 +960,34 @@ encoded_update_dict = response.read() if encoded_update_dict: update_dict = encoding_util.tool_shed_decode( encoded_update_dict ) - changeset_revision = update_dict[ 'changeset_revision' ] - ctx_rev = update_dict[ 'ctx_rev' ] + includes_data_managers = update_dict.get( 'includes_data_managers', False ) + includes_datatypes = update_dict.get( 'includes_datatypes', False ) includes_tools = update_dict.get( 'includes_tools', False ) + includes_tool_dependencies = update_dict.get( 'includes_tool_dependencies', False ) + includes_workflows = update_dict.get( 'includes_workflows', False ) has_repository_dependencies = update_dict.get( 'has_repository_dependencies', False ) + changeset_revision = update_dict.get( 'changeset_revision', None ) + ctx_rev = update_dict.get( 'ctx_rev', None ) response.close() + changeset_revision_dict[ 'includes_data_managers' ] = includes_data_managers + changeset_revision_dict[ 'includes_datatypes' ] = includes_datatypes + changeset_revision_dict[ 'includes_tools' ] = includes_tools + changeset_revision_dict[ 'includes_tool_dependencies' ] = includes_tool_dependencies + changeset_revision_dict[ 'includes_workflows' ] = includes_workflows + changeset_revision_dict[ 'has_repository_dependencies' ] = has_repository_dependencies + changeset_revision_dict[ 'changeset_revision' ] = changeset_revision + changeset_revision_dict[ 'ctx_rev' ] = ctx_rev except Exception, e: log.debug( "Error getting change set revision for update from the tool shed for repository '%s': %s" % ( repository.name, str( e ) ) ) - includes_tools = False - has_repository_dependencies = False - changeset_revision = None - ctx_rev = None - return changeset_revision, ctx_rev, includes_tools, has_repository_dependencies + changeset_revision_dict[ 'includes_data_managers' ] = False + changeset_revision_dict[ 'includes_datatypes' ] = False + changeset_revision_dict[ 'includes_tools' ] = False + changeset_revision_dict[ 'includes_tool_dependencies' ] = False + changeset_revision_dict[ 'includes_workflows' ] = False + changeset_revision_dict[ 'has_repository_dependencies' ] = False + changeset_revision_dict[ 'changeset_revision' ] = None + changeset_revision_dict[ 'ctx_rev' ] = None + return changeset_revision_dict def handle_missing_data_table_entry( app, relative_install_dir, tool_path, repository_tools_tups ): """ Inspect each tool to see if any have input parameters that are dynamically generated select lists that require entries in the diff -r 32fc25b8900059f63b0d41d52aa582f06426928c -r 305680a482c3096b082daffa5ff665f5f60d1528 lib/galaxy/webapps/community/controllers/repository.py --- a/lib/galaxy/webapps/community/controllers/repository.py +++ b/lib/galaxy/webapps/community/controllers/repository.py @@ -1298,21 +1298,29 @@ @web.expose def get_changeset_revision_and_ctx_rev( self, trans, **kwd ): """Handle a request from a local Galaxy instance to retrieve the changeset revision hash to which an installed repository can be updated.""" - def has_tools_and_repository_dependencies( repository_metadata ): + def has_galaxy_utilities( repository_metadata ): + includes_data_managers = False + includes_datatypes = False includes_tools = False has_repository_dependencies = False + includes_tool_dependencies = False + includes_workflows = False if repository_metadata: metadata = repository_metadata.metadata if metadata: + if 'data_manager' in metadata: + includes_data_managers = True + if 'datatypes' in metadata: + includes_datatypes = True if 'tools' in metadata: includes_tools = True - else: - includes_tools = False + if 'tool_dependencies' in metadata: + includes_tool_dependencies = True if 'repository_dependencies' in metadata: has_repository_dependencies = True - else: - has_repository_dependencies = False - return includes_tools, has_repository_dependencies + if 'workflows' in metadata: + includes_workflows = True + return includes_data_managers, includes_datatypes, includes_tools, includes_tool_dependencies, has_repository_dependencies, includes_workflows params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) @@ -1324,7 +1332,8 @@ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) - includes_tools, has_repository_dependencies = has_tools_and_repository_dependencies( repository_metadata ) + includes_data_managers, includes_datatypes, includes_tools, includes_tool_dependencies, has_repository_dependencies, includes_workflows = \ + has_galaxy_utilities( repository_metadata ) repo_dir = repository.repo_path( trans.app ) repo = hg.repository( suc.get_configured_ui(), repo_dir ) # Default to the received changeset revision and ctx_rev. @@ -1333,8 +1342,12 @@ latest_changeset_revision = changeset_revision update_dict = dict( changeset_revision=changeset_revision, ctx_rev=ctx_rev, + includes_data_managers=includes_data_managers, + includes_datatypes=includes_datatypes, includes_tools=includes_tools, - has_repository_dependencies=has_repository_dependencies ) + includes_tool_dependencies=includes_tool_dependencies, + has_repository_dependencies=has_repository_dependencies, + includes_workflows=includes_workflows ) if changeset_revision == repository.tip( trans.app ): # If changeset_revision is the repository tip, there are no additional updates. return encoding_util.tool_shed_encode( update_dict ) @@ -1356,7 +1369,8 @@ trans.security.encode_id( repository.id ), changeset_hash ) if update_to_repository_metadata: - includes_tools, has_repository_dependencies = has_tools_and_repository_dependencies( update_to_repository_metadata ) + includes_data_managers, includes_datatypes, includes_tools, includes_tool_dependencies, has_repository_dependencies, includes_workflows = \ + has_galaxy_utilities( update_to_repository_metadata ) # We found a RepositoryMetadata record. if changeset_hash == repository.tip( trans.app ): # The current ctx is the repository tip, so use it. @@ -1369,7 +1383,11 @@ elif not update_to_changeset_hash and changeset_hash == changeset_revision: # We've found the changeset in the changelog for which we need to get the next update. update_to_changeset_hash = changeset_hash + update_dict[ 'includes_data_managers' ] = includes_data_managers + update_dict[ 'includes_datatypes' ] = includes_datatypes update_dict[ 'includes_tools' ] = includes_tools + update_dict[ 'includes_tool_dependencies' ] = includes_tool_dependencies + update_dict[ 'includes_workflows' ] = includes_workflows update_dict[ 'has_repository_dependencies' ] = has_repository_dependencies update_dict[ 'changeset_revision' ] = str( latest_changeset_revision ) update_dict[ 'ctx_rev' ] = str( update_to_ctx.rev() ) @@ -1601,16 +1619,22 @@ repository_metadata=repository_metadata, tool_dependencies=None, repository_dependencies=None ) + includes_data_managers = False + includes_datatypes = False + includes_tools = False + includes_workflows = False + readme_files_dict = None metadata = repository_metadata.metadata if metadata: - readme_files_dict = suc.build_readme_files_dict( metadata ) + if 'data_manager' in metadata: + includes_data_managers = True + if 'datatypes' in metadata: + includes_datatypes = True if 'tools' in metadata: includes_tools = True - else: - includes_tools = False - else: - readme_files_dict = None - includes_tools = False + if 'workflows' in metadata: + includes_workflows = True + readme_files_dict = suc.build_readme_files_dict( metadata ) # See if the repo_info_dict was populated with repository_dependencies or tool_dependencies. for name, repo_info_tuple in repo_info_dict.items(): description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \ @@ -1623,9 +1647,12 @@ includes_tool_dependencies = True else: includes_tool_dependencies = False - return dict( includes_tools=includes_tools, + return dict( includes_data_managers=includes_data_managers, + includes_datatypes=includes_datatypes, + includes_tools=includes_tools, has_repository_dependencies=has_repository_dependencies, includes_tool_dependencies=includes_tool_dependencies, + includes_workflows=includes_workflows, readme_files_dict=readme_files_dict, repo_info_dict=repo_info_dict ) def get_versions_of_tool( self, trans, repository, repository_metadata, guid ): diff -r 32fc25b8900059f63b0d41d52aa582f06426928c -r 305680a482c3096b082daffa5ff665f5f60d1528 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 @@ -383,29 +383,23 @@ if repository.uninstalled: # Since we're reinstalling the repository we need to find the latest changeset revision to which it can be updated so that we # can reset the metadata if necessary. This will ensure that information about repository dependencies and tool dependencies - # will be current. Only allow selecting a different section in the tool panel if the repository was uninstalled. - current_changeset_revision, current_ctx_rev, includes_tools, has_repository_dependencies = \ - shed_util.get_update_to_changeset_revision_and_ctx_rev( trans, repository ) - if current_ctx_rev == repository.ctx_rev: - # The uninstalled repository is current. - if repository.includes_tools or repository.has_repository_dependencies: + # will be current. Only allow selecting a different section in the tool panel if the repository was uninstalled. + changeset_revision_dict = shed_util.get_update_to_changeset_revision_and_ctx_rev( trans, repository ) + current_changeset_revision = changeset_revision_dict.get( 'changeset_revision', None ) + current_ctx_rev = changeset_revision_dict.get( 'ctx_rev', None ) + if current_changeset_revision and current_ctx_rev: + if current_ctx_rev == repository.ctx_rev: + # The uninstalled repository is current. return trans.response.send_redirect( web.url_for( controller='admin_toolshed', action='reselect_tool_panel_section', **kwd ) ) else: - return trans.response.send_redirect( web.url_for( controller='admin_toolshed', - action='reinstall_repository', - **kwd ) ) - else: - # The uninstalled repository has updates available in the tool shed. - updated_repo_info_dict = self.get_updated_repository_information( trans=trans, - repository_id=trans.security.encode_id( repository.id ), - repository_name=repository.name, - repository_owner=repository.owner, - changeset_revision=current_changeset_revision ) - has_repository_dependencies = updated_repo_info_dict.get( 'has_repository_dependencies', False ) - includes_tool_dependencies = updated_repo_info_dict.get( 'includes_tool_dependencies', False ) - if has_repository_dependencies or includes_tool_dependencies: + # The uninstalled repository has updates available in the tool shed. + updated_repo_info_dict = self.get_updated_repository_information( trans=trans, + repository_id=trans.security.encode_id( repository.id ), + repository_name=repository.name, + repository_owner=repository.owner, + changeset_revision=current_changeset_revision ) json_repo_info_dict = json.to_json_string( updated_repo_info_dict ) encoded_repo_info_dict = encoding_util.tool_shed_encode( json_repo_info_dict ) kwd[ 'latest_changeset_revision' ] = current_changeset_revision @@ -414,10 +408,14 @@ return trans.response.send_redirect( web.url_for( controller='admin_toolshed', action='reselect_tool_panel_section', **kwd ) ) - else: - return trans.response.send_redirect( web.url_for( controller='admin_toolshed', - action='reinstall_repository', - **kwd ) ) + else: + message = "Unable to get latest revision for repository <b>%s</b> from the tool shed, so repository " % str( repository.name ) + message += "reinstallation is not possible at this time." + status = "error" + return trans.response.send_redirect( web.url_for( controller='admin_toolshed', + action='browse_repositories', + message=message, + status=status ) ) else: return trans.response.send_redirect( web.url_for( controller='admin_toolshed', action='activate_repository', @@ -903,8 +901,9 @@ if cloned_ok: if reinstalling: # Since we're reinstalling the repository we need to find the latest changeset revision to which is can be updated. - current_changeset_revision, current_ctx_rev, includes_tools, has_repository_dependencies = \ - shed_util.get_update_to_changeset_revision_and_ctx_rev( trans, tool_shed_repository ) + changeset_revision_dict = shed_util.get_update_to_changeset_revision_and_ctx_rev( trans, tool_shed_repository ) + current_changeset_revision = changeset_revision_dict.get( 'changeset_revision', None ) + current_ctx_rev = changeset_revision_dict.get( 'ctx_rev', None ) if current_ctx_rev != ctx_rev: repo = hg.repository( suc.get_configured_ui(), path=os.path.abspath( install_dir ) ) shed_util.pull_repository( repo, repository_clone_url, current_changeset_revision ) @@ -1367,7 +1366,7 @@ containers_dicts.append( containers_dict ) # Merge all containers into a single container. containers_dict = shed_util.merge_containers_dicts_for_new_install( containers_dicts ) - # Handle tool dependencies chack box. + # 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> " @@ -1566,6 +1565,7 @@ Galaxy database will not be used since it is outdated. """ message = '' + status = 'done' repository_id = kwd.get( 'id', None ) latest_changeset_revision = kwd.get( 'latest_changeset_revision', None ) latest_ctx_rev = kwd.get( 'latest_ctx_rev', None ) @@ -1580,19 +1580,36 @@ encoded_updated_repo_info_dict = kwd.get( 'updated_repo_info_dict', None ) updated_repo_info_dict = encoding_util.tool_shed_decode( encoded_updated_repo_info_dict ) readme_files_dict = updated_repo_info_dict.get( 'readme_files_dict', None ) + includes_data_managers = updated_repo_info_dict.get( 'includes_data_managers', False ) + includes_datatypes = updated_repo_info_dict.get( 'includes_datatypes', False ) includes_tools = updated_repo_info_dict.get( 'includes_tools', False ) + includes_workflows = updated_repo_info_dict.get( 'includes_workflows', False ) has_repository_dependencies = updated_repo_info_dict.get( 'has_repository_dependencies', False ) includes_tool_dependencies = updated_repo_info_dict.get( 'includes_tool_dependencies', False ) repo_info_dict = updated_repo_info_dict[ 'repo_info_dict' ] else: # There are no updates available from the tool shed for the repository, so use it's locally stored metadata. + has_repository_dependencies = False + includes_data_managers = False + includes_datatypes = False + includes_tool_dependencies = False + includes_tools = False + includes_workflows = False + readme_files_dict = None + tool_dependencies = None if metadata: + if 'data_manager' in metadata: + includes_data_managers = True + if 'datatypes' in metadata: + includes_datatypes = True + if 'tools' in metadata: + includes_tools = True + if 'tool_dependencies' in metadata: + includes_tool_dependencies = True + if 'workflows' in metadata: + includes_workflows = True readme_files_dict = suc.build_readme_files_dict( metadata ) tool_dependencies = metadata.get( 'tool_dependencies', None ) - else: - readme_files_dict = None - tool_dependencies = None - includes_tool_dependencies = tool_shed_repository.includes_tool_dependencies repository_dependencies = self.get_repository_dependencies( trans=trans, repository_id=repository_id, repository_name=tool_shed_repository.name, @@ -1615,33 +1632,39 @@ has_repository_dependencies = True else: has_repository_dependencies = False - # 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' ] - if tool_panel_dict: - if shed_util.panel_entry_per_tool( tool_panel_dict ): - # The following forces everything to be 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_name = tool_section_dict[ 'name' ] + if includes_tools: + # Get the location in the tool panel in which the tools were originally loaded. + if 'tool_panel_section' in metadata: + tool_panel_dict = metadata[ 'tool_panel_section' ] + if tool_panel_dict: + if shed_util.panel_entry_per_tool( tool_panel_dict ): + # The following forces everything to be 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_name = tool_section_dict[ 'name' ] + else: + original_section_name = tool_panel_dict[ 'name' ] else: - original_section_name = tool_panel_dict[ 'name' ] + original_section_name = '' else: original_section_name = '' + tool_panel_section_select_field = build_tool_panel_section_select_field( trans ) + no_changes_check_box = CheckboxField( 'no_changes', checked=True ) + if original_section_name: + message += "The tools contained in your <b>%s</b> repository were last loaded into the tool panel section <b>%s</b>. " \ + % ( tool_shed_repository.name, original_section_name ) + message += "Uncheck the <b>No changes</b> check box and select a different tool panel section to load the tools in a " + message += "different section in the tool panel. " + status = 'warning' + else: + message += "The tools contained in your <b>%s</b> repository were last loaded into the tool panel outside of any sections. " % tool_shed_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' else: + no_changes_check_box = None original_section_name = '' - tool_panel_section_select_field = build_tool_panel_section_select_field( trans ) - no_changes_check_box = CheckboxField( 'no_changes', checked=True ) - if original_section_name: - message += "The tools contained in your <b>%s</b> repository were last loaded into the tool panel section <b>%s</b>. " \ - % ( tool_shed_repository.name, original_section_name ) - message += "Uncheck the <b>No changes</b> check box and select a different tool panel section to load the tools in a " - message += "different section in the tool panel. " - status = 'warning' - else: - message += "The tools contained in your <b>%s</b> repository were last loaded into the tool panel outside of any sections. " % tool_shed_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' + tool_panel_section_select_field = None + shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans ) containers_dict = shed_util.populate_containers_dict_for_new_install( trans=trans, tool_shed_url=tool_shed_url, tool_path=tool_path, @@ -1669,12 +1692,17 @@ repository=tool_shed_repository, no_changes_check_box=no_changes_check_box, original_section_name=original_section_name, + includes_data_managers=includes_data_managers, + includes_datatypes=includes_datatypes, + includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies, + includes_workflows=includes_workflows, has_repository_dependencies=has_repository_dependencies, 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, + shed_tool_conf_select_field=shed_tool_conf_select_field, encoded_repo_info_dict=encoding_util.tool_shed_encode( repo_info_dict ), repo_info_dict=repo_info_dict, message=message, diff -r 32fc25b8900059f63b0d41d52aa582f06426928c -r 305680a482c3096b082daffa5ff665f5f60d1528 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 @@ -41,28 +41,55 @@ </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"> - ${no_changes_check_box.get_html()} - <label style="display: inline;">No changes</label> - <div class="toolParamHelp" style="clear: both;"> - Uncheck and select a different tool panel section to load the tools into a different section in the tool panel. + %if shed_tool_conf_select_field: + <div class="form-row"> + <table class="colored" width="100%"> + <th bgcolor="#EBD9B2">Choose the configuration file whose tool_path setting will be used for installing repositories</th> + </table></div> - </div> - <div class="form-row"> - <label>Add new tool panel section:</label> - <input name="new_tool_panel_section" type="textfield" value="" size="40"/> - <div class="toolParamHelp" style="clear: both;"> - Add a new tool panel section to contain the installed tools (optional). + <% + if len( shed_tool_conf_select_field.options ) == 1: + select_help = "Your Galaxy instance is configured with 1 shed-related tool configuration file, so repositories will be " + select_help += "installed using it's <b>tool_path</b> setting." + else: + select_help = "Your Galaxy instance is configured with %d shed-related tool configuration files, " % len( shed_tool_conf_select_field.options ) + select_help += "so select the file whose <b>tool_path</b> setting you want used for installing repositories." + %> + <div class="form-row"> + <label>Shed tool configuration file:</label> + ${shed_tool_conf_select_field.get_html()} + <div class="toolParamHelp" style="clear: both;"> + ${select_help} + </div></div> - </div> - <div class="form-row"> - <label>Select existing tool panel section:</label> - ${tool_panel_section_select_field.get_html()} - <div class="toolParamHelp" style="clear: both;"> - Choose an existing section in your tool panel to contain the installed tools (optional). + <div style="clear: both"></div> + %else: + <input type="hidden" name="shed_tool_conf" value="${shed_tool_conf}"/> + %endif + %if includes_tools: + <div style="clear: both"></div> + <div class="form-row"> + ${no_changes_check_box.get_html()} + <label style="display: inline;">No changes</label> + <div class="toolParamHelp" style="clear: both;"> + Uncheck and select a different tool panel section to load the tools into a different section in the tool panel. + </div></div> - </div> + <div class="form-row"> + <label>Add new tool panel section:</label> + <input name="new_tool_panel_section" type="textfield" value="" size="40"/> + <div class="toolParamHelp" style="clear: both;"> + Add a new tool panel section to contain the installed tools (optional). + </div> + </div> + <div class="form-row"> + <label>Select existing tool panel section:</label> + ${tool_panel_section_select_field.get_html()} + <div class="toolParamHelp" style="clear: both;"> + Choose an existing section in your tool panel to contain the installed tools (optional). + </div> + </div> + %endif <div class="form-row"><input type="submit" name="select_tool_panel_section_button" value="Install"/></div> diff -r 32fc25b8900059f63b0d41d52aa582f06426928c -r 305680a482c3096b082daffa5ff665f5f60d1528 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 @@ -81,12 +81,12 @@ ${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"> + <table class="colored" width="100%"> + <th bgcolor="#EBD9B2">Choose the tool panel section to contain the installed tools (optional)</th> + </table> + </div><% if len( shed_tool_conf_select_field.options ) == 1: select_help = "Your Galaxy instance is configured with 1 shed-related tool configuration file, so repositories will be " 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