Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r10935 - in main/trunk/pym: _emerge portage portage/dbapi
Date: Sat, 05 Jul 2008 07:18:38
Message-Id: E1KF22S-0007ub-Ch@stork.gentoo.org
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