From dafa844aa36433100aa16b3b4c4124d944cc6df6 Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Mon, 23 Feb 2015 17:42:17 -0500 Subject: [PATCH] add API endpoint to create TS repository --- .../webapps/tool_shed/api/repositories.py | 64 ++++++++++++++++++- lib/galaxy/webapps/tool_shed/buildapp.py | 5 ++ lib/tool_shed/util/repository_util.py | 13 ++-- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/lib/galaxy/webapps/tool_shed/api/repositories.py b/lib/galaxy/webapps/tool_shed/api/repositories.py index 5c530f8dc365..abdafcd8797c 100644 --- a/lib/galaxy/webapps/tool_shed/api/repositories.py +++ b/lib/galaxy/webapps/tool_shed/api/repositories.py @@ -10,8 +10,10 @@ from galaxy import util from galaxy import web +from galaxy import exceptions from galaxy.datatypes import checkers from galaxy.model.orm import and_ +from galaxy.web import _future_expose_api as expose_api from galaxy.web.base.controller import BaseAPIController from galaxy.web.base.controller import HTTPBadRequest from galaxy.web.framework.helpers import time_ago @@ -31,6 +33,7 @@ from tool_shed.util import shed_util_common as suc from tool_shed.util import tool_util + log = logging.getLogger( __name__ ) @@ -577,13 +580,72 @@ def show( self, trans, id, **kwd ): id=trans.security.encode_id( repository.id ) ) return repository_dict + @expose_api + def create( self, trans, payload, **kwd ): + """ + create( self, trans, payload, **kwd ) + * POST /api/repositories: + Creates a new repository. + Only ``name`` and ``synopsis`` parameters are required. + + :param payload: dictionary structure containing:: + 'name': new repo's name (required) + 'synopsis': new repo's synopsis (required) + 'description': new repo's description (optional) + 'remote_repository_url': new repo's remote repo (optional) + 'homepage_url': new repo's homepage url (optional) + 'category_ids[]': list of existing encoded TS category ids + the new repo should be associated with (optional) + 'type': new repo's type, defaults to ``unrestricted`` (optional) + + :type payload: dict + + :returns: detailed repository information + :rtype: dict + + :raises: RequestParameterMissingException + """ + params = util.Params( payload ) + name = util.restore_text( params.get( 'name', None ) ) + if not name: + raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." ) + synopsis = util.restore_text( params.get( 'synopsis', None ) ) + if not synopsis: + raise exceptions.RequestParameterMissingException( "Missing required parameter 'synopsis'." ) + + description = util.restore_text( params.get( 'description', '' ) ) + remote_repository_url = util.restore_text( params.get( 'remote_repository_url', '' ) ) + homepage_url = util.restore_text( params.get( 'homepage_url', '' ) ) + category_ids = util.listify( params.get( 'category_ids[]', '' ) ) + selected_categories = [ trans.security.decode_id( id ) for id in category_ids ] + + repo_type = kwd.get( 'type', rt_util.UNRESTRICTED ) + if repo_type not in rt_util.types: + raise exceptions.RequestParameterInvalidException( 'This repository type is not valid' ) + + invalid_message = repository_util.validate_repository_name( trans.app, name, trans.user ) + if invalid_message: + raise exceptions.RequestParameterInvalidException( invalid_message ) + + repo, message = repository_util.create_repository( app=trans.app, + name=name, + type=repo_type, + description=synopsis, + long_description=description, + user_id = trans.user.id, + category_ids=category_ids, + remote_repository_url=remote_repository_url, + homepage_url=homepage_url ) + + return repo.to_dict( view='element', value_mapper=self.__get_value_mapper( trans ) ) + @web.expose_api def create_changeset_revision( self, trans, id, payload, **kwd ): """ POST /api/repositories/{encoded_repository_id}/changeset_revision Create a new tool shed repository commit - leaving PUT on parent - resource open for updating meta-attirbutes of the repository (and + resource open for updating meta-attributes of the repository (and Galaxy doesn't allow PUT multipart data anyway https://trello.com/c/CQwmCeG6). diff --git a/lib/galaxy/webapps/tool_shed/buildapp.py b/lib/galaxy/webapps/tool_shed/buildapp.py index b32036f164c5..1dbe74fabf58 100644 --- a/lib/galaxy/webapps/tool_shed/buildapp.py +++ b/lib/galaxy/webapps/tool_shed/buildapp.py @@ -129,6 +129,11 @@ def app_factory( global_conf, **kwargs ): controller='repositories', action='create_changeset_revision', conditions=dict( method=[ "POST" ] ) ) + webapp.mapper.connect( 'create_repository', + '/api/repositories', + controller='repositories', + action='create', + conditions=dict( method=[ "POST" ] ) ) webapp.finalize_config() # Wrap the webapp in some useful middleware diff --git a/lib/tool_shed/util/repository_util.py b/lib/tool_shed/util/repository_util.py index aaaef52838ff..132184f10ce2 100644 --- a/lib/tool_shed/util/repository_util.py +++ b/lib/tool_shed/util/repository_util.py @@ -313,8 +313,11 @@ def handle_role_associations( app, role, repository, **kwd ): return associations_dict def validate_repository_name( app, name, user ): - # Repository names must be unique for each user, must be at least four characters - # in length and must contain only lower-case letters, numbers, and the '_' character. + """ + Validate whether the given name qualifies as a new TS repo name. + Repository names must be unique for each user, must be at least two characters + in length and must contain only lower-case letters, numbers, and the '_' character. + """ if name in [ 'None', None, '' ]: return 'Enter the required repository name.' if name in [ 'repos' ]: @@ -322,13 +325,13 @@ def validate_repository_name( app, name, user ): check_existing = suc.get_repository_by_name_and_owner( app, name, user.username ) if check_existing is not None: if check_existing.deleted: - return 'You have a deleted repository named %s, so choose a different name.' % name + return 'You own a deleted repository named %s, please choose a different name.' % escape( name ) else: - return "You already have a repository named %s, so choose a different name." % name + return "You already own a repository named %s, please choose a different name." % escape( name ) if len( name ) < 2: return "Repository names must be at least 2 characters in length." if len( name ) > 80: return "Repository names cannot be more than 80 characters in length." if not( VALID_REPOSITORYNAME_RE.match( name ) ): - return "Repository names must contain only lower-case letters, numbers and underscore _." + return "Repository names must contain only lower-case letters, numbers and underscore." return ''