예제 #1
0
 def get_required_repo_info_dicts(self, tool_shed_url, repo_info_dicts):
     """
     Inspect the list of repo_info_dicts for repository dependencies and append a repo_info_dict for each of
     them to the list.  All repository_dependency entries in each of the received repo_info_dicts includes
     all required repositories, so only one pass through this method is required to retrieve all repository
     dependencies.
     """
     all_required_repo_info_dict = {}
     all_repo_info_dicts = []
     if repo_info_dicts:
         # We'll send tuples of ( tool_shed, repository_name, repository_owner, changeset_revision ) to the tool
         # shed to discover repository ids.
         required_repository_tups = []
         for repo_info_dict in repo_info_dicts:
             if repo_info_dict not in all_repo_info_dicts:
                 all_repo_info_dicts.append(repo_info_dict)
             for repository_name, repo_info_tup in repo_info_dict.items():
                 description, \
                     repository_clone_url, \
                     changeset_revision, \
                     ctx_rev, \
                     repository_owner, \
                     repository_dependencies, \
                     tool_dependencies = \
                     repository_util.get_repo_info_tuple_contents(repo_info_tup)
                 if repository_dependencies:
                     for key, val in repository_dependencies.items():
                         if key in ['root_key', 'description']:
                             continue
                         repository_components_tuple = get_components_from_key(
                             key)
                         components_list = repository_util.extract_components_from_tuple(
                             repository_components_tuple)
                         # Skip listing a repository dependency if it is required only to compile a tool dependency
                         # defined for the dependent repository since in this case, the repository dependency is really
                         # a dependency of the dependent repository's contained tool dependency, and only if that
                         # tool dependency requires compilation.
                         # For backward compatibility to the 12/20/12 Galaxy release.
                         only_if_compiling_contained_td = 'False'
                         if len(components_list) == 4:
                             only_if_compiling_contained_td = 'False'
                         elif len(components_list) == 5:
                             only_if_compiling_contained_td = 'False'
                         if not asbool(only_if_compiling_contained_td):
                             if components_list not in required_repository_tups:
                                 required_repository_tups.append(
                                     components_list)
                         for components_list in val:
                             try:
                                 only_if_compiling_contained_td = components_list[
                                     5]
                             except IndexError:
                                 only_if_compiling_contained_td = 'False'
                             # Skip listing a repository dependency if it is required only to compile a tool dependency
                             # defined for the dependent repository (see above comment).
                             if not asbool(only_if_compiling_contained_td):
                                 if components_list not in required_repository_tups:
                                     required_repository_tups.append(
                                         components_list)
                 else:
                     # We have a single repository with no dependencies.
                     components_list = [
                         tool_shed_url, repository_name, repository_owner,
                         changeset_revision
                     ]
                     required_repository_tups.append(components_list)
             if required_repository_tups:
                 # The value of required_repository_tups is a list of tuples, so we need to encode it.
                 encoded_required_repository_tups = []
                 for required_repository_tup in required_repository_tups:
                     # Convert every item in required_repository_tup to a string.
                     required_repository_tup = [
                         str(item) for item in required_repository_tup
                     ]
                     encoded_required_repository_tups.append(
                         encoding_util.encoding_sep.join(
                             required_repository_tup))
                 encoded_required_repository_str = encoding_util.encoding_sep2.join(
                     encoded_required_repository_tups)
                 encoded_required_repository_str = encoding_util.tool_shed_encode(
                     encoded_required_repository_str)
                 if repository_util.is_tool_shed_client(self.app):
                     # Handle secure / insecure Tool Shed URL protocol changes and port changes.
                     tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry(
                         self.app, tool_shed_url)
                 pathspec = ['repository', 'get_required_repo_info_dict']
                 url = build_url(tool_shed_url, pathspec=pathspec)
                 # Fix for handling 307 redirect not being handled nicely by urlopen() when the Request() has data provided
                 try:
                     url = _urlopen(url).geturl()
                 except HTTPError as e:
                     if e.code == 502:
                         pass
                     else:
                         raise
                 payload = urlencode(
                     dict(encoded_str=encoded_required_repository_str))
                 response = _urlopen(url, payload).read()
                 if response:
                     try:
                         required_repo_info_dict = json.loads(
                             unicodify(response))
                     except Exception as e:
                         log.exception(e)
                         return all_repo_info_dicts
                     required_repo_info_dicts = []
                     for k, v in required_repo_info_dict.items():
                         if k == 'repo_info_dicts':
                             encoded_dict_strings = required_repo_info_dict[
                                 'repo_info_dicts']
                             for encoded_dict_str in encoded_dict_strings:
                                 decoded_dict = encoding_util.tool_shed_decode(
                                     encoded_dict_str)
                                 required_repo_info_dicts.append(
                                     decoded_dict)
                         else:
                             if k not in all_required_repo_info_dict:
                                 all_required_repo_info_dict[k] = v
                             else:
                                 if v and not all_required_repo_info_dict[k]:
                                     all_required_repo_info_dict[k] = v
                         if required_repo_info_dicts:
                             for required_repo_info_dict in required_repo_info_dicts:
                                 # Each required_repo_info_dict has a single entry, and all_repo_info_dicts is a list
                                 # of dictionaries, each of which has a single entry.  We'll check keys here rather than
                                 # the entire dictionary because a dictionary entry in all_repo_info_dicts will include
                                 # lists of discovered repository dependencies, but these lists will be empty in the
                                 # required_repo_info_dict since dependency discovery has not yet been performed for these
                                 # dictionaries.
                                 required_repo_info_dict_key = next(
                                     iter(required_repo_info_dict))
                                 all_repo_info_dicts_keys = [
                                     next(iter(d))
                                     for d in all_repo_info_dicts
                                 ]
                                 if required_repo_info_dict_key not in all_repo_info_dicts_keys:
                                     all_repo_info_dicts.append(
                                         required_repo_info_dict)
                                 else:
                                     # required_repo_info_dict_key corresponds to the repo name.
                                     # A single install transaction might require the installation of 2 or more repos
                                     # with the same repo name but different owners or versions.
                                     # Therefore, if required_repo_info_dict_key is already in all_repo_info_dicts,
                                     # check that the tool id is already present. If it is not, we are dealing with the same repo name,
                                     # but a different owner/changeset revision or version and we add the repo to the list of repos to be installed.
                                     tool_id = required_repo_info_dict[
                                         required_repo_info_dict_key][1]
                                     is_present = False
                                     for repo_info_dict in all_repo_info_dicts:
                                         for k, v in repo_info_dict.items():
                                             if required_repo_info_dict_key == k:
                                                 if tool_id == v[1]:
                                                     is_present = True
                                                     break
                                     if not is_present:
                                         all_repo_info_dicts.append(
                                             required_repo_info_dict)
                     all_required_repo_info_dict[
                         'all_repo_info_dicts'] = all_repo_info_dicts
     return all_required_repo_info_dict
예제 #2
0
 def build_repository_dependency_relationships(self, repo_info_dicts,
                                               tool_shed_repositories):
     """
     Build relationships between installed tool shed repositories and other installed
     tool shed repositories upon which they depend.  These relationships are defined in
     the repository_dependencies entry for each dictionary in the received list of repo_info_dicts.
     Each of these dictionaries is associated with a repository in the received tool_shed_repositories
     list.
     """
     install_model = self.app.install_model
     log.debug("Building repository dependency relationships...")
     for repo_info_dict in repo_info_dicts:
         for name, repo_info_tuple in repo_info_dict.items():
             description, \
                 repository_clone_url, \
                 changeset_revision, \
                 ctx_rev, \
                 repository_owner, \
                 repository_dependencies, \
                 tool_dependencies = \
                 repository_util.get_repo_info_tuple_contents(repo_info_tuple)
             if repository_dependencies:
                 for key, val in repository_dependencies.items():
                     if key in ['root_key', 'description']:
                         continue
                     d_repository = None
                     repository_components_tuple = get_components_from_key(
                         key)
                     components_list = repository_util.extract_components_from_tuple(
                         repository_components_tuple)
                     d_toolshed, d_name, d_owner, d_changeset_revision = components_list[
                         0:4]
                     for tsr in tool_shed_repositories:
                         # Get the the tool_shed_repository defined by name, owner and changeset_revision.  This is
                         # the repository that will be dependent upon each of the tool shed repositories contained in
                         # val.  We'll need to check tool_shed_repository.tool_shed as well if/when repository dependencies
                         # across tool sheds is supported.
                         if tsr.name == d_name and tsr.owner == d_owner and tsr.changeset_revision == d_changeset_revision:
                             d_repository = tsr
                             break
                     if d_repository is None:
                         # The dependent repository is not in the received list so look in the database.
                         d_repository = self.get_or_create_tool_shed_repository(
                             d_toolshed, d_name, d_owner,
                             d_changeset_revision)
                     # Process each repository_dependency defined for the current dependent repository.
                     for repository_dependency_components_list in val:
                         required_repository = None
                         rd_toolshed, \
                             rd_name, \
                             rd_owner, \
                             rd_changeset_revision, \
                             rd_prior_installation_required, \
                             rd_only_if_compiling_contained_td = \
                             common_util.parse_repository_dependency_tuple(repository_dependency_components_list)
                         # Get the the tool_shed_repository defined by rd_name, rd_owner and rd_changeset_revision.  This
                         # is the repository that will be required by the current d_repository.
                         # TODO: Check tool_shed_repository.tool_shed as well when repository dependencies across tool sheds is supported.
                         for tsr in tool_shed_repositories:
                             if tsr.name == rd_name and tsr.owner == rd_owner and tsr.changeset_revision == rd_changeset_revision:
                                 required_repository = tsr
                                 break
                         if required_repository is None:
                             # The required repository is not in the received list so look in the database.
                             required_repository = self.get_or_create_tool_shed_repository(
                                 rd_toolshed, rd_name, rd_owner,
                                 rd_changeset_revision)
                         # Ensure there is a repository_dependency relationship between d_repository and required_repository.
                         rrda = None
                         for rd in d_repository.repository_dependencies:
                             if rd.id == required_repository.id:
                                 rrda = rd
                                 break
                         if not rrda:
                             # Make sure required_repository is in the repository_dependency table.
                             repository_dependency = self.get_repository_dependency_by_repository_id(
                                 install_model, required_repository.id)
                             if not repository_dependency:
                                 log.debug(
                                     'Creating new repository_dependency record for installed revision %s of repository: %s owned by %s.',
                                     required_repository.
                                     installed_changeset_revision,
                                     required_repository.name,
                                     required_repository.owner)
                                 repository_dependency = install_model.RepositoryDependency(
                                     tool_shed_repository_id=
                                     required_repository.id)
                                 install_model.context.add(
                                     repository_dependency)
                                 install_model.context.flush()
                             # Build the relationship between the d_repository and the required_repository.
                             rrda = install_model.RepositoryRepositoryDependencyAssociation(
                                 tool_shed_repository_id=d_repository.id,
                                 repository_dependency_id=
                                 repository_dependency.id)
                             install_model.context.add(rrda)
                             install_model.context.flush()