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