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 (...) --- |