reposyntax: Print cpv from all repos for "masked by" messages
[portage.git] / pym / _emerge / PackageVirtualDbapi.py
1 # Copyright 1999-2009 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 import sys
5 from portage.dbapi import dbapi
6
7 class PackageVirtualDbapi(dbapi):
8         """
9         A dbapi-like interface class that represents the state of the installed
10         package database as new packages are installed, replacing any packages
11         that previously existed in the same slot. The main difference between
12         this class and fakedbapi is that this one uses Package instances
13         internally (passed in via cpv_inject() and cpv_remove() calls).
14         """
15         def __init__(self, settings):
16                 dbapi.__init__(self)
17                 self.settings = settings
18                 self._match_cache = {}
19                 self._cp_map = {}
20                 self._cpv_map = {}
21
22         def clear(self):
23                 """
24                 Remove all packages.
25                 """
26                 if self._cpv_map:
27                         self._clear_cache()
28                         self._cp_map.clear()
29                         self._cpv_map.clear()
30
31         def copy(self):
32                 obj = PackageVirtualDbapi(self.settings)
33                 obj._match_cache = self._match_cache.copy()
34                 obj._cp_map = self._cp_map.copy()
35                 for k, v in obj._cp_map.items():
36                         obj._cp_map[k] = v[:]
37                 obj._cpv_map = self._cpv_map.copy()
38                 return obj
39
40         def __bool__(self):
41                 return bool(self._cpv_map)
42
43         if sys.hexversion < 0x3000000:
44                 __nonzero__ = __bool__
45
46         def __iter__(self):
47                 return iter(self._cpv_map.values())
48
49         def __contains__(self, item):
50                 existing = self._cpv_map.get(item.cpv)
51                 if existing is not None and \
52                         existing == item:
53                         return True
54                 return False
55
56         def get(self, item, default=None):
57                 cpv = getattr(item, "cpv", None)
58                 if cpv is None:
59                         if len(item) != 4:
60                                 return default
61                         type_name, root, cpv, operation = item
62
63                 existing = self._cpv_map.get(cpv)
64                 if existing is not None and \
65                         existing == item:
66                         return existing
67                 return default
68
69         def match_pkgs(self, atom):
70                 return [self._cpv_map[cpv] for cpv in self.match(atom)]
71
72         def _clear_cache(self):
73                 if self._categories is not None:
74                         self._categories = None
75                 if self._match_cache:
76                         self._match_cache = {}
77
78         def match(self, origdep, use_cache=1):
79                 result = self._match_cache.get(origdep)
80                 if result is not None:
81                         return result[:]
82                 result = dbapi.match(self, origdep, use_cache=use_cache)
83                 self._match_cache[origdep] = result
84                 return result[:]
85
86         def cpv_exists(self, cpv, myrepo=None):
87                 return cpv in self._cpv_map
88
89         def cp_list(self, mycp, use_cache=1):
90                 cachelist = self._match_cache.get(mycp)
91                 # cp_list() doesn't expand old-style virtuals
92                 if cachelist and cachelist[0].startswith(mycp):
93                         return cachelist[:]
94                 cpv_list = self._cp_map.get(mycp)
95                 if cpv_list is None:
96                         cpv_list = []
97                 else:
98                         cpv_list = [pkg.cpv for pkg in cpv_list]
99                 self._cpv_sort_ascending(cpv_list)
100                 if not (not cpv_list and mycp.startswith("virtual/")):
101                         self._match_cache[mycp] = cpv_list
102                 return cpv_list[:]
103
104         def cp_all(self):
105                 return list(self._cp_map)
106
107         def cpv_all(self):
108                 return list(self._cpv_map)
109
110         def cpv_inject(self, pkg):
111                 cp_list = self._cp_map.get(pkg.cp)
112                 if cp_list is None:
113                         cp_list = []
114                         self._cp_map[pkg.cp] = cp_list
115                 e_pkg = self._cpv_map.get(pkg.cpv)
116                 if e_pkg is not None:
117                         if e_pkg == pkg:
118                                 return
119                         self.cpv_remove(e_pkg)
120                 for e_pkg in cp_list:
121                         if e_pkg.slot_atom == pkg.slot_atom:
122                                 if e_pkg == pkg:
123                                         return
124                                 self.cpv_remove(e_pkg)
125                                 break
126                 cp_list.append(pkg)
127                 self._cpv_map[pkg.cpv] = pkg
128                 self._clear_cache()
129
130         def cpv_remove(self, pkg):
131                 old_pkg = self._cpv_map.get(pkg.cpv)
132                 if old_pkg != pkg:
133                         raise KeyError(pkg)
134                 self._cp_map[pkg.cp].remove(pkg)
135                 del self._cpv_map[pkg.cpv]
136                 self._clear_cache()
137
138         def aux_get(self, cpv, wants, myrepo=None):
139                 metadata = self._cpv_map[cpv].metadata
140                 return [metadata.get(x, "") for x in wants]
141
142         def aux_update(self, cpv, values):
143                 self._cpv_map[cpv].metadata.update(values)
144                 self._clear_cache()
145