1 |
Extend the _pkg_str class with build_id, build_time, file_size, and |
2 |
mtime attributes. These will be used to distinguish binary package |
3 |
instances that have the same cpv. Package sorting accounts for |
4 |
build_time, which will be used to prefer newer builds over older builds |
5 |
when their versions are identical. |
6 |
--- |
7 |
[PATCH 1/7 v2] updates pkg_desc_index._pkg_node to have a build_time |
8 |
attribute, which fixes an AttributeError raised from dbapi._cmp_cpv |
9 |
for some emerge search actions. |
10 |
|
11 |
pym/_emerge/Package.py | 51 +++++++++++++++++++++---------- |
12 |
pym/_emerge/resolver/output.py | 21 ++++++++++--- |
13 |
pym/portage/cache/index/pkg_desc_index.py | 1 + |
14 |
pym/portage/dbapi/__init__.py | 10 ++++-- |
15 |
pym/portage/dbapi/vartree.py | 8 +++-- |
16 |
pym/portage/versions.py | 28 +++++++++++++++-- |
17 |
6 files changed, 93 insertions(+), 26 deletions(-) |
18 |
|
19 |
diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py |
20 |
index e8a13cb..975335d 100644 |
21 |
--- a/pym/_emerge/Package.py |
22 |
+++ b/pym/_emerge/Package.py |
23 |
@@ -41,12 +41,12 @@ class Package(Task): |
24 |
"_validated_atoms", "_visible") |
25 |
|
26 |
metadata_keys = [ |
27 |
- "BUILD_TIME", "CHOST", "COUNTER", "DEPEND", "EAPI", |
28 |
- "HDEPEND", "INHERITED", "IUSE", "KEYWORDS", |
29 |
- "LICENSE", "PDEPEND", "PROVIDE", "RDEPEND", |
30 |
- "repository", "PROPERTIES", "RESTRICT", "SLOT", "USE", |
31 |
- "_mtime_", "DEFINED_PHASES", "REQUIRED_USE", "PROVIDES", |
32 |
- "REQUIRES"] |
33 |
+ "BUILD_ID", "BUILD_TIME", "CHOST", "COUNTER", "DEFINED_PHASES", |
34 |
+ "DEPEND", "EAPI", "HDEPEND", "INHERITED", "IUSE", "KEYWORDS", |
35 |
+ "LICENSE", "MD5", "PDEPEND", "PROVIDE", "PROVIDES", |
36 |
+ "RDEPEND", "repository", "REQUIRED_USE", |
37 |
+ "PROPERTIES", "REQUIRES", "RESTRICT", "SIZE", |
38 |
+ "SLOT", "USE", "_mtime_"] |
39 |
|
40 |
_dep_keys = ('DEPEND', 'HDEPEND', 'PDEPEND', 'RDEPEND') |
41 |
_buildtime_keys = ('DEPEND', 'HDEPEND') |
42 |
@@ -114,13 +114,14 @@ class Package(Task): |
43 |
return self._metadata["EAPI"] |
44 |
|
45 |
@property |
46 |
+ def build_id(self): |
47 |
+ return self.cpv.build_id |
48 |
+ |
49 |
+ @property |
50 |
def build_time(self): |
51 |
if not self.built: |
52 |
raise AttributeError('build_time') |
53 |
- try: |
54 |
- return long(self._metadata['BUILD_TIME']) |
55 |
- except (KeyError, ValueError): |
56 |
- return 0 |
57 |
+ return self.cpv.build_time |
58 |
|
59 |
@property |
60 |
def defined_phases(self): |
61 |
@@ -509,9 +510,15 @@ class Package(Task): |
62 |
else: |
63 |
cpv_color = "PKG_NOMERGE" |
64 |
|
65 |
+ build_id_str = "" |
66 |
+ if isinstance(self.cpv.build_id, long) and self.cpv.build_id > 0: |
67 |
+ build_id_str = "-%s" % self.cpv.build_id |
68 |
+ |
69 |
s = "(%s, %s" \ |
70 |
- % (portage.output.colorize(cpv_color, self.cpv + _slot_separator + \ |
71 |
- self.slot + "/" + self.sub_slot + _repo_separator + self.repo) , self.type_name) |
72 |
+ % (portage.output.colorize(cpv_color, self.cpv + |
73 |
+ build_id_str + _slot_separator + self.slot + "/" + |
74 |
+ self.sub_slot + _repo_separator + self.repo), |
75 |
+ self.type_name) |
76 |
|
77 |
if self.type_name == "installed": |
78 |
if self.root_config.settings['ROOT'] != "/": |
79 |
@@ -755,29 +762,41 @@ class Package(Task): |
80 |
def __lt__(self, other): |
81 |
if other.cp != self.cp: |
82 |
return self.cp < other.cp |
83 |
- if portage.vercmp(self.version, other.version) < 0: |
84 |
+ result = portage.vercmp(self.version, other.version) |
85 |
+ if result < 0: |
86 |
return True |
87 |
+ if result == 0 and self.built and other.built: |
88 |
+ return self.build_time < other.build_time |
89 |
return False |
90 |
|
91 |
def __le__(self, other): |
92 |
if other.cp != self.cp: |
93 |
return self.cp <= other.cp |
94 |
- if portage.vercmp(self.version, other.version) <= 0: |
95 |
+ result = portage.vercmp(self.version, other.version) |
96 |
+ if result <= 0: |
97 |
return True |
98 |
+ if result == 0 and self.built and other.built: |
99 |
+ return self.build_time <= other.build_time |
100 |
return False |
101 |
|
102 |
def __gt__(self, other): |
103 |
if other.cp != self.cp: |
104 |
return self.cp > other.cp |
105 |
- if portage.vercmp(self.version, other.version) > 0: |
106 |
+ result = portage.vercmp(self.version, other.version) |
107 |
+ if result > 0: |
108 |
return True |
109 |
+ if result == 0 and self.built and other.built: |
110 |
+ return self.build_time > other.build_time |
111 |
return False |
112 |
|
113 |
def __ge__(self, other): |
114 |
if other.cp != self.cp: |
115 |
return self.cp >= other.cp |
116 |
- if portage.vercmp(self.version, other.version) >= 0: |
117 |
+ result = portage.vercmp(self.version, other.version) |
118 |
+ if result >= 0: |
119 |
return True |
120 |
+ if result == 0 and self.built and other.built: |
121 |
+ return self.build_time >= other.build_time |
122 |
return False |
123 |
|
124 |
def with_use(self, use): |
125 |
diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py |
126 |
index 7df0302..400617d 100644 |
127 |
--- a/pym/_emerge/resolver/output.py |
128 |
+++ b/pym/_emerge/resolver/output.py |
129 |
@@ -424,6 +424,18 @@ class Display(object): |
130 |
pkg_str += _repo_separator + pkg.repo |
131 |
return pkg_str |
132 |
|
133 |
+ def _append_build_id(self, pkg_str, pkg, pkg_info): |
134 |
+ """Potentially appends repository to package string. |
135 |
+ |
136 |
+ @param pkg_str: string |
137 |
+ @param pkg: _emerge.Package.Package instance |
138 |
+ @param pkg_info: dictionary |
139 |
+ @rtype string |
140 |
+ """ |
141 |
+ if pkg.type_name == "binary" and pkg.cpv.build_id is not None: |
142 |
+ pkg_str += "-%s" % pkg.cpv.build_id |
143 |
+ return pkg_str |
144 |
+ |
145 |
def _set_non_root_columns(self, pkg, pkg_info): |
146 |
"""sets the indent level and formats the output |
147 |
|
148 |
@@ -431,7 +443,7 @@ class Display(object): |
149 |
@param pkg_info: dictionary |
150 |
@rtype string |
151 |
""" |
152 |
- ver_str = pkg_info.ver |
153 |
+ ver_str = self._append_build_id(pkg_info.ver, pkg, pkg_info) |
154 |
if self.conf.verbosity == 3: |
155 |
ver_str = self._append_slot(ver_str, pkg, pkg_info) |
156 |
ver_str = self._append_repository(ver_str, pkg, pkg_info) |
157 |
@@ -470,7 +482,7 @@ class Display(object): |
158 |
@rtype string |
159 |
Modifies self.verboseadd |
160 |
""" |
161 |
- ver_str = pkg_info.ver |
162 |
+ ver_str = self._append_build_id(pkg_info.ver, pkg, pkg_info) |
163 |
if self.conf.verbosity == 3: |
164 |
ver_str = self._append_slot(ver_str, pkg, pkg_info) |
165 |
ver_str = self._append_repository(ver_str, pkg, pkg_info) |
166 |
@@ -507,7 +519,7 @@ class Display(object): |
167 |
@param pkg_info: dictionary |
168 |
@rtype the updated addl |
169 |
""" |
170 |
- pkg_str = pkg.cpv |
171 |
+ pkg_str = self._append_build_id(pkg.cpv, pkg, pkg_info) |
172 |
if self.conf.verbosity == 3: |
173 |
pkg_str = self._append_slot(pkg_str, pkg, pkg_info) |
174 |
pkg_str = self._append_repository(pkg_str, pkg, pkg_info) |
175 |
@@ -868,7 +880,8 @@ class Display(object): |
176 |
if self.conf.columns: |
177 |
myprint = self._set_non_root_columns(pkg, pkg_info) |
178 |
else: |
179 |
- pkg_str = pkg.cpv |
180 |
+ pkg_str = self._append_build_id( |
181 |
+ pkg.cpv, pkg, pkg_info) |
182 |
if self.conf.verbosity == 3: |
183 |
pkg_str = self._append_slot(pkg_str, pkg, pkg_info) |
184 |
pkg_str = self._append_repository(pkg_str, pkg, pkg_info) |
185 |
diff --git a/pym/portage/cache/index/pkg_desc_index.py b/pym/portage/cache/index/pkg_desc_index.py |
186 |
index a2e45da..dbcbb83 100644 |
187 |
--- a/pym/portage/cache/index/pkg_desc_index.py |
188 |
+++ b/pym/portage/cache/index/pkg_desc_index.py |
189 |
@@ -26,6 +26,7 @@ class pkg_node(_unicode): |
190 |
self.__dict__['cp'] = cp |
191 |
self.__dict__['repo'] = repo |
192 |
self.__dict__['version'] = version |
193 |
+ self.__dict__['build_time'] = None |
194 |
|
195 |
def __new__(cls, cp, version, repo=None): |
196 |
return _unicode.__new__(cls, cp + "-" + version) |
197 |
diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py |
198 |
index 34dfaa7..044faec 100644 |
199 |
--- a/pym/portage/dbapi/__init__.py |
200 |
+++ b/pym/portage/dbapi/__init__.py |
201 |
@@ -31,7 +31,8 @@ class dbapi(object): |
202 |
_use_mutable = False |
203 |
_known_keys = frozenset(x for x in auxdbkeys |
204 |
if not x.startswith("UNUSED_0")) |
205 |
- _pkg_str_aux_keys = ("EAPI", "KEYWORDS", "SLOT", "repository") |
206 |
+ _pkg_str_aux_keys = ("BUILD_TIME", "EAPI", "BUILD_ID", |
207 |
+ "KEYWORDS", "SLOT", "repository") |
208 |
|
209 |
def __init__(self): |
210 |
pass |
211 |
@@ -57,7 +58,12 @@ class dbapi(object): |
212 |
|
213 |
@staticmethod |
214 |
def _cmp_cpv(cpv1, cpv2): |
215 |
- return vercmp(cpv1.version, cpv2.version) |
216 |
+ result = vercmp(cpv1.version, cpv2.version) |
217 |
+ if (result == 0 and cpv1.build_time is not None and |
218 |
+ cpv2.build_time is not None): |
219 |
+ result = ((cpv1.build_time > cpv2.build_time) - |
220 |
+ (cpv1.build_time < cpv2.build_time)) |
221 |
+ return result |
222 |
|
223 |
@staticmethod |
224 |
def _cpv_sort_ascending(cpv_list): |
225 |
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py |
226 |
index cf31c8e..277c2f1 100644 |
227 |
--- a/pym/portage/dbapi/vartree.py |
228 |
+++ b/pym/portage/dbapi/vartree.py |
229 |
@@ -173,7 +173,8 @@ class vardbapi(dbapi): |
230 |
self.vartree = vartree |
231 |
self._aux_cache_keys = set( |
232 |
["BUILD_TIME", "CHOST", "COUNTER", "DEPEND", "DESCRIPTION", |
233 |
- "EAPI", "HDEPEND", "HOMEPAGE", "IUSE", "KEYWORDS", |
234 |
+ "EAPI", "HDEPEND", "HOMEPAGE", |
235 |
+ "BUILD_ID", "IUSE", "KEYWORDS", |
236 |
"LICENSE", "PDEPEND", "PROPERTIES", "PROVIDE", "RDEPEND", |
237 |
"repository", "RESTRICT" , "SLOT", "USE", "DEFINED_PHASES", |
238 |
"PROVIDES", "REQUIRES" |
239 |
@@ -425,7 +426,10 @@ class vardbapi(dbapi): |
240 |
continue |
241 |
if len(mysplit) > 1: |
242 |
if ps[0] == mysplit[1]: |
243 |
- returnme.append(_pkg_str(mysplit[0]+"/"+x)) |
244 |
+ cpv = "%s/%s" % (mysplit[0], x) |
245 |
+ metadata = dict(zip(self._aux_cache_keys, |
246 |
+ self.aux_get(cpv, self._aux_cache_keys))) |
247 |
+ returnme.append(_pkg_str(cpv, metadata=metadata)) |
248 |
self._cpv_sort_ascending(returnme) |
249 |
if use_cache: |
250 |
self.cpcache[mycp] = [mystat, returnme[:]] |
251 |
diff --git a/pym/portage/versions.py b/pym/portage/versions.py |
252 |
index 2c9fe5b..1ca9a36 100644 |
253 |
--- a/pym/portage/versions.py |
254 |
+++ b/pym/portage/versions.py |
255 |
@@ -18,6 +18,7 @@ if sys.hexversion < 0x3000000: |
256 |
_unicode = unicode |
257 |
else: |
258 |
_unicode = str |
259 |
+ long = int |
260 |
|
261 |
import portage |
262 |
portage.proxy.lazyimport.lazyimport(globals(), |
263 |
@@ -361,11 +362,13 @@ class _pkg_str(_unicode): |
264 |
""" |
265 |
|
266 |
def __new__(cls, cpv, metadata=None, settings=None, eapi=None, |
267 |
- repo=None, slot=None): |
268 |
+ repo=None, slot=None, build_time=None, build_id=None, |
269 |
+ file_size=None, mtime=None): |
270 |
return _unicode.__new__(cls, cpv) |
271 |
|
272 |
def __init__(self, cpv, metadata=None, settings=None, eapi=None, |
273 |
- repo=None, slot=None): |
274 |
+ repo=None, slot=None, build_time=None, build_id=None, |
275 |
+ file_size=None, mtime=None): |
276 |
if not isinstance(cpv, _unicode): |
277 |
# Avoid TypeError from _unicode.__init__ with PyPy. |
278 |
cpv = _unicode_decode(cpv) |
279 |
@@ -375,10 +378,19 @@ class _pkg_str(_unicode): |
280 |
slot = metadata.get('SLOT', slot) |
281 |
repo = metadata.get('repository', repo) |
282 |
eapi = metadata.get('EAPI', eapi) |
283 |
+ build_time = metadata.get('BUILD_TIME', build_time) |
284 |
+ file_size = metadata.get('SIZE', file_size) |
285 |
+ build_id = metadata.get('BUILD_ID', build_id) |
286 |
+ mtime = metadata.get('_mtime_', mtime) |
287 |
if settings is not None: |
288 |
self.__dict__['_settings'] = settings |
289 |
if eapi is not None: |
290 |
self.__dict__['eapi'] = eapi |
291 |
+ |
292 |
+ self.__dict__['build_time'] = self._long(build_time, 0) |
293 |
+ self.__dict__['file_size'] = self._long(file_size, None) |
294 |
+ self.__dict__['build_id'] = self._long(build_id, None) |
295 |
+ self.__dict__['mtime'] = self._long(mtime, None) |
296 |
self.__dict__['cpv_split'] = catpkgsplit(cpv, eapi=eapi) |
297 |
if self.cpv_split is None: |
298 |
raise InvalidData(cpv) |
299 |
@@ -419,6 +431,18 @@ class _pkg_str(_unicode): |
300 |
raise AttributeError("_pkg_str instances are immutable", |
301 |
self.__class__, name, value) |
302 |
|
303 |
+ @staticmethod |
304 |
+ def _long(var, default): |
305 |
+ if var is not None: |
306 |
+ try: |
307 |
+ var = long(var) |
308 |
+ except ValueError: |
309 |
+ if var: |
310 |
+ var = -1 |
311 |
+ else: |
312 |
+ var = default |
313 |
+ return var |
314 |
+ |
315 |
@property |
316 |
def stable(self): |
317 |
try: |
318 |
-- |
319 |
2.0.5 |