Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: man/, pym/portage/package/ebuild/, pym/portage/dbapi/, ...
Date: Tue, 21 Aug 2012 21:17:14
Message-Id: 1345580539.accee1b7c61da284022f86d9ab39bcb492ea4023.zmedico@gentoo
1 commit: accee1b7c61da284022f86d9ab39bcb492ea4023
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Tue Aug 21 20:22:19 2012 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Tue Aug 21 20:22:19 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=accee1b7
7
8 Implement PORTAGE_CHECKSUM_FILTER for bug #432170
9
10 ---
11 man/make.conf.5 | 19 +++++++-
12 pym/_emerge/EbuildFetcher.py | 4 +-
13 pym/portage/checksum.py | 54 ++++++++++++++++++++
14 pym/portage/dbapi/bintree.py | 6 ++-
15 pym/portage/manifest.py | 15 +++--
16 .../package/ebuild/_config/special_env_vars.py | 1 +
17 pym/portage/package/ebuild/digestcheck.py | 13 +++--
18 pym/portage/package/ebuild/fetch.py | 13 +++--
19 8 files changed, 107 insertions(+), 18 deletions(-)
20
21 diff --git a/man/make.conf.5 b/man/make.conf.5
22 index c617fbc..59f32b8 100644
23 --- a/man/make.conf.5
24 +++ b/man/make.conf.5
25 @@ -1,4 +1,4 @@
26 -.TH "MAKE.CONF" "5" "Jul 2012" "Portage VERSION" "Portage"
27 +.TH "MAKE.CONF" "5" "Aug 2012" "Portage VERSION" "Portage"
28 .SH "NAME"
29 make.conf \- custom settings for Portage
30 .SH "SYNOPSIS"
31 @@ -697,6 +697,23 @@ for bzip2 compression operations. \fBPORTAGE_BZIP2_COMMAND\fR will also be
32 called for extraction operation, with -d appended, unless the
33 \fBPORTAGE_BUNZIP2_COMMAND\fR variable is set.
34 .TP
35 +\fBPORTAGE_CHECKSUM_FILTER\fR = \fI[space delimited list of hash names]\fR
36 +This variable may be used to filter the hash functions that are used to
37 +verify integrity of files. Hash functions names are case\-insensitive, and
38 +the \fI*\fR and \fI\-*\fR wildcard tokens are supported.
39 +.br
40 +Defaults to the value of *.
41 +.br
42 +.I Examples:
43 +.nf
44 +# Use all available hash functions
45 +PORTAGE_CHECKSUM_FILTER="*"
46 +# Use any function except whirlpool
47 +PORTAGE_CHECKSUM_FILTER="* \-whirlpool"
48 +# Only use sha256
49 +PORTAGE_CHECKSUM_FILTER="\-* sha256"
50 +.fi
51 +.TP
52 \fBPORTAGE_COMPRESS\fR = \fI"bzip2"\fR
53 This variable contains the command used to compress documentation during the
54 install phase.
55
56 diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py
57 index c0a7fdd..bbcb6a9 100644
58 --- a/pym/_emerge/EbuildFetcher.py
59 +++ b/pym/_emerge/EbuildFetcher.py
60 @@ -13,6 +13,7 @@ from portage import os
61 from portage import _encodings
62 from portage import _unicode_encode
63 from portage import _unicode_decode
64 +from portage.checksum import _hash_filter
65 from portage.elog.messages import eerror
66 from portage.package.ebuild.fetch import _check_distfile, fetch
67 from portage.util._pty import _create_pty_or_pipe
68 @@ -57,6 +58,7 @@ class EbuildFetcher(SpawnProcess):
69 if st.st_size != expected_size:
70 return False
71
72 + hash_filter = _hash_filter(settings.get("PORTAGE_CHECKSUM_FILTER", ""))
73 stdout_orig = sys.stdout
74 stderr_orig = sys.stderr
75 global_havecolor = portage.output.havecolor
76 @@ -78,7 +80,7 @@ class EbuildFetcher(SpawnProcess):
77 break
78 continue
79 ok, st = _check_distfile(os.path.join(distdir, filename),
80 - mydigests, eout, show_errors=False)
81 + mydigests, eout, show_errors=False, hash_filter=hash_filter)
82 if not ok:
83 success = False
84 break
85
86 diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
87 index daf4a0c..de4cc66 100644
88 --- a/pym/portage/checksum.py
89 +++ b/pym/portage/checksum.py
90 @@ -217,6 +217,60 @@ def _filter_unaccelarated_hashes(digests):
91
92 return digests
93
94 +class _hash_filter(object):
95 + """
96 + Implements filtering for PORTAGE_CHECKSUM_FILTER.
97 + """
98 +
99 + __slots__ = ('transparent', '_tokens',)
100 +
101 + def __init__(self, filter_str):
102 + tokens = filter_str.upper().split()
103 + if not tokens or tokens[-1] == "*":
104 + del tokens[:]
105 + self.transparent = not tokens
106 + tokens.reverse()
107 + self._tokens = tuple(tokens)
108 +
109 + def __call__(self, hash_name):
110 + if self.transparent:
111 + return True
112 + matches = ("*", hash_name)
113 + for token in self._tokens:
114 + if token in matches:
115 + return True
116 + elif token[:1] == "-":
117 + if token[1:] in matches:
118 + return False
119 + return False
120 +
121 +def _apply_hash_filter(digests, hash_filter):
122 + """
123 + Return a new dict containing the filtered digests, or the same
124 + dict if no changes are necessary. This will always preserve at
125 + at least one digest, in order to ensure that they are not all
126 + discarded.
127 + """
128 + if hash_filter.transparent:
129 + return digests
130 +
131 + verifiable_hash_types = set(digests).intersection(hashfunc_map)
132 + verifiable_hash_types.discard("size")
133 + modified = False
134 + if len(verifiable_hash_types) > 1:
135 + for k in list(verifiable_hash_types):
136 + if not hash_filter(k):
137 + modified = True
138 + verifiable_hash_types.remove(k)
139 + if len(verifiable_hash_types) == 1:
140 + break
141 +
142 + if modified:
143 + digests = dict((k, v) for (k, v) in digests.items()
144 + if k == "size" or k in verifiable_hash_types)
145 +
146 + return digests
147 +
148 def verify_all(filename, mydict, calc_prelink=0, strict=0):
149 """
150 Verify all checksums against a file.
151
152 diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
153 index 6c01867..a2fd5ea 100644
154 --- a/pym/portage/dbapi/bintree.py
155 +++ b/pym/portage/dbapi/bintree.py
156 @@ -5,7 +5,8 @@ __all__ = ["bindbapi", "binarytree"]
157
158 import portage
159 portage.proxy.lazyimport.lazyimport(globals(),
160 - 'portage.checksum:hashfunc_map,perform_multiple_checksums,verify_all',
161 + 'portage.checksum:hashfunc_map,perform_multiple_checksums,' + \
162 + 'verify_all,_apply_hash_filter,_hash_filter',
163 'portage.dbapi.dep_expand:dep_expand',
164 'portage.dep:dep_getkey,isjustname,isvalidatom,match_from_list',
165 'portage.output:EOutput,colorize',
166 @@ -1462,6 +1463,9 @@ class binarytree(object):
167 if not digests:
168 return False
169
170 + hash_filter = _hash_filter(
171 + self.settings.get("PORTAGE_CHECKSUM_FILTER", ""))
172 + digests = _apply_hash_filter(digests, hash_filter)
173 eout = EOutput()
174 eout.quiet = self.settings.get("PORTAGE_QUIET") == "1"
175 ok, st = _check_distfile(pkg_path, digests, eout, show_errors=0)
176
177 diff --git a/pym/portage/manifest.py b/pym/portage/manifest.py
178 index a04b717..b2f1ff2 100644
179 --- a/pym/portage/manifest.py
180 +++ b/pym/portage/manifest.py
181 @@ -9,7 +9,7 @@ import warnings
182 import portage
183 portage.proxy.lazyimport.lazyimport(globals(),
184 'portage.checksum:hashfunc_map,perform_multiple_checksums,' + \
185 - 'verify_all,_filter_unaccelarated_hashes',
186 + 'verify_all,_apply_hash_filter,_filter_unaccelarated_hashes',
187 'portage.util:write_atomic',
188 )
189
190 @@ -502,14 +502,17 @@ class Manifest(object):
191 for t in MANIFEST2_IDENTIFIERS:
192 self.checkTypeHashes(t, ignoreMissingFiles=ignoreMissingFiles)
193
194 - def checkTypeHashes(self, idtype, ignoreMissingFiles=False):
195 + def checkTypeHashes(self, idtype, ignoreMissingFiles=False, hash_filter=None):
196 for f in self.fhashdict[idtype]:
197 - self.checkFileHashes(idtype, f, ignoreMissing=ignoreMissingFiles)
198 + self.checkFileHashes(idtype, f, ignoreMissing=ignoreMissingFiles,
199 + hash_filter=hash_filter)
200
201 - def checkFileHashes(self, ftype, fname, ignoreMissing=False):
202 + def checkFileHashes(self, ftype, fname, ignoreMissing=False, hash_filter=None):
203 + digests = _filter_unaccelarated_hashes(self.fhashdict[ftype][fname])
204 + if hash_filter is not None:
205 + digests = _apply_hash_filter(digests, hash_filter)
206 try:
207 - ok, reason = verify_all(self._getAbsname(ftype, fname),
208 - _filter_unaccelarated_hashes(self.fhashdict[ftype][fname]))
209 + ok, reason = verify_all(self._getAbsname(ftype, fname), digests)
210 if not ok:
211 raise DigestException(tuple([self._getAbsname(ftype, fname)]+list(reason)))
212 return ok, reason
213
214 diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py
215 index 6ed6d05..c974eb9 100644
216 --- a/pym/portage/package/ebuild/_config/special_env_vars.py
217 +++ b/pym/portage/package/ebuild/_config/special_env_vars.py
218 @@ -150,6 +150,7 @@ environ_filter += [
219 "PORTAGE_BACKGROUND", "PORTAGE_BACKGROUND_UNMERGE",
220 "PORTAGE_BINHOST",
221 "PORTAGE_BINHOST_CHUNKSIZE", "PORTAGE_BUILDIR_LOCKED",
222 + "PORTAGE_CHECKSUM_FILTER",
223 "PORTAGE_ELOG_CLASSES",
224 "PORTAGE_ELOG_MAILFROM", "PORTAGE_ELOG_MAILSUBJECT",
225 "PORTAGE_ELOG_MAILURI", "PORTAGE_ELOG_SYSTEM",
226
227 diff --git a/pym/portage/package/ebuild/digestcheck.py b/pym/portage/package/ebuild/digestcheck.py
228 index 8705639..1d59948 100644
229 --- a/pym/portage/package/ebuild/digestcheck.py
230 +++ b/pym/portage/package/ebuild/digestcheck.py
231 @@ -1,4 +1,4 @@
232 -# Copyright 2010-2011 Gentoo Foundation
233 +# Copyright 2010-2012 Gentoo Foundation
234 # Distributed under the terms of the GNU General Public License v2
235
236 __all__ = ['digestcheck']
237 @@ -6,6 +6,7 @@ __all__ = ['digestcheck']
238 import warnings
239
240 from portage import os, _encodings, _unicode_decode
241 +from portage.checksum import _hash_filter
242 from portage.exception import DigestException, FileNotFound
243 from portage.localization import _
244 from portage.output import EOutput
245 @@ -28,6 +29,7 @@ def digestcheck(myfiles, mysettings, strict=False, justmanifest=None, mf=None):
246 if mysettings.get("EBUILD_SKIP_MANIFEST") == "1":
247 return 1
248 pkgdir = mysettings["O"]
249 + hash_filter = _hash_filter(mysettings.get("PORTAGE_CHECKSUM_FILTER", ""))
250 if mf is None:
251 mf = mysettings.repositories.get_repo_for_location(
252 os.path.dirname(os.path.dirname(pkgdir)))
253 @@ -38,15 +40,16 @@ def digestcheck(myfiles, mysettings, strict=False, justmanifest=None, mf=None):
254 if not mf.thin and strict and "PORTAGE_PARALLEL_FETCHONLY" not in mysettings:
255 if mf.fhashdict.get("EBUILD"):
256 eout.ebegin(_("checking ebuild checksums ;-)"))
257 - mf.checkTypeHashes("EBUILD")
258 + mf.checkTypeHashes("EBUILD", hash_filter=hash_filter)
259 eout.eend(0)
260 if mf.fhashdict.get("AUX"):
261 eout.ebegin(_("checking auxfile checksums ;-)"))
262 - mf.checkTypeHashes("AUX")
263 + mf.checkTypeHashes("AUX", hash_filter=hash_filter)
264 eout.eend(0)
265 if mf.fhashdict.get("MISC"):
266 eout.ebegin(_("checking miscfile checksums ;-)"))
267 - mf.checkTypeHashes("MISC", ignoreMissingFiles=True)
268 + mf.checkTypeHashes("MISC", ignoreMissingFiles=True,
269 + hash_filter=hash_filter)
270 eout.eend(0)
271 for f in myfiles:
272 eout.ebegin(_("checking %s ;-)") % f)
273 @@ -58,7 +61,7 @@ def digestcheck(myfiles, mysettings, strict=False, justmanifest=None, mf=None):
274 writemsg(_("\n!!! Missing digest for '%s'\n") % (f,),
275 noiselevel=-1)
276 return 0
277 - mf.checkFileHashes(ftype, f)
278 + mf.checkFileHashes(ftype, f, hash_filter=hash_filter)
279 eout.eend(0)
280 except FileNotFound as e:
281 eout.eend(1)
282
283 diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py
284 index 60ed04d..8365ad2 100644
285 --- a/pym/portage/package/ebuild/fetch.py
286 +++ b/pym/portage/package/ebuild/fetch.py
287 @@ -26,7 +26,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
288 from portage import OrderedDict, os, selinux, shutil, _encodings, \
289 _shell_quote, _unicode_encode
290 from portage.checksum import (hashfunc_map, perform_md5, verify_all,
291 - _filter_unaccelarated_hashes)
292 + _filter_unaccelarated_hashes, _hash_filter, _apply_hash_filter)
293 from portage.const import BASH_BINARY, CUSTOM_MIRRORS_FILE, \
294 GLOBAL_CONFIG_PATH
295 from portage.data import portage_gid, portage_uid, secpass, userpriv_groups
296 @@ -185,7 +185,7 @@ def _check_digests(filename, digests, show_errors=1):
297 return False
298 return True
299
300 -def _check_distfile(filename, digests, eout, show_errors=1):
301 +def _check_distfile(filename, digests, eout, show_errors=1, hash_filter=None):
302 """
303 @return a tuple of (match, stat_obj) where match is True if filename
304 matches all given digests (if any) and stat_obj is a stat result, or
305 @@ -212,6 +212,8 @@ def _check_distfile(filename, digests, eout, show_errors=1):
306 return (False, st)
307 else:
308 digests = _filter_unaccelarated_hashes(digests)
309 + if hash_filter is not None:
310 + digests = _apply_hash_filter(digests, hash_filter)
311 if _check_digests(filename, digests, show_errors=show_errors):
312 eout.ebegin("%s %s ;-)" % (os.path.basename(filename),
313 " ".join(sorted(digests))))
314 @@ -355,6 +357,7 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
315 if try_mirrors:
316 mymirrors += [x.rstrip("/") for x in mysettings["GENTOO_MIRRORS"].split() if x]
317
318 + hash_filter = _hash_filter(mysettings.get("PORTAGE_CHECKSUM_FILTER", ""))
319 skip_manifest = mysettings.get("EBUILD_SKIP_MANIFEST") == "1"
320 if skip_manifest:
321 allow_missing_digests = True
322 @@ -637,7 +640,7 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
323 eout = EOutput()
324 eout.quiet = mysettings.get("PORTAGE_QUIET") == "1"
325 match, mystat = _check_distfile(
326 - myfile_path, pruned_digests, eout)
327 + myfile_path, pruned_digests, eout, hash_filter=hash_filter)
328 if match:
329 # Skip permission adjustment for symlinks, since we don't
330 # want to modify anything outside of the primary DISTDIR,
331 @@ -709,7 +712,7 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
332 for x in ro_distdirs:
333 filename = os.path.join(x, myfile)
334 match, mystat = _check_distfile(
335 - filename, pruned_digests, eout)
336 + filename, pruned_digests, eout, hash_filter=hash_filter)
337 if match:
338 readonly_file = filename
339 break
340 @@ -796,6 +799,7 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
341 continue
342 else:
343 digests = _filter_unaccelarated_hashes(mydigests[myfile])
344 + digests = _apply_hash_filter(digests, hash_filter)
345 verified_ok, reason = verify_all(myfile_path, digests)
346 if not verified_ok:
347 writemsg(_("!!! Previously fetched"
348 @@ -1053,6 +1057,7 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
349 # net connection. This way we have a chance to try to download
350 # from another mirror...
351 digests = _filter_unaccelarated_hashes(mydigests[myfile])
352 + digests = _apply_hash_filter(digests, hash_filter)
353 verified_ok, reason = verify_all(myfile_path, digests)
354 if not verified_ok:
355 writemsg(_("!!! Fetched file: %s VERIFY FAILED!\n") % myfile,