Gentoo Archives: gentoo-commits

From: "André Erdmann" <dywi@×××××××.de>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/manifest/, roverlay/overlay/manifest/
Date: Mon, 30 Jul 2012 08:54:48
Message-Id: 1342800647.5af2290c757997b706406b4dc5a83967c0bc26f7.dywi@gentoo
1 commit: 5af2290c757997b706406b4dc5a83967c0bc26f7
2 Author: André Erdmann <dywi <AT> mailerd <DOT> de>
3 AuthorDate: Fri Jul 20 16:10:47 2012 +0000
4 Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
5 CommitDate: Fri Jul 20 16:10:47 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=5af2290c
7
8 ManifestCreation is broken!
9
10 * Just for a complete commit history
11
12 This commit tries to fix problems with multiple distdirs (e.g. when creating a
13 Manifest for ebuilds from both CRAN and BIOC) using PORTAGE_RO_DISTDIRS.
14 In short, this does not work ("src file not found").
15
16 gelöscht: roverlay/manifest/helpers.py
17 umbenannt: roverlay/manifest/__init__.py -> roverlay/overlay/manifest/__init__.py
18 neue Datei: roverlay/overlay/manifest/env.py
19 neue Datei: roverlay/overlay/manifest/helpers.py
20
21 ---
22 roverlay/manifest/helpers.py | 221 ---------------------------
23 roverlay/{ => overlay}/manifest/__init__.py | 19 ++-
24 roverlay/overlay/manifest/env.py | 112 ++++++++++++++
25 roverlay/overlay/manifest/helpers.py | 98 ++++++++++++
26 4 files changed, 224 insertions(+), 226 deletions(-)
27
28 diff --git a/roverlay/manifest/helpers.py b/roverlay/manifest/helpers.py
29 deleted file mode 100644
30 index 47e1e20..0000000
31 --- a/roverlay/manifest/helpers.py
32 +++ /dev/null
33 @@ -1,221 +0,0 @@
34 -# R Overlay -- Manifest creation for ebuilds
35 -# Copyright 2006-2012 Gentoo Foundation
36 -# Distributed under the terms of the GNU General Public License v2
37 -
38 -
39 -# TODO (in future): could use portage api directly, namely
40 -# '/usr/lib/portage/pym/portage/package/ebuild/doebuild.py'
41 -# instead of using '/usr/bin/ebuild'
42 -
43 -import os
44 -import re
45 -import copy
46 -import logging
47 -import subprocess
48 -import threading
49 -
50 -from roverlay import config, util
51 -
52 -class _ManifestCreation ( object ):
53 - """This is the base class for Manifest file creation."""
54 -
55 - def __init__ ( self ):
56 - self.logger = logging.getLogger ( 'ManifestCreation' )
57 - # --- end of __init__ (...) ---
58 -
59 - def create_for ( self, package_info ):
60 - """Creates a Manifest file for the ebuild of the given package_info."""
61 - raise Exception ( "method stub" )
62 - # --- end of create_for (...) ---
63 -
64 - @classmethod
65 - def do ( cls, package_info ):
66 - """Class access to Manifest creation."""
67 - return cls().create_for ( package_info )
68 - # --- end of do (...) ---
69 -
70 -
71 -class ExternalManifestCreation ( _ManifestCreation ):
72 - """This class implements Manifest creation using the low level ebuild
73 - interface, ebuild(1), which is called in a filtered environment.
74 - """
75 -
76 - envlock = threading.Lock()
77 - manifest_env = None
78 -
79 - @classmethod
80 - def get_env ( cls, repo_dir ):
81 - cls.envlock.acquire()
82 - try:
83 - if cls.manifest_env is None:
84 - cls.manifest_env = ManifestEnv ( filter_env=True )
85 - ret = cls.manifest_env [repo_dir]
86 - finally:
87 - cls.envlock.release()
88 -
89 - return ret
90 -
91 -
92 - def __init__ ( self ):
93 - super ( ExternalManifestCreation, self ) . __init__ ()
94 - # ebuild <ebuild_file> <target>, where target is:
95 - self.ebuild_tgt = config.get ( 'TOOLS.EBUILD.target', 'manifest' )
96 - self.ebuild_prog = config.get ( 'TOOLS.EBUILD.prog', '/usr/bin/ebuild' )
97 -
98 - # --- end of __init__ (...) ---
99 -
100 - def create_for ( self, package_info ):
101 - """See ManifestCreation.create_for.
102 - Calls ebuild, returns True on success else False.
103 -
104 - raises: *passes Exceptions from failed config lookups
105 - """
106 -
107 - my_env = self.__class__.get_env ( package_info ['distdir'] )
108 -
109 - ebuild_file = package_info ['ebuild_file']
110 -
111 - ebuild_call = subprocess.Popen (
112 - (
113 - self.ebuild_prog,
114 - ebuild_file,
115 - self.ebuild_tgt
116 - ),
117 - stdin=None,
118 - stdout=subprocess.PIPE,
119 - stderr=subprocess.PIPE,
120 - env=my_env
121 - )
122 -
123 - output = ebuild_call.communicate()
124 -
125 - # log stdout?
126 - #for line in util.pipe_lines ( output [0] ):
127 - # LOGGER.debug ( line )
128 - #for line in util.pipe_lines ( output [0] ): print ( line )
129 -
130 - # log stderr
131 - for line in util.pipe_lines ( output [1], use_filter=True ):
132 - self.logger.warning ( line )
133 -
134 - if ebuild_call.returncode == 0:
135 - self.logger.debug ( "Manifest written." )
136 - return True
137 - else:
138 - self.logger.error (
139 - "Couldn't create Manifest for %s! Return code was %i."
140 - % ( ebuild_file, ebuild_call.returncode )
141 - )
142 - return False
143 - # --- end of create_for (...) ---
144 -
145 -
146 -class ManifestEnv ( object ):
147 - """per-repo environment container for Manifest creation using ebuild."""
148 -
149 - def __init__ ( self, filter_env=True ):
150 - """Initializes a ManifestEnv.
151 -
152 - arguments:
153 - * filter_env -- if True: start with an empty env and copy vars
154 - from os.environ selectively
155 - else : start with os.environ as env
156 - """
157 - self.filter_env = filter_env
158 - self._manenv = dict()
159 - self.logger = logging.getLogger ( 'ManifestEnv' )
160 - self._common_env = None
161 - # --- end of __init__ (...) ---
162 -
163 - def get_env ( self, repo_dir ):
164 - """Returns an env dict for repo_dir.
165 -
166 - arguments:
167 - * repo_dir --
168 - """
169 - if not repo_dir in self._manenv:
170 - repo_env = self._get_common_manifest_env()
171 - repo_env ['DISTDIR'] = repo_dir
172 - self._manenv [repo_dir] = repo_env
173 -
174 - return self._manenv [repo_dir]
175 - # --- end of get_env (...) ---
176 -
177 - # x = ManifestEnv(); env = x [<sth>] etc.
178 - __getitem__ = get_env
179 - # ---
180 -
181 - def _get_common_manifest_env ( self, noret=False ):
182 - """Creates an environment suitable for an
183 - "ebuild <ebuild> digest|manifest" call (or uses an already existing env).
184 - Returns a shallow copy of this env which can then be locally modified
185 - (setting DISTDIR).
186 -
187 - arguments:
188 - * noret -- do not return copied env if True
189 - """
190 -
191 - if self._common_env is None:
192 -
193 - if self.filter_env:
194 -
195 - # selectively import os.environ
196 - # FIXME: keep EBUILD_DEFAULT_OPTS?
197 - our_env = util.keepenv (
198 - ( 'PATH', '' ),
199 - 'LANG',
200 - 'PWD',
201 - 'EBUILD_DEFAULT_OPTS'
202 - )
203 - else:
204 - # copy os.environ
205 - our_env = dict ( os.environ )
206 -
207 - # -- common env part
208 -
209 - # set FEATURES
210 - # * digest -- needed? (works without it)
211 - # * assume-digests --
212 - # * unknown-features-warn -- should FEATURES ever change
213 - #
214 - # * noauto -- should prevent ebuild from adding additional actions,
215 - # it still tries to download source packages, which is just wrong
216 - # here 'cause it is expected that the R package file exists when
217 - # calling this function, so FETCHCOMMAND/RESUMECOMMAND will be set
218 - # to /bin/true if possible.
219 - #
220 - # * distlocks -- disabled if FETCHCOMMAND/RESUMECOMMAND set to no-op
221 - #
222 - our_env ['FEATURES'] = \
223 - "noauto digest assume-digests unknown-features-warn"
224 -
225 - # try to prevent src fetching
226 - fetch_nop = util.sysnop (
227 - nop_returns_success=True,
228 - format_str="%s \${DISTDIR} \${FILE} \${URI}"
229 - )
230 -
231 - if not fetch_nop is None:
232 - self.logger.debug (
233 - "%s disables/replaces FETCHCOMMAND,RESUMECOMMAND."
234 - % fetch_nop [0]
235 - )
236 - our_env ['FETCHCOMMAND'] = fetch_nop [1]
237 - our_env ['RESUMECOMMAND'] = fetch_nop [1]
238 - our_env ['FEATURES'] += " -distlocks"
239 -
240 -
241 -
242 - # set PORDIR_OVERLAY
243 - # ! FIXME the overlay module does not enforce usage of this config key
244 - our_env ['PORTDIR_OVERLAY'] = config.get_or_fail (
245 - [ 'OVERLAY', 'dir' ]
246 - )
247 -
248 - self._common_env = our_env
249 - # -- end if
250 - if noret:
251 - return None
252 - else:
253 - return copy.copy ( self._common_env )
254 - # --- end of _get_common_manifest_env (...) ---
255
256 diff --git a/roverlay/manifest/__init__.py b/roverlay/overlay/manifest/__init__.py
257 similarity index 53%
258 rename from roverlay/manifest/__init__.py
259 rename to roverlay/overlay/manifest/__init__.py
260 index b95a855..9a49c7f 100644
261 --- a/roverlay/manifest/__init__.py
262 +++ b/roverlay/overlay/manifest/__init__.py
263 @@ -2,13 +2,18 @@
264 # Copyright 2006-2012 Gentoo Foundation
265 # Distributed under the terms of the GNU General Public License v2
266 import logging
267 +import threading
268
269 -from roverlay.manifest import helpers
270 +from roverlay.overlay.manifest import helpers
271
272 -_MANIFEST_IMPLEMENTATION = helpers.ExternalManifestCreation
273 +_manifest_creation = helpers.ExternalManifestCreation()
274 +# ExternalManifestCreation does not support threads (-> multiprocesses)
275 +# for one directory/overlay
276 +_manifest_lock = threading.Lock()
277
278
279 -def create_manifest ( package_info, nofail=False ):
280 +
281 +def create_manifest ( package_info_list, nofail=False ):
282 """Creates a Manifest for package_info, using the <<best>> implementation
283 available.
284
285 @@ -18,12 +23,16 @@ def create_manifest ( package_info, nofail=False ):
286 * package_info --
287 * nofail -- catch exceptions and return False
288 """
289 + ret = False
290 try:
291 - return _MANIFEST_IMPLEMENTATION.do ( package_info )
292 + _manifest_lock.acquire()
293 + ret = _manifest_creation.create_for ( package_info_list )
294 except Exception as e:
295 logging.exception ( e )
296 if nofail:
297 - return False
298 + ret = False
299 else:
300 raise
301 + finally:
302 + _manifest_lock.release()
303 # --- end of create_manifest (...) ---
304
305 diff --git a/roverlay/overlay/manifest/env.py b/roverlay/overlay/manifest/env.py
306 new file mode 100644
307 index 0000000..58548a4
308 --- /dev/null
309 +++ b/roverlay/overlay/manifest/env.py
310 @@ -0,0 +1,112 @@
311 +# R Overlay -- Manifest creation for ebuilds
312 +# Copyright 2006-2012 Gentoo Foundation
313 +# Distributed under the terms of the GNU General Public License v2
314 +
315 +import os
316 +import copy
317 +import logging
318 +
319 +from roverlay import util
320 +
321 +class ManifestEnv ( object ):
322 + """per-repo environment container for Manifest creation using ebuild."""
323 +
324 + @classmethod
325 + def get_new ( cls ):
326 + return cls ( filter_env=True ).get_env (
327 + distdir="", portage_ro_distdirs=""
328 + )
329 + # --- end of get_new (...) ---
330 +
331 + def __init__ ( self, filter_env=True ):
332 + """Initializes a ManifestEnv.
333 +
334 + arguments:
335 + * filter_env -- if True: start with an empty env and copy vars
336 + from os.environ selectively
337 + else : start with os.environ as env
338 + """
339 + self.filter_env = filter_env
340 + self._manenv = dict()
341 + self.logger = logging.getLogger ( 'ManifestEnv' )
342 + self._common_env = None
343 + # --- end of __init__ (...) ---
344 +
345 + def get_env ( self, distdir, portage_ro_distdirs ):
346 + """Returns an env dict for repo_dir.
347 +
348 + arguments:
349 + * repo_dir --
350 + """
351 + env = self._get_common_manifest_env()
352 + env ['DISTDIR'] = distdir
353 + env ['PORTAGE_RO_DISTDIRS'] = portage_ro_distdirs
354 + return env
355 + # --- end of get_env (...) ---
356 +
357 + def _get_common_manifest_env ( self, noret=False ):
358 + """Creates an environment suitable for an
359 + "ebuild <ebuild> digest|manifest" call (or uses an already existing env).
360 + Returns a shallow copy of this env which can then be locally modified
361 + (setting DISTDIR, PORTAGE_RO_DISTDIRS).
362 +
363 + arguments:
364 + * noret -- do not return copied env if True
365 + """
366 +
367 + if self._common_env is None:
368 +
369 + if self.filter_env:
370 +
371 + # selectively import os.environ
372 + # FIXME: keep EBUILD_DEFAULT_OPTS?
373 + our_env = util.keepenv (
374 + ( 'PATH', '' ),
375 + 'LANG',
376 + 'PWD',
377 + 'EBUILD_DEFAULT_OPTS'
378 + )
379 + else:
380 + # copy os.environ
381 + our_env = dict ( os.environ )
382 +
383 + # -- common env part
384 +
385 + # set FEATURES
386 + # * digest -- needed? (works without it)
387 + # * assume-digests --
388 + # * unknown-features-warn -- should FEATURES ever change
389 + #
390 + # * noauto -- should prevent ebuild from adding additional actions,
391 + # it still tries to download source packages, which is just wrong
392 + # here 'cause it is expected that the R package file exists when
393 + # calling this function, so FETCHCOMMAND/RESUMECOMMAND will be set
394 + # to /bin/true if possible.
395 + #
396 + # * distlocks -- disabled if FETCHCOMMAND/RESUMECOMMAND set to no-op
397 + #
398 + our_env ['FEATURES'] = \
399 + "noauto digest assume-digests unknown-features-warn"
400 +
401 + # try to prevent src fetching
402 + fetch_nop = util.sysnop (
403 + nop_returns_success=True,
404 + format_str="%s \${DISTDIR} \${FILE} \${URI}"
405 + )
406 +
407 + if not fetch_nop is None:
408 + self.logger.debug (
409 + fetch_nop [0] + " disables/replaces FETCHCOMMAND,RESUMECOMMAND."
410 + )
411 + our_env ['FETCHCOMMAND'] = fetch_nop [1]
412 + our_env ['RESUMECOMMAND'] = fetch_nop [1]
413 + our_env ['FEATURES'] += " -distlocks"
414 +
415 +
416 + self._common_env = our_env
417 + # -- end if
418 + if noret:
419 + return None
420 + else:
421 + return copy.copy ( self._common_env )
422 + # --- end of _get_common_manifest_env (...) ---
423
424 diff --git a/roverlay/overlay/manifest/helpers.py b/roverlay/overlay/manifest/helpers.py
425 new file mode 100644
426 index 0000000..168a119
427 --- /dev/null
428 +++ b/roverlay/overlay/manifest/helpers.py
429 @@ -0,0 +1,98 @@
430 +# R Overlay -- Manifest creation for ebuilds
431 +# Copyright 2006-2012 Gentoo Foundation
432 +# Distributed under the terms of the GNU General Public License v2
433 +
434 +# TODO (in future): could use portage api directly, namely
435 +# '/usr/lib/portage/pym/portage/package/ebuild/doebuild.py'
436 +# instead of using '/usr/bin/ebuild'
437 +
438 +import os.path
439 +import copy
440 +import logging
441 +import subprocess
442 +
443 +
444 +from roverlay import config, util
445 +
446 +from roverlay.overlay.manifest.env import ManifestEnv
447 +
448 +class ExternalManifestCreation ( object ):
449 + """This class implements Manifest creation using the low level ebuild
450 + interface, ebuild(1), which is called in a filtered environment.
451 + """
452 + # NOTE:
453 + # ebuild <ebuild> digest does not support multiprocesses for one overlay,
454 +
455 + def __init__ ( self ):
456 + self.logger = logging.getLogger ( 'ManifestCreation' )
457 + self.manifest_env = ManifestEnv.get_new()
458 + self.ebuild_tgt = config.get ( 'TOOLS.EBUILD.target', 'manifest' )
459 + self.ebuild_prog = config.get ( 'TOOLS.EBUILD.prog', '/usr/bin/ebuild' )
460 +
461 + # set PORDIR_OVERLAY and DISTDIR
462 + self.manifest_env ['PORTDIR_OVERLAY'] = config.get_or_fail (
463 + 'OVERLAY.dir'
464 + )
465 + # !! FIXME: tell the <others> that __tmp__ is a reserved directory
466 + self.manifest_env ['DISTDIR'] = \
467 + config.get_or_fail ( 'DISTFILES.ROOT' ) + os.path.sep + '__tmp__'
468 +
469 +
470 + # --- end of __init__ (...) ---
471 +
472 + def create_for ( self, package_info_list ):
473 + """See ManifestCreation.create_for.
474 + Calls ebuild, returns True on success else False.
475 +
476 + raises: *passes Exceptions from failed config lookups
477 + """
478 + self.logger.critical (
479 + "Manifest creation is broken! PORTAGE_RO_DISTDIRS does not work."
480 + )
481 + return False
482 +
483 + distdirs = ' '.join ( set (
484 + p ['distdir'] for p in package_info_list
485 + ) )
486 + ebuild_file = package_info_list [0] ['ebuild_file']
487 +
488 +
489 + self.manifest_env ['PORTAGE_RO_DISTDIRS'] = distdirs
490 +
491 + #util.dodir ( self.manifest_env ['DISTDIR'] )
492 +
493 + ebuild_call = subprocess.Popen (
494 + (
495 + self.ebuild_prog,
496 + ebuild_file,
497 + self.ebuild_tgt
498 + ),
499 + stdin=None,
500 + stdout=subprocess.PIPE,
501 + stderr=subprocess.PIPE,
502 + env=self.manifest_env
503 + )
504 +
505 + output = ebuild_call.communicate()
506 +
507 + # log stdout?
508 + #for line in util.pipe_lines ( output [0] ):
509 + # LOGGER.debug ( line )
510 + #for line in util.pipe_lines ( output [0] ): print ( line )
511 +
512 + # log stderr
513 + for line in util.pipe_lines ( output [1], use_filter=True ):
514 + self.logger.warning ( line )
515 +
516 + if ebuild_call.returncode == 0:
517 + self.logger.debug ( "Manifest written." )
518 + return True
519 + else:
520 + self.logger.error (
521 + 'Couldn\'t create Manifest for {ebuild}! '
522 + 'Return code was {ret}.'.format (
523 + ebuild=ebuild_file, ret=ebuild_call.returncode
524 + )
525 + )
526 + return False
527 + # --- end of create_for (...) ---