Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r15478 - in main/branches/prefix/pym: _emerge portage portage/dbapi portage/package/ebuild portage/tests/ebuild portage/util
Date: Sat, 27 Feb 2010 18:31:01
Message-Id: E1NlRRE-00074g-Hk@stork.gentoo.org
1 Author: grobian
2 Date: 2010-02-27 18:30:51 +0000 (Sat, 27 Feb 2010)
3 New Revision: 15478
4
5 Added:
6 main/branches/prefix/pym/portage/package/ebuild/_pty.py
7 main/branches/prefix/pym/portage/package/ebuild/doebuild.py
8 main/branches/prefix/pym/portage/package/ebuild/prepare_build_dirs.py
9 Modified:
10 main/branches/prefix/pym/_emerge/AbstractEbuildProcess.py
11 main/branches/prefix/pym/_emerge/EbuildFetcher.py
12 main/branches/prefix/pym/_emerge/EbuildPhase.py
13 main/branches/prefix/pym/_emerge/EbuildProcess.py
14 main/branches/prefix/pym/_emerge/MiscFunctionsProcess.py
15 main/branches/prefix/pym/_emerge/depgraph.py
16 main/branches/prefix/pym/portage/__init__.py
17 main/branches/prefix/pym/portage/dbapi/bintree.py
18 main/branches/prefix/pym/portage/dbapi/vartree.py
19 main/branches/prefix/pym/portage/package/ebuild/fetch.py
20 main/branches/prefix/pym/portage/tests/ebuild/test_pty_eof.py
21 main/branches/prefix/pym/portage/util/digraph.py
22 Log:
23 Merged from trunk -r15438:15449
24
25 | 15445 | Add missing writmsg import. |
26 | zmedico | |
27
28 | 15446 | Fix a logic error which causes blockers from installed |
29 | zmedico | packages to be ignored in some cases. Thanks to Brian Dolbec |
30 | | (dol-sen) for reporting. |
31
32 | 15447 | Remove unused 'expandcache' global variable. |
33 | zmedico | |
34
35 | 15448 | Split doebuild and related code to the |
36 | zmedico | portage.package.ebuild module. |
37
38 | 15449 | Make auxdbkeys a tuple instead of a list. |
39 | zmedico | |
40
41
42 Modified: main/branches/prefix/pym/_emerge/AbstractEbuildProcess.py
43 ===================================================================
44 --- main/branches/prefix/pym/_emerge/AbstractEbuildProcess.py 2010-02-27 04:35:02 UTC (rev 15477)
45 +++ main/branches/prefix/pym/_emerge/AbstractEbuildProcess.py 2010-02-27 18:30:51 UTC (rev 15478)
46 @@ -5,6 +5,7 @@
47 from _emerge.SpawnProcess import SpawnProcess
48 import portage
49 from portage import os
50 +from portage.package.ebuild._pty import _create_pty_or_pipe
51
52 class AbstractEbuildProcess(SpawnProcess):
53
54 @@ -13,7 +14,7 @@
55 def _pipe(self, fd_pipes):
56 stdout_pipe = fd_pipes.get(1)
57 got_pty, master_fd, slave_fd = \
58 - portage._create_pty_or_pipe(copy_term_size=stdout_pipe)
59 + _create_pty_or_pipe(copy_term_size=stdout_pipe)
60 return (master_fd, slave_fd)
61
62 def _can_log(self, slave_fd):
63
64 Modified: main/branches/prefix/pym/_emerge/EbuildFetcher.py
65 ===================================================================
66 --- main/branches/prefix/pym/_emerge/EbuildFetcher.py 2010-02-27 04:35:02 UTC (rev 15477)
67 +++ main/branches/prefix/pym/_emerge/EbuildFetcher.py 2010-02-27 18:30:51 UTC (rev 15478)
68 @@ -13,6 +13,7 @@
69 from portage import _unicode_encode
70 import codecs
71 from portage.elog.messages import eerror
72 +from portage.package.ebuild._pty import _create_pty_or_pipe
73
74 class EbuildFetcher(SpawnProcess):
75
76 @@ -144,7 +145,7 @@
77 return os.pipe()
78 stdout_pipe = fd_pipes.get(1)
79 got_pty, master_fd, slave_fd = \
80 - portage._create_pty_or_pipe(copy_term_size=stdout_pipe)
81 + _create_pty_or_pipe(copy_term_size=stdout_pipe)
82 return (master_fd, slave_fd)
83
84 def _set_returncode(self, wait_retval):
85
86 Modified: main/branches/prefix/pym/_emerge/EbuildPhase.py
87 ===================================================================
88 --- main/branches/prefix/pym/_emerge/EbuildPhase.py 2010-02-27 04:35:02 UTC (rev 15477)
89 +++ main/branches/prefix/pym/_emerge/EbuildPhase.py 2010-02-27 18:30:51 UTC (rev 15478)
90 @@ -5,6 +5,9 @@
91 from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
92 from _emerge.EbuildProcess import EbuildProcess
93 from _emerge.CompositeTask import CompositeTask
94 +from portage.package.ebuild.doebuild import _check_build_log, \
95 + _post_phase_cmds, _post_src_install_chost_fix, \
96 + _post_src_install_uid_fix
97 from portage.util import writemsg, writemsg_stdout
98 import portage
99 from portage import os
100 @@ -18,8 +21,6 @@
101 __slots__ = ("background", "pkg", "phase",
102 "scheduler", "settings", "tree")
103
104 - _post_phase_cmds = portage._post_phase_cmds
105 -
106 def _start(self):
107
108 ebuild_process = EbuildProcess(background=self.background,
109 @@ -39,7 +40,7 @@
110 encoding=_encodings['fs'], errors='strict'),
111 mode='a', encoding=_encodings['content'], errors='replace')
112 try:
113 - portage._check_build_log(self.settings, out=out)
114 + _check_build_log(self.settings, out=out)
115 msg = _unicode_decode(out.getvalue(),
116 encoding=_encodings['content'], errors='replace')
117 if msg:
118 @@ -66,12 +67,12 @@
119 encoding=_encodings['fs'], errors='strict'),
120 mode='a', encoding=_encodings['content'], errors='replace')
121 out = log_file
122 - portage._post_src_install_chost_fix(settings)
123 - portage._post_src_install_uid_fix(settings, out=out)
124 + _post_src_install_chost_fix(settings)
125 + _post_src_install_uid_fix(settings, out=out)
126 if log_file is not None:
127 log_file.close()
128
129 - post_phase_cmds = self._post_phase_cmds.get(self.phase)
130 + post_phase_cmds = _post_phase_cmds.get(self.phase)
131 if post_phase_cmds is not None:
132 post_phase = MiscFunctionsProcess(background=self.background,
133 commands=post_phase_cmds, phase=self.phase, pkg=self.pkg,
134
135 Modified: main/branches/prefix/pym/_emerge/EbuildProcess.py
136 ===================================================================
137 --- main/branches/prefix/pym/_emerge/EbuildProcess.py 2010-02-27 04:35:02 UTC (rev 15477)
138 +++ main/branches/prefix/pym/_emerge/EbuildProcess.py 2010-02-27 18:30:51 UTC (rev 15478)
139 @@ -3,8 +3,9 @@
140 # $Id$
141
142 from _emerge.AbstractEbuildProcess import AbstractEbuildProcess
143 -import portage
144 from portage import os
145 +from portage.package.ebuild.doebuild import doebuild, \
146 + _doebuild_exit_status_check_and_log, _post_phase_userpriv_perms
147
148 class EbuildProcess(AbstractEbuildProcess):
149
150 @@ -26,8 +27,9 @@
151 settings = self.settings
152 ebuild_path = settings["EBUILD"]
153 debug = settings.get("PORTAGE_DEBUG") == "1"
154 +
155
156 - rval = portage.doebuild(ebuild_path, self.phase,
157 + rval = doebuild(ebuild_path, self.phase,
158 root_config.root, settings, debug,
159 mydbapi=mydbapi, tree=tree, **kwargs)
160
161 @@ -37,12 +39,12 @@
162 AbstractEbuildProcess._set_returncode(self, wait_retval)
163
164 if self.phase not in ("clean", "cleanrm"):
165 - self.returncode = portage._doebuild_exit_status_check_and_log(
166 + self.returncode = _doebuild_exit_status_check_and_log(
167 self.settings, self.phase, self.returncode)
168
169 if self.phase == "test" and self.returncode != os.EX_OK and \
170 "test-fail-continue" in self.settings.features:
171 self.returncode = os.EX_OK
172
173 - portage._post_phase_userpriv_perms(self.settings)
174 + _post_phase_userpriv_perms(self.settings)
175
176
177 Modified: main/branches/prefix/pym/_emerge/MiscFunctionsProcess.py
178 ===================================================================
179 --- main/branches/prefix/pym/_emerge/MiscFunctionsProcess.py 2010-02-27 04:35:02 UTC (rev 15477)
180 +++ main/branches/prefix/pym/_emerge/MiscFunctionsProcess.py 2010-02-27 18:30:51 UTC (rev 15478)
181 @@ -5,6 +5,8 @@
182 from _emerge.AbstractEbuildProcess import AbstractEbuildProcess
183 import portage
184 from portage import os
185 +from portage.package.ebuild.doebuild import spawn, \
186 + _doebuild_exit_status_check_and_log, _doebuild_exit_status_unlink
187
188 class MiscFunctionsProcess(AbstractEbuildProcess):
189 """
190 @@ -23,7 +25,7 @@
191 self.args = [portage._shell_quote(misc_sh_binary)] + self.commands
192 self.logfile = settings.get("PORTAGE_LOG_FILE")
193
194 - portage._doebuild_exit_status_unlink(
195 + _doebuild_exit_status_unlink(
196 settings.get("EBUILD_EXIT_STATUS_FILE"))
197
198 AbstractEbuildProcess._start(self)
199 @@ -31,11 +33,11 @@
200 def _spawn(self, args, **kwargs):
201 settings = self.settings
202 debug = settings.get("PORTAGE_DEBUG") == "1"
203 - return portage.spawn(" ".join(args), settings,
204 + return spawn(" ".join(args), settings,
205 debug=debug, **kwargs)
206
207 def _set_returncode(self, wait_retval):
208 AbstractEbuildProcess._set_returncode(self, wait_retval)
209 - self.returncode = portage._doebuild_exit_status_check_and_log(
210 + self.returncode = _doebuild_exit_status_check_and_log(
211 self.settings, self.phase, self.returncode)
212
213
214 Modified: main/branches/prefix/pym/_emerge/depgraph.py
215 ===================================================================
216 --- main/branches/prefix/pym/_emerge/depgraph.py 2010-02-27 04:35:02 UTC (rev 15477)
217 +++ main/branches/prefix/pym/_emerge/depgraph.py 2010-02-27 18:30:51 UTC (rev 15478)
218 @@ -141,6 +141,10 @@
219 # uninstallation but may not have been added to the graph
220 # if the graph is not complete yet.
221 self._blocked_world_pkgs = {}
222 + # Contains packages whose dependencies have been traversed.
223 + # This use used to check if we have accounted for blockers
224 + # relevant to a package.
225 + self._traversed_pkg_deps = set()
226 self._slot_collision_info = {}
227 # Slot collision nodes are not allowed to block other packages since
228 # blocker validation is only able to account for one package per slot.
229 @@ -1211,6 +1215,7 @@
230 return 0
231 finally:
232 portage.dep._dep_check_strict = True
233 + self._dynamic_config._traversed_pkg_deps.add(pkg)
234 return 1
235
236 def _add_pkg_dep_string(self, pkg, dep_root, dep_priority, dep_string,
237 @@ -2848,6 +2853,8 @@
238 cpv = pkg.cpv
239 stale_cache.discard(cpv)
240 pkg_in_graph = self._dynamic_config.digraph.contains(pkg)
241 + pkg_deps_added = \
242 + pkg in self._dynamic_config._traversed_pkg_deps
243
244 # Check for masked installed packages. Only warn about
245 # packages that are in the graph in order to avoid warning
246 @@ -2864,7 +2871,7 @@
247
248 blocker_atoms = None
249 blockers = None
250 - if pkg_in_graph:
251 + if pkg_deps_added:
252 blockers = []
253 try:
254 blockers.extend(
255
256 Modified: main/branches/prefix/pym/portage/__init__.py
257 ===================================================================
258 --- main/branches/prefix/pym/portage/__init__.py 2010-02-27 04:35:02 UTC (rev 15477)
259 +++ main/branches/prefix/pym/portage/__init__.py 2010-02-27 18:30:51 UTC (rev 15478)
260 @@ -102,9 +102,12 @@
261 'portage.manifest:Manifest',
262 'portage.output',
263 'portage.output:bold,colorize',
264 + 'portage.package.ebuild.doebuild:doebuild,' + \
265 + 'doebuild_environment,spawn,spawnebuild',
266 'portage.package.ebuild.config:autouse,best_from_dict,' + \
267 'check_config_instance,config',
268 'portage.package.ebuild.fetch:fetch',
269 + 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
270 'portage.process',
271 'portage.process:atexit_register,run_exitfuncs',
272 'portage.update:dep_transform,fixdbentries,grab_updates,' + \
273 @@ -1014,6 +1017,7 @@
274
275 return (version,None)
276
277 +<<<<<<< .working
278
279
280
281 @@ -1396,6 +1400,8 @@
282 return retval >> 8
283 return retval
284
285 +=======
286 +>>>>>>> .merge-right.r15449
287 def digestgen(myarchives=None, mysettings=None,
288 overwrite=None, manifestonly=None, myportdb=None):
289 """
290 @@ -1739,500 +1745,6 @@
291 return 0
292 return 1
293
294 -# parse actionmap to spawn ebuild with the appropriate args
295 -def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0,
296 - logfile=None, fd_pipes=None, returnpid=False):
297 - if not returnpid and \
298 - (alwaysdep or "noauto" not in mysettings.features):
299 - # process dependency first
300 - if "dep" in actionmap[mydo]:
301 - retval = spawnebuild(actionmap[mydo]["dep"], actionmap,
302 - mysettings, debug, alwaysdep=alwaysdep, logfile=logfile,
303 - fd_pipes=fd_pipes, returnpid=returnpid)
304 - if retval:
305 - return retval
306 -
307 - eapi = mysettings["EAPI"]
308 -
309 - if mydo == "configure" and eapi in ("0", "1"):
310 - return os.EX_OK
311 -
312 - if mydo == "prepare" and eapi in ("0", "1"):
313 - return os.EX_OK
314 -
315 - if mydo == "pretend" and eapi in ("0", "1", "2", "3", "3_pre2"):
316 - return os.EX_OK
317 -
318 - kwargs = actionmap[mydo]["args"]
319 - mysettings["EBUILD_PHASE"] = mydo
320 - _doebuild_exit_status_unlink(
321 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
322 -
323 - try:
324 - phase_retval = spawn(actionmap[mydo]["cmd"] % mydo,
325 - mysettings, debug=debug, logfile=logfile,
326 - fd_pipes=fd_pipes, returnpid=returnpid, **kwargs)
327 - finally:
328 - mysettings["EBUILD_PHASE"] = ""
329 -
330 - if returnpid:
331 - return phase_retval
332 -
333 - msg = _doebuild_exit_status_check(mydo, mysettings)
334 - if msg:
335 - if phase_retval == os.EX_OK:
336 - phase_retval = 1
337 - from textwrap import wrap
338 - from portage.elog.messages import eerror
339 - for l in wrap(msg, 72):
340 - eerror(l, phase=mydo, key=mysettings.mycpv)
341 -
342 - _post_phase_userpriv_perms(mysettings)
343 - if mydo == "install":
344 - out = StringIO()
345 - _check_build_log(mysettings, out=out)
346 - msg = _unicode_decode(out.getvalue(),
347 - encoding=_encodings['content'], errors='replace')
348 - if msg:
349 - writemsg_stdout(msg, noiselevel=-1)
350 - if logfile is not None:
351 - try:
352 - f = codecs.open(_unicode_encode(logfile,
353 - encoding=_encodings['fs'], errors='strict'),
354 - mode='a', encoding=_encodings['content'],
355 - errors='replace')
356 - except EnvironmentError:
357 - pass
358 - else:
359 - f.write(msg)
360 - f.close()
361 - if phase_retval == os.EX_OK:
362 - _post_src_install_chost_fix(mysettings)
363 - phase_retval = _post_src_install_checks(mysettings)
364 -
365 - if mydo == "test" and phase_retval != os.EX_OK and \
366 - "test-fail-continue" in mysettings.features:
367 - phase_retval = os.EX_OK
368 -
369 - return phase_retval
370 -
371 -_post_phase_cmds = {
372 -
373 - "install" : [
374 - "install_qa_check",
375 - "install_symlink_html_docs"],
376 -
377 - "preinst" : [
378 - "preinst_aix",
379 - "preinst_bsdflags",
380 - "preinst_sfperms",
381 - "preinst_selinux_labels",
382 - "preinst_suid_scan",
383 - "preinst_mask"],
384 -
385 - "postinst" : [
386 - "postinst_aix",
387 - "postinst_bsdflags"]
388 -}
389 -
390 -def _post_phase_userpriv_perms(mysettings):
391 - if "userpriv" in mysettings.features and secpass >= 2:
392 - """ Privileged phases may have left files that need to be made
393 - writable to a less privileged user."""
394 - apply_recursive_permissions(mysettings["T"],
395 - uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
396 - filemode=0o60, filemask=0)
397 -
398 -def _post_src_install_checks(mysettings):
399 - _post_src_install_uid_fix(mysettings)
400 - global _post_phase_cmds
401 - retval = _spawn_misc_sh(mysettings, _post_phase_cmds["install"],
402 - phase='internal_post_src_install')
403 - if retval != os.EX_OK:
404 - writemsg(_("!!! install_qa_check failed; exiting.\n"),
405 - noiselevel=-1)
406 - return retval
407 -
408 -def _check_build_log(mysettings, out=None):
409 - """
410 - Search the content of $PORTAGE_LOG_FILE if it exists
411 - and generate the following QA Notices when appropriate:
412 -
413 - * Automake "maintainer mode"
414 - * command not found
415 - * Unrecognized configure options
416 - """
417 - logfile = mysettings.get("PORTAGE_LOG_FILE")
418 - if logfile is None:
419 - return
420 - try:
421 - f = codecs.open(_unicode_encode(logfile,
422 - encoding=_encodings['fs'], errors='strict'),
423 - mode='r', encoding=_encodings['content'], errors='replace')
424 - except EnvironmentError:
425 - return
426 -
427 - am_maintainer_mode = []
428 - bash_command_not_found = []
429 - bash_command_not_found_re = re.compile(
430 - r'(.*): line (\d*): (.*): command not found$')
431 - command_not_found_exclude_re = re.compile(r'/configure: line ')
432 - helper_missing_file = []
433 - helper_missing_file_re = re.compile(
434 - r'^!!! (do|new).*: .* does not exist$')
435 -
436 - configure_opts_warn = []
437 - configure_opts_warn_re = re.compile(
438 - r'^configure: WARNING: [Uu]nrecognized options: ')
439 -
440 - # Exclude output from dev-libs/yaz-3.0.47 which looks like this:
441 - #
442 - #Configuration:
443 - # Automake: ${SHELL} /var/tmp/portage/dev-libs/yaz-3.0.47/work/yaz-3.0.47/config/missing --run automake-1.10
444 - am_maintainer_mode_re = re.compile(r'/missing --run ')
445 - am_maintainer_mode_exclude_re = \
446 - re.compile(r'(/missing --run (autoheader|makeinfo)|^\s*Automake:\s)')
447 -
448 - make_jobserver_re = \
449 - re.compile(r'g?make\[\d+\]: warning: jobserver unavailable:')
450 - make_jobserver = []
451 -
452 - try:
453 - for line in f:
454 - if am_maintainer_mode_re.search(line) is not None and \
455 - am_maintainer_mode_exclude_re.search(line) is None:
456 - am_maintainer_mode.append(line.rstrip("\n"))
457 -
458 - if bash_command_not_found_re.match(line) is not None and \
459 - command_not_found_exclude_re.search(line) is None:
460 - bash_command_not_found.append(line.rstrip("\n"))
461 -
462 - if helper_missing_file_re.match(line) is not None:
463 - helper_missing_file.append(line.rstrip("\n"))
464 -
465 - if configure_opts_warn_re.match(line) is not None:
466 - configure_opts_warn.append(line.rstrip("\n"))
467 -
468 - if make_jobserver_re.match(line) is not None:
469 - make_jobserver.append(line.rstrip("\n"))
470 -
471 - finally:
472 - f.close()
473 -
474 - from portage.elog.messages import eqawarn
475 - def _eqawarn(lines):
476 - for line in lines:
477 - eqawarn(line, phase="install", key=mysettings.mycpv, out=out)
478 - from textwrap import wrap
479 - wrap_width = 70
480 -
481 - if am_maintainer_mode:
482 - msg = [_("QA Notice: Automake \"maintainer mode\" detected:")]
483 - msg.append("")
484 - msg.extend("\t" + line for line in am_maintainer_mode)
485 - msg.append("")
486 - msg.extend(wrap(_(
487 - "If you patch Makefile.am, "
488 - "configure.in, or configure.ac then you "
489 - "should use autotools.eclass and "
490 - "eautomake or eautoreconf. Exceptions "
491 - "are limited to system packages "
492 - "for which it is impossible to run "
493 - "autotools during stage building. "
494 - "See http://www.gentoo.org/p"
495 - "roj/en/qa/autofailure.xml for more information."),
496 - wrap_width))
497 - _eqawarn(msg)
498 -
499 - if bash_command_not_found:
500 - msg = [_("QA Notice: command not found:")]
501 - msg.append("")
502 - msg.extend("\t" + line for line in bash_command_not_found)
503 - _eqawarn(msg)
504 -
505 - if helper_missing_file:
506 - msg = [_("QA Notice: file does not exist:")]
507 - msg.append("")
508 - msg.extend("\t" + line[4:] for line in helper_missing_file)
509 - _eqawarn(msg)
510 -
511 - if configure_opts_warn:
512 - msg = [_("QA Notice: Unrecognized configure options:")]
513 - msg.append("")
514 - msg.extend("\t" + line for line in configure_opts_warn)
515 - _eqawarn(msg)
516 -
517 - if make_jobserver:
518 - msg = [_("QA Notice: make jobserver unavailable:")]
519 - msg.append("")
520 - msg.extend("\t" + line for line in make_jobserver)
521 - _eqawarn(msg)
522 -
523 -def _post_src_install_chost_fix(settings):
524 - """
525 - It's possible that the ebuild has changed the
526 - CHOST variable, so revert it to the initial
527 - setting.
528 - """
529 - if settings.get('CATEGORY') == 'virtual':
530 - return
531 -
532 - chost = settings.get('CHOST')
533 - if chost:
534 - write_atomic(os.path.join(settings['PORTAGE_BUILDDIR'],
535 - 'build-info', 'CHOST'), chost + '\n')
536 -
537 -_vdb_use_conditional_keys = ('DEPEND', 'LICENSE', 'PDEPEND',
538 - 'PROPERTIES', 'PROVIDE', 'RDEPEND', 'RESTRICT',)
539 -_vdb_use_conditional_atoms = frozenset(['DEPEND', 'PDEPEND', 'RDEPEND'])
540 -
541 -def _post_src_install_uid_fix(mysettings, out=None):
542 - """
543 - Files in $D with user and group bits that match the "portage"
544 - user or group are automatically mapped to PORTAGE_INST_UID and
545 - PORTAGE_INST_GID if necessary. The chown system call may clear
546 - S_ISUID and S_ISGID bits, so those bits are restored if
547 - necessary.
548 - """
549 -
550 - os = _os_merge
551 -
552 - inst_uid = int(mysettings["PORTAGE_INST_UID"])
553 - inst_gid = int(mysettings["PORTAGE_INST_GID"])
554 -
555 - if bsd_chflags:
556 - # Temporarily remove all of the flags in order to avoid EPERM errors.
557 - os.system("mtree -c -p %s -k flags > %s" % \
558 - (_shell_quote(mysettings["D"]),
559 - _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree"))))
560 - os.system("chflags -R noschg,nouchg,nosappnd,nouappnd %s" % \
561 - (_shell_quote(mysettings["D"]),))
562 - os.system("chflags -R nosunlnk,nouunlnk %s 2>/dev/null" % \
563 - (_shell_quote(mysettings["D"]),))
564 -
565 - destdir = mysettings["D"]
566 - unicode_errors = []
567 -
568 - while True:
569 -
570 - unicode_error = False
571 - size = 0
572 - counted_inodes = set()
573 -
574 - for parent, dirs, files in os.walk(destdir):
575 - try:
576 - parent = _unicode_decode(parent,
577 - encoding=_encodings['merge'], errors='strict')
578 - except UnicodeDecodeError:
579 - new_parent = _unicode_decode(parent,
580 - encoding=_encodings['merge'], errors='replace')
581 - new_parent = _unicode_encode(new_parent,
582 - encoding=_encodings['merge'], errors='backslashreplace')
583 - new_parent = _unicode_decode(new_parent,
584 - encoding=_encodings['merge'], errors='replace')
585 - os.rename(parent, new_parent)
586 - unicode_error = True
587 - unicode_errors.append(new_parent[len(destdir):])
588 - break
589 -
590 - for fname in chain(dirs, files):
591 - try:
592 - fname = _unicode_decode(fname,
593 - encoding=_encodings['merge'], errors='strict')
594 - except UnicodeDecodeError:
595 - fpath = _os.path.join(
596 - parent.encode(_encodings['merge']), fname)
597 - new_fname = _unicode_decode(fname,
598 - encoding=_encodings['merge'], errors='replace')
599 - new_fname = _unicode_encode(new_fname,
600 - encoding=_encodings['merge'], errors='backslashreplace')
601 - new_fname = _unicode_decode(new_fname,
602 - encoding=_encodings['merge'], errors='replace')
603 - new_fpath = os.path.join(parent, new_fname)
604 - os.rename(fpath, new_fpath)
605 - unicode_error = True
606 - unicode_errors.append(new_fpath[len(destdir):])
607 - fname = new_fname
608 - fpath = new_fpath
609 - else:
610 - fpath = os.path.join(parent, fname)
611 -
612 - mystat = os.lstat(fpath)
613 - if stat.S_ISREG(mystat.st_mode) and \
614 - mystat.st_ino not in counted_inodes:
615 - counted_inodes.add(mystat.st_ino)
616 - size += mystat.st_size
617 - if mystat.st_uid != portage_uid and \
618 - mystat.st_gid != portage_gid:
619 - continue
620 - myuid = -1
621 - mygid = -1
622 - if mystat.st_uid == portage_uid:
623 - myuid = inst_uid
624 - if mystat.st_gid == portage_gid:
625 - mygid = inst_gid
626 - apply_secpass_permissions(
627 - _unicode_encode(fpath, encoding=_encodings['merge']),
628 - uid=myuid, gid=mygid,
629 - mode=mystat.st_mode, stat_cached=mystat,
630 - follow_links=False)
631 -
632 - if unicode_error:
633 - break
634 -
635 - if not unicode_error:
636 - break
637 -
638 - if unicode_errors:
639 - from portage.elog.messages import eerror
640 - for l in _merge_unicode_error(unicode_errors):
641 - eerror(l, phase='install', key=mysettings.mycpv, out=out)
642 -
643 - build_info_dir = os.path.join(mysettings['PORTAGE_BUILDDIR'],
644 - 'build-info')
645 -
646 - codecs.open(_unicode_encode(os.path.join(build_info_dir,
647 - 'SIZE'), encoding=_encodings['fs'], errors='strict'),
648 - 'w', encoding=_encodings['repo.content'],
649 - errors='strict').write(str(size) + '\n')
650 -
651 - codecs.open(_unicode_encode(os.path.join(build_info_dir,
652 - 'BUILD_TIME'), encoding=_encodings['fs'], errors='strict'),
653 - 'w', encoding=_encodings['repo.content'],
654 - errors='strict').write(str(int(time.time())) + '\n')
655 -
656 - use = frozenset(mysettings['PORTAGE_USE'].split())
657 - for k in _vdb_use_conditional_keys:
658 - v = mysettings.configdict['pkg'].get(k)
659 - if v is None:
660 - continue
661 - v = dep.paren_reduce(v)
662 - v = dep.use_reduce(v, uselist=use)
663 - v = dep.paren_normalize(v)
664 - v = dep.paren_enclose(v)
665 - if not v:
666 - continue
667 - if v in _vdb_use_conditional_atoms:
668 - v_split = []
669 - for x in v.split():
670 - try:
671 - x = dep.Atom(x)
672 - except exception.InvalidAtom:
673 - v_split.append(x)
674 - else:
675 - v_split.append(str(x.evaluate_conditionals(use)))
676 - v = ' '.join(v_split)
677 - codecs.open(_unicode_encode(os.path.join(build_info_dir,
678 - k), encoding=_encodings['fs'], errors='strict'),
679 - mode='w', encoding=_encodings['repo.content'],
680 - errors='strict').write(v + '\n')
681 -
682 - if bsd_chflags:
683 - # Restore all of the flags saved above.
684 - os.system("mtree -e -p %s -U -k flags < %s > /dev/null" % \
685 - (_shell_quote(mysettings["D"]),
686 - _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree"))))
687 -
688 -def _merge_unicode_error(errors):
689 - from textwrap import wrap
690 - lines = []
691 -
692 - msg = _("This package installs one or more file names containing "
693 - "characters that do not match your current locale "
694 - "settings. The current setting for filesystem encoding is '%s'.") \
695 - % _encodings['merge']
696 - lines.extend(wrap(msg, 72))
697 -
698 - lines.append("")
699 - errors.sort()
700 - lines.extend("\t" + x for x in errors)
701 - lines.append("")
702 -
703 - if _encodings['merge'].lower().replace('_', '').replace('-', '') != 'utf8':
704 - msg = _("For best results, UTF-8 encoding is recommended. See "
705 - "the Gentoo Linux Localization Guide for instructions "
706 - "about how to configure your locale for UTF-8 encoding:")
707 - lines.extend(wrap(msg, 72))
708 - lines.append("")
709 - lines.append("\t" + \
710 - "http://www.gentoo.org/doc/en/guide-localization.xml")
711 - lines.append("")
712 -
713 - return lines
714 -
715 -def _post_pkg_preinst_cmd(mysettings):
716 - """
717 - Post phase logic and tasks that have been factored out of
718 - ebuild.sh. Call preinst_mask last so that INSTALL_MASK can
719 - can be used to wipe out any gmon.out files created during
720 - previous functions (in case any tools were built with -pg
721 - in CFLAGS).
722 - """
723 -
724 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
725 - misc_sh_binary = os.path.join(portage_bin_path,
726 - os.path.basename(MISC_SH_BINARY))
727 -
728 - mysettings["EBUILD_PHASE"] = ""
729 - global _post_phase_cmds
730 - myargs = [_shell_quote(misc_sh_binary)] + _post_phase_cmds["preinst"]
731 -
732 - return myargs
733 -
734 -def _post_pkg_postinst_cmd(mysettings):
735 - """
736 - Post phase logic and tasks that have been factored out of
737 - build.sh.
738 - """
739 -
740 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
741 - misc_sh_binary = os.path.join(portage_bin_path,
742 - os.path.basename(MISC_SH_BINARY))
743 -
744 - mysettings["EBUILD_PHASE"] = ""
745 - global _post_phase_cmds
746 - myargs = [_shell_quote(misc_sh_binary)] + _post_phase_cmds["postinst"]
747 -
748 - return myargs
749 -
750 -def _spawn_misc_sh(mysettings, commands, phase=None, **kwargs):
751 - """
752 - @param mysettings: the ebuild config
753 - @type mysettings: config
754 - @param commands: a list of function names to call in misc-functions.sh
755 - @type commands: list
756 - @rtype: int
757 - @returns: the return value from the spawn() call
758 - """
759 -
760 - # Note: PORTAGE_BIN_PATH may differ from the global
761 - # constant when portage is reinstalling itself.
762 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
763 - misc_sh_binary = os.path.join(portage_bin_path,
764 - os.path.basename(MISC_SH_BINARY))
765 - mycommand = " ".join([_shell_quote(misc_sh_binary)] + commands)
766 - _doebuild_exit_status_unlink(
767 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
768 - debug = mysettings.get("PORTAGE_DEBUG") == "1"
769 - logfile = mysettings.get("PORTAGE_LOG_FILE")
770 - mysettings.pop("EBUILD_PHASE", None)
771 - try:
772 - rval = spawn(mycommand, mysettings, debug=debug,
773 - logfile=logfile, **kwargs)
774 - finally:
775 - pass
776 -
777 - msg = _doebuild_exit_status_check(phase, mysettings)
778 - if msg:
779 - if rval == os.EX_OK:
780 - rval = 1
781 - from textwrap import wrap
782 - from portage.elog.messages import eerror
783 - for l in wrap(msg, 72):
784 - eerror(l, phase=mydo, key=mysettings.mycpv)
785 -
786 - return rval
787 -
788 _testing_eapis = frozenset()
789 _deprecated_eapis = frozenset(["3_pre2", "3_pre1", "2_pre3", "2_pre2", "2_pre1"])
790
791 @@ -2298,6 +1810,7 @@
792 return (None, None)
793 return (m.group(1), m.group(3))
794
795 +<<<<<<< .working
796 def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, mydbapi):
797
798 ebuild_path = os.path.abspath(myebuild)
799 @@ -3624,6 +3137,8 @@
800
801 expandcache={}
802
803 +=======
804 +>>>>>>> .merge-right.r15449
805 def _movefile(src, dest, **kwargs):
806 """Calls movefile and raises a PortageException if an error occurs."""
807 if movefile(src, dest, **kwargs) is None:
808 @@ -4858,14 +4373,14 @@
809
810 return rValue
811
812 -auxdbkeys=[
813 +auxdbkeys = (
814 'DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
815 'RESTRICT', 'HOMEPAGE', 'LICENSE', 'DESCRIPTION',
816 'KEYWORDS', 'INHERITED', 'IUSE', 'UNUSED_00',
817 'PDEPEND', 'PROVIDE', 'EAPI',
818 'PROPERTIES', 'DEFINED_PHASES', 'UNUSED_05', 'UNUSED_04',
819 'UNUSED_03', 'UNUSED_02', 'UNUSED_01',
820 - ]
821 +)
822 auxdbkeylen=len(auxdbkeys)
823
824 def pkgmerge(mytbz2, myroot, mysettings, mydbapi=None,
825
826 Modified: main/branches/prefix/pym/portage/dbapi/bintree.py
827 ===================================================================
828 --- main/branches/prefix/pym/portage/dbapi/bintree.py 2010-02-27 04:35:02 UTC (rev 15477)
829 +++ main/branches/prefix/pym/portage/dbapi/bintree.py 2010-02-27 18:30:51 UTC (rev 15478)
830 @@ -10,6 +10,7 @@
831 portage.proxy.lazyimport.lazyimport(globals(),
832 'portage.dep:dep_getkey,isjustname,match_from_list',
833 'portage.output:EOutput,colorize',
834 + 'portage.package.ebuild.doebuild:_vdb_use_conditional_atoms',
835 'portage.update:update_dbentries',
836 'portage.util:ensure_dirs,normalize_path,writemsg,writemsg_stdout',
837 'portage.versions:best,catpkgsplit,catsplit',
838 @@ -1068,7 +1069,7 @@
839 writemsg("%s: %s\n" % (k, str(e)),
840 noiselevel=-1)
841 raise
842 - if k in portage._vdb_use_conditional_atoms:
843 + if k in _vdb_use_conditional_atoms:
844 v_split = []
845 for x in deps.split():
846 try:
847
848 Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
849 ===================================================================
850 --- main/branches/prefix/pym/portage/dbapi/vartree.py 2010-02-27 04:35:02 UTC (rev 15477)
851 +++ main/branches/prefix/pym/portage/dbapi/vartree.py 2010-02-27 18:30:51 UTC (rev 15478)
852 @@ -17,6 +17,9 @@
853 'portage.elog:elog_process',
854 'portage.locks:lockdir,unlockdir',
855 'portage.output:bold,colorize',
856 + 'portage.package.ebuild.doebuild:doebuild,doebuild_environment,' + \
857 + '_spawn_misc_sh',
858 + 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
859 'portage.update:fixdbentries',
860 'portage.util:apply_secpass_permissions,ConfigProtect,ensure_dirs,' + \
861 'writemsg,writemsg_level,write_atomic,atomic_ofstream,writedict,' + \
862 @@ -34,7 +37,7 @@
863 from portage.localization import _
864
865 from portage import listdir, dep_expand, digraph, flatten, \
866 - doebuild_environment, doebuild, env_update, prepare_build_dirs, \
867 + env_update, \
868 abssymlink, movefile, _movefile, bsd_chflags, cpv_getkey
869
870 # This is a special version of the os module, wrapped for unicode support.
871
872 Copied: main/branches/prefix/pym/portage/package/ebuild/_pty.py (from rev 15449, main/trunk/pym/portage/package/ebuild/_pty.py)
873 ===================================================================
874 --- main/branches/prefix/pym/portage/package/ebuild/_pty.py (rev 0)
875 +++ main/branches/prefix/pym/portage/package/ebuild/_pty.py 2010-02-27 18:30:51 UTC (rev 15478)
876 @@ -0,0 +1,192 @@
877 +# Copyright 2010 Gentoo Foundation
878 +# Distributed under the terms of the GNU General Public License v2
879 +# $Id$
880 +
881 +import array
882 +import fcntl
883 +import platform
884 +import pty
885 +import select
886 +import sys
887 +import termios
888 +
889 +from portage import os, _unicode_decode, _unicode_encode
890 +from portage.process import spawn_bash
891 +from portage.util import writemsg
892 +
893 +def _can_test_pty_eof():
894 + """
895 + The _test_pty_eof() function seems to hang on most
896 + kernels other than Linux.
897 + This was reported for the following kernels which used to work fine
898 + without this EOF test: Darwin, AIX, FreeBSD. They seem to hang on
899 + the slave_file.close() call. Note that Python's implementation of
900 + openpty on Solaris already caused random hangs without this EOF test
901 + and hence is globally disabled.
902 + @rtype: bool
903 + @returns: True if _test_pty_eof() won't hang, False otherwise.
904 + """
905 + return platform.system() in ("Linux",)
906 +
907 +def _test_pty_eof():
908 + """
909 + Returns True if this issues is fixed for the currently
910 + running version of python: http://bugs.python.org/issue5380
911 + Raises an EnvironmentError from openpty() if it fails.
912 + """
913 +
914 + use_fork = False
915 +
916 + test_string = 2 * "blah blah blah\n"
917 + test_string = _unicode_decode(test_string,
918 + encoding='utf_8', errors='strict')
919 +
920 + # may raise EnvironmentError
921 + master_fd, slave_fd = pty.openpty()
922 +
923 + # Non-blocking mode is required for Darwin kernel.
924 + fcntl.fcntl(master_fd, fcntl.F_SETFL,
925 + fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
926 +
927 + # Disable post-processing of output since otherwise weird
928 + # things like \n -> \r\n transformations may occur.
929 + mode = termios.tcgetattr(slave_fd)
930 + mode[1] &= ~termios.OPOST
931 + termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
932 +
933 + # Simulate a subprocess writing some data to the
934 + # slave end of the pipe, and then exiting.
935 + pid = None
936 + if use_fork:
937 + pids = spawn_bash(_unicode_encode("echo -n '%s'" % test_string,
938 + encoding='utf_8', errors='strict'), env=os.environ,
939 + fd_pipes={0:sys.stdin.fileno(), 1:slave_fd, 2:slave_fd},
940 + returnpid=True)
941 + if isinstance(pids, int):
942 + os.close(master_fd)
943 + os.close(slave_fd)
944 + raise EnvironmentError('spawn failed')
945 + pid = pids[0]
946 + else:
947 + os.write(slave_fd, _unicode_encode(test_string,
948 + encoding='utf_8', errors='strict'))
949 + os.close(slave_fd)
950 +
951 + # If using a fork, we must wait for the child here,
952 + # in order to avoid a race condition that would
953 + # lead to inconsistent results.
954 + if pid is not None:
955 + os.waitpid(pid, 0)
956 +
957 + master_file = os.fdopen(master_fd, 'rb')
958 + eof = False
959 + data = []
960 + iwtd = [master_file]
961 + owtd = []
962 + ewtd = []
963 +
964 + while not eof:
965 +
966 + events = select.select(iwtd, owtd, ewtd)
967 + if not events[0]:
968 + eof = True
969 + break
970 +
971 + buf = array.array('B')
972 + try:
973 + buf.fromfile(master_file, 1024)
974 + except EOFError:
975 + eof = True
976 + except IOError:
977 + # This is where data loss occurs.
978 + eof = True
979 +
980 + if not buf:
981 + eof = True
982 + else:
983 + data.append(_unicode_decode(buf.tostring(),
984 + encoding='utf_8', errors='strict'))
985 +
986 + master_file.close()
987 +
988 + return test_string == ''.join(data)
989 +
990 +# If _test_pty_eof() can't be used for runtime detection of
991 +# http://bugs.python.org/issue5380, openpty can't safely be used
992 +# unless we can guarantee that the current version of python has
993 +# been fixed (affects all current versions of python3). When
994 +# this issue is fixed in python3, we can add another sys.hexversion
995 +# conditional to enable openpty support in the fixed versions.
996 +if sys.hexversion >= 0x3000000 and not _can_test_pty_eof():
997 + _disable_openpty = True
998 +else:
999 + # Disable the use of openpty on Solaris as it seems Python's openpty
1000 + # implementation doesn't play nice on Solaris with Portage's
1001 + # behaviour causing hangs/deadlocks.
1002 + # Additional note for the future: on Interix, pipes do NOT work, so
1003 + # _disable_openpty on Interix must *never* be True
1004 + _disable_openpty = platform.system() in ("SunOS",)
1005 +_tested_pty = False
1006 +
1007 +if not _can_test_pty_eof():
1008 + # Skip _test_pty_eof() on systems where it hangs.
1009 + _tested_pty = True
1010 +
1011 +def _create_pty_or_pipe(copy_term_size=None):
1012 + """
1013 + Try to create a pty and if then fails then create a normal
1014 + pipe instead.
1015 +
1016 + @param copy_term_size: If a tty file descriptor is given
1017 + then the term size will be copied to the pty.
1018 + @type copy_term_size: int
1019 + @rtype: tuple
1020 + @returns: A tuple of (is_pty, master_fd, slave_fd) where
1021 + is_pty is True if a pty was successfully allocated, and
1022 + False if a normal pipe was allocated.
1023 + """
1024 +
1025 + got_pty = False
1026 +
1027 + global _disable_openpty, _tested_pty
1028 + if not (_tested_pty or _disable_openpty):
1029 + try:
1030 + if not _test_pty_eof():
1031 + _disable_openpty = True
1032 + except EnvironmentError as e:
1033 + _disable_openpty = True
1034 + writemsg("openpty failed: '%s'\n" % str(e),
1035 + noiselevel=-1)
1036 + del e
1037 + _tested_pty = True
1038 +
1039 + if _disable_openpty:
1040 + master_fd, slave_fd = os.pipe()
1041 + else:
1042 + from pty import openpty
1043 + try:
1044 + master_fd, slave_fd = openpty()
1045 + got_pty = True
1046 + except EnvironmentError as e:
1047 + _disable_openpty = True
1048 + writemsg("openpty failed: '%s'\n" % str(e),
1049 + noiselevel=-1)
1050 + del e
1051 + master_fd, slave_fd = os.pipe()
1052 +
1053 + if got_pty:
1054 + # Disable post-processing of output since otherwise weird
1055 + # things like \n -> \r\n transformations may occur.
1056 + import termios
1057 + mode = termios.tcgetattr(slave_fd)
1058 + mode[1] &= ~termios.OPOST
1059 + termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
1060 +
1061 + if got_pty and \
1062 + copy_term_size is not None and \
1063 + os.isatty(copy_term_size):
1064 + from portage.output import get_term_size, set_term_size
1065 + rows, columns = get_term_size()
1066 + set_term_size(rows, columns, slave_fd)
1067 +
1068 + return (got_pty, master_fd, slave_fd)
1069
1070 Copied: main/branches/prefix/pym/portage/package/ebuild/doebuild.py (from rev 15449, main/trunk/pym/portage/package/ebuild/doebuild.py)
1071 ===================================================================
1072 --- main/branches/prefix/pym/portage/package/ebuild/doebuild.py (rev 0)
1073 +++ main/branches/prefix/pym/portage/package/ebuild/doebuild.py 2010-02-27 18:30:51 UTC (rev 15478)
1074 @@ -0,0 +1,1759 @@
1075 +# Copyright 2010 Gentoo Foundation
1076 +# Distributed under the terms of the GNU General Public License v2
1077 +# $Id$
1078 +
1079 +from __future__ import print_function
1080 +
1081 +__all__ = ['doebuild', 'doebuild_environment', 'spawn', 'spawnebuild']
1082 +
1083 +import codecs
1084 +import errno
1085 +from itertools import chain
1086 +import logging
1087 +import os as _os
1088 +import re
1089 +import shutil
1090 +import stat
1091 +import sys
1092 +from textwrap import wrap
1093 +import time
1094 +
1095 +import portage
1096 +portage.proxy.lazyimport.lazyimport(globals(),
1097 + 'portage.package.ebuild.config:check_config_instance',
1098 +)
1099 +
1100 +from portage import auxdbkeys, bsd_chflags, dep_check, digestcheck, digestgen, eapi_is_supported, ExtractKernelVersion, merge, os, selinux, StringIO, unmerge, _encodings, _parse_eapi_ebuild_head, _os_merge, _shell_quote, _split_ebuild_name_glep55, _unicode_decode, _unicode_encode
1101 +from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY
1102 +from portage.data import portage_gid, portage_uid, secpass, uid, userpriv_groups
1103 +from portage.dbapi.virtual import fakedbapi
1104 +from portage.dep import Atom, paren_enclose, paren_normalize, paren_reduce, use_reduce
1105 +from portage.elog import elog_process
1106 +from portage.elog.messages import eerror, eqawarn
1107 +from portage.exception import DigestException, FileNotFound, IncorrectParameter, InvalidAtom, InvalidDependString, PermissionDenied, UnsupportedAPIException
1108 +from portage.localization import _
1109 +from portage.manifest import Manifest
1110 +from portage.output import style_to_ansi_code
1111 +from portage.package.ebuild.fetch import fetch
1112 +from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs
1113 +from portage.package.ebuild._pty import _create_pty_or_pipe
1114 +from portage.util import apply_recursive_permissions, apply_secpass_permissions, noiselimit, normalize_path, writemsg, writemsg_stdout, write_atomic
1115 +from portage.versions import _pkgsplit
1116 +
1117 +def doebuild_environment(myebuild, mydo, myroot, mysettings,
1118 + debug, use_cache, mydbapi):
1119 +
1120 + ebuild_path = os.path.abspath(myebuild)
1121 + pkg_dir = os.path.dirname(ebuild_path)
1122 +
1123 + if "CATEGORY" in mysettings.configdict["pkg"]:
1124 + cat = mysettings.configdict["pkg"]["CATEGORY"]
1125 + else:
1126 + cat = os.path.basename(normalize_path(os.path.join(pkg_dir, "..")))
1127 +
1128 + eapi = None
1129 + if 'parse-eapi-glep-55' in mysettings.features:
1130 + mypv, eapi = _split_ebuild_name_glep55(
1131 + os.path.basename(myebuild))
1132 + else:
1133 + mypv = os.path.basename(ebuild_path)[:-7]
1134 +
1135 + mycpv = cat+"/"+mypv
1136 + mysplit = _pkgsplit(mypv)
1137 + if mysplit is None:
1138 + raise IncorrectParameter(
1139 + _("Invalid ebuild path: '%s'") % myebuild)
1140 +
1141 + # Make a backup of PORTAGE_TMPDIR prior to calling config.reset()
1142 + # so that the caller can override it.
1143 + tmpdir = mysettings["PORTAGE_TMPDIR"]
1144 +
1145 + if mydo == 'depend':
1146 + if mycpv != mysettings.mycpv:
1147 + # Don't pass in mydbapi here since the resulting aux_get
1148 + # call would lead to infinite 'depend' phase recursion.
1149 + mysettings.setcpv(mycpv)
1150 + else:
1151 + # If IUSE isn't in configdict['pkg'], it means that setcpv()
1152 + # hasn't been called with the mydb argument, so we have to
1153 + # call it here (portage code always calls setcpv properly,
1154 + # but api consumers might not).
1155 + if mycpv != mysettings.mycpv or \
1156 + 'IUSE' not in mysettings.configdict['pkg']:
1157 + # Reload env.d variables and reset any previous settings.
1158 + mysettings.reload()
1159 + mysettings.reset()
1160 + mysettings.setcpv(mycpv, mydb=mydbapi)
1161 +
1162 + # config.reset() might have reverted a change made by the caller,
1163 + # so restore it to it's original value.
1164 + mysettings["PORTAGE_TMPDIR"] = tmpdir
1165 +
1166 + mysettings.pop("EBUILD_PHASE", None) # remove from backupenv
1167 + mysettings["EBUILD_PHASE"] = mydo
1168 +
1169 + mysettings["PORTAGE_MASTER_PID"] = str(os.getpid())
1170 +
1171 + # We are disabling user-specific bashrc files.
1172 + mysettings["BASH_ENV"] = INVALID_ENV_FILE
1173 +
1174 + if debug: # Otherwise it overrides emerge's settings.
1175 + # We have no other way to set debug... debug can't be passed in
1176 + # due to how it's coded... Don't overwrite this so we can use it.
1177 + mysettings["PORTAGE_DEBUG"] = "1"
1178 +
1179 + mysettings["EBUILD"] = ebuild_path
1180 + mysettings["O"] = pkg_dir
1181 + mysettings.configdict["pkg"]["CATEGORY"] = cat
1182 + mysettings["FILESDIR"] = pkg_dir+"/files"
1183 + mysettings["PF"] = mypv
1184 +
1185 + if hasattr(mydbapi, '_repo_info'):
1186 + mytree = os.path.dirname(os.path.dirname(pkg_dir))
1187 + repo_info = mydbapi._repo_info[mytree]
1188 + mysettings['PORTDIR'] = repo_info.portdir
1189 + mysettings['PORTDIR_OVERLAY'] = repo_info.portdir_overlay
1190 +
1191 + mysettings["PORTDIR"] = os.path.realpath(mysettings["PORTDIR"])
1192 + mysettings["DISTDIR"] = os.path.realpath(mysettings["DISTDIR"])
1193 + mysettings["RPMDIR"] = os.path.realpath(mysettings["RPMDIR"])
1194 +
1195 + mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass"
1196 + mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_")
1197 +
1198 + mysettings["PROFILE_PATHS"] = "\n".join(mysettings.profiles)
1199 + mysettings["P"] = mysplit[0]+"-"+mysplit[1]
1200 + mysettings["PN"] = mysplit[0]
1201 + mysettings["PV"] = mysplit[1]
1202 + mysettings["PR"] = mysplit[2]
1203 +
1204 + if noiselimit < 0:
1205 + mysettings["PORTAGE_QUIET"] = "1"
1206 +
1207 + if mydo == 'depend' and \
1208 + 'EAPI' not in mysettings.configdict['pkg']:
1209 +
1210 + if eapi is not None:
1211 + # From parse-eapi-glep-55 above.
1212 + pass
1213 + elif 'parse-eapi-ebuild-head' in mysettings.features:
1214 + eapi = _parse_eapi_ebuild_head(
1215 + codecs.open(_unicode_encode(ebuild_path,
1216 + encoding=_encodings['fs'], errors='strict'),
1217 + mode='r', encoding=_encodings['content'], errors='replace'))
1218 +
1219 + if eapi is not None:
1220 + if not eapi_is_supported(eapi):
1221 + raise UnsupportedAPIException(mycpv, eapi)
1222 + mysettings.configdict['pkg']['EAPI'] = eapi
1223 +
1224 + if mydo != "depend":
1225 + # Metadata vars such as EAPI and RESTRICT are
1226 + # set by the above config.setcpv() call.
1227 + eapi = mysettings["EAPI"]
1228 + if not eapi_is_supported(eapi):
1229 + # can't do anything with this.
1230 + raise UnsupportedAPIException(mycpv, eapi)
1231 +
1232 + if mysplit[2] == "r0":
1233 + mysettings["PVR"]=mysplit[1]
1234 + else:
1235 + mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
1236 +
1237 + if "PATH" in mysettings:
1238 + mysplit=mysettings["PATH"].split(":")
1239 + else:
1240 + mysplit=[]
1241 + # Note: PORTAGE_BIN_PATH may differ from the global constant
1242 + # when portage is reinstalling itself.
1243 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1244 + if portage_bin_path not in mysplit:
1245 + mysettings["PATH"] = portage_bin_path + ":" + mysettings["PATH"]
1246 +
1247 + # Sandbox needs cannonical paths.
1248 + mysettings["PORTAGE_TMPDIR"] = os.path.realpath(
1249 + mysettings["PORTAGE_TMPDIR"])
1250 + mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
1251 + mysettings["PKG_TMPDIR"] = mysettings["PORTAGE_TMPDIR"]+"/binpkgs"
1252 +
1253 + # Package {pre,post}inst and {pre,post}rm may overlap, so they must have separate
1254 + # locations in order to prevent interference.
1255 + if mydo in ("unmerge", "prerm", "postrm", "cleanrm"):
1256 + mysettings["PORTAGE_BUILDDIR"] = os.path.join(
1257 + mysettings["PKG_TMPDIR"],
1258 + mysettings["CATEGORY"], mysettings["PF"])
1259 + else:
1260 + mysettings["PORTAGE_BUILDDIR"] = os.path.join(
1261 + mysettings["BUILD_PREFIX"],
1262 + mysettings["CATEGORY"], mysettings["PF"])
1263 +
1264 + mysettings["HOME"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "homedir")
1265 + mysettings["WORKDIR"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "work")
1266 + mysettings["D"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "image") + os.sep
1267 + mysettings["T"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "temp")
1268 +
1269 + # Prefix forward compatability
1270 + mysettings["ED"] = mysettings["D"]
1271 +
1272 + mysettings["PORTAGE_BASHRC"] = os.path.join(
1273 + mysettings["PORTAGE_CONFIGROOT"], EBUILD_SH_ENV_FILE)
1274 + mysettings["EBUILD_EXIT_STATUS_FILE"] = os.path.join(
1275 + mysettings["PORTAGE_BUILDDIR"], ".exit_status")
1276 +
1277 + #set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
1278 + if eapi not in ('0', '1', '2', '3', '3_pre2'):
1279 + # Discard KV for EAPIs that don't support it. Cache KV is restored
1280 + # from the backupenv whenever config.reset() is called.
1281 + mysettings.pop('KV', None)
1282 + elif mydo != 'depend' and 'KV' not in mysettings and \
1283 + mydo in ('compile', 'config', 'configure', 'info',
1284 + 'install', 'nofetch', 'postinst', 'postrm', 'preinst',
1285 + 'prepare', 'prerm', 'setup', 'test', 'unpack'):
1286 + mykv,err1=ExtractKernelVersion(os.path.join(myroot, "usr/src/linux"))
1287 + if mykv:
1288 + # Regular source tree
1289 + mysettings["KV"]=mykv
1290 + else:
1291 + mysettings["KV"]=""
1292 + mysettings.backup_changes("KV")
1293 +
1294 + # Allow color.map to control colors associated with einfo, ewarn, etc...
1295 + mycolors = []
1296 + for c in ("GOOD", "WARN", "BAD", "HILITE", "BRACKET"):
1297 + mycolors.append("%s=$'%s'" % \
1298 + (c, style_to_ansi_code(c)))
1299 + mysettings["PORTAGE_COLORMAP"] = "\n".join(mycolors)
1300 +
1301 +def _doebuild_exit_status_check(mydo, settings):
1302 + """
1303 + Returns an error string if the shell appeared
1304 + to exit unsuccessfully, None otherwise.
1305 + """
1306 + exit_status_file = settings.get("EBUILD_EXIT_STATUS_FILE")
1307 + if not exit_status_file or \
1308 + os.path.exists(exit_status_file):
1309 + return None
1310 + msg = _("The ebuild phase '%s' has exited "
1311 + "unexpectedly. This type of behavior "
1312 + "is known to be triggered "
1313 + "by things such as failed variable "
1314 + "assignments (bug #190128) or bad substitution "
1315 + "errors (bug #200313). Normally, before exiting, bash should "
1316 + "have displayed an error message above. If bash did not "
1317 + "produce an error message above, it's possible "
1318 + "that the ebuild has called `exit` when it "
1319 + "should have called `die` instead. This behavior may also "
1320 + "be triggered by a corrupt bash binary or a hardware "
1321 + "problem such as memory or cpu malfunction. If the problem is not "
1322 + "reproducible or it appears to occur randomly, then it is likely "
1323 + "to be triggered by a hardware problem. "
1324 + "If you suspect a hardware problem then you should "
1325 + "try some basic hardware diagnostics such as memtest. "
1326 + "Please do not report this as a bug unless it is consistently "
1327 + "reproducible and you are sure that your bash binary and hardware "
1328 + "are functioning properly.") % mydo
1329 + return msg
1330 +
1331 +def _doebuild_exit_status_check_and_log(settings, mydo, retval):
1332 + msg = _doebuild_exit_status_check(mydo, settings)
1333 + if msg:
1334 + if retval == os.EX_OK:
1335 + retval = 1
1336 + for l in wrap(msg, 72):
1337 + eerror(l, phase=mydo, key=settings.mycpv)
1338 + return retval
1339 +
1340 +def _doebuild_exit_status_unlink(exit_status_file):
1341 + """
1342 + Double check to make sure it really doesn't exist
1343 + and raise an OSError if it still does (it shouldn't).
1344 + OSError if necessary.
1345 + """
1346 + if not exit_status_file:
1347 + return
1348 + try:
1349 + os.unlink(exit_status_file)
1350 + except OSError:
1351 + pass
1352 + if os.path.exists(exit_status_file):
1353 + os.unlink(exit_status_file)
1354 +
1355 +_doebuild_manifest_exempt_depend = 0
1356 +_doebuild_manifest_cache = None
1357 +_doebuild_broken_ebuilds = set()
1358 +_doebuild_broken_manifests = set()
1359 +
1360 +def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
1361 + fetchonly=0, cleanup=0, dbkey=None, use_cache=1, fetchall=0, tree=None,
1362 + mydbapi=None, vartree=None, prev_mtimes=None,
1363 + fd_pipes=None, returnpid=False):
1364 +
1365 + """
1366 + Wrapper function that invokes specific ebuild phases through the spawning
1367 + of ebuild.sh
1368 +
1369 + @param myebuild: name of the ebuild to invoke the phase on (CPV)
1370 + @type myebuild: String
1371 + @param mydo: Phase to run
1372 + @type mydo: String
1373 + @param myroot: $ROOT (usually '/', see man make.conf)
1374 + @type myroot: String
1375 + @param mysettings: Portage Configuration
1376 + @type mysettings: instance of portage.config
1377 + @param debug: Turns on various debug information (eg, debug for spawn)
1378 + @type debug: Boolean
1379 + @param listonly: Used to wrap fetch(); passed such that fetch only lists files required.
1380 + @type listonly: Boolean
1381 + @param fetchonly: Used to wrap fetch(); passed such that files are only fetched (no other actions)
1382 + @type fetchonly: Boolean
1383 + @param cleanup: Passed to prepare_build_dirs (TODO: what does it do?)
1384 + @type cleanup: Boolean
1385 + @param dbkey: A dict (usually keys and values from the depend phase, such as KEYWORDS, USE, etc..)
1386 + @type dbkey: Dict or String
1387 + @param use_cache: Enables the cache
1388 + @type use_cache: Boolean
1389 + @param fetchall: Used to wrap fetch(), fetches all URIs (even ones invalid due to USE conditionals)
1390 + @type fetchall: Boolean
1391 + @param tree: Which tree to use ('vartree','porttree','bintree', etc..), defaults to 'porttree'
1392 + @type tree: String
1393 + @param mydbapi: a dbapi instance to pass to various functions; this should be a portdbapi instance.
1394 + @type mydbapi: portdbapi instance
1395 + @param vartree: A instance of vartree; used for aux_get calls, defaults to db[myroot]['vartree']
1396 + @type vartree: vartree instance
1397 + @param prev_mtimes: A dict of { filename:mtime } keys used by merge() to do config_protection
1398 + @type prev_mtimes: dictionary
1399 + @param fd_pipes: A dict of mapping for pipes, { '0': stdin, '1': stdout }
1400 + for example.
1401 + @type fd_pipes: Dictionary
1402 + @param returnpid: Return a list of process IDs for a successful spawn, or
1403 + an integer value if spawn is unsuccessful. NOTE: This requires the
1404 + caller clean up all returned PIDs.
1405 + @type returnpid: Boolean
1406 + @rtype: Boolean
1407 + @returns:
1408 + 1. 0 for success
1409 + 2. 1 for error
1410 +
1411 + Most errors have an accompanying error message.
1412 +
1413 + listonly and fetchonly are only really necessary for operations involving 'fetch'
1414 + prev_mtimes are only necessary for merge operations.
1415 + Other variables may not be strictly required, many have defaults that are set inside of doebuild.
1416 +
1417 + """
1418 +
1419 + if not tree:
1420 + writemsg("Warning: tree not specified to doebuild\n")
1421 + tree = "porttree"
1422 +
1423 + # chunked out deps for each phase, so that ebuild binary can use it
1424 + # to collapse targets down.
1425 + actionmap_deps={
1426 + "setup": [],
1427 + "unpack": ["setup"],
1428 + "prepare": ["unpack"],
1429 + "configure": ["prepare"],
1430 + "compile":["configure"],
1431 + "test": ["compile"],
1432 + "install":["test"],
1433 + "rpm": ["install"],
1434 + "package":["install"],
1435 + }
1436 +
1437 + if mydbapi is None:
1438 + mydbapi = portage.db[myroot][tree].dbapi
1439 +
1440 + if vartree is None and mydo in ("merge", "qmerge", "unmerge"):
1441 + vartree = portage.db[myroot]["vartree"]
1442 +
1443 + features = mysettings.features
1444 +
1445 + clean_phases = ("clean", "cleanrm")
1446 + validcommands = ["help","clean","prerm","postrm","cleanrm","preinst","postinst",
1447 + "config", "info", "setup", "depend", "pretend",
1448 + "fetch", "fetchall", "digest",
1449 + "unpack", "prepare", "configure", "compile", "test",
1450 + "install", "rpm", "qmerge", "merge",
1451 + "package","unmerge", "manifest"]
1452 +
1453 + if mydo not in validcommands:
1454 + validcommands.sort()
1455 + writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % mydo,
1456 + noiselevel=-1)
1457 + for vcount in range(len(validcommands)):
1458 + if vcount%6 == 0:
1459 + writemsg("\n!!! ", noiselevel=-1)
1460 + writemsg(validcommands[vcount].ljust(11), noiselevel=-1)
1461 + writemsg("\n", noiselevel=-1)
1462 + return 1
1463 +
1464 + if mydo == "fetchall":
1465 + fetchall = 1
1466 + mydo = "fetch"
1467 +
1468 + parallel_fetchonly = mydo in ("fetch", "fetchall") and \
1469 + "PORTAGE_PARALLEL_FETCHONLY" in mysettings
1470 +
1471 + if mydo not in clean_phases and not os.path.exists(myebuild):
1472 + writemsg("!!! doebuild: %s not found for %s\n" % (myebuild, mydo),
1473 + noiselevel=-1)
1474 + return 1
1475 +
1476 + global _doebuild_manifest_exempt_depend
1477 +
1478 + if "strict" in features and \
1479 + "digest" not in features and \
1480 + tree == "porttree" and \
1481 + mydo not in ("digest", "manifest", "help") and \
1482 + not _doebuild_manifest_exempt_depend:
1483 + # Always verify the ebuild checksums before executing it.
1484 + global _doebuild_manifest_cache, _doebuild_broken_ebuilds, \
1485 + _doebuild_broken_ebuilds
1486 +
1487 + if myebuild in _doebuild_broken_ebuilds:
1488 + return 1
1489 +
1490 + pkgdir = os.path.dirname(myebuild)
1491 + manifest_path = os.path.join(pkgdir, "Manifest")
1492 +
1493 + # Avoid checking the same Manifest several times in a row during a
1494 + # regen with an empty cache.
1495 + if _doebuild_manifest_cache is None or \
1496 + _doebuild_manifest_cache.getFullname() != manifest_path:
1497 + _doebuild_manifest_cache = None
1498 + if not os.path.exists(manifest_path):
1499 + out = portage.output.EOutput()
1500 + out.eerror(_("Manifest not found for '%s'") % (myebuild,))
1501 + _doebuild_broken_ebuilds.add(myebuild)
1502 + return 1
1503 + mf = Manifest(pkgdir, mysettings["DISTDIR"])
1504 +
1505 + else:
1506 + mf = _doebuild_manifest_cache
1507 +
1508 + try:
1509 + mf.checkFileHashes("EBUILD", os.path.basename(myebuild))
1510 + except KeyError:
1511 + out = portage.output.EOutput()
1512 + out.eerror(_("Missing digest for '%s'") % (myebuild,))
1513 + _doebuild_broken_ebuilds.add(myebuild)
1514 + return 1
1515 + except FileNotFound:
1516 + out = portage.output.EOutput()
1517 + out.eerror(_("A file listed in the Manifest "
1518 + "could not be found: '%s'") % (myebuild,))
1519 + _doebuild_broken_ebuilds.add(myebuild)
1520 + return 1
1521 + except DigestException as e:
1522 + out = portage.output.EOutput()
1523 + out.eerror(_("Digest verification failed:"))
1524 + out.eerror("%s" % e.value[0])
1525 + out.eerror(_("Reason: %s") % e.value[1])
1526 + out.eerror(_("Got: %s") % e.value[2])
1527 + out.eerror(_("Expected: %s") % e.value[3])
1528 + _doebuild_broken_ebuilds.add(myebuild)
1529 + return 1
1530 +
1531 + if mf.getFullname() in _doebuild_broken_manifests:
1532 + return 1
1533 +
1534 + if mf is not _doebuild_manifest_cache:
1535 +
1536 + # Make sure that all of the ebuilds are
1537 + # actually listed in the Manifest.
1538 + glep55 = 'parse-eapi-glep-55' in mysettings.features
1539 + for f in os.listdir(pkgdir):
1540 + pf = None
1541 + if glep55:
1542 + pf, eapi = _split_ebuild_name_glep55(f)
1543 + elif f[-7:] == '.ebuild':
1544 + pf = f[:-7]
1545 + if pf is not None and not mf.hasFile("EBUILD", f):
1546 + f = os.path.join(pkgdir, f)
1547 + if f not in _doebuild_broken_ebuilds:
1548 + out = portage.output.EOutput()
1549 + out.eerror(_("A file is not listed in the "
1550 + "Manifest: '%s'") % (f,))
1551 + _doebuild_broken_manifests.add(manifest_path)
1552 + return 1
1553 +
1554 + # Only cache it if the above stray files test succeeds.
1555 + _doebuild_manifest_cache = mf
1556 +
1557 + def exit_status_check(retval):
1558 + msg = _doebuild_exit_status_check(mydo, mysettings)
1559 + if msg:
1560 + if retval == os.EX_OK:
1561 + retval = 1
1562 + for l in wrap(msg, 72):
1563 + eerror(l, phase=mydo, key=mysettings.mycpv)
1564 + return retval
1565 +
1566 + # Note: PORTAGE_BIN_PATH may differ from the global
1567 + # constant when portage is reinstalling itself.
1568 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1569 + ebuild_sh_binary = os.path.join(portage_bin_path,
1570 + os.path.basename(EBUILD_SH_BINARY))
1571 + misc_sh_binary = os.path.join(portage_bin_path,
1572 + os.path.basename(MISC_SH_BINARY))
1573 +
1574 + logfile=None
1575 + builddir_lock = None
1576 + tmpdir = None
1577 + tmpdir_orig = None
1578 +
1579 + try:
1580 + if mydo in ("digest", "manifest", "help"):
1581 + # Temporarily exempt the depend phase from manifest checks, in case
1582 + # aux_get calls trigger cache generation.
1583 + _doebuild_manifest_exempt_depend += 1
1584 +
1585 + # If we don't need much space and we don't need a constant location,
1586 + # we can temporarily override PORTAGE_TMPDIR with a random temp dir
1587 + # so that there's no need for locking and it can be used even if the
1588 + # user isn't in the portage group.
1589 + if mydo in ("info",):
1590 + from tempfile import mkdtemp
1591 + tmpdir = mkdtemp()
1592 + tmpdir_orig = mysettings["PORTAGE_TMPDIR"]
1593 + mysettings["PORTAGE_TMPDIR"] = tmpdir
1594 +
1595 + doebuild_environment(myebuild, mydo, myroot, mysettings, debug,
1596 + use_cache, mydbapi)
1597 +
1598 + if mydo in clean_phases:
1599 + retval = spawn(_shell_quote(ebuild_sh_binary) + " clean",
1600 + mysettings, debug=debug, fd_pipes=fd_pipes, free=1,
1601 + logfile=None, returnpid=returnpid)
1602 + return retval
1603 +
1604 + restrict = set(mysettings.get('PORTAGE_RESTRICT', '').split())
1605 + # get possible slot information from the deps file
1606 + if mydo == "depend":
1607 + writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
1608 + droppriv = "userpriv" in mysettings.features
1609 + if returnpid:
1610 + mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
1611 + mysettings, fd_pipes=fd_pipes, returnpid=True,
1612 + droppriv=droppriv)
1613 + return mypids
1614 + elif isinstance(dbkey, dict):
1615 + mysettings["dbkey"] = ""
1616 + pr, pw = os.pipe()
1617 + fd_pipes = {
1618 + 0:sys.stdin.fileno(),
1619 + 1:sys.stdout.fileno(),
1620 + 2:sys.stderr.fileno(),
1621 + 9:pw}
1622 + mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
1623 + mysettings,
1624 + fd_pipes=fd_pipes, returnpid=True, droppriv=droppriv)
1625 + os.close(pw) # belongs exclusively to the child process now
1626 + f = os.fdopen(pr, 'rb')
1627 + for k, v in zip(auxdbkeys,
1628 + (_unicode_decode(line).rstrip('\n') for line in f)):
1629 + dbkey[k] = v
1630 + f.close()
1631 + retval = os.waitpid(mypids[0], 0)[1]
1632 + portage.process.spawned_pids.remove(mypids[0])
1633 + # If it got a signal, return the signal that was sent, but
1634 + # shift in order to distinguish it from a return value. (just
1635 + # like portage.process.spawn() would do).
1636 + if retval & 0xff:
1637 + retval = (retval & 0xff) << 8
1638 + else:
1639 + # Otherwise, return its exit code.
1640 + retval = retval >> 8
1641 + if retval == os.EX_OK and len(dbkey) != len(auxdbkeys):
1642 + # Don't trust bash's returncode if the
1643 + # number of lines is incorrect.
1644 + retval = 1
1645 + return retval
1646 + elif dbkey:
1647 + mysettings["dbkey"] = dbkey
1648 + else:
1649 + mysettings["dbkey"] = \
1650 + os.path.join(mysettings.depcachedir, "aux_db_key_temp")
1651 +
1652 + return spawn(_shell_quote(ebuild_sh_binary) + " depend",
1653 + mysettings,
1654 + droppriv=droppriv)
1655 +
1656 + # Validate dependency metadata here to ensure that ebuilds with invalid
1657 + # data are never installed via the ebuild command. Don't bother when
1658 + # returnpid == True since there's no need to do this every time emerge
1659 + # executes a phase.
1660 + if not returnpid:
1661 + rval = _validate_deps(mysettings, myroot, mydo, mydbapi)
1662 + if rval != os.EX_OK:
1663 + return rval
1664 +
1665 + if "PORTAGE_TMPDIR" not in mysettings or \
1666 + not os.path.isdir(mysettings["PORTAGE_TMPDIR"]):
1667 + writemsg(_("The directory specified in your "
1668 + "PORTAGE_TMPDIR variable, '%s',\n"
1669 + "does not exist. Please create this directory or "
1670 + "correct your PORTAGE_TMPDIR setting.\n") % mysettings.get("PORTAGE_TMPDIR", ""), noiselevel=-1)
1671 + return 1
1672 +
1673 + # as some people use a separate PORTAGE_TMPDIR mount
1674 + # we prefer that as the checks below would otherwise be pointless
1675 + # for those people.
1676 + if os.path.exists(os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")):
1677 + checkdir = os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")
1678 + else:
1679 + checkdir = mysettings["PORTAGE_TMPDIR"]
1680 +
1681 + if not os.access(checkdir, os.W_OK):
1682 + writemsg(_("%s is not writable.\n"
1683 + "Likely cause is that you've mounted it as readonly.\n") % checkdir,
1684 + noiselevel=-1)
1685 + return 1
1686 + else:
1687 + from tempfile import NamedTemporaryFile
1688 + fd = NamedTemporaryFile(prefix="exectest-", dir=checkdir)
1689 + os.chmod(fd.name, 0o755)
1690 + if not os.access(fd.name, os.X_OK):
1691 + writemsg(_("Can not execute files in %s\n"
1692 + "Likely cause is that you've mounted it with one of the\n"
1693 + "following mount options: 'noexec', 'user', 'users'\n\n"
1694 + "Please make sure that portage can execute files in this directory.\n") % checkdir,
1695 + noiselevel=-1)
1696 + fd.close()
1697 + return 1
1698 + fd.close()
1699 + del checkdir
1700 +
1701 + if mydo == "unmerge":
1702 + return unmerge(mysettings["CATEGORY"],
1703 + mysettings["PF"], myroot, mysettings, vartree=vartree)
1704 +
1705 + # Build directory creation isn't required for any of these.
1706 + # In the fetch phase, the directory is needed only for RESTRICT=fetch
1707 + # in order to satisfy the sane $PWD requirement (from bug #239560)
1708 + # when pkg_nofetch is spawned.
1709 + have_build_dirs = False
1710 + if not parallel_fetchonly and \
1711 + mydo not in ('digest', 'help', 'manifest') and \
1712 + not (mydo == 'fetch' and 'fetch' not in restrict):
1713 + mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
1714 + if mystatus:
1715 + return mystatus
1716 + have_build_dirs = True
1717 +
1718 + # emerge handles logging externally
1719 + if not returnpid:
1720 + # PORTAGE_LOG_FILE is set by the
1721 + # above prepare_build_dirs() call.
1722 + logfile = mysettings.get("PORTAGE_LOG_FILE")
1723 +
1724 + if have_build_dirs:
1725 + env_file = os.path.join(mysettings["T"], "environment")
1726 + env_stat = None
1727 + saved_env = None
1728 + try:
1729 + env_stat = os.stat(env_file)
1730 + except OSError as e:
1731 + if e.errno != errno.ENOENT:
1732 + raise
1733 + del e
1734 + if not env_stat:
1735 + saved_env = os.path.join(
1736 + os.path.dirname(myebuild), "environment.bz2")
1737 + if not os.path.isfile(saved_env):
1738 + saved_env = None
1739 + if saved_env:
1740 + retval = os.system(
1741 + "bzip2 -dc %s > %s" % \
1742 + (_shell_quote(saved_env),
1743 + _shell_quote(env_file)))
1744 + try:
1745 + env_stat = os.stat(env_file)
1746 + except OSError as e:
1747 + if e.errno != errno.ENOENT:
1748 + raise
1749 + del e
1750 + if os.WIFEXITED(retval) and \
1751 + os.WEXITSTATUS(retval) == os.EX_OK and \
1752 + env_stat and env_stat.st_size > 0:
1753 + # This is a signal to ebuild.sh, so that it knows to filter
1754 + # out things like SANDBOX_{DENY,PREDICT,READ,WRITE} that
1755 + # would be preserved between normal phases.
1756 + open(_unicode_encode(env_file + '.raw'), 'w')
1757 + else:
1758 + writemsg(_("!!! Error extracting saved "
1759 + "environment: '%s'\n") % \
1760 + saved_env, noiselevel=-1)
1761 + try:
1762 + os.unlink(env_file)
1763 + except OSError as e:
1764 + if e.errno != errno.ENOENT:
1765 + raise
1766 + del e
1767 + env_stat = None
1768 + if env_stat:
1769 + pass
1770 + else:
1771 + for var in ("ARCH", ):
1772 + value = mysettings.get(var)
1773 + if value and value.strip():
1774 + continue
1775 + msg = _("%(var)s is not set... "
1776 + "Are you missing the '%(configroot)setc/make.profile' symlink? "
1777 + "Is the symlink correct? "
1778 + "Is your portage tree complete?") % \
1779 + {"var": var, "configroot": mysettings["PORTAGE_CONFIGROOT"]}
1780 + for line in wrap(msg, 70):
1781 + eerror(line, phase="setup", key=mysettings.mycpv)
1782 + elog_process(mysettings.mycpv, mysettings)
1783 + return 1
1784 + del env_file, env_stat, saved_env
1785 + _doebuild_exit_status_unlink(
1786 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
1787 + else:
1788 + mysettings.pop("EBUILD_EXIT_STATUS_FILE", None)
1789 +
1790 + # if any of these are being called, handle them -- running them out of
1791 + # the sandbox -- and stop now.
1792 + if mydo == "help":
1793 + return spawn(_shell_quote(ebuild_sh_binary) + " " + mydo,
1794 + mysettings, debug=debug, free=1, logfile=logfile)
1795 + elif mydo == "setup":
1796 + retval = spawn(
1797 + _shell_quote(ebuild_sh_binary) + " " + mydo, mysettings,
1798 + debug=debug, free=1, logfile=logfile, fd_pipes=fd_pipes,
1799 + returnpid=returnpid)
1800 + if returnpid:
1801 + return retval
1802 + retval = exit_status_check(retval)
1803 + if secpass >= 2:
1804 + """ Privileged phases may have left files that need to be made
1805 + writable to a less privileged user."""
1806 + apply_recursive_permissions(mysettings["T"],
1807 + uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
1808 + filemode=0o60, filemask=0)
1809 + return retval
1810 + elif mydo == "preinst":
1811 + phase_retval = spawn(
1812 + _shell_quote(ebuild_sh_binary) + " " + mydo,
1813 + mysettings, debug=debug, free=1, logfile=logfile,
1814 + fd_pipes=fd_pipes, returnpid=returnpid)
1815 +
1816 + if returnpid:
1817 + return phase_retval
1818 +
1819 + phase_retval = exit_status_check(phase_retval)
1820 + if phase_retval == os.EX_OK:
1821 + _doebuild_exit_status_unlink(
1822 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
1823 + mysettings.pop("EBUILD_PHASE", None)
1824 + phase_retval = spawn(
1825 + " ".join(_post_pkg_preinst_cmd(mysettings)),
1826 + mysettings, debug=debug, free=1, logfile=logfile)
1827 + phase_retval = exit_status_check(phase_retval)
1828 + if phase_retval != os.EX_OK:
1829 + writemsg(_("!!! post preinst failed; exiting.\n"),
1830 + noiselevel=-1)
1831 + return phase_retval
1832 + elif mydo == "postinst":
1833 + phase_retval = spawn(
1834 + _shell_quote(ebuild_sh_binary) + " " + mydo,
1835 + mysettings, debug=debug, free=1, logfile=logfile,
1836 + fd_pipes=fd_pipes, returnpid=returnpid)
1837 +
1838 + if returnpid:
1839 + return phase_retval
1840 +
1841 + phase_retval = exit_status_check(phase_retval)
1842 + if phase_retval == os.EX_OK:
1843 + _doebuild_exit_status_unlink(
1844 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
1845 + mysettings.pop("EBUILD_PHASE", None)
1846 + phase_retval = spawn(" ".join(_post_pkg_postinst_cmd(mysettings)),
1847 + mysettings, debug=debug, free=1, logfile=logfile)
1848 + phase_retval = exit_status_check(phase_retval)
1849 + if phase_retval != os.EX_OK:
1850 + writemsg(_("!!! post postinst failed; exiting.\n"),
1851 + noiselevel=-1)
1852 + return phase_retval
1853 + elif mydo in ("prerm", "postrm", "config", "info"):
1854 + retval = spawn(
1855 + _shell_quote(ebuild_sh_binary) + " " + mydo,
1856 + mysettings, debug=debug, free=1, logfile=logfile,
1857 + fd_pipes=fd_pipes, returnpid=returnpid)
1858 +
1859 + if returnpid:
1860 + return retval
1861 +
1862 + retval = exit_status_check(retval)
1863 + return retval
1864 +
1865 + mycpv = "/".join((mysettings["CATEGORY"], mysettings["PF"]))
1866 +
1867 + emerge_skip_distfiles = returnpid
1868 + emerge_skip_digest = returnpid
1869 + # Only try and fetch the files if we are going to need them ...
1870 + # otherwise, if user has FEATURES=noauto and they run `ebuild clean
1871 + # unpack compile install`, we will try and fetch 4 times :/
1872 + need_distfiles = not emerge_skip_distfiles and \
1873 + (mydo in ("fetch", "unpack") or \
1874 + mydo not in ("digest", "manifest") and "noauto" not in features)
1875 + alist = mysettings.configdict["pkg"].get("A")
1876 + aalist = mysettings.configdict["pkg"].get("AA")
1877 + if alist is None or aalist is None:
1878 + # Make sure we get the correct tree in case there are overlays.
1879 + mytree = os.path.realpath(
1880 + os.path.dirname(os.path.dirname(mysettings["O"])))
1881 + useflags = mysettings["PORTAGE_USE"].split()
1882 + try:
1883 + alist = mydbapi.getFetchMap(mycpv, useflags=useflags,
1884 + mytree=mytree)
1885 + aalist = mydbapi.getFetchMap(mycpv, mytree=mytree)
1886 + except InvalidDependString as e:
1887 + writemsg("!!! %s\n" % str(e), noiselevel=-1)
1888 + writemsg(_("!!! Invalid SRC_URI for '%s'.\n") % mycpv,
1889 + noiselevel=-1)
1890 + del e
1891 + return 1
1892 + mysettings.configdict["pkg"]["A"] = " ".join(alist)
1893 + mysettings.configdict["pkg"]["AA"] = " ".join(aalist)
1894 + else:
1895 + alist = set(alist.split())
1896 + aalist = set(aalist.split())
1897 + if ("mirror" in features) or fetchall:
1898 + fetchme = aalist
1899 + checkme = aalist
1900 + else:
1901 + fetchme = alist
1902 + checkme = alist
1903 +
1904 + if mydo == "fetch":
1905 + # Files are already checked inside fetch(),
1906 + # so do not check them again.
1907 + checkme = []
1908 +
1909 + if not emerge_skip_distfiles and \
1910 + need_distfiles and not fetch(
1911 + fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
1912 + return 1
1913 +
1914 + if mydo == "fetch" and listonly:
1915 + return 0
1916 +
1917 + try:
1918 + if mydo == "manifest":
1919 + return not digestgen(mysettings=mysettings, myportdb=mydbapi)
1920 + elif mydo == "digest":
1921 + return not digestgen(mysettings=mysettings, myportdb=mydbapi)
1922 + elif mydo != 'fetch' and not emerge_skip_digest and \
1923 + "digest" in mysettings.features:
1924 + # Don't do this when called by emerge or when called just
1925 + # for fetch (especially parallel-fetch) since it's not needed
1926 + # and it can interfere with parallel tasks.
1927 + digestgen(mysettings=mysettings, myportdb=mydbapi)
1928 + except PermissionDenied as e:
1929 + writemsg(_("!!! Permission Denied: %s\n") % (e,), noiselevel=-1)
1930 + if mydo in ("digest", "manifest"):
1931 + return 1
1932 +
1933 + # See above comment about fetching only when needed
1934 + if not emerge_skip_distfiles and \
1935 + not digestcheck(checkme, mysettings, "strict" in features):
1936 + return 1
1937 +
1938 + if mydo == "fetch":
1939 + return 0
1940 +
1941 + # remove PORTAGE_ACTUAL_DISTDIR once cvs/svn is supported via SRC_URI
1942 + if (mydo != "setup" and "noauto" not in features) or mydo == "unpack":
1943 + orig_distdir = mysettings["DISTDIR"]
1944 + mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir
1945 + edpath = mysettings["DISTDIR"] = \
1946 + os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir")
1947 + portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0o755)
1948 +
1949 + # Remove any unexpected files or directories.
1950 + for x in os.listdir(edpath):
1951 + symlink_path = os.path.join(edpath, x)
1952 + st = os.lstat(symlink_path)
1953 + if x in alist and stat.S_ISLNK(st.st_mode):
1954 + continue
1955 + if stat.S_ISDIR(st.st_mode):
1956 + shutil.rmtree(symlink_path)
1957 + else:
1958 + os.unlink(symlink_path)
1959 +
1960 + # Check for existing symlinks and recreate if necessary.
1961 + for x in alist:
1962 + symlink_path = os.path.join(edpath, x)
1963 + target = os.path.join(orig_distdir, x)
1964 + try:
1965 + link_target = os.readlink(symlink_path)
1966 + except OSError:
1967 + os.symlink(target, symlink_path)
1968 + else:
1969 + if link_target != target:
1970 + os.unlink(symlink_path)
1971 + os.symlink(target, symlink_path)
1972 +
1973 + #initial dep checks complete; time to process main commands
1974 +
1975 + restrict = mysettings["PORTAGE_RESTRICT"].split()
1976 + nosandbox = (("userpriv" in features) and \
1977 + ("usersandbox" not in features) and \
1978 + "userpriv" not in restrict and \
1979 + "nouserpriv" not in restrict)
1980 + if nosandbox and ("userpriv" not in features or \
1981 + "userpriv" in restrict or \
1982 + "nouserpriv" in restrict):
1983 + nosandbox = ("sandbox" not in features and \
1984 + "usersandbox" not in features)
1985 +
1986 + if not portage.process.sandbox_capable:
1987 + nosandbox = True
1988 +
1989 + sesandbox = mysettings.selinux_enabled() and \
1990 + "sesandbox" in mysettings.features
1991 +
1992 + droppriv = "userpriv" in mysettings.features and \
1993 + "userpriv" not in restrict and \
1994 + secpass >= 2
1995 +
1996 + fakeroot = "fakeroot" in mysettings.features
1997 +
1998 + ebuild_sh = _shell_quote(ebuild_sh_binary) + " %s"
1999 + misc_sh = _shell_quote(misc_sh_binary) + " dyn_%s"
2000 +
2001 + # args are for the to spawn function
2002 + actionmap = {
2003 +"pretend": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1, "sesandbox":0, "fakeroot":0}},
2004 +"setup": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1, "sesandbox":0, "fakeroot":0}},
2005 +"unpack": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0, "sesandbox":sesandbox, "fakeroot":0}},
2006 +"prepare": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0, "sesandbox":sesandbox, "fakeroot":0}},
2007 +"configure":{"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
2008 +"compile": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
2009 +"test": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
2010 +"install": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":0, "sesandbox":sesandbox, "fakeroot":fakeroot}},
2011 +"rpm": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":fakeroot}},
2012 +"package": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":fakeroot}},
2013 + }
2014 +
2015 + # merge the deps in so we have again a 'full' actionmap
2016 + # be glad when this can die.
2017 + for x in actionmap:
2018 + if len(actionmap_deps.get(x, [])):
2019 + actionmap[x]["dep"] = ' '.join(actionmap_deps[x])
2020 +
2021 + if mydo in actionmap:
2022 + if mydo == "package":
2023 + # Make sure the package directory exists before executing
2024 + # this phase. This can raise PermissionDenied if
2025 + # the current user doesn't have write access to $PKGDIR.
2026 + parent_dir = os.path.join(mysettings["PKGDIR"],
2027 + mysettings["CATEGORY"])
2028 + portage.util.ensure_dirs(parent_dir)
2029 + if not os.access(parent_dir, os.W_OK):
2030 + raise PermissionDenied(
2031 + "access('%s', os.W_OK)" % parent_dir)
2032 + retval = spawnebuild(mydo,
2033 + actionmap, mysettings, debug, logfile=logfile,
2034 + fd_pipes=fd_pipes, returnpid=returnpid)
2035 + elif mydo=="qmerge":
2036 + # check to ensure install was run. this *only* pops up when users
2037 + # forget it and are using ebuild
2038 + if not os.path.exists(
2039 + os.path.join(mysettings["PORTAGE_BUILDDIR"], ".installed")):
2040 + writemsg(_("!!! mydo=qmerge, but the install phase has not been run\n"),
2041 + noiselevel=-1)
2042 + return 1
2043 + # qmerge is a special phase that implies noclean.
2044 + if "noclean" not in mysettings.features:
2045 + mysettings.features.add("noclean")
2046 + #qmerge is specifically not supposed to do a runtime dep check
2047 + retval = merge(
2048 + mysettings["CATEGORY"], mysettings["PF"], mysettings["D"],
2049 + os.path.join(mysettings["PORTAGE_BUILDDIR"], "build-info"),
2050 + myroot, mysettings, myebuild=mysettings["EBUILD"], mytree=tree,
2051 + mydbapi=mydbapi, vartree=vartree, prev_mtimes=prev_mtimes)
2052 + elif mydo=="merge":
2053 + retval = spawnebuild("install", actionmap, mysettings, debug,
2054 + alwaysdep=1, logfile=logfile, fd_pipes=fd_pipes,
2055 + returnpid=returnpid)
2056 + retval = exit_status_check(retval)
2057 + if retval != os.EX_OK:
2058 + # The merge phase handles this already. Callers don't know how
2059 + # far this function got, so we have to call elog_process() here
2060 + # so that it's only called once.
2061 + from portage.elog import elog_process
2062 + elog_process(mysettings.mycpv, mysettings)
2063 + if retval == os.EX_OK:
2064 + retval = merge(mysettings["CATEGORY"], mysettings["PF"],
2065 + mysettings["D"], os.path.join(mysettings["PORTAGE_BUILDDIR"],
2066 + "build-info"), myroot, mysettings,
2067 + myebuild=mysettings["EBUILD"], mytree=tree, mydbapi=mydbapi,
2068 + vartree=vartree, prev_mtimes=prev_mtimes)
2069 + else:
2070 + print(_("!!! Unknown mydo: %s") % mydo)
2071 + return 1
2072 +
2073 + return retval
2074 +
2075 + finally:
2076 +
2077 + if tmpdir:
2078 + mysettings["PORTAGE_TMPDIR"] = tmpdir_orig
2079 + shutil.rmtree(tmpdir)
2080 + if builddir_lock:
2081 + portage.locks.unlockdir(builddir_lock)
2082 +
2083 + # Make sure that DISTDIR is restored to it's normal value before we return!
2084 + if "PORTAGE_ACTUAL_DISTDIR" in mysettings:
2085 + mysettings["DISTDIR"] = mysettings["PORTAGE_ACTUAL_DISTDIR"]
2086 + del mysettings["PORTAGE_ACTUAL_DISTDIR"]
2087 +
2088 + if logfile:
2089 + try:
2090 + if os.stat(logfile).st_size == 0:
2091 + os.unlink(logfile)
2092 + except OSError:
2093 + pass
2094 +
2095 + if mydo in ("digest", "manifest", "help"):
2096 + # If necessary, depend phase has been triggered by aux_get calls
2097 + # and the exemption is no longer needed.
2098 + _doebuild_manifest_exempt_depend -= 1
2099 +
2100 +def _validate_deps(mysettings, myroot, mydo, mydbapi):
2101 +
2102 + invalid_dep_exempt_phases = \
2103 + set(["clean", "cleanrm", "help", "prerm", "postrm"])
2104 + dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
2105 + misc_keys = ["LICENSE", "PROPERTIES", "PROVIDE", "RESTRICT", "SRC_URI"]
2106 + other_keys = ["SLOT"]
2107 + all_keys = dep_keys + misc_keys + other_keys
2108 + metadata = dict(zip(all_keys,
2109 + mydbapi.aux_get(mysettings.mycpv, all_keys)))
2110 +
2111 + class FakeTree(object):
2112 + def __init__(self, mydb):
2113 + self.dbapi = mydb
2114 + dep_check_trees = {myroot:{}}
2115 + dep_check_trees[myroot]["porttree"] = \
2116 + FakeTree(fakedbapi(settings=mysettings))
2117 +
2118 + msgs = []
2119 + for dep_type in dep_keys:
2120 + mycheck = dep_check(metadata[dep_type], None, mysettings,
2121 + myuse="all", myroot=myroot, trees=dep_check_trees)
2122 + if not mycheck[0]:
2123 + msgs.append(" %s: %s\n %s\n" % (
2124 + dep_type, metadata[dep_type], mycheck[1]))
2125 +
2126 + for k in misc_keys:
2127 + try:
2128 + use_reduce(
2129 + paren_reduce(metadata[k]), matchall=True)
2130 + except InvalidDependString as e:
2131 + msgs.append(" %s: %s\n %s\n" % (
2132 + k, metadata[k], str(e)))
2133 +
2134 + if not metadata["SLOT"]:
2135 + msgs.append(_(" SLOT is undefined\n"))
2136 +
2137 + if msgs:
2138 + portage.util.writemsg_level(_("Error(s) in metadata for '%s':\n") % \
2139 + (mysettings.mycpv,), level=logging.ERROR, noiselevel=-1)
2140 + for x in msgs:
2141 + portage.util.writemsg_level(x,
2142 + level=logging.ERROR, noiselevel=-1)
2143 + if mydo not in invalid_dep_exempt_phases:
2144 + return 1
2145 +
2146 + return os.EX_OK
2147 +
2148 +# XXX This would be to replace getstatusoutput completely.
2149 +# XXX Issue: cannot block execution. Deadlock condition.
2150 +def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakeroot=0, **keywords):
2151 + """
2152 + Spawn a subprocess with extra portage-specific options.
2153 + Optiosn include:
2154 +
2155 + Sandbox: Sandbox means the spawned process will be limited in its ability t
2156 + read and write files (normally this means it is restricted to ${D}/)
2157 + SElinux Sandbox: Enables sandboxing on SElinux
2158 + Reduced Privileges: Drops privilages such that the process runs as portage:portage
2159 + instead of as root.
2160 +
2161 + Notes: os.system cannot be used because it messes with signal handling. Instead we
2162 + use the portage.process spawn* family of functions.
2163 +
2164 + This function waits for the process to terminate.
2165 +
2166 + @param mystring: Command to run
2167 + @type mystring: String
2168 + @param mysettings: Either a Dict of Key,Value pairs or an instance of portage.config
2169 + @type mysettings: Dictionary or config instance
2170 + @param debug: Ignored
2171 + @type debug: Boolean
2172 + @param free: Enable sandboxing for this process
2173 + @type free: Boolean
2174 + @param droppriv: Drop to portage:portage when running this command
2175 + @type droppriv: Boolean
2176 + @param sesandbox: Enable SELinux Sandboxing (toggles a context switch)
2177 + @type sesandbox: Boolean
2178 + @param fakeroot: Run this command with faked root privileges
2179 + @type fakeroot: Boolean
2180 + @param keywords: Extra options encoded as a dict, to be passed to spawn
2181 + @type keywords: Dictionary
2182 + @rtype: Integer
2183 + @returns:
2184 + 1. The return code of the spawned process.
2185 + """
2186 +
2187 + if isinstance(mysettings, dict):
2188 + env=mysettings
2189 + keywords["opt_name"]="[ %s ]" % "portage"
2190 + else:
2191 + check_config_instance(mysettings)
2192 + env=mysettings.environ()
2193 + if mysettings.mycpv is not None:
2194 + keywords["opt_name"] = "[%s]" % mysettings.mycpv
2195 + else:
2196 + keywords["opt_name"] = "[%s/%s]" % \
2197 + (mysettings.get("CATEGORY",""), mysettings.get("PF",""))
2198 +
2199 + fd_pipes = keywords.get("fd_pipes")
2200 + if fd_pipes is None:
2201 + fd_pipes = {
2202 + 0:sys.stdin.fileno(),
2203 + 1:sys.stdout.fileno(),
2204 + 2:sys.stderr.fileno(),
2205 + }
2206 + # In some cases the above print statements don't flush stdout, so
2207 + # it needs to be flushed before allowing a child process to use it
2208 + # so that output always shows in the correct order.
2209 + stdout_filenos = (sys.stdout.fileno(), sys.stderr.fileno())
2210 + for fd in fd_pipes.values():
2211 + if fd in stdout_filenos:
2212 + sys.stdout.flush()
2213 + sys.stderr.flush()
2214 + break
2215 +
2216 + # The default policy for the sesandbox domain only allows entry (via exec)
2217 + # from shells and from binaries that belong to portage (the number of entry
2218 + # points is minimized). The "tee" binary is not among the allowed entry
2219 + # points, so it is spawned outside of the sesandbox domain and reads from a
2220 + # pseudo-terminal that connects two domains.
2221 + logfile = keywords.get("logfile")
2222 + mypids = []
2223 + master_fd = None
2224 + slave_fd = None
2225 + fd_pipes_orig = None
2226 + got_pty = False
2227 + if logfile:
2228 + del keywords["logfile"]
2229 + if 1 not in fd_pipes or 2 not in fd_pipes:
2230 + raise ValueError(fd_pipes)
2231 +
2232 + got_pty, master_fd, slave_fd = \
2233 + _create_pty_or_pipe(copy_term_size=fd_pipes[1])
2234 +
2235 + if not got_pty and 'sesandbox' in mysettings.features \
2236 + and mysettings.selinux_enabled():
2237 + # With sesandbox, logging works through a pty but not through a
2238 + # normal pipe. So, disable logging if ptys are broken.
2239 + # See Bug #162404.
2240 + logfile = None
2241 + os.close(master_fd)
2242 + master_fd = None
2243 + os.close(slave_fd)
2244 + slave_fd = None
2245 +
2246 + if logfile:
2247 +
2248 + fd_pipes.setdefault(0, sys.stdin.fileno())
2249 + fd_pipes_orig = fd_pipes.copy()
2250 +
2251 + # We must set non-blocking mode before we close the slave_fd
2252 + # since otherwise the fcntl call can fail on FreeBSD (the child
2253 + # process might have already exited and closed slave_fd so we
2254 + # have to keep it open in order to avoid FreeBSD potentially
2255 + # generating an EAGAIN exception).
2256 + import fcntl
2257 + fcntl.fcntl(master_fd, fcntl.F_SETFL,
2258 + fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
2259 +
2260 + fd_pipes[0] = fd_pipes_orig[0]
2261 + fd_pipes[1] = slave_fd
2262 + fd_pipes[2] = slave_fd
2263 + keywords["fd_pipes"] = fd_pipes
2264 +
2265 + features = mysettings.features
2266 + # TODO: Enable fakeroot to be used together with droppriv. The
2267 + # fake ownership/permissions will have to be converted to real
2268 + # permissions in the merge phase.
2269 + fakeroot = fakeroot and uid != 0 and portage.process.fakeroot_capable
2270 + if droppriv and not uid and portage_gid and portage_uid:
2271 + keywords.update({"uid":portage_uid,"gid":portage_gid,
2272 + "groups":userpriv_groups,"umask":0o02})
2273 + if not free:
2274 + free=((droppriv and "usersandbox" not in features) or \
2275 + (not droppriv and "sandbox" not in features and \
2276 + "usersandbox" not in features and not fakeroot))
2277 +
2278 + if not free and not (fakeroot or portage.process.sandbox_capable):
2279 + free = True
2280 +
2281 + if free or "SANDBOX_ACTIVE" in os.environ:
2282 + keywords["opt_name"] += " bash"
2283 + spawn_func = portage.process.spawn_bash
2284 + elif fakeroot:
2285 + keywords["opt_name"] += " fakeroot"
2286 + keywords["fakeroot_state"] = os.path.join(mysettings["T"], "fakeroot.state")
2287 + spawn_func = portage.process.spawn_fakeroot
2288 + else:
2289 + keywords["opt_name"] += " sandbox"
2290 + spawn_func = portage.process.spawn_sandbox
2291 +
2292 + if sesandbox:
2293 + spawn_func = selinux.spawn_wrapper(spawn_func,
2294 + mysettings["PORTAGE_SANDBOX_T"])
2295 +
2296 + returnpid = keywords.get("returnpid")
2297 + keywords["returnpid"] = True
2298 + try:
2299 + mypids.extend(spawn_func(mystring, env=env, **keywords))
2300 + finally:
2301 + if logfile:
2302 + os.close(slave_fd)
2303 +
2304 + if returnpid:
2305 + return mypids
2306 +
2307 + if logfile:
2308 + log_file = open(_unicode_encode(logfile), mode='ab')
2309 + apply_secpass_permissions(logfile,
2310 + uid=portage_uid, gid=portage_gid, mode=0o664)
2311 + stdout_file = os.fdopen(os.dup(fd_pipes_orig[1]), 'wb')
2312 + master_file = os.fdopen(master_fd, 'rb')
2313 + iwtd = [master_file]
2314 + owtd = []
2315 + ewtd = []
2316 + import array, select
2317 + buffsize = 65536
2318 + eof = False
2319 + while not eof:
2320 + events = select.select(iwtd, owtd, ewtd)
2321 + for f in events[0]:
2322 + # Use non-blocking mode to prevent read
2323 + # calls from blocking indefinitely.
2324 + buf = array.array('B')
2325 + try:
2326 + buf.fromfile(f, buffsize)
2327 + except EOFError:
2328 + pass
2329 + if not buf:
2330 + eof = True
2331 + break
2332 + if f is master_file:
2333 + buf.tofile(stdout_file)
2334 + stdout_file.flush()
2335 + buf.tofile(log_file)
2336 + log_file.flush()
2337 + log_file.close()
2338 + stdout_file.close()
2339 + master_file.close()
2340 + pid = mypids[-1]
2341 + retval = os.waitpid(pid, 0)[1]
2342 + portage.process.spawned_pids.remove(pid)
2343 + if retval != os.EX_OK:
2344 + if retval & 0xff:
2345 + return (retval & 0xff) << 8
2346 + return retval >> 8
2347 + return retval
2348 +
2349 +
2350 +# parse actionmap to spawn ebuild with the appropriate args
2351 +def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0,
2352 + logfile=None, fd_pipes=None, returnpid=False):
2353 + if not returnpid and \
2354 + (alwaysdep or "noauto" not in mysettings.features):
2355 + # process dependency first
2356 + if "dep" in actionmap[mydo]:
2357 + retval = spawnebuild(actionmap[mydo]["dep"], actionmap,
2358 + mysettings, debug, alwaysdep=alwaysdep, logfile=logfile,
2359 + fd_pipes=fd_pipes, returnpid=returnpid)
2360 + if retval:
2361 + return retval
2362 +
2363 + eapi = mysettings["EAPI"]
2364 +
2365 + if mydo == "configure" and eapi in ("0", "1"):
2366 + return os.EX_OK
2367 +
2368 + if mydo == "prepare" and eapi in ("0", "1"):
2369 + return os.EX_OK
2370 +
2371 + if mydo == "pretend" and eapi in ("0", "1", "2", "3", "3_pre2"):
2372 + return os.EX_OK
2373 +
2374 + kwargs = actionmap[mydo]["args"]
2375 + mysettings["EBUILD_PHASE"] = mydo
2376 + _doebuild_exit_status_unlink(
2377 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
2378 +
2379 + try:
2380 + phase_retval = spawn(actionmap[mydo]["cmd"] % mydo,
2381 + mysettings, debug=debug, logfile=logfile,
2382 + fd_pipes=fd_pipes, returnpid=returnpid, **kwargs)
2383 + finally:
2384 + mysettings["EBUILD_PHASE"] = ""
2385 +
2386 + if returnpid:
2387 + return phase_retval
2388 +
2389 + msg = _doebuild_exit_status_check(mydo, mysettings)
2390 + if msg:
2391 + if phase_retval == os.EX_OK:
2392 + phase_retval = 1
2393 + for l in wrap(msg, 72):
2394 + eerror(l, phase=mydo, key=mysettings.mycpv)
2395 +
2396 + _post_phase_userpriv_perms(mysettings)
2397 + if mydo == "install":
2398 + out = StringIO()
2399 + _check_build_log(mysettings, out=out)
2400 + msg = _unicode_decode(out.getvalue(),
2401 + encoding=_encodings['content'], errors='replace')
2402 + if msg:
2403 + writemsg_stdout(msg, noiselevel=-1)
2404 + if logfile is not None:
2405 + try:
2406 + f = codecs.open(_unicode_encode(logfile,
2407 + encoding=_encodings['fs'], errors='strict'),
2408 + mode='a', encoding=_encodings['content'],
2409 + errors='replace')
2410 + except EnvironmentError:
2411 + pass
2412 + else:
2413 + f.write(msg)
2414 + f.close()
2415 + if phase_retval == os.EX_OK:
2416 + _post_src_install_chost_fix(mysettings)
2417 + phase_retval = _post_src_install_checks(mysettings)
2418 +
2419 + if mydo == "test" and phase_retval != os.EX_OK and \
2420 + "test-fail-continue" in mysettings.features:
2421 + phase_retval = os.EX_OK
2422 +
2423 + return phase_retval
2424 +
2425 +_post_phase_cmds = {
2426 +
2427 + "install" : [
2428 + "install_qa_check",
2429 + "install_symlink_html_docs"],
2430 +
2431 + "preinst" : [
2432 + "preinst_bsdflags",
2433 + "preinst_sfperms",
2434 + "preinst_selinux_labels",
2435 + "preinst_suid_scan",
2436 + "preinst_mask"],
2437 +
2438 + "postinst" : [
2439 + "postinst_bsdflags"]
2440 +}
2441 +
2442 +def _post_phase_userpriv_perms(mysettings):
2443 + if "userpriv" in mysettings.features and secpass >= 2:
2444 + """ Privileged phases may have left files that need to be made
2445 + writable to a less privileged user."""
2446 + apply_recursive_permissions(mysettings["T"],
2447 + uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
2448 + filemode=0o60, filemask=0)
2449 +
2450 +def _post_src_install_checks(mysettings):
2451 + _post_src_install_uid_fix(mysettings)
2452 + global _post_phase_cmds
2453 + retval = _spawn_misc_sh(mysettings, _post_phase_cmds["install"],
2454 + phase='internal_post_src_install')
2455 + if retval != os.EX_OK:
2456 + writemsg(_("!!! install_qa_check failed; exiting.\n"),
2457 + noiselevel=-1)
2458 + return retval
2459 +
2460 +def _check_build_log(mysettings, out=None):
2461 + """
2462 + Search the content of $PORTAGE_LOG_FILE if it exists
2463 + and generate the following QA Notices when appropriate:
2464 +
2465 + * Automake "maintainer mode"
2466 + * command not found
2467 + * Unrecognized configure options
2468 + """
2469 + logfile = mysettings.get("PORTAGE_LOG_FILE")
2470 + if logfile is None:
2471 + return
2472 + try:
2473 + f = codecs.open(_unicode_encode(logfile,
2474 + encoding=_encodings['fs'], errors='strict'),
2475 + mode='r', encoding=_encodings['content'], errors='replace')
2476 + except EnvironmentError:
2477 + return
2478 +
2479 + am_maintainer_mode = []
2480 + bash_command_not_found = []
2481 + bash_command_not_found_re = re.compile(
2482 + r'(.*): line (\d*): (.*): command not found$')
2483 + command_not_found_exclude_re = re.compile(r'/configure: line ')
2484 + helper_missing_file = []
2485 + helper_missing_file_re = re.compile(
2486 + r'^!!! (do|new).*: .* does not exist$')
2487 +
2488 + configure_opts_warn = []
2489 + configure_opts_warn_re = re.compile(
2490 + r'^configure: WARNING: [Uu]nrecognized options: ')
2491 +
2492 + # Exclude output from dev-libs/yaz-3.0.47 which looks like this:
2493 + #
2494 + #Configuration:
2495 + # Automake: ${SHELL} /var/tmp/portage/dev-libs/yaz-3.0.47/work/yaz-3.0.47/config/missing --run automake-1.10
2496 + am_maintainer_mode_re = re.compile(r'/missing --run ')
2497 + am_maintainer_mode_exclude_re = \
2498 + re.compile(r'(/missing --run (autoheader|makeinfo)|^\s*Automake:\s)')
2499 +
2500 + make_jobserver_re = \
2501 + re.compile(r'g?make\[\d+\]: warning: jobserver unavailable:')
2502 + make_jobserver = []
2503 +
2504 + try:
2505 + for line in f:
2506 + if am_maintainer_mode_re.search(line) is not None and \
2507 + am_maintainer_mode_exclude_re.search(line) is None:
2508 + am_maintainer_mode.append(line.rstrip("\n"))
2509 +
2510 + if bash_command_not_found_re.match(line) is not None and \
2511 + command_not_found_exclude_re.search(line) is None:
2512 + bash_command_not_found.append(line.rstrip("\n"))
2513 +
2514 + if helper_missing_file_re.match(line) is not None:
2515 + helper_missing_file.append(line.rstrip("\n"))
2516 +
2517 + if configure_opts_warn_re.match(line) is not None:
2518 + configure_opts_warn.append(line.rstrip("\n"))
2519 +
2520 + if make_jobserver_re.match(line) is not None:
2521 + make_jobserver.append(line.rstrip("\n"))
2522 +
2523 + finally:
2524 + f.close()
2525 +
2526 + def _eqawarn(lines):
2527 + for line in lines:
2528 + eqawarn(line, phase="install", key=mysettings.mycpv, out=out)
2529 + wrap_width = 70
2530 +
2531 + if am_maintainer_mode:
2532 + msg = [_("QA Notice: Automake \"maintainer mode\" detected:")]