1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/144ae945768a/ changeset: 144ae945768a user: greg date: 2012-10-19 22:25:08 summary: Some tool she drepository grid cleanup, and add the ability to mark a repository as deprecated / undeprecated. Repositories in the tool shed that are marked as deprecated have restricted tool shed features and will not be included in several queries. affected #: 12 files diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf lib/galaxy/webapps/community/controllers/admin.py --- a/lib/galaxy/webapps/community/controllers/admin.py +++ b/lib/galaxy/webapps/community/controllers/admin.py @@ -7,7 +7,7 @@ from galaxy.util import inflector from galaxy.util.shed_util import get_changectx_for_changeset, get_configured_ui from common import * -from repository import RepositoryListGrid, CategoryListGrid +from repository import RepositoryGrid, CategoryGrid from galaxy import eggs eggs.require( 'mercurial' ) @@ -17,7 +17,7 @@ log = logging.getLogger( __name__ ) -class UserListGrid( grids.Grid ): +class UserGrid( grids.Grid ): # TODO: move this to an admin_common controller since it is virtually the same in the galaxy webapp. class UserLoginColumn( grids.TextColumn ): def get_value( self, trans, grid, user ): @@ -66,10 +66,10 @@ default_sort_key = "email" columns = [ UserLoginColumn( "Email", - key="email", - link=( lambda item: dict( operation="information", id=item.id ) ), - attach_popup=True, - filterable="advanced" ), + key="email", + link=( lambda item: dict( operation="information", id=item.id ) ), + attach_popup=True, + filterable="advanced" ), UserNameColumn( "User Name", key="username", attach_popup=False, @@ -116,7 +116,7 @@ def get_current_item( self, trans, **kwargs ): return trans.user -class RoleListGrid( grids.Grid ): +class RoleGrid( grids.Grid ): # TODO: move this to an admin_common controller since it is virtually the same in the galaxy webapp. class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, role ): @@ -207,7 +207,7 @@ def apply_query_filter( self, trans, query, **kwd ): return query.filter( model.Role.type != model.Role.types.PRIVATE ) -class GroupListGrid( grids.Grid ): +class GroupGrid( grids.Grid ): # TODO: move this to an admin_common controller since it is virtually the same in the galaxy webapp. class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, group ): @@ -278,34 +278,35 @@ preserve_state = False use_paging = True -class ManageCategoryListGrid( CategoryListGrid ): - columns = [ col for col in CategoryListGrid.columns ] +class ManageCategoryGrid( CategoryGrid ): + columns = [ col for col in CategoryGrid.columns ] # Override the NameColumn to include an Edit link - columns[ 0 ] = CategoryListGrid.NameColumn( "Name", - key="Category.name", - link=( lambda item: dict( operation="Edit", id=item.id ) ), - model_class=model.Category, - attach_popup=False ) + columns[ 0 ] = CategoryGrid.NameColumn( "Name", + key="Category.name", + link=( lambda item: dict( operation="Edit", id=item.id ) ), + model_class=model.Category, + attach_popup=False ) global_actions = [ grids.GridAction( "Add new category", dict( controller='admin', action='manage_categories', operation='create' ) ) ] -class AdminRepositoryListGrid( RepositoryListGrid ): - columns = [ RepositoryListGrid.NameColumn( "Name", - key="name", - link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), - attach_popup=True ), - RepositoryListGrid.DescriptionColumn( "Synopsis", - key="description", - attach_popup=False ), - RepositoryListGrid.MetadataRevisionColumn( "Metadata Revisions" ), - RepositoryListGrid.UserColumn( "Owner", - model_class=model.User, - link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), - attach_popup=False, - key="User.username" ), - RepositoryListGrid.EmailAlertsColumn( "Alert", attach_popup=False ), +class AdminRepositoryGrid( RepositoryGrid ): + columns = [ RepositoryGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), + RepositoryGrid.DescriptionColumn( "Synopsis", + key="description", + attach_popup=False ), + RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ), + RepositoryGrid.UserColumn( "Owner", + model_class=model.User, + link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), + attach_popup=False, + key="User.username" ), + RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ), + RepositoryGrid.DeprecatedColumn( "Deprecated", attach_popup=False ), # Columns that are valid for filtering but are not visible. grids.DeletedColumn( "Deleted", key="deleted", @@ -316,7 +317,7 @@ key="free-text-search", visible=False, filterable="standard" ) ) - operations = [ operation for operation in RepositoryListGrid.operations ] + operations = [ operation for operation in RepositoryGrid.operations ] operations.append( grids.GridOperation( "Delete", allow_multiple=False, condition=( lambda item: not item.deleted ), @@ -327,7 +328,7 @@ async_compatible=False ) ) standard_filters = [] -class RepositoryMetadataListGrid( grids.Grid ): +class RepositoryMetadataGrid( grids.Grid ): class IdColumn( grids.IntegerColumn ): def get_value( self, trans, grid, repository_metadata ): return repository_metadata.id @@ -414,17 +415,18 @@ preserve_state = False use_paging = True def build_initial_query( self, trans, **kwd ): - return trans.sa_session.query( self.model_class ) \ - .join( model.Repository.table ) + return trans.sa_session.query( model.RepositoryMetadata ) \ + .join( model.Repository.table ) \ + .filter( model.Repository.table.c.deprecated == False ) class AdminController( BaseUIController, Admin ): - user_list_grid = UserListGrid() - role_list_grid = RoleListGrid() - group_list_grid = GroupListGrid() - manage_category_list_grid = ManageCategoryListGrid() - repository_list_grid = AdminRepositoryListGrid() - repository_metadata_list_grid = RepositoryMetadataListGrid() + user_list_grid = UserGrid() + role_list_grid = RoleGrid() + group_list_grid = GroupGrid() + manage_category_grid = ManageCategoryGrid() + repository_grid = AdminRepositoryGrid() + repository_metadata_grid = RepositoryMetadataGrid() @web.expose @web.require_admin @@ -477,7 +479,7 @@ return self.delete_repository( trans, **kwd ) elif operation == "undelete": return self.undelete_repository( trans, **kwd ) - # The changeset_revision_select_field in the RepositoryListGrid performs a refresh_on_change + # The changeset_revision_select_field in the RepositoryGrid performs a refresh_on_change # which sends in request parameters like changeset_revison_1, changeset_revision_2, etc. One # of the many select fields on the grid performed the refresh_on_change, so we loop through # all of the received values to see which value is not the repository tip. If we find it, we @@ -495,7 +497,7 @@ id=trans.security.encode_id( repository.id ), changeset_revision=v ) ) # Render the list view - return self.repository_list_grid( trans, **kwd ) + return self.repository_grid( trans, **kwd ) @web.expose @web.require_admin def browse_repository_metadata( self, trans, **kwd ): @@ -515,7 +517,7 @@ return trans.response.send_redirect( web.url_for( controller='repository', action='browse_repositories', **kwd ) ) - return self.repository_metadata_list_grid( trans, **kwd ) + return self.repository_metadata_grid( trans, **kwd ) @web.expose @web.require_admin def create_category( self, trans, **kwd ): @@ -645,9 +647,9 @@ @web.require_admin def manage_categories( self, trans, **kwd ): if 'f-free-text-search' in kwd: - # Trick to enable searching repository name, description from the CategoryListGrid. - # What we've done is rendered the search box for the RepositoryListGrid on the grid.mako - # template for the CategoryListGrid. See ~/templates/webapps/community/category/grid.mako. + # Trick to enable searching repository name, description from the CategoryGrid. + # What we've done is rendered the search box for the RepositoryGrid on the grid.mako + # template for the CategoryGrid. See ~/templates/webapps/community/category/grid.mako. # Since we are searching repositories and not categories, redirect to browse_repositories(). return trans.response.send_redirect( web.url_for( controller='admin', action='browse_repositories', @@ -674,7 +676,7 @@ return trans.response.send_redirect( web.url_for( controller='admin', action='edit_category', **kwd ) ) - return self.manage_category_list_grid( trans, **kwd ) + return self.manage_category_grid( trans, **kwd ) @web.expose @web.require_admin def regenerate_statistics( self, trans, **kwd ): @@ -732,7 +734,8 @@ multiple=True, display='checkboxes' ) for repository in trans.sa_session.query( trans.model.Repository ) \ - .filter( trans.model.Repository.table.c.deleted == False ) \ + .filter( and_( trans.model.Repository.table.c.deleted == False, + trans.model.Repository.table.c.deprecated == False ) ) \ .order_by( trans.model.Repository.table.c.name, trans.model.Repository.table.c.user_id ): owner = repository.user.username diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf lib/galaxy/webapps/community/controllers/repository.py --- a/lib/galaxy/webapps/community/controllers/repository.py +++ b/lib/galaxy/webapps/community/controllers/repository.py @@ -25,7 +25,7 @@ VALID_REPOSITORYNAME_RE = re.compile( "^[a-z0-9\_]+$" ) -class CategoryListGrid( grids.Grid ): +class CategoryGrid( grids.Grid ): class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, category ): return category.name @@ -65,14 +65,14 @@ preserve_state = False use_paging = True -class ValidCategoryListGrid( CategoryListGrid ): +class ValidCategoryGrid( CategoryGrid ): class RepositoriesColumn( grids.TextColumn ): def get_value( self, trans, grid, category ): if category.repositories: viewable_repositories = 0 for rca in category.repositories: repository = rca.repository - if repository.downloadable_revisions: + if not repository.deprecated and repository.downloadable_revisions: viewable_repositories += 1 return viewable_repositories return 0 @@ -81,13 +81,13 @@ template='/webapps/community/category/valid_grid.mako' default_sort_key = "name" columns = [ - CategoryListGrid.NameColumn( "Name", - key="Category.name", - link=( lambda item: dict( operation="valid_repositories_by_category", id=item.id ) ), - attach_popup=False ), - CategoryListGrid.DescriptionColumn( "Description", - key="Category.description", - attach_popup=False ), + CategoryGrid.NameColumn( "Name", + key="Category.name", + link=( lambda item: dict( operation="valid_repositories_by_category", id=item.id ) ), + attach_popup=False ), + CategoryGrid.DescriptionColumn( "Description", + key="Category.description", + attach_popup=False ), # Columns that are valid for filtering but are not visible. RepositoriesColumn( "Valid repositories", model_class=model.Repository, @@ -102,7 +102,7 @@ preserve_state = False use_paging = True -class RepositoryListGrid( grids.Grid ): +class RepositoryGrid( grids.Grid ): class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, repository ): return repository.name @@ -188,6 +188,11 @@ if trans.user and repository.email_alerts and trans.user.email in from_json_string( repository.email_alerts ): return 'yes' return '' + class DeprecatedColumn( grids.TextColumn ): + def get_value( self, trans, grid, repository ): + if repository.deprecated: + return 'yes' + return '' # Grid definition title = "Repositories" model_class = model.Repository @@ -248,21 +253,83 @@ .outerjoin( model.RepositoryCategoryAssociation.table ) \ .outerjoin( model.Category.table ) -class EmailAlertsRepositoryListGrid( RepositoryListGrid ): +class RepositoriesIOwnGrid( RepositoryGrid ): + title = "Repositories I own" columns = [ - RepositoryListGrid.NameColumn( "Name", - key="name", - link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + RepositoryGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), + RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ), + RepositoryGrid.TipRevisionColumn( "Tip Revision" ), + RepositoryGrid.CategoryColumn( "Category", + model_class=model.Category, + key="Category.name", attach_popup=False ), - RepositoryListGrid.DescriptionColumn( "Synopsis", - key="description", - attach_popup=False ), - RepositoryListGrid.UserColumn( "Owner", - model_class=model.User, - link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), - attach_popup=False, - key="User.username" ), - RepositoryListGrid.EmailAlertsColumn( "Alert", attach_popup=False ), + RepositoryGrid.DeprecatedColumn( "Deprecated" ) + ] + columns.append( grids.MulticolFilterColumn( "Search repository name", + cols_to_filter=[ columns[0] ], + key="free-text-search", + visible=False, + filterable="standard" ) ) + operations = [ grids.GridOperation( "Mark as deprecated", + allow_multiple=False, + condition=( lambda item: not item.deleted and not item.deprecated ), + async_compatible=False ), + grids.GridOperation( "Mark as not deprecated", + allow_multiple=False, + condition=( lambda item: not item.deleted and item.deprecated ), + async_compatible=False ) ] + def build_initial_query( self, trans, **kwd ): + return trans.sa_session.query( model.Repository ) \ + .filter( model.Repository.table.c.user_id == trans.user.id ) \ + .join( model.User.table ) \ + .outerjoin( model.RepositoryCategoryAssociation.table ) \ + .outerjoin( model.Category.table ) + +class DeprecatedRepositoriesIOwnGrid( RepositoriesIOwnGrid ): + title = "Deprecated repositories I own" + columns = [ + RepositoriesIOwnGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), + RepositoriesIOwnGrid.MetadataRevisionColumn( "Metadata Revisions" ), + RepositoriesIOwnGrid.TipRevisionColumn( "Tip Revision" ), + RepositoriesIOwnGrid.CategoryColumn( "Category", + model_class=model.Category, + key="Category.name", + attach_popup=False ), + ] + columns.append( grids.MulticolFilterColumn( "Search repository name", + cols_to_filter=[ columns[0] ], + key="free-text-search", + visible=False, + filterable="standard" ) ) + def build_initial_query( self, trans, **kwd ): + return trans.sa_session.query( model.Repository ) \ + .filter( and_( model.Repository.table.c.user_id == trans.user.id, + model.Repository.table.c.deprecated == True ) ) \ + .join( model.User.table ) \ + .outerjoin( model.RepositoryCategoryAssociation.table ) \ + .outerjoin( model.Category.table ) + +class EmailAlertsRepositoryGrid( RepositoryGrid ): + columns = [ + RepositoryGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=False ), + RepositoryGrid.DescriptionColumn( "Synopsis", + key="description", + attach_popup=False ), + RepositoryGrid.UserColumn( "Owner", + model_class=model.User, + link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), + attach_popup=False, + key="User.username" ), + RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ), # Columns that are valid for filtering but are not visible. grids.DeletedColumn( "Deleted", key="deleted", @@ -277,29 +344,67 @@ grids.GridAction( "User preferences", dict( controller='user', action='index', cntrller='repository' ) ) ] -class WritableRepositoryListGrid( RepositoryListGrid ): +class MyWritableRepositoriesGrid( RepositoryGrid ): + # This grid filters out repositories that have been marked as deprecated. + columns = [ + RepositoryGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), + RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ), + RepositoryGrid.TipRevisionColumn( "Tip Revision" ), + RepositoryGrid.UserColumn( "Owner", + model_class=model.User, + link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), + attach_popup=False, + key="User.username" ), + RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ), + # Columns that are valid for filtering but are not visible. + RepositoryGrid.EmailColumn( "Email", + model_class=model.User, + key="email", + visible=False ), + RepositoryGrid.RepositoryCategoryColumn( "Category", + model_class=model.Category, + key="Category.name", + visible=False ), + grids.DeletedColumn( "Deleted", + key="deleted", + visible=False, + filterable="advanced" ) + ] + columns.append( grids.MulticolFilterColumn( "Search repository name", + cols_to_filter=[ columns[0] ], + key="free-text-search", + visible=False, + filterable="standard" ) ) + operations = [ grids.GridOperation( "Receive email alerts", + allow_multiple=False, + condition=( lambda item: not item.deleted ), + async_compatible=False ) ] def build_initial_query( self, trans, **kwd ): # TODO: improve performance by adding a db table associating users with repositories for which they have write access. - username = kwd[ 'username' ] + username = trans.user.username clause_list = [] - for repository in trans.sa_session.query( self.model_class ) \ - .filter( self.model_class.table.c.deleted == False ): + for repository in trans.sa_session.query( model.Repository ) \ + .filter( and_( model.Repository.table.c.deprecated == False, + model.Repository.table.c.deleted == False ) ): allow_push = repository.allow_push if allow_push: allow_push_usernames = allow_push.split( ',' ) if username in allow_push_usernames: - clause_list.append( self.model_class.table.c.id == repository.id ) + clause_list.append( model.Repository.table.c.id == repository.id ) if clause_list: - return trans.sa_session.query( self.model_class ) \ + return trans.sa_session.query( model.Repository ) \ .filter( or_( *clause_list ) ) \ .join( model.User.table ) \ .outerjoin( model.RepositoryCategoryAssociation.table ) \ .outerjoin( model.Category.table ) # Return an empty query. - return trans.sa_session.query( self.model_class ) \ - .filter( self.model_class.table.c.id < 0 ) + return [] -class ValidRepositoryListGrid( RepositoryListGrid ): +class ValidRepositoryGrid( RepositoryGrid ): + # This grid filters out repositories that have been marked as deprecated. class CategoryColumn( grids.TextColumn ): def get_value( self, trans, grid, repository ): rval = '<ul>' @@ -330,16 +435,16 @@ return '' title = "Valid repositories" columns = [ - RepositoryListGrid.NameColumn( "Name", - key="name", - attach_popup=True ), - RepositoryListGrid.DescriptionColumn( "Synopsis", - key="description", - attach_popup=False ), + RepositoryGrid.NameColumn( "Name", + key="name", + attach_popup=True ), + RepositoryGrid.DescriptionColumn( "Synopsis", + key="description", + attach_popup=False ), RevisionColumn( "Installable Revisions" ), - RepositoryListGrid.UserColumn( "Owner", - model_class=model.User, - attach_popup=False ), + RepositoryGrid.UserColumn( "Owner", + model_class=model.User, + attach_popup=False ), # Columns that are valid for filtering but are not visible. RepositoryCategoryColumn( "Category", model_class=model.Category, @@ -355,22 +460,25 @@ def build_initial_query( self, trans, **kwd ): if 'id' in kwd: # The user is browsing categories of valid repositories, so filter the request by the received id, which is a category id. - return trans.sa_session.query( self.model_class ) \ + return trans.sa_session.query( model.Repository ) \ + .filter( model.Repository.table.c.deprecated == False ) \ .join( model.RepositoryMetadata.table ) \ .join( model.User.table ) \ .join( model.RepositoryCategoryAssociation.table ) \ .join( model.Category.table ) \ .filter( and_( model.Category.table.c.id == trans.security.decode_id( kwd[ 'id' ] ), model.RepositoryMetadata.table.c.downloadable == True ) ) - # The user performed a free text search on the ValidCategoryListGrid. - return trans.sa_session.query( self.model_class ) \ + # The user performed a free text search on the ValidCategoryGrid. + return trans.sa_session.query( model.Repository ) \ + .filter( model.Repository.table.c.deprecated == False ) \ .join( model.RepositoryMetadata.table ) \ .join( model.User.table ) \ .outerjoin( model.RepositoryCategoryAssociation.table ) \ .outerjoin( model.Category.table ) \ .filter( model.RepositoryMetadata.table.c.downloadable == True ) -class MatchedRepositoryListGrid( grids.Grid ): +class MatchedRepositoryGrid( grids.Grid ): + # This grid filters out repositories that have been marked as deprecated. class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, repository_metadata ): return repository_metadata.repository.name @@ -413,38 +521,38 @@ if match_tuples: for match_tuple in match_tuples: repository_id, changeset_revision = match_tuple - clause_list.append( "%s=%d and %s='%s'" % ( self.model_class.table.c.repository_id, + clause_list.append( "%s=%d and %s='%s'" % ( model.RepositoryMetadata.table.c.repository_id, int( repository_id ), - self.model_class.table.c.changeset_revision, + model.RepositoryMetadata.table.c.changeset_revision, changeset_revision ) ) - return trans.sa_session.query( self.model_class ) \ + return trans.sa_session.query( model.RepositoryMetadata ) \ .join( model.Repository ) \ + .filter( model.Repository.table.c.deprecated == False ) \ .join( model.User.table ) \ .filter( or_( *clause_list ) ) \ .order_by( model.Repository.name ) # Return an empty query - return trans.sa_session.query( self.model_class ) \ - .join( model.Repository ) \ - .join( model.User.table ) \ - .filter( self.model_class.table.c.repository_id == 0 ) + return [] -class InstallMatchedRepositoryListGrid( MatchedRepositoryListGrid ): - columns = [ col for col in MatchedRepositoryListGrid.columns ] +class InstallMatchedRepositoryGrid( MatchedRepositoryGrid ): + columns = [ col for col in MatchedRepositoryGrid.columns ] # Override the NameColumn - columns[ 0 ] = MatchedRepositoryListGrid.NameColumn( "Name", - link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), - attach_popup=False ) + columns[ 0 ] = MatchedRepositoryGrid.NameColumn( "Name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=False ) class RepositoryController( BaseUIController, ItemRatings ): - install_matched_repository_list_grid = InstallMatchedRepositoryListGrid() - matched_repository_list_grid = MatchedRepositoryListGrid() - valid_repository_list_grid = ValidRepositoryListGrid() - repository_list_grid = RepositoryListGrid() - email_alerts_repository_list_grid = EmailAlertsRepositoryListGrid() - category_list_grid = CategoryListGrid() - valid_category_list_grid = ValidCategoryListGrid() - writable_repository_list_grid = WritableRepositoryListGrid() + install_matched_repository_grid = InstallMatchedRepositoryGrid() + matched_repository_grid = MatchedRepositoryGrid() + valid_repository_grid = ValidRepositoryGrid() + repository_grid = RepositoryGrid() + email_alerts_repository_grid = EmailAlertsRepositoryGrid() + category_grid = CategoryGrid() + valid_category_grid = ValidCategoryGrid() + my_writable_repositories_grid = MyWritableRepositoriesGrid() + repositories_i_own_grid = RepositoriesIOwnGrid() + deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid() def __add_hgweb_config_entry( self, trans, repository, repository_path ): # Add an entry in the hgweb.config file for a new repository. An entry looks something like: @@ -470,8 +578,8 @@ def browse_categories( self, trans, **kwd ): # The request came from the tool shed. if 'f-free-text-search' in kwd: - # Trick to enable searching repository name, description from the CategoryListGrid. What we've done is rendered the search box for the - # RepositoryListGrid on the grid.mako template for the CategoryListGrid. See ~/templates/webapps/community/category/grid.mako. Since we + # Trick to enable searching repository name, description from the CategoryGrid. What we've done is rendered the search box for the + # RepositoryGrid on the grid.mako template for the CategoryGrid. See ~/templates/webapps/community/category/grid.mako. Since we # are searching repositories and not categories, redirect to browse_repositories(). if 'id' in kwd and 'f-free-text-search' in kwd and kwd[ 'id' ] == kwd[ 'f-free-text-search' ]: # The value of 'id' has been set to the search string, which is a repository name. We'll try to get the desired encoded repository id to pass on. @@ -491,7 +599,7 @@ return trans.response.send_redirect( web.url_for( controller='repository', action='browse_repositories', **kwd ) ) - return self.category_list_grid( trans, **kwd ) + return self.category_grid( trans, **kwd ) @web.expose def browse_invalid_tools( self, trans, **kwd ): params = util.Params( kwd ) @@ -564,13 +672,27 @@ for k, v in kwd.items(): if k.startswith( 'f-' ): del kwd[ k ] - kwd[ 'f-email' ] = trans.user.email + return self.repositories_i_own_grid( trans, **kwd ) + elif operation == "deprecated_repositories_i_own": + # Eliminate the current filters if any exist. + for k, v in kwd.items(): + if k.startswith( 'f-' ): + del kwd[ k ] + return self.deprecated_repositories_i_own_grid( trans, **kwd ) + elif operation in [ 'mark as deprecated', 'mark as not deprecated' ]: + # Eliminate the current filters if any exist. + for k, v in kwd.items(): + if k.startswith( 'f-' ): + del kwd[ k ] + kwd[ 'mark_deprecated' ] = operation == 'mark as deprecated' + return trans.response.send_redirect( web.url_for( controller='repository', + action='deprecate', + **kwd ) ) elif operation == "reviewed_repositories_i_own": return trans.response.send_redirect( web.url_for( controller='repository_review', action='reviewed_repositories_i_own' ) ) - elif operation == "writable_repositories": - kwd[ 'username' ] = trans.user.username - return self.writable_repository_list_grid( trans, **kwd ) + elif operation == "my_writable_repositories": + return self.my_writable_repositories_grid( trans, **kwd ) elif operation == "repositories_by_category": # Eliminate the current filters if any exist. for k, v in kwd.items(): @@ -590,7 +712,7 @@ kwd[ 'message' ] = 'You must be logged in to set email alerts.' kwd[ 'status' ] = 'error' del kwd[ 'operation' ] - # The changeset_revision_select_field in the RepositoryListGrid performs a refresh_on_change + # The changeset_revision_select_field in the RepositoryGrid performs a refresh_on_change # which sends in request parameters like changeset_revison_1, changeset_revision_2, etc. One # of the many select fields on the grid performed the refresh_on_change, so we loop through # all of the received values to see which value is not the repository tip. If we find it, we @@ -607,7 +729,7 @@ operation='view_or_manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=v ) ) - return self.repository_list_grid( trans, **kwd ) + return self.repository_grid( trans, **kwd ) @web.expose def browse_repository( self, trans, id, **kwd ): params = util.Params( kwd ) @@ -637,7 +759,7 @@ if kwd[ 'f-free-text-search' ] == 'All': # The user performed a search, then clicked the "x" to eliminate the search criteria. new_kwd = {} - return self.valid_category_list_grid( trans, **new_kwd ) + return self.valid_category_grid( trans, **new_kwd ) # Since we are searching valid repositories and not categories, redirect to browse_valid_repositories(). if 'id' in kwd and 'f-free-text-search' in kwd and kwd[ 'id' ] == kwd[ 'f-free-text-search' ]: # The value of 'id' has been set to the search string, which is a repository name. @@ -658,7 +780,7 @@ return trans.response.send_redirect( web.url_for( controller='repository', action='browse_valid_repositories', **kwd ) ) - return self.valid_category_list_grid( trans, **kwd ) + return self.valid_category_grid( trans, **kwd ) @web.expose def browse_valid_repositories( self, trans, **kwd ): galaxy_url = kwd.get( 'galaxy_url', None ) @@ -667,7 +789,7 @@ # The user browsed to a category and then entered a search string, so get the category associated with it's value. category_name = kwd[ 'f-Category.name' ] category = get_category_by_name( trans, category_name ) - # Set the id value in kwd since it is required by the ValidRepositoryListGrid.build_initial_query method. + # Set the id value in kwd since it is required by the ValidRepositoryGrid.build_initial_query method. kwd[ 'id' ] = trans.security.encode_id( category.id ) if galaxy_url: trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' ) @@ -690,7 +812,7 @@ category_id = kwd.get( 'id', None ) category = get_category( trans, category_id ) kwd[ 'f-Category.name' ] = category.name - # The changeset_revision_select_field in the ValidRepositoryListGrid performs a refresh_on_change which sends in request parameters like + # The changeset_revision_select_field in the ValidRepositoryGrid performs a refresh_on_change which sends in request parameters like # changeset_revison_1, changeset_revision_2, etc. One of the many select fields on the grid performed the refresh_on_change, so we loop # through all of the received values to see which value is not the repository tip. If we find it, we know the refresh_on_change occurred # and we have the necessary repository id and change set revision to pass on. @@ -708,11 +830,11 @@ url_args = dict( action='browse_valid_repositories', operation='preview_tools_in_changeset', repository_id=repository_id ) - self.valid_repository_list_grid.operations = [ grids.GridOperation( "Preview and install", + self.valid_repository_grid.operations = [ grids.GridOperation( "Preview and install", url_args=url_args, allow_multiple=False, async_compatible=False ) ] - return self.valid_repository_list_grid( trans, **kwd ) + return self.valid_repository_grid( trans, **kwd ) def __build_allow_push_select_field( self, trans, current_push_list, selected_value='none' ): options = [] for user in trans.sa_session.query( trans.model.User ): @@ -931,6 +1053,27 @@ message=message, status=status ) @web.expose + @web.require_login( "deprecate repository" ) + def deprecate( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + repository_id = params.get( 'id', None ) + repository = get_repository( trans, repository_id ) + mark_deprecated = util.string_as_bool( params.get( 'mark_deprecated', False ) ) + repository.deprecated = mark_deprecated + trans.sa_session.add( repository ) + trans.sa_session.flush() + if mark_deprecated: + message = 'The repository <b>%s</b> has been marked as deprecated.' % repository.name + else: + message = 'The repository <b>%s</b> has been marked as not deprecated.' % repository.name + trans.response.send_redirect( web.url_for( controller='repository', + action='browse_repositories', + operation='repositories_i_own', + message=message, + status=status ) ) + @web.expose def display_tool( self, trans, repository_id, tool_config, changeset_revision, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) @@ -1049,16 +1192,16 @@ dict( controller='repository', action='find_tools' ) ), grids.GridAction( "Search for workflows", dict( controller='repository', action='find_workflows' ) ) ] - self.install_matched_repository_list_grid.global_actions = global_actions + self.install_matched_repository_grid.global_actions = global_actions install_url_args = dict( controller='repository', action='find_tools' ) operations = [ grids.GridOperation( "Install", url_args=install_url_args, allow_multiple=True, async_compatible=False ) ] - self.install_matched_repository_list_grid.operations = operations - return self.install_matched_repository_list_grid( trans, **kwd ) + self.install_matched_repository_grid.operations = operations + return self.install_matched_repository_grid( trans, **kwd ) else: kwd[ 'message' ] = "tool id: <b>%s</b><br/>tool name: <b>%s</b><br/>tool version: <b>%s</b><br/>exact matches only: <b>%s</b>" % \ ( self.__stringify( tool_ids ), self.__stringify( tool_names ), self.__stringify( tool_versions ), str( exact_matches_checked ) ) - self.matched_repository_list_grid.title = "Repositories with matching tools" - return self.matched_repository_list_grid( trans, **kwd ) + self.matched_repository_grid.title = "Repositories with matching tools" + return self.matched_repository_grid( trans, **kwd ) else: message = "No search performed - each field must contain the same number of comma-separated items." status = "error" @@ -1135,16 +1278,16 @@ dict( controller='repository', action='find_tools' ) ), grids.GridAction( "Search for workflows", dict( controller='repository', action='find_workflows' ) ) ] - self.install_matched_repository_list_grid.global_actions = global_actions + self.install_matched_repository_grid.global_actions = global_actions install_url_args = dict( controller='repository', action='find_workflows' ) operations = [ grids.GridOperation( "Install", url_args=install_url_args, allow_multiple=True, async_compatible=False ) ] - self.install_matched_repository_list_grid.operations = operations - return self.install_matched_repository_list_grid( trans, **kwd ) + self.install_matched_repository_grid.operations = operations + return self.install_matched_repository_grid( trans, **kwd ) else: kwd[ 'message' ] = "workflow name: <b>%s</b><br/>exact matches only: <b>%s</b>" % \ ( self.__stringify( workflow_names ), str( exact_matches_checked ) ) - self.matched_repository_list_grid.title = "Repositories with matching workflows" - return self.matched_repository_list_grid( trans, **kwd ) + self.matched_repository_grid.title = "Repositories with matching workflows" + return self.matched_repository_grid( trans, **kwd ) else: message = "No search performed - each field must contain the same number of comma-separated items." status = "error" @@ -1407,17 +1550,24 @@ status = params.get( 'status', 'done' ) # See if there are any RepositoryMetadata records since menu items require them. repository_metadata = trans.sa_session.query( model.RepositoryMetadata ).first() - # See if the current user owns any repositories that have been reviewed. + current_user = trans.user has_reviewed_repositories = False - current_user = trans.user + has_deprecated_repositories = False if current_user: + # See if the current user owns any repositories that have been reviewed. for repository in current_user.active_repositories: if repository.reviewed_revisions: has_reviewed_repositories = True break + # See if the current user has any repositories that have been marked as deprecated. + for repository in current_user.active_repositories: + if repository.deprecated: + has_deprecated_repositories = True + break return trans.fill_template( '/webapps/community/index.mako', repository_metadata=repository_metadata, has_reviewed_repositories=has_reviewed_repositories, + has_deprecated_repositories=has_deprecated_repositories, message=message, status=status ) @web.expose @@ -1738,7 +1888,8 @@ kwd[ 'message' ] = 'You must be logged in to set email alerts.' kwd[ 'status' ] = 'error' del kwd[ 'operation' ] - return self.email_alerts_repository_list_grid( trans, **kwd ) + self.email_alerts_repository_grid.title = "Set email alerts for repository changes" + return self.email_alerts_repository_grid( trans, **kwd ) def __new_state( self, trans, all_pages=False ): """ Create a new `DefaultToolState` for this tool. It will not be initialized diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf lib/galaxy/webapps/community/controllers/repository_review.py --- a/lib/galaxy/webapps/community/controllers/repository_review.py +++ b/lib/galaxy/webapps/community/controllers/repository_review.py @@ -7,7 +7,7 @@ from galaxy.model.orm import * from sqlalchemy.sql.expression import func from common import * -from repository import RepositoryListGrid +from repository import RepositoryGrid from galaxy.util.shed_util import get_configured_ui from galaxy.util.odict import odict @@ -48,36 +48,33 @@ preserve_state = False use_paging = True -class RepositoriesWithReviewsGrid( RepositoryListGrid ): +class RepositoriesWithReviewsGrid( RepositoryGrid ): + # This grid filters out repositories that have been marked as deprecated. class ReviewersColumn( grids.TextColumn ): def get_value( self, trans, grid, repository ): + rval = '' if repository.reviewers: - rval = '' for user in repository.reviewers: - rval += '%s<br/>' % user.username - return rval - return '' - title = "All reviewed Repositories" + rval += '<a class="view-info" href="repository_reviews_by_user?id=%s">' % trans.security.encode_id( user.id ) + rval += '%s</a> | ' % user.username + rval = rval.rstrip( ' | ' ) + return rval + title = "All reviewed repositories" model_class = model.Repository template='/webapps/community/repository_review/grid.mako' default_sort_key = "Repository.name" columns = [ - RepositoryListGrid.NameColumn( "Repository name", - key="name", - link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), - attach_popup=True ), - RepositoryListGrid.DescriptionColumn( "Synopsis", - key="description", - attach_popup=False ), - RepositoryListGrid.WithReviewsRevisionColumn( "Reviewed revisions" ), - RepositoryListGrid.WithoutReviewsRevisionColumn( "Revisions for review" ), - RepositoryListGrid.UserColumn( "Owner", - attach_popup=False ), - ReviewersColumn( "Reviewers", - attach_popup=False ) + RepositoryGrid.NameColumn( "Repository name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), + RepositoryGrid.WithReviewsRevisionColumn( "Reviewed revisions" ), + RepositoryGrid.WithoutReviewsRevisionColumn( "Revisions for review" ), + RepositoryGrid.UserColumn( "Owner", attach_popup=False ), + ReviewersColumn( "Reviewers", attach_popup=False ) ] - columns.append( grids.MulticolFilterColumn( "Search repository name, description", - cols_to_filter=[ columns[0], columns[1] ], + columns.append( grids.MulticolFilterColumn( "Search repository name", + cols_to_filter=[ columns[0] ], key="free-text-search", visible=False, filterable="standard" ) ) @@ -89,12 +86,14 @@ ] def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( model.Repository ) \ + .filter( model.Repository.table.c.deprecated == False ) \ .join( ( model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \ .join( ( model.User.table, model.User.table.c.id == model.Repository.table.c.user_id ) ) \ .outerjoin( ( model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id ) ) \ .outerjoin( ( model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id ) ) class RepositoriesWithoutReviewsGrid( RepositoriesWithReviewsGrid ): + # This grid filters out repositories that have been marked as deprecated. title = "Repositories with no reviews" columns = [ RepositoriesWithReviewsGrid.NameColumn( "Repository name", @@ -119,12 +118,15 @@ async_compatible=False ) ] def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( model.Repository ) \ - .filter( model.Repository.reviews == None ) \ + .filter( and_( model.Repository.table.c.deprecated == False, + model.Repository.reviews == None ) ) \ .join( model.User.table ) class RepositoriesReviewedByMeGrid( RepositoriesWithReviewsGrid ): + # This grid filters out repositories that have been marked as deprecated. def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( model.Repository ) \ + .filter( model.Repository.table.c.deprecated == False ) \ .join( ( model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \ .filter( model.RepositoryReview.table.c.user_id == trans.user.id ) \ .join( ( model.User.table, model.User.table.c.id == model.RepositoryReview.table.c.user_id ) ) \ @@ -132,6 +134,7 @@ .outerjoin( ( model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id ) ) class RepositoryReviewsByUserGrid( grids.Grid ): + # This grid filters out repositories that have been marked as deprecated. class RepositoryNameColumn( grids.TextColumn ): def get_value( self, trans, grid, review ): return review.repository.name @@ -166,33 +169,61 @@ default_sort_key = 'repository_id' columns = [ RepositoryNameColumn( "Repository Name", - model_class=model.Repository, - key="Repository.name", - attach_popup=False ), + model_class=model.Repository, + key="Repository.name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), RepositoryDescriptionColumn( "Description", - model_class=model.Repository, - key="Repository.description", - attach_popup=False ), - RevisionColumn( "Revision", - attach_popup=False ), - RatingColumn( "Rating", - attach_popup=False ) + model_class=model.Repository, + key="Repository.description", + attach_popup=False ), + RevisionColumn( "Revision", attach_popup=False ), + RatingColumn( "Rating", attach_popup=False ), ] # Override these default_filter = {} global_actions = [] - operations = [] + operations = [ + grids.GridOperation( "Inspect repository revisions", + allow_multiple=False, + condition=( lambda item: not item.deleted ), + async_compatible=False ) + ] standard_filters = [] num_rows_per_page = 50 preserve_state = False use_paging = True def build_initial_query( self, trans, **kwd ): user_id = trans.security.decode_id( kwd[ 'id' ] ) - return trans.sa_session.query( self.model_class ) \ + return trans.sa_session.query( model.RepositoryReview ) \ .filter( and_( model.RepositoryReview.table.c.deleted == False, \ - model.RepositoryReview.table.c.user_id == user_id ) ) + model.RepositoryReview.table.c.user_id == user_id ) ) \ + .join( ( model.Repository.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \ + .filter( model.Repository.table.c.deprecated == False ) class ReviewedRepositoriesIOwnGrid( RepositoriesWithReviewsGrid ): + title = "Reviewed repositories I own" + columns = [ + RepositoriesWithReviewsGrid.NameColumn( "Repository name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=True ), + RepositoriesWithReviewsGrid.WithReviewsRevisionColumn( "Reviewed revisions" ), + RepositoriesWithReviewsGrid.WithoutReviewsRevisionColumn( "Revisions for review" ), + RepositoriesWithReviewsGrid.ReviewersColumn( "Reviewers", attach_popup=False ), + RepositoryGrid.DeprecatedColumn( "Deprecated" ) + ] + columns.append( grids.MulticolFilterColumn( "Search repository name", + cols_to_filter=[ columns[0] ], + key="free-text-search", + visible=False, + filterable="standard" ) ) + operations = [ + grids.GridOperation( "Inspect repository revisions", + allow_multiple=False, + condition=( lambda item: not item.deleted ), + async_compatible=False ) + ] def build_initial_query( self, trans, **kwd ): return trans.sa_session.query( model.Repository ) \ .join( ( model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \ @@ -655,10 +686,26 @@ @web.expose @web.require_login( "repository reviews by user" ) def repository_reviews_by_user( self, trans, **kwd ): - # The user may not be the current user. The value of the received id is the encoded user id. params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) + + if 'operation' in kwd: + operation = kwd['operation'].lower() + # The value of the received id is the encoded review id. + review = get_review( trans, kwd[ 'id' ] ) + repository = review.repository + kwd[ 'id' ] = trans.security.encode_id( repository.id ) + if operation == "inspect repository revisions": + return trans.response.send_redirect( web.url_for( controller='repository_review', + action='manage_repository_reviews', + **kwd ) ) + if operation == "view_or_manage_repository": + kwd[ 'changeset_revision' ] = review.changeset_revision + return trans.response.send_redirect( web.url_for( controller='repository_review', + action='view_or_manage_repository', + **kwd ) ) + # The user may not be the current user. The value of the received id is the encoded user id. user = get_user( trans, kwd[ 'id' ] ) self.repository_reviews_by_user_grid.title = "All repository revision reviews for user '%s'" % user.username return self.repository_reviews_by_user_grid( trans, **kwd ) @@ -668,6 +715,13 @@ params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) + # The value of the received id is the encoded repository id. + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "view_or_manage_repository": + return trans.response.send_redirect( web.url_for( controller='repository_review', + action='view_or_manage_repository', + **kwd ) ) return self.reviewed_repositories_i_own_grid( trans, **kwd ) @web.expose @web.require_login( "select previous review" ) diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf lib/galaxy/webapps/community/model/__init__.py --- a/lib/galaxy/webapps/community/model/__init__.py +++ b/lib/galaxy/webapps/community/model/__init__.py @@ -109,7 +109,8 @@ MARKED_FOR_REMOVAL = 'r', MARKED_FOR_ADDITION = 'a', NOT_TRACKED = '?' ) - def __init__( self, name=None, description=None, long_description=None, user_id=None, private=False, email_alerts=None, times_downloaded=0 ): + def __init__( self, name=None, description=None, long_description=None, user_id=None, private=False, email_alerts=None, times_downloaded=0, + deprecated=False ): self.name = name or "Unnamed repository" self.description = description self.long_description = long_description @@ -117,6 +118,7 @@ self.private = private self.email_alerts = email_alerts self.times_downloaded = times_downloaded + self.deprecated = deprecated @property def repo_path( self ): # Repository locations on disk are defined in the hgweb.config file diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf lib/galaxy/webapps/community/model/mapping.py --- a/lib/galaxy/webapps/community/model/mapping.py +++ b/lib/galaxy/webapps/community/model/mapping.py @@ -111,7 +111,8 @@ Column( "private", Boolean, default=False ), Column( "deleted", Boolean, index=True, default=False ), Column( "email_alerts", JSONType, nullable=True ), - Column( "times_downloaded", Integer ) ) + Column( "times_downloaded", Integer ), + Column( "deprecated", Boolean, default=False ) ) RepositoryMetadata.table = Table( "repository_metadata", metadata, Column( "id", Integer, primary_key=True ), @@ -218,7 +219,10 @@ properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[ Tag.table.c.id ] ) ) ) ) assign_mapper( context, Category, Category.table, - properties=dict( repositories=relation( RepositoryCategoryAssociation ) ) ) + properties=dict( repositories=relation( RepositoryCategoryAssociation, + secondary=Repository.table, + primaryjoin=( Category.table.c.id == RepositoryCategoryAssociation.table.c.category_id ), + secondaryjoin=( ( RepositoryCategoryAssociation.table.c.repository_id == Repository.table.c.id ) & ( Repository.table.c.deprecated == False ) ) ) ) ) assign_mapper( context, Repository, Repository.table, properties = dict( diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf lib/galaxy/webapps/community/model/migrate/versions/0014_add_deprecated_column.py --- /dev/null +++ b/lib/galaxy/webapps/community/model/migrate/versions/0014_add_deprecated_column.py @@ -0,0 +1,53 @@ +""" +Migration script to add the deprecated column to the repository table. +""" + +from sqlalchemy import * +from sqlalchemy.orm import * +from migrate import * +from migrate.changeset import * + +# Need our custom types, but don't import anything else from model +from galaxy.model.custom_types import * + +import sys, logging +log = logging.getLogger( __name__ ) +log.setLevel(logging.DEBUG) +handler = logging.StreamHandler( sys.stdout ) +format = "%(name)s %(levelname)s %(asctime)s %(message)s" +formatter = logging.Formatter( format ) +handler.setFormatter( formatter ) +log.addHandler( handler ) + +metadata = MetaData( migrate_engine ) +db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) ) + +def upgrade(): + print __doc__ + metadata.reflect() + # Create and initialize imported column in job table. + Repository_table = Table( "repository", metadata, autoload=True ) + c = Column( "deprecated", Boolean, default=False ) + try: + # Create + c.create( Repository_table ) + assert c is Repository_table.c.deprecated + # Initialize. + if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite': + default_false = "0" + elif migrate_engine.name == 'postgres': + default_false = "false" + db_session.execute( "UPDATE repository SET deprecated=%s" % default_false ) + except Exception, e: + print "Adding deprecated column to the repository table failed: %s" % str( e ) + log.debug( "Adding deprecated column to the repository table failed: %s" % str( e ) ) + +def downgrade(): + metadata.reflect() + # Drop email_alerts column from repository table. + Repository_table = Table( "repository", metadata, autoload=True ) + try: + Repository_table.c.deprecated.drop() + except Exception, e: + print "Dropping column deprecated from the repository table failed: %s" % str( e ) + log.debug( "Dropping column deprecated from the repository table failed: %s" % str( e ) ) diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf templates/webapps/community/category/grid.mako --- a/templates/webapps/community/category/grid.mako +++ b/templates/webapps/community/category/grid.mako @@ -49,8 +49,8 @@ <%def name="grid_body( grid )"><% - from galaxy.webapps.community.controllers.repository import RepositoryListGrid - repo_grid = RepositoryListGrid() + from galaxy.webapps.community.controllers.repository import RepositoryGrid + repo_grid = RepositoryGrid() %> ${self.make_grid( grid, repo_grid )} </%def> diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf templates/webapps/community/category/valid_grid.mako --- a/templates/webapps/community/category/valid_grid.mako +++ b/templates/webapps/community/category/valid_grid.mako @@ -48,8 +48,8 @@ <%def name="grid_body( grid )"><% - from galaxy.webapps.community.controllers.repository import ValidRepositoryListGrid - repo_grid = ValidRepositoryListGrid() + from galaxy.webapps.community.controllers.repository import ValidRepositoryGrid + repo_grid = ValidRepositoryGrid() %> ${self.make_grid( grid, repo_grid )} </%def> diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf templates/webapps/community/index.mako --- a/templates/webapps/community/index.mako +++ b/templates/webapps/community/index.mako @@ -78,8 +78,13 @@ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='reviewed_repositories_i_own' )}">Reviewed repositories I own</a></div> %endif + %if has_deprecated_repositories: + <div class="toolTitle"> + <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='deprecated_repositories_i_own' )}">Deprecated repositories I own</a> + </div> + %endif <div class="toolTitle"> - <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='writable_repositories' )}">My writable repositories</a> + <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='my_writable_repositories' )}">My writable repositories</a></div><div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_invalid_tools', cntrller='repository' )}">My invalid tools</a> diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf templates/webapps/community/repository/manage_repository.mako --- a/templates/webapps/community/repository/manage_repository.mako +++ b/templates/webapps/community/repository/manage_repository.mako @@ -7,22 +7,25 @@ from galaxy.web.framework.helpers import time_ago is_admin = trans.user_is_admin() is_new = repository.is_new + is_deprecated = repository.deprecated can_contact_owner = trans.user and trans.user != repository.user - can_push = trans.app.security_agent.can_push( trans.user, repository ) + can_push = not is_deprecated and trans.app.security_agent.can_push( trans.user, repository ) can_upload = can_push - can_download = not is_new and ( not is_malicious or 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 - can_rate = not is_new and trans.user and repository.user != trans.user + 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 if can_push: browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip - can_reset_all_metadata = is_admin and len( repo ) > 0 + 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 = trans.app.security_agent.user_can_review_repositories( trans.user ) + can_review_repository = not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) reviewing_repository = cntrller and cntrller == 'repository_review' if changeset_revision == repository.tip: tip_str = 'repository tip' @@ -87,6 +90,12 @@ %if can_reset_all_metadata: <a class="action-button" href="${h.url_for( controller='repository', action='reset_all_metadata', id=trans.security.encode_id( repository.id ) )}">Reset all repository metadata</a> %endif + %if can_deprecate: + <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=True )}">Mark repository as deprecated</a> + %endif + %if can_undeprecate: + <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=False )}">Mark repository as not deprecated</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> @@ -101,6 +110,12 @@ ${render_msg( message, status )} %endif +%if repository.deprecated: + <div class="warningmessage"> + This repository has been marked as deprecated, so some tool shed features may be restricted. + </div> +%endif + %if len( changeset_revision_select_field.options ) > 1: <div class="toolForm"><div class="toolFormTitle">Repository revision</div> @@ -122,7 +137,7 @@ <p/> %endif <div class="toolForm"> - <div class="toolFormTitle">${repository.name}</div> + <div class="toolFormTitle">Repository '${repository.name}'</div><div class="toolFormBody"><form name="edit_repository" id="edit_repository" action="${h.url_for( controller='repository', action='manage_repository', id=trans.security.encode_id( repository.id ) )}" method="post" > %if can_download: diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf templates/webapps/community/repository/view_repository.mako --- a/templates/webapps/community/repository/view_repository.mako +++ b/templates/webapps/community/repository/view_repository.mako @@ -6,11 +6,12 @@ <% from galaxy.web.framework.helpers import time_ago is_new = repository.is_new + is_deprecated = repository.deprecated can_contact_owner = trans.user and trans.user != repository.user - can_push = trans.app.security_agent.can_push( trans.user, repository ) - can_rate = not is_new and trans.user and repository.user != trans.user + can_push = not is_deprecated and trans.app.security_agent.can_push( trans.user, repository ) + can_rate = not is_deprecated and 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_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 if can_push: @@ -19,7 +20,7 @@ browse_label = 'Browse repository tip files' has_readme = metadata and 'readme' in metadata reviewing_repository = cntrller and cntrller == 'repository_review' - can_review_repository = trans.app.security_agent.user_can_review_repositories( trans.user ) + can_review_repository = not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) %><%! @@ -100,6 +101,12 @@ ${render_msg( message, status )} %endif +%if repository.deprecated: + <div class="warningmessage"> + This repository has been marked as deprecated, so some tool shed features may be restricted. + </div> +%endif + %if len( changeset_revision_select_field.options ) > 1: <div class="toolForm"><div class="toolFormTitle">Repository revision</div> @@ -123,7 +130,7 @@ <p/> %endif <div class="toolForm"> - <div class="toolFormTitle">${repository.name}</div> + <div class="toolFormTitle">Repository '${repository.name}'</div><div class="toolFormBody"> %if can_download: <div class="form-row"> diff -r ae9d794074bcc4732601e480ff54d53b0b2ee6e7 -r 144ae945768aea03c56f80cb4d6db953fa88cbaf 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 @@ -110,7 +110,7 @@ <p/> %if can_download: <div class="toolForm"> - <div class="toolFormTitle">${repository.name}</div> + <div class="toolFormTitle">Repository '${repository.name}'</div><div class="toolFormBody"><div class="form-row"><label>Clone this repository:</label> 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.