1from collections import OrderedDict, namedtuple 2 3from conans.errors import NotFoundException, ConanException 4from conans.search.search import (filter_outdated, search_packages, search_recipes, 5 filter_by_revision) 6 7 8class Search(object): 9 def __init__(self, cache, remote_manager, remotes): 10 self._cache = cache 11 self._remote_manager = remote_manager 12 self._remotes = remotes 13 14 def search_recipes(self, pattern, remote_name=None, case_sensitive=False): 15 ignorecase = not case_sensitive 16 17 references = OrderedDict() 18 if not remote_name: 19 references[None] = search_recipes(self._cache, pattern, ignorecase) 20 return references 21 22 if remote_name == 'all': 23 # We have to check if there is a remote called "all" 24 # Deprecate: 2.0 can remove this check 25 if 'all' not in self._remotes: 26 for remote in self._remotes.values(): 27 refs = self._remote_manager.search_recipes(remote, pattern, ignorecase) 28 if refs: 29 references[remote.name] = sorted(refs) 30 return references 31 # single remote 32 remote = self._remotes[remote_name] 33 refs = self._remote_manager.search_recipes(remote, pattern, ignorecase) 34 references[remote.name] = sorted(refs) 35 return references 36 37 remote_ref = namedtuple('remote_ref', 'ordered_packages recipe_hash') 38 39 def search_packages(self, ref=None, remote_name=None, query=None, outdated=False): 40 """ Return the single information saved in conan.vars about all the packages 41 or the packages which match with a pattern 42 43 Attributes: 44 pattern = string to match packages 45 remote_name = search on another origin to get packages info 46 packages_pattern = String query with binary 47 packages properties: "arch=x86 AND os=Windows" 48 """ 49 if not remote_name: 50 return self._search_packages_in_local(ref, query, outdated) 51 52 if ref.revision and not self._cache.config.revisions_enabled: 53 raise ConanException("Revisions not enabled in the client, specify a " 54 "reference without revision") 55 56 if remote_name == 'all': 57 return self._search_packages_in_all(ref, query, outdated) 58 59 return self._search_packages_in(remote_name, ref, query, outdated) 60 61 def _search_packages_in_local(self, ref=None, query=None, outdated=False): 62 package_layout = self._cache.package_layout(ref, short_paths=None) 63 packages_props = search_packages(package_layout, query) 64 ordered_packages = OrderedDict(sorted(packages_props.items())) 65 66 try: 67 recipe_hash = package_layout.recipe_manifest().summary_hash 68 except IOError: # It could not exist in local 69 recipe_hash = None 70 71 if outdated: 72 ordered_packages = filter_outdated(ordered_packages, recipe_hash) 73 elif self._cache.config.revisions_enabled: 74 # With revisions, by default filter the packages not belonging to the recipe 75 # unless outdated is specified. 76 metadata = package_layout.load_metadata() 77 ordered_packages = filter_by_revision(metadata, ordered_packages) 78 79 references = OrderedDict() 80 references[None] = self.remote_ref(ordered_packages, recipe_hash) 81 return references 82 83 def _search_packages_in_all(self, ref=None, query=None, outdated=False): 84 references = OrderedDict() 85 # We have to check if there is a remote called "all" 86 # Deprecate: 2.0 can remove this check 87 if 'all' not in self._remotes: 88 for remote in self._remotes.values(): 89 try: 90 packages_props = self._remote_manager.search_packages(remote, ref, query) 91 if packages_props: 92 ordered_packages = OrderedDict(sorted(packages_props.items())) 93 manifest, _ = self._remote_manager.get_recipe_manifest(ref, remote) 94 95 recipe_hash = manifest.summary_hash 96 97 if outdated and recipe_hash: 98 ordered_packages = filter_outdated(ordered_packages, recipe_hash) 99 100 references[remote.name] = self.remote_ref(ordered_packages, recipe_hash) 101 except NotFoundException: 102 continue 103 return references 104 105 return self._search_packages_in('all', ref, query, outdated) 106 107 def _search_packages_in(self, remote_name, ref=None, query=None, outdated=False): 108 remote = self._remotes[remote_name] 109 packages_props = self._remote_manager.search_packages(remote, ref, query) 110 ordered_packages = OrderedDict(sorted(packages_props.items())) 111 manifest, ref = self._remote_manager.get_recipe_manifest(ref, remote) 112 113 recipe_hash = manifest.summary_hash 114 115 if outdated and recipe_hash: 116 ordered_packages = filter_outdated(ordered_packages, recipe_hash) 117 118 references = OrderedDict() 119 references[remote.name] = self.remote_ref(ordered_packages, recipe_hash) 120 return references 121