1 |
Author: zmedico |
2 |
Date: 2008-07-05 07:18:31 +0000 (Sat, 05 Jul 2008) |
3 |
New Revision: 10935 |
4 |
|
5 |
Modified: |
6 |
main/trunk/pym/_emerge/__init__.py |
7 |
main/trunk/pym/portage/__init__.py |
8 |
main/trunk/pym/portage/dbapi/bintree.py |
9 |
Log: |
10 |
* Implement a new binarytree.digestCheck() method and use it to check |
11 |
digests for binary packages. |
12 |
|
13 |
* Split out a AsynchronousTask base class from SubProcess. |
14 |
|
15 |
* Derive a new BinpkgVerifier class from AsynchronousTask. Even though |
16 |
this is not really asynchronous yet, it can fake the interface by |
17 |
doing everything in the start() method. |
18 |
|
19 |
|
20 |
|
21 |
Modified: main/trunk/pym/_emerge/__init__.py |
22 |
=================================================================== |
23 |
--- main/trunk/pym/_emerge/__init__.py 2008-07-04 22:49:04 UTC (rev 10934) |
24 |
+++ main/trunk/pym/_emerge/__init__.py 2008-07-05 07:18:31 UTC (rev 10935) |
25 |
@@ -1454,10 +1454,31 @@ |
26 |
mydbapi=portdb, tree="porttree") |
27 |
return retval |
28 |
|
29 |
-class SubProcess(SlotObject): |
30 |
- __slots__ = ("cancelled", "pid", "returncode") |
31 |
+class AsynchronousTask(SlotObject): |
32 |
+ __slots__ = ("cancelled", "returncode") |
33 |
|
34 |
+ def start(self): |
35 |
+ """ |
36 |
+ Start an asynchronous task and then return as soon as possible. |
37 |
+ """ |
38 |
+ pass |
39 |
+ |
40 |
+ def isAlive(self): |
41 |
+ return self.returncode is None |
42 |
+ |
43 |
def poll(self): |
44 |
+ return self.returncode |
45 |
+ |
46 |
+ def wait(self): |
47 |
+ return self.returncode |
48 |
+ |
49 |
+ def cancel(self): |
50 |
+ pass |
51 |
+ |
52 |
+class SubProcess(AsynchronousTask): |
53 |
+ __slots__ = ("pid",) |
54 |
+ |
55 |
+ def poll(self): |
56 |
if self.returncode is not None: |
57 |
return self.returncode |
58 |
retval = os.waitpid(self.pid, os.WNOHANG) |
59 |
@@ -2175,6 +2196,8 @@ |
60 |
tree = "bintree" |
61 |
settings.setcpv(pkg) |
62 |
debug = settings.get("PORTAGE_DEBUG") == "1" |
63 |
+ verify = "strict" in settings.features and \ |
64 |
+ not opts.pretend |
65 |
|
66 |
# The prefetcher has already completed or it |
67 |
# could be running now. If it's running now, |
68 |
@@ -2227,6 +2250,13 @@ |
69 |
if opts.fetchonly: |
70 |
return os.EX_OK |
71 |
|
72 |
+ if verify: |
73 |
+ verifier = BinpkgVerifier(pkg=pkg) |
74 |
+ verifier.start() |
75 |
+ retval = verifier.wait() |
76 |
+ if retval != os.EX_OK: |
77 |
+ return retval |
78 |
+ |
79 |
msg = " === (%s of %s) Merging Binary (%s::%s)" % \ |
80 |
(pkg_count.curval, pkg_count.maxval, pkg.cpv, pkg_path) |
81 |
short_msg = "emerge: (%s of %s) %s Merge Binary" % \ |
82 |
@@ -2352,8 +2382,7 @@ |
83 |
|
84 |
class BinpkgFetcher(Task): |
85 |
|
86 |
- __slots__ = ("use_locks", "pkg", "pretend", |
87 |
- "pkg_path", "remote") |
88 |
+ __slots__ = ("use_locks", "pkg", "pretend", "pkg_path", "remote") |
89 |
|
90 |
def __init__(self, **kwargs): |
91 |
Task.__init__(self, **kwargs) |
92 |
@@ -2498,6 +2527,47 @@ |
93 |
self._lock_obj = None |
94 |
self.locked = False |
95 |
|
96 |
+class BinpkgVerifier(AsynchronousTask): |
97 |
+ __slots__ = ("pkg",) |
98 |
+ |
99 |
+ def start(self): |
100 |
+ """ |
101 |
+ Note: Unlike a normal AsynchronousTask.start() method, |
102 |
+ this one does all work is synchronously. The returncode |
103 |
+ attribute will be set before it returns. |
104 |
+ """ |
105 |
+ |
106 |
+ pkg = self.pkg |
107 |
+ root_config = pkg.root_config |
108 |
+ bintree = root_config.trees["bintree"] |
109 |
+ rval = os.EX_OK |
110 |
+ try: |
111 |
+ bintree.digestCheck(pkg) |
112 |
+ except portage.exception.FileNotFound: |
113 |
+ writemsg("!!! Fetching Binary failed " + \ |
114 |
+ "for '%s'\n" % pkg.cpv, noiselevel=-1) |
115 |
+ rval = 1 |
116 |
+ except portage.exception.DigestException, e: |
117 |
+ writemsg("\n!!! Digest verification failed:\n", |
118 |
+ noiselevel=-1) |
119 |
+ writemsg("!!! %s\n" % e.value[0], |
120 |
+ noiselevel=-1) |
121 |
+ writemsg("!!! Reason: %s\n" % e.value[1], |
122 |
+ noiselevel=-1) |
123 |
+ writemsg("!!! Got: %s\n" % e.value[2], |
124 |
+ noiselevel=-1) |
125 |
+ writemsg("!!! Expected: %s\n" % e.value[3], |
126 |
+ noiselevel=-1) |
127 |
+ rval = 1 |
128 |
+ |
129 |
+ self.returncode = rval |
130 |
+ |
131 |
+ def cancel(self): |
132 |
+ self.cancelled = True |
133 |
+ |
134 |
+ def poll(self): |
135 |
+ return self.returncode |
136 |
+ |
137 |
class BinpkgExtractorAsync(SpawnProcess): |
138 |
|
139 |
__slots__ = ("image_dir", "pkg", "pkg_path") |
140 |
|
141 |
Modified: main/trunk/pym/portage/__init__.py |
142 |
=================================================================== |
143 |
--- main/trunk/pym/portage/__init__.py 2008-07-04 22:49:04 UTC (rev 10934) |
144 |
+++ main/trunk/pym/portage/__init__.py 2008-07-05 07:18:31 UTC (rev 10935) |
145 |
@@ -3143,24 +3143,25 @@ |
146 |
os.rename(filename, temp_filename) |
147 |
return temp_filename |
148 |
|
149 |
-def _check_digests(filename, digests): |
150 |
+def _check_digests(filename, digests, show_errors=1): |
151 |
""" |
152 |
Check digests and display a message if an error occurs. |
153 |
@return True if all digests match, False otherwise. |
154 |
""" |
155 |
verified_ok, reason = portage.checksum.verify_all(filename, digests) |
156 |
if not verified_ok: |
157 |
- writemsg("!!! Previously fetched" + \ |
158 |
- " file: '%s'\n" % filename, noiselevel=-1) |
159 |
- writemsg("!!! Reason: %s\n" % reason[0], |
160 |
- noiselevel=-1) |
161 |
- writemsg(("!!! Got: %s\n" + \ |
162 |
- "!!! Expected: %s\n") % \ |
163 |
- (reason[1], reason[2]), noiselevel=-1) |
164 |
+ if show_errors: |
165 |
+ writemsg("!!! Previously fetched" + \ |
166 |
+ " file: '%s'\n" % filename, noiselevel=-1) |
167 |
+ writemsg("!!! Reason: %s\n" % reason[0], |
168 |
+ noiselevel=-1) |
169 |
+ writemsg(("!!! Got: %s\n" + \ |
170 |
+ "!!! Expected: %s\n") % \ |
171 |
+ (reason[1], reason[2]), noiselevel=-1) |
172 |
return False |
173 |
return True |
174 |
|
175 |
-def _check_distfile(filename, digests, eout): |
176 |
+def _check_distfile(filename, digests, eout, show_errors=1): |
177 |
""" |
178 |
@return a tuple of (match, stat_obj) where match is True if filename |
179 |
matches all given digests (if any) and stat_obj is a stat result, or |
180 |
@@ -3183,7 +3184,7 @@ |
181 |
eout.ebegin("%s %s ;-)" % (os.path.basename(filename), "size")) |
182 |
eout.eend(0) |
183 |
else: |
184 |
- if _check_digests(filename, digests): |
185 |
+ if _check_digests(filename, digests, show_errors=show_errors): |
186 |
eout.ebegin("%s %s ;-)" % (os.path.basename(filename), |
187 |
" ".join(sorted(digests)))) |
188 |
eout.eend(0) |
189 |
|
190 |
Modified: main/trunk/pym/portage/dbapi/bintree.py |
191 |
=================================================================== |
192 |
--- main/trunk/pym/portage/dbapi/bintree.py 2008-07-04 22:49:04 UTC (rev 10934) |
193 |
+++ main/trunk/pym/portage/dbapi/bintree.py 2008-07-05 07:18:31 UTC (rev 10935) |
194 |
@@ -7,12 +7,12 @@ |
195 |
from portage.dbapi.virtual import fakedbapi |
196 |
from portage.exception import InvalidPackageName, InvalidAtom, \ |
197 |
PermissionDenied, PortageException |
198 |
-from portage.output import green |
199 |
+from portage.output import green, EOutput |
200 |
from portage.util import ensure_dirs, normalize_path, writemsg, writemsg_stdout |
201 |
from portage.versions import best, catpkgsplit, catsplit |
202 |
from portage.update import update_dbentries |
203 |
|
204 |
-from portage import dep_expand, listdir, _movefile |
205 |
+from portage import dep_expand, listdir, _check_distfile, _movefile |
206 |
|
207 |
import portage.xpak, portage.getbinpkg |
208 |
|
209 |
@@ -991,26 +991,6 @@ |
210 |
if not fcmd: |
211 |
fcmd = self.settings.get(fcmd_prefix) |
212 |
success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd) |
213 |
- if success and "strict" in self.settings.features: |
214 |
- metadata = self._remotepkgs[pkgname] |
215 |
- digests = {} |
216 |
- from portage.checksum import hashfunc_map, verify_all |
217 |
- for k in hashfunc_map: |
218 |
- v = metadata.get(k) |
219 |
- if not v: |
220 |
- continue |
221 |
- digests[k] = v |
222 |
- if "SIZE" in metadata: |
223 |
- try: |
224 |
- digests["size"] = long(self._remotepkgs[pkgname]["SIZE"]) |
225 |
- except ValueError: |
226 |
- writemsg("!!! Malformed SIZE attribute in remote " + \ |
227 |
- "metadata for '%s'\n" % pkgname) |
228 |
- if digests: |
229 |
- ok, reason = verify_all(tbz2_path, digests) |
230 |
- if not ok: |
231 |
- raise portage.exception.DigestException( |
232 |
- tuple([tbz2_path]+list(reason))) |
233 |
if not success: |
234 |
try: |
235 |
os.unlink(self.getname(pkgname)) |
236 |
@@ -1019,6 +999,72 @@ |
237 |
raise portage.exception.FileNotFound(mydest) |
238 |
self.inject(pkgname) |
239 |
|
240 |
+ def _load_pkgindex(self): |
241 |
+ pkgindex = self._new_pkgindex() |
242 |
+ try: |
243 |
+ f = open(self._pkgindex_file) |
244 |
+ except EnvironmentError: |
245 |
+ pass |
246 |
+ else: |
247 |
+ try: |
248 |
+ pkgindex.read(f) |
249 |
+ finally: |
250 |
+ f.close() |
251 |
+ return pkgindex |
252 |
+ |
253 |
+ def digestCheck(self, pkg): |
254 |
+ """ |
255 |
+ Verify digests for the given package and raise DigestException |
256 |
+ if verification fails. |
257 |
+ @rtype: bool |
258 |
+ @returns: True if digests could be located, False otherwise. |
259 |
+ """ |
260 |
+ cpv = pkg |
261 |
+ if not isinstance(cpv, basestring): |
262 |
+ cpv = pkg.cpv |
263 |
+ pkg = None |
264 |
+ |
265 |
+ pkg_path = self.getname(cpv) |
266 |
+ metadata = None |
267 |
+ if self._remotepkgs is None or cpv not in self._remotepkgs: |
268 |
+ for d in self._load_pkgindex().packages: |
269 |
+ if d["CPV"] == cpv: |
270 |
+ metadata = d |
271 |
+ break |
272 |
+ else: |
273 |
+ metadata = self._remotepkgs[cpv] |
274 |
+ if metadata is None: |
275 |
+ return False |
276 |
+ |
277 |
+ digests = {} |
278 |
+ from portage.checksum import hashfunc_map, verify_all |
279 |
+ for k in hashfunc_map: |
280 |
+ v = metadata.get(k) |
281 |
+ if not v: |
282 |
+ continue |
283 |
+ digests[k] = v |
284 |
+ |
285 |
+ if "SIZE" in metadata: |
286 |
+ try: |
287 |
+ digests["size"] = int(metadata["SIZE"]) |
288 |
+ except ValueError: |
289 |
+ writemsg("!!! Malformed SIZE attribute in remote " + \ |
290 |
+ "metadata for '%s'\n" % cpv) |
291 |
+ |
292 |
+ if not digests: |
293 |
+ return False |
294 |
+ |
295 |
+ eout = EOutput() |
296 |
+ eout.quiet = self.settings.get("PORTAGE_QUIET") == "1" |
297 |
+ ok, st = _check_distfile(pkg_path, digests, eout, show_errors=0) |
298 |
+ if not ok: |
299 |
+ ok, reason = verify_all(pkg_path, digests) |
300 |
+ if not ok: |
301 |
+ raise portage.exception.DigestException( |
302 |
+ (pkg_path,) + tuple(reason)) |
303 |
+ |
304 |
+ return True |
305 |
+ |
306 |
def getslot(self, mycatpkg): |
307 |
"Get a slot for a catpkg; assume it exists." |
308 |
myslot = "" |
309 |
|
310 |
-- |
311 |
gentoo-commits@l.g.o mailing list |