diff --git a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py index 425bb38aefb..be4c0908e0c 100644 --- a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py +++ b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py @@ -170,11 +170,13 @@ class RepositoryRevisionsController( BaseAPIController ): new_changeset_revision = suc.get_next_downloadable_changeset_revision( repository_dependency, repo, changeset_revision ) - repository_dependency_repository_metadata = \ - suc.get_repository_metadata_by_changeset_revision( trans.app, - repository_dependency_id, - new_changeset_revision ) - if repository_dependency_repository_metadata is None: + if new_changeset_revision != changeset_revision: + repository_dependency_repository_metadata = \ + suc.get_repository_metadata_by_changeset_revision( trans.app, + repository_dependency_id, + new_changeset_revision ) + changeset_revision = new_changeset_revision + else: decoded_repository_dependency_id = trans.security.decode_id( repository_dependency_id ) debug_msg = 'Cannot locate repository_metadata with id %d for repository dependency %s owned by %s ' % \ ( decoded_repository_dependency_id, str( name ), str( owner ) ) @@ -182,8 +184,6 @@ class RepositoryRevisionsController( BaseAPIController ): ( str( changeset_revision ), str( new_changeset_revision ) ) log.debug( debug_msg ) continue - else: - changeset_revision = new_changeset_revision repository_dependency_metadata_dict = \ repository_dependency_repository_metadata.to_dict( view='element', value_mapper=self.__get_value_mapper( trans ) ) diff --git a/lib/galaxy/webapps/tool_shed/controllers/repository.py b/lib/galaxy/webapps/tool_shed/controllers/repository.py index 5a26fa02d99..da721837f5a 100644 --- a/lib/galaxy/webapps/tool_shed/controllers/repository.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py @@ -2415,9 +2415,9 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): repository = suc.get_repository_by_name_and_owner( trans.app, name, owner ) repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False ) # Get the next installable changeset_revision beyond the received changeset_revision. - changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision ) - if changeset_revision: - return changeset_revision + next_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision ) + if next_changeset_revision and next_changeset_revision != changeset_revision: + return next_changeset_revision return '' @web.json @@ -2865,7 +2865,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): # Get updates to the received changeset_revision if any exist. repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False ) upper_bound_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision ) - if upper_bound_changeset_revision: + if upper_bound_changeset_revision and upper_bound_changeset_revision != changeset_revision: changeset_revision = upper_bound_changeset_revision repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans.app, repository_id, @@ -2914,12 +2914,12 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): else: next_installable_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision ) if repository_metadata is None: - if next_installable_revision: + if next_installable_revision and next_installable_revision != changeset_revision: tool_shed_status_dict[ 'latest_installable_revision' ] = 'True' else: tool_shed_status_dict[ 'latest_installable_revision' ] = 'False' else: - if next_installable_revision: + if next_installable_revision and next_installable_revision != changeset_revision: tool_shed_status_dict[ 'latest_installable_revision' ] = 'False' else: tool_shed_status_dict[ 'latest_installable_revision' ] = 'True' diff --git a/lib/tool_shed/capsule/capsule_manager.py b/lib/tool_shed/capsule/capsule_manager.py index 5fcd84c5b18..5f6ec1b3d64 100644 --- a/lib/tool_shed/capsule/capsule_manager.py +++ b/lib/tool_shed/capsule/capsule_manager.py @@ -596,7 +596,7 @@ class ImportRepositoryManager( object ): suc.get_next_downloadable_changeset_revision( defined_repository, defined_repo, changeset_revision ) - if updated_changeset_revision == rm_changeset_revision: + if updated_changeset_revision == rm_changeset_revision and updated_changeset_revision != changeset_revision: dependent_downloadable_revisions.append( downloadable_revision ) return dependent_downloadable_revisions diff --git a/lib/tool_shed/dependencies/repository/relation_builder.py b/lib/tool_shed/dependencies/repository/relation_builder.py index c25ad317903..6bc2e578aac 100644 --- a/lib/tool_shed/dependencies/repository/relation_builder.py +++ b/lib/tool_shed/dependencies/repository/relation_builder.py @@ -197,10 +197,11 @@ class RelationBuilder( object ): # The repository changeset_revision is no longer installable, so see if there's been an update. repo = hg_util.get_repo_for_repository( self.app, repository=repository, repo_path=None, create=False ) changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, rd_changeset_revision ) - repository_metadata = \ - metadata_util.get_repository_metadata_by_repository_id_changeset_revision( self.app, - repository_id, - changeset_revision ) + if changeset_revision != rd_changeset_revision: + repository_metadata = \ + metadata_util.get_repository_metadata_by_repository_id_changeset_revision( self.app, + repository_id, + changeset_revision ) if repository_metadata: new_key_rd_dict = {} new_key_rd_dict[ key ] = \ diff --git a/lib/tool_shed/util/metadata_util.py b/lib/tool_shed/util/metadata_util.py index 19f430a59d7..cf4f3361d61 100644 --- a/lib/tool_shed/util/metadata_util.py +++ b/lib/tool_shed/util/metadata_util.py @@ -39,7 +39,11 @@ def get_dependencies_for_metadata_revision( app, metadata ): dependencies = [] for shed, name, owner, changeset, prior, _ in metadata[ 'repository_dependencies' ]: required_repository = suc.get_repository_by_name_and_owner( app, name, owner ) - metadata_entry = suc.get_repository_metadata_by_changeset_revision( app, app.security.encode_id( required_repository.id ), changeset ) + repo = hg_util.get_repo_for_repository( app, repository=required_repository, repo_path=None, create=False ) + updated_changeset = suc.get_next_downloadable_changeset_revision( required_repository, repo, changeset ) + if updated_changeset is None: + continue + metadata_entry = suc.get_repository_metadata_by_changeset_revision( app, app.security.encode_id( required_repository.id ), updated_changeset ) dependencies.append( metadata_entry ) return dependencies diff --git a/lib/tool_shed/util/repository_util.py b/lib/tool_shed/util/repository_util.py index 035acc46d7b..59f95f7b0aa 100644 --- a/lib/tool_shed/util/repository_util.py +++ b/lib/tool_shed/util/repository_util.py @@ -299,7 +299,7 @@ def get_repo_info_dict( app, user, repository_id, changeset_revision ): # repository_suite_definition or tool_dependency_definition. next_downloadable_changeset_revision = \ suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision ) - if next_downloadable_changeset_revision: + if next_downloadable_changeset_revision and next_downloadable_changeset_revision != changeset_revision: repository_metadata = suc.get_repository_metadata_by_changeset_revision( app, repository_id, next_downloadable_changeset_revision ) diff --git a/lib/tool_shed/util/shed_util_common.py b/lib/tool_shed/util/shed_util_common.py index 51467fc6ed0..5347d0bc746 100644 --- a/lib/tool_shed/util/shed_util_common.py +++ b/lib/tool_shed/util/shed_util_common.py @@ -318,7 +318,7 @@ def get_current_repository_metadata_for_changeset_revision( app, repository, cha updated_changeset_revision = get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision=changeset_revision ) - if updated_changeset_revision: + if updated_changeset_revision and updated_changeset_revision != changeset_revision: repository_metadata = get_repository_metadata_by_changeset_revision( app, encoded_repository_id, updated_changeset_revision ) @@ -391,13 +391,14 @@ def get_metadata_changeset_revisions( repository, repo ): def get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision ): """ Return the installable changeset_revision in the repository changelog after the changeset to which - after_changeset_revision refers. If there isn't one, return None. + after_changeset_revision refers. If there isn't one, return None. If there is only one installable + changeset, and that matches the requested revision, return it. """ changeset_revisions = [ revision[ 1 ] for revision in get_metadata_revisions( repository, repo ) ] if len( changeset_revisions ) == 1: changeset_revision = changeset_revisions[ 0 ] if changeset_revision == after_changeset_revision: - return None + return after_changeset_revision found_after_changeset_revision = False for changeset in repo.changelog: changeset_revision = str( repo.changectx( changeset ) ) diff --git a/test/shed_functional/functional/test_0540_get_all_metadata_from_api.py b/test/shed_functional/functional/test_0540_get_all_metadata_from_api.py index 5e4fb20bd09..b4d94b5b9d4 100644 --- a/test/shed_functional/functional/test_0540_get_all_metadata_from_api.py +++ b/test/shed_functional/functional/test_0540_get_all_metadata_from_api.py @@ -87,6 +87,7 @@ class TestGetAllMetadata( ShedTwillTestCase ): commit_message='Uploaded column maker 1.0.', strings_displayed=[], strings_not_displayed=[] ) + # Add a dependency on BWA. self.upload_file( repository, filename='0540_files/convert_chars/tool_dependencies.xml', filepath=None, @@ -96,7 +97,7 @@ class TestGetAllMetadata( ShedTwillTestCase ): commit_message='Uploaded column maker 1.0.', strings_displayed=[], strings_not_displayed=[] ) - # Visit the manage repository page for package_bwa_0_5_9_0100. + # Visit the manage repository page for convert_chars_0540. self.display_manage_repository_page( repository, strings_displayed=[ repositories['bwa']['name'] ] ) def test_0015_create_column_repository( self ): @@ -129,7 +130,7 @@ class TestGetAllMetadata( ShedTwillTestCase ): valid_tools_only=True, uncompress_file=True, remove_repo_files_not_in_tar=False, - commit_message='Uploaded column maker 1.0.', + commit_message='Uploaded column maker 2.0.', strings_displayed=[], strings_not_displayed=[] ) diff --git a/test/shed_functional/functional/test_0550_metadata_updated_dependencies.py b/test/shed_functional/functional/test_0550_metadata_updated_dependencies.py new file mode 100644 index 00000000000..7313b4e2500 --- /dev/null +++ b/test/shed_functional/functional/test_0550_metadata_updated_dependencies.py @@ -0,0 +1,157 @@ +import logging + +from shed_functional.base.twilltestcase import common, ShedTwillTestCase + +log = logging.getLogger( __name__ ) + +repositories = dict( freebayes=dict( name='package_freebayes_0550', + description='Description for package_freebayes_0550', + long_description='Long description for package_freebayes_0550' ), + samtools=dict( name='package_samtools_0550', + description='Description for package_samtools_0550', + long_description='Long description for package_samtools_0550' ), + filtering=dict( name='filtering_0550', + description='Description for filtering_0550', + long_description='Long description for filtering_0550' ) ) + +category_name = 'Test 0550' +category_description = 'Verify metadata updates' + +''' +1. Create repository package_freebayes_0550. + +2. Create repository package_samtools_0550. + +3. Create repository filtering_0550. + +4. Create dependency on package_freebayes_0550 for filtering_0550. + +5. Create dependency on package_samtools_0550 for filtering_0550. + +6. Update package_freebayes_0550 and package_samtools_0550. + +5. Load /api/repositories/{filtering_0550}.id/metadata and verify contents. +''' + + +class TestGetUpdatedMetadata( ShedTwillTestCase ): + '''Verify that updated repositories still have correct dependency links.''' + + def test_0000_initiate_users( self ): + """Create necessary user accounts.""" + self.login( email=common.test_user_1_email, username=common.test_user_1_name ) + test_user_1 = self.test_db_util.get_user( common.test_user_1_email ) + assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email + self.test_db_util.get_private_role( test_user_1 ) + self.login( email=common.admin_email, username=common.admin_username ) + admin_user = self.test_db_util.get_user( common.admin_email ) + assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email + self.test_db_util.get_private_role( admin_user ) + + def test_0005_freebayes_repository( self ): + '''Create and populate package_freebayes_0550.''' + category = self.create_category( name=category_name, description=category_description ) + self.login( email=common.test_user_1_email, username=common.test_user_1_name ) + # Create a repository named package_freebayes_0550 owned by user1. + freebayes = self.get_or_create_repository( name=repositories['freebayes']['name'], + description=repositories['freebayes']['description'], + long_description=repositories['freebayes']['long_description'], + owner=common.test_user_1_name, + category_id=self.security.encode_id( category.id ), + strings_displayed=[] ) + assert freebayes is not None, 'Error creating freebayes %s' % repositories['freebayes']['name'] + self.upload_file( freebayes, + filename='0550_files/package_freebayes_1_0550.tgz', + filepath=None, + valid_tools_only=True, + uncompress_file=False, + remove_repo_files_not_in_tar=False, + commit_message='Uploaded.', + strings_displayed=[ 'has been successfully uploaded to the repository', 'contains a single file' ], + strings_not_displayed=None ) + # Visit the manage repository page for package_freebayes_0_5_9_0100. + self.display_manage_repository_page( freebayes, strings_displayed=[ 'Tool dependencies', 'will not be', 'to this repository' ] ) + + def test_0010_create_samtools_repository( self ): + '''Create and populate the package_samtools_0550 repository.''' + category = self.create_category( name=category_name, description=category_description ) + samtools = self.get_or_create_repository( name=repositories['samtools']['name'], + description=repositories['samtools']['description'], + long_description=repositories['samtools']['long_description'], + owner=common.test_user_1_name, + category_id=self.security.encode_id( category.id ), + strings_displayed=[] ) + assert samtools is not None, 'Error creating samtools %s' % repositories['samtools']['name'] + self.upload_file( samtools, + filename='0550_files/package_samtools_1_0550.tgz', + filepath=None, + valid_tools_only=True, + uncompress_file=True, + remove_repo_files_not_in_tar=False, + commit_message='Uploaded samtools 1.0.', + strings_displayed=[ 'has been successfully uncompressed and uploaded to the repository' ], + strings_not_displayed=[] ) + + def test_0015_create_filtering_repository( self ): + '''Create the filtering_0550 repository.''' + category = self.create_category( name=category_name, description=category_description ) + repository = self.get_or_create_repository( name=repositories['filtering']['name'], + description=repositories['filtering']['description'], + long_description=repositories['filtering']['long_description'], + owner=common.test_user_1_name, + category_id=self.security.encode_id( category.id ), + strings_displayed=[] ) + assert repository is not None, 'Error creating repository %s' % repositories['filtering']['name'] + self.upload_file( repository, + filename='0550_files/filtering_1.0.tgz', + filepath=None, + valid_tools_only=True, + uncompress_file=True, + remove_repo_files_not_in_tar=False, + commit_message='Uploaded filtering 1.0.', + strings_displayed=[ 'has been successfully uncompressed and uploaded to the repository' ], + strings_not_displayed=[] ) + + def test_0020_check_repository_dependency( self ): + '''Make filtering depend on samtools and freebayes.''' + freebayes = self.test_db_util.get_repository_by_name_and_owner( repositories[ 'freebayes' ][ 'name' ], + common.test_user_1_name ) + samtools = self.test_db_util.get_repository_by_name_and_owner( repositories[ 'samtools' ][ 'name' ], + common.test_user_1_name ) + filtering = self.test_db_util.get_repository_by_name_and_owner( repositories[ 'filtering' ][ 'name' ], + common.test_user_1_name ) + strings_displayed = [ self.security.encode_id( freebayes.id ), self.security.encode_id( samtools.id ) ] + self.display_manage_repository_page( filtering, strings_displayed=strings_displayed ) + + def test_0025_update_dependent_repositories( self ): + ''' + Update freebayes and samtools, load the API endpoint again. + ''' + freebayes = self.test_db_util.get_repository_by_name_and_owner( repositories[ 'freebayes' ][ 'name' ], + common.test_user_1_name ) + samtools = self.test_db_util.get_repository_by_name_and_owner( repositories[ 'samtools' ][ 'name' ], + common.test_user_1_name ) + filtering = self.test_db_util.get_repository_by_name_and_owner( repositories[ 'filtering' ][ 'name' ], + common.test_user_1_name ) + self.upload_file( freebayes, + filename='0550_files/package_freebayes_2_0550.tgz', + filepath=None, + valid_tools_only=True, + uncompress_file=True, + remove_repo_files_not_in_tar=False, + commit_message='Uploaded freebayes 2.0.', + strings_displayed=[ 'has been successfully uncompressed and uploaded to the repository' ], + strings_not_displayed=[] ) + self.upload_file( samtools, + filename='0550_files/package_samtools_2_0550.tgz', + filepath=None, + valid_tools_only=True, + uncompress_file=True, + remove_repo_files_not_in_tar=False, + commit_message='Uploaded samtools 2.0.', + strings_displayed=[ 'has been successfully uncompressed and uploaded to the repository' ], + strings_not_displayed=[] ) + strings_displayed = [ repositories[ 'freebayes' ][ 'name' ], + repositories[ 'samtools' ][ 'name' ], + repositories[ 'filtering' ][ 'name' ] ] + self.fetch_repository_metadata( filtering, strings_displayed=strings_displayed, strings_not_displayed=None ) diff --git a/test/shed_functional/test_data/0550_files/filtering_1.0.tgz b/test/shed_functional/test_data/0550_files/filtering_1.0.tgz new file mode 100644 index 00000000000..c2a06127223 Binary files /dev/null and b/test/shed_functional/test_data/0550_files/filtering_1.0.tgz differ diff --git a/test/shed_functional/test_data/0550_files/package_freebayes_1_0550.tgz b/test/shed_functional/test_data/0550_files/package_freebayes_1_0550.tgz new file mode 100644 index 00000000000..2befe2b7bc3 Binary files /dev/null and b/test/shed_functional/test_data/0550_files/package_freebayes_1_0550.tgz differ diff --git a/test/shed_functional/test_data/0550_files/package_freebayes_2_0550.tgz b/test/shed_functional/test_data/0550_files/package_freebayes_2_0550.tgz new file mode 100644 index 00000000000..eaeaefb8248 Binary files /dev/null and b/test/shed_functional/test_data/0550_files/package_freebayes_2_0550.tgz differ diff --git a/test/shed_functional/test_data/0550_files/package_samtools_1_0550.tgz b/test/shed_functional/test_data/0550_files/package_samtools_1_0550.tgz new file mode 100644 index 00000000000..db60638275d Binary files /dev/null and b/test/shed_functional/test_data/0550_files/package_samtools_1_0550.tgz differ diff --git a/test/shed_functional/test_data/0550_files/package_samtools_2_0550.tgz b/test/shed_functional/test_data/0550_files/package_samtools_2_0550.tgz new file mode 100644 index 00000000000..6567721d117 Binary files /dev/null and b/test/shed_functional/test_data/0550_files/package_samtools_2_0550.tgz differ diff --git a/test/shed_functional/test_data/0550_files/temp/tool_dependencies.xml b/test/shed_functional/test_data/0550_files/temp/tool_dependencies.xml new file mode 100644 index 00000000000..1e754894aab --- /dev/null +++ b/test/shed_functional/test_data/0550_files/temp/tool_dependencies.xml @@ -0,0 +1,17 @@ + + + + + + echo "Success." + + $INSTALL_DIR/bin + + + + +Compiling SAMtools requires the ncurses and zlib development libraries. + + + +