public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] portage r10879 - in main/branches/prefix/pym: _emerge portage
@ 2008-07-01 17:09 Fabian Groffen (grobian)
  0 siblings, 0 replies; only message in thread
From: Fabian Groffen (grobian) @ 2008-07-01 17:09 UTC (permalink / raw
  To: gentoo-commits

Author: grobian
Date: 2008-07-01 17:09:13 +0000 (Tue, 01 Jul 2008)
New Revision: 10879

Modified:
   main/branches/prefix/pym/_emerge/__init__.py
   main/branches/prefix/pym/portage/__init__.py
Log:
   Merged from trunk 10843:10853

   | 10844   | Handle invalid atoms inside depgraph._add_pkg_deps(), to     |
   | zmedico | avoid an unhandled InvalidAtom exception from dep_expand()   |
   |         | when matching against the vardb.                             |
   
   | 10845   | Split out a _spawn_misc_sh() function from spawnebuild().    |
   | zmedico |                                                              |
   
   | 10846   | Split out a _post_src_install_uid_fix() function from        |
   | zmedico | spawnebuild().                                               |
   
   | 10847   | Split out a _check_build_log() function from spawnebuild().  |
   | zmedico |                                                              |
   
   | 10848   | In EbuildBuild.execute(), call doebuild() separately for     |
   | zmedico | each phase since it will be easier to add asynchronous       |
   |         | support to doebuild() if it's called this way.               |
   
   | 10849   | * Add "fd_pipes" and "returnpid" parameters to doebuild()    |
   | zmedico | and pass these into spawn calls, enabling ebuild processes   |
   |         | to execute asynchronously. * Add a EbuildPhase class that's  |
   |         | derived from the pty logging code inside portage.spawn(). *  |
   |         | Integrate post-phase code from spawnebuild() into            |
   |         | EbuildBuild.execute() so that it still gets called even      |
   |         | though doebuild() calls execute asynchronously.              |
   
   | 10850   | Add EMERGE_FROM to the blacklisted vars in the config        |
   | zmedico | constructor.                                                 |
   
   | 10851   | Centralize select.poll() event handling in                   |
   | zmedico | MergeTask._schedule(). This will allow the parent process to |
   |         | handle output of multiple child processes running in         |
   |         | parllel.                                                     |
   
   | 10852   | * Tweak conditionals in doebuild() to fix emerge --fetch     |
   | zmedico | breakage reported by Arfrever. * Change a couple EMERGE_FROM |
   |         | conditionals to use the "returnpid" parameter instead.       |
   
   | 10853   | Rename the MergeTask class to Scheduler.                     |
   | zmedico |                                                              |


Modified: main/branches/prefix/pym/_emerge/__init__.py
===================================================================
--- main/branches/prefix/pym/_emerge/__init__.py	2008-07-01 16:59:40 UTC (rev 10878)
+++ main/branches/prefix/pym/_emerge/__init__.py	2008-07-01 17:09:13 UTC (rev 10879)
@@ -20,6 +20,8 @@
 except KeyboardInterrupt:
 	sys.exit(1)
 
+import array
+import select
 import gc
 import os, stat
 import platform
@@ -1554,8 +1556,10 @@
 	"""
 	TODO: Support asynchronous execution, to implement parallel builds.
 	"""
-	__slots__ = ("pkg", "settings")
+	__slots__ = ("pkg", "register", "schedule", "settings", "unregister")
 
+	_phases = ("setup", "unpack", "compile", "test", "install")
+
 	def _get_hash_key(self):
 		hash_key = getattr(self, "_hash_key", None)
 		if hash_key is None:
@@ -1566,19 +1570,171 @@
 		root_config = self.pkg.root_config
 		portdb = root_config.trees["porttree"].dbapi
 		ebuild_path = portdb.findname(self.pkg.cpv)
-		debug = self.settings.get("PORTAGE_DEBUG") == "1"
+		settings = self.settings
+		debug = settings.get("PORTAGE_DEBUG") == "1"
+		cleanup = 1
 
 		retval = portage.doebuild(ebuild_path, "clean",
-			root_config.root, self.settings, debug, cleanup=1,
+			root_config.root, settings, debug, cleanup=cleanup,
 			mydbapi=portdb, tree="porttree")
 		if retval != os.EX_OK:
 			return retval
 
-		retval = portage.doebuild(ebuild_path, "install",
-			root_config.root, self.settings, debug,
-			mydbapi=portdb, tree="porttree")
-		return retval
+		# This initializes PORTAGE_LOG_FILE.
+		portage.prepare_build_dirs(root_config.root, settings, cleanup)
 
+		fd_pipes = {
+			0 : sys.stdin.fileno(),
+			1 : sys.stdout.fileno(),
+			2 : sys.stderr.fileno(),
+		}
+
+		for mydo in self._phases:
+			ebuild_phase = EbuildPhase(fd_pipes=fd_pipes,
+				pkg=self.pkg, phase=mydo, register=self.register,
+				settings=settings, unregister=self.unregister)
+			ebuild_phase.start()
+			self.schedule()
+			retval = ebuild_phase.wait()
+
+			portage._post_phase_userpriv_perms(settings)
+			if mydo == "install":
+				portage._check_build_log(settings)
+				if retval == os.EX_OK:
+					retval = portage._post_src_install_checks(settings)
+
+			if retval != os.EX_OK:
+				return retval
+
+		return os.EX_OK
+
+class EbuildPhase(SlotObject):
+
+	__slots__ = ("fd_pipes", "phase", "pkg",
+		"register", "settings", "unregister",
+		"pid", "returncode", "files")
+
+	_file_names = ("log", "stdout", "ebuild")
+	_files_dict = slot_dict_class(_file_names)
+	_bufsize = 4096
+
+	def start(self):
+		root_config = self.pkg.root_config
+		portdb = root_config.trees["porttree"].dbapi
+		ebuild_path = portdb.findname(self.pkg.cpv)
+		settings = self.settings
+		debug = settings.get("PORTAGE_DEBUG") == "1"
+		logfile = settings.get("PORTAGE_LOG_FILE")
+		master_fd = None
+		slave_fd = None
+		fd_pipes = self.fd_pipes.copy()
+
+		# flush any pending output
+		for fd in fd_pipes.itervalues():
+			if fd == sys.stdout.fileno():
+				sys.stdout.flush()
+			if fd == sys.stderr.fileno():
+				sys.stderr.flush()
+
+		fd_pipes_orig = None
+		self.files = self._files_dict()
+		files = self.files
+		got_pty = False
+
+		portage._doebuild_exit_status_unlink(
+			settings.get("EBUILD_EXIT_STATUS_FILE"))
+
+		if logfile:
+			if portage._disable_openpty:
+				master_fd, slave_fd = os.pipe()
+			else:
+				from pty import openpty
+				try:
+					master_fd, slave_fd = openpty()
+					got_pty = True
+				except EnvironmentError, e:
+					portage._disable_openpty = True
+					portage.writemsg("openpty failed: '%s'\n" % str(e),
+						noiselevel=-1)
+					del e
+					master_fd, slave_fd = os.pipe()
+
+			if got_pty:
+				# Disable post-processing of output since otherwise weird
+				# things like \n -> \r\n transformations may occur.
+				import termios
+				mode = termios.tcgetattr(slave_fd)
+				mode[1] &= ~termios.OPOST
+				termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
+
+			import fcntl
+			fcntl.fcntl(master_fd, fcntl.F_SETFL,
+				fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
+
+			fd_pipes.setdefault(0, sys.stdin.fileno())
+			fd_pipes_orig = fd_pipes.copy()
+			if got_pty and os.isatty(fd_pipes_orig[1]):
+				from portage.output import get_term_size, set_term_size
+				rows, columns = get_term_size()
+				set_term_size(rows, columns, slave_fd)
+			fd_pipes[0] = fd_pipes_orig[0]
+			fd_pipes[1] = slave_fd
+			fd_pipes[2] = slave_fd
+
+		retval = portage.doebuild(ebuild_path, self.phase,
+			root_config.root, settings, debug,
+			mydbapi=portdb, tree="porttree",
+			fd_pipes=fd_pipes, returnpid=True)
+
+		self.pid = retval[0]
+
+		if logfile:
+			os.close(slave_fd)
+			files["log"] = open(logfile, 'a')
+			files["stdout"] = os.fdopen(os.dup(fd_pipes_orig[1]), 'w')
+			files["ebuild"] = os.fdopen(master_fd, 'r')
+			self.register(files["ebuild"].fileno(),
+				select.POLLIN, self._output_handler)
+
+	def _output_handler(self, fd, event):
+		files = self.files
+		buf = array.array('B')
+		try:
+			buf.fromfile(files["ebuild"], self._bufsize)
+		except EOFError:
+			pass
+		if buf:
+			buf.tofile(files["stdout"])
+			files["stdout"].flush()
+			buf.tofile(files["log"])
+			files["log"].flush()
+		else:
+			self.unregister(files["ebuild"].fileno())
+			for f in files.values():
+				f.close()
+
+	def wait(self):
+		pid = self.pid
+		retval = os.waitpid(pid, 0)[1]
+		portage.process.spawned_pids.remove(pid)
+		if retval != os.EX_OK:
+			if retval & 0xff:
+				retval = (retval & 0xff) << 8
+			else:
+				retval = retval >> 8
+
+		msg = portage._doebuild_exit_status_check(
+			self.phase, self.settings)
+		if msg:
+			retval = 1
+			from textwrap import wrap
+			from portage.elog.messages import eerror
+			for l in wrap(msg, 72):
+				eerror(l, phase=self.phase, key=self.pkg.cpv)
+
+		self.returncode = retval
+		return self.returncode
+
 class EbuildBinpkg(Task):
 	"""
 	This assumes that src_install() has successfully completed.
@@ -2776,6 +2932,13 @@
 				if debug:
 					print "Candidates:", selected_atoms
 				for atom in selected_atoms:
+					if isinstance(atom, basestring) \
+						and not portage.isvalidatom(atom):
+						show_invalid_depstring_notice(
+							pkg, dep_string, str(atom))
+						if not pkg.installed:
+							return 0
+						continue
 					blocker = atom.startswith("!")
 					if blocker:
 						atom = atom[1:]
@@ -6198,7 +6361,7 @@
 					(self.blocks - self.blocks_satisfied))
 		return "".join(myoutput)
 
-class MergeTask(object):
+class Scheduler(object):
 
 	_opts_ignore_blockers = \
 		frozenset(["--buildpkgonly",
@@ -6224,6 +6387,8 @@
 				clone=trees[root]["vartree"].settings)
 		self.curval = 0
 		self._spawned_pids = []
+		self._poll_event_handlers = {}
+		self._poll = select.poll()
 
 	class _pkg_failure(portage.exception.PortageException):
 		"""
@@ -6388,6 +6553,19 @@
 				pass
 			spawned_pids.remove(pid)
 
+	def _register(self, f, eventmask, handler):
+		self._poll_event_handlers[f] = handler
+		self._poll.register(f, eventmask)
+
+	def _unregister(self, f):
+		self._poll.unregister(f)
+		del self._poll_event_handlers[f]
+
+	def _schedule(self):
+		while self._poll_event_handlers:
+			for f, event in self._poll.poll():
+				self._poll_event_handlers[f](f, event)
+
 	def _merge(self):
 		mylist = self._mergelist
 		favorites = self._favorites
@@ -6626,7 +6804,9 @@
 							(mergecount, len(mymergelist), pkg_key)
 						emergelog(xterm_titles, msg, short_msg=short_msg)
 
-						build = EbuildBuild(pkg=pkg, settings=pkgsettings)
+						build = EbuildBuild(pkg=pkg, register=self._register,
+							schedule=self._schedule, settings=pkgsettings,
+							unregister=self._unregister)
 						retval = build.execute()
 						if retval != os.EX_OK:
 							raise self._pkg_failure(retval)
@@ -6661,7 +6841,9 @@
 							(mergecount, len(mymergelist), pkg_key)
 						emergelog(xterm_titles, msg, short_msg=short_msg)
 
-						build = EbuildBuild(pkg=pkg, settings=pkgsettings)
+						build = EbuildBuild(pkg=pkg, register=self._register,
+							schedule=self._schedule, settings=pkgsettings,
+							unregister=self._unregister)
 						retval = build.execute()
 						if retval != os.EX_OK:
 							raise self._pkg_failure(retval)
@@ -9297,7 +9479,7 @@
 			mymergelist = mydepgraph.altlist()
 			mydepgraph.break_refs(mymergelist)
 			mydepgraph.break_refs(mydepgraph.digraph.order)
-			mergetask = MergeTask(settings, trees, mtimedb, myopts,
+			mergetask = Scheduler(settings, trees, mtimedb, myopts,
 				spinner, mymergelist, favorites, mydepgraph.digraph)
 			del mydepgraph
 			clear_caches(trees)
@@ -9344,7 +9526,7 @@
 			mydepgraph.saveNomergeFavorites()
 			mydepgraph.break_refs(pkglist)
 			mydepgraph.break_refs(mydepgraph.digraph.order)
-			mergetask = MergeTask(settings, trees, mtimedb, myopts,
+			mergetask = Scheduler(settings, trees, mtimedb, myopts,
 				spinner, pkglist, favorites, mydepgraph.digraph)
 			del mydepgraph
 			clear_caches(trees)

Modified: main/branches/prefix/pym/portage/__init__.py
===================================================================
--- main/branches/prefix/pym/portage/__init__.py	2008-07-01 16:59:40 UTC (rev 10878)
+++ main/branches/prefix/pym/portage/__init__.py	2008-07-01 17:09:13 UTC (rev 10879)
@@ -1405,7 +1405,7 @@
 
 			# Blacklist vars that could interfere with portage internals.
 			for blacklisted in "CATEGORY", "EBUILD_PHASE", \
-				"PKGUSE", "PORTAGE_CONFIGROOT", \
+				"EMERGE_FROM", "PKGUSE", "PORTAGE_CONFIGROOT", \
 				"PORTAGE_IUSE", "PORTAGE_USE", "ROOT", \
 				"EPREFIX", "EROOT":
 				for cfg in self.lookuplist:
@@ -2960,6 +2960,10 @@
 		env=mysettings.environ()
 		keywords["opt_name"]="[%s]" % mysettings["PF"]
 
+	if keywords.get("returnpid"):
+		# emerge handles logging externally
+		keywords.pop("logfile", None)
+
 	fd_pipes = keywords.get("fd_pipes")
 	if fd_pipes is None:
 		fd_pipes = {
@@ -4180,11 +4184,15 @@
 	return 1
 
 # parse actionmap to spawn ebuild with the appropriate args
-def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None):
-	if alwaysdep or "noauto" not in mysettings.features:
+def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0,
+	logfile=None, fd_pipes=None, returnpid=False):
+	if not returnpid and \
+		(alwaysdep or "noauto" not in mysettings.features):
 		# process dependency first
 		if "dep" in actionmap[mydo]:
-			retval=spawnebuild(actionmap[mydo]["dep"],actionmap,mysettings,debug,alwaysdep=alwaysdep,logfile=logfile)
+			retval = spawnebuild(actionmap[mydo]["dep"], actionmap,
+				mysettings, debug, alwaysdep=alwaysdep, logfile=logfile,
+				fd_pipes=fd_pipes, returnpid=returnpid)
 			if retval:
 				return retval
 	kwargs = actionmap[mydo]["args"]
@@ -4196,10 +4204,13 @@
 		mysettings._filter_calling_env = True
 	try:
 		phase_retval = spawn(actionmap[mydo]["cmd"] % mydo,
-			mysettings, debug=debug, logfile=logfile, **kwargs)
+			mysettings, debug=debug, logfile=logfile,
+			fd_pipes=fd_pipes, returnpid=returnpid, **kwargs)
 	finally:
 		mysettings["EBUILD_PHASE"] = ""
 		mysettings._filter_calling_env = filter_calling_env_state
+	if returnpid:
+		return phase_retval
 	msg = _doebuild_exit_status_check(mydo, mysettings)
 	if msg:
 		phase_retval = 1
@@ -4208,138 +4219,174 @@
 		for l in wrap(msg, 72):
 			eerror(l, phase=mydo, key=mysettings.mycpv)
 
-	if "userpriv" in mysettings.features and \
-		not kwargs["droppriv"] and secpass >= 2:
+	_post_phase_userpriv_perms(mysettings)
+	if mydo == "install":
+		_check_build_log(mysettings)
+		if phase_retval == os.EX_OK:
+			phase_retval = _post_src_install_checks(mysettings)
+	return phase_retval
+
+def _post_phase_userpriv_perms(mysettings):
+	if "userpriv" in mysettings.features and secpass >= 2:
 		""" Privileged phases may have left files that need to be made
 		writable to a less privileged user."""
 		apply_recursive_permissions(mysettings["T"],
 			uid=portage_uid, gid=portage_gid, dirmode=070, dirmask=0,
 			filemode=060, filemask=0)
 
-	if phase_retval == os.EX_OK:
-		if mydo == "install" and logfile:
-			try:
-				f = open(logfile, 'rb')
-			except EnvironmentError:
-				pass
-			else:
-				am_maintainer_mode = []
+def _post_src_install_checks(mysettings):
+	_post_src_install_uid_fix(mysettings)
+	retval = _spawn_misc_sh(mysettings, ["install_qa_check",
+		"install_symlink_html_docs"])
+	if retval != os.EX_OK:
+		writemsg("!!! install_qa_check failed; exiting.\n",
+			noiselevel=-1)
+	return retval
 
-				bash_command_not_found = []
-				bash_command_not_found_re = re.compile(
-					r'(.*): line (\d*): (.*): command not found$')
+def _check_build_log(mysettings):
+	"""
+	Search the content of $PORTAGE_LOG_FILE if it exists
+	and generate the following QA Notices when appropriate:
 
-				configure_opts_warn = []
-				configure_opts_warn_re = re.compile(
-					r'^configure: WARNING: Unrecognized options: .*')
-				am_maintainer_mode_re = re.compile(r'.*/missing --run .*')
-				am_maintainer_mode_exclude_re = \
-					re.compile(r'.*/missing --run (autoheader|makeinfo)')
-				try:
-					for line in f:
-						if am_maintainer_mode_re.search(line) is not None and \
-							am_maintainer_mode_exclude_re.search(line) is None:
-							am_maintainer_mode.append(line.rstrip("\n"))
+	  * Automake "maintainer mode"
+	  * command not found
+	  * Unrecognized configure options
+	"""
+	logfile = mysettings.get("PORTAGE_LOG_FILE")
+	if logfile is None:
+		return
+	try:
+		f = open(logfile, 'rb')
+	except EnvironmentError:
+		return
 
-						if bash_command_not_found_re.match(line) is not None:
-							bash_command_not_found.append(line.rstrip("\n"))
+	am_maintainer_mode = []
+	bash_command_not_found = []
+	bash_command_not_found_re = re.compile(
+		r'(.*): line (\d*): (.*): command not found$')
 
-						if configure_opts_warn_re.match(line) is not None:
-							configure_opts_warn.append(line.rstrip("\n"))
-				finally:
-					f.close()
+	configure_opts_warn = []
+	configure_opts_warn_re = re.compile(
+		r'^configure: WARNING: Unrecognized options: .*')
+	am_maintainer_mode_re = re.compile(r'.*/missing --run .*')
+	am_maintainer_mode_exclude_re = \
+		re.compile(r'.*/missing --run (autoheader|makeinfo)')
+	try:
+		for line in f:
+			if am_maintainer_mode_re.search(line) is not None and \
+				am_maintainer_mode_exclude_re.search(line) is None:
+				am_maintainer_mode.append(line.rstrip("\n"))
 
-				from portage.elog.messages import eqawarn
-				def _eqawarn(lines):
-					for line in lines:
-						eqawarn(line, phase=mydo, key=mysettings.mycpv)
-				from textwrap import wrap
-				wrap_width = 70
+			if bash_command_not_found_re.match(line) is not None:
+				bash_command_not_found.append(line.rstrip("\n"))
 
-				if am_maintainer_mode:
-					msg = ["QA Notice: Automake \"maintainer mode\" detected:"]
-					msg.append("")
-					msg.extend("\t" + line for line in am_maintainer_mode)
-					msg.append("")
-					msg.extend(wrap(
-						"If you patch Makefile.am, " + \
-						"configure.in,  or configure.ac then you " + \
-						"should use autotools.eclass and " + \
-						"eautomake or eautoreconf. Exceptions " + \
-						"are limited to system packages " + \
-						"for which it is impossible to run " + \
-						"autotools during stage building. " + \
-						"See http://www.gentoo.org/p" + \
-						"roj/en/qa/autofailure.xml for more information.",
-						wrap_width))
-					_eqawarn(msg)
+			if configure_opts_warn_re.match(line) is not None:
+				configure_opts_warn.append(line.rstrip("\n"))
+	finally:
+		f.close()
 
-				if bash_command_not_found:
-					msg = ["QA Notice: command not found:"]
-					msg.append("")
-					msg.extend("\t" + line for line in bash_command_not_found)
-					_eqawarn(msg)
+	from portage.elog.messages import eqawarn
+	def _eqawarn(lines):
+		for line in lines:
+			eqawarn(line, phase="install", key=mysettings.mycpv)
+	from textwrap import wrap
+	wrap_width = 70
 
-				if configure_opts_warn:
-					msg = ["QA Notice: Unrecognized configure options:"]
-					msg.append("")
-					msg.extend("\t" + line for line in configure_opts_warn)
-					_eqawarn(msg)
+	if am_maintainer_mode:
+		msg = ["QA Notice: Automake \"maintainer mode\" detected:"]
+		msg.append("")
+		msg.extend("\t" + line for line in am_maintainer_mode)
+		msg.append("")
+		msg.extend(wrap(
+			"If you patch Makefile.am, " + \
+			"configure.in,  or configure.ac then you " + \
+			"should use autotools.eclass and " + \
+			"eautomake or eautoreconf. Exceptions " + \
+			"are limited to system packages " + \
+			"for which it is impossible to run " + \
+			"autotools during stage building. " + \
+			"See http://www.gentoo.org/p" + \
+			"roj/en/qa/autofailure.xml for more information.",
+			wrap_width))
+		_eqawarn(msg)
 
-		if mydo == "install":
-			# User and group bits that match the "portage" user or group are
-			# automatically mapped to PORTAGE_INST_UID and PORTAGE_INST_GID if
-			# necessary.  The chown system call may clear S_ISUID and S_ISGID
-			# bits, so those bits are restored if necessary.
-			inst_uid = int(mysettings["PORTAGE_INST_UID"])
-			inst_gid = int(mysettings["PORTAGE_INST_GID"])
-			for parent, dirs, files in os.walk(mysettings["D"]):
-				for fname in chain(dirs, files):
-					fpath = os.path.join(parent, fname)
-					mystat = os.lstat(fpath)
-					if mystat.st_uid != portage_uid and \
-						mystat.st_gid != portage_gid:
-						continue
-					myuid = -1
-					mygid = -1
-					if mystat.st_uid == portage_uid:
-						myuid = inst_uid
-					if mystat.st_gid == portage_gid:
-						mygid = inst_gid
-					apply_secpass_permissions(fpath, uid=myuid, gid=mygid,
-						mode=mystat.st_mode, stat_cached=mystat,
-						follow_links=False)
-			# Note: PORTAGE_BIN_PATH may differ from the global
-			# constant when portage is reinstalling itself.
-			portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
-			misc_sh_binary = os.path.join(portage_bin_path,
-				os.path.basename(MISC_SH_BINARY))
-			mycommand = " ".join([_shell_quote(misc_sh_binary),
-				"install_qa_check", "install_symlink_html_docs"])
-			_doebuild_exit_status_unlink(
-				mysettings.get("EBUILD_EXIT_STATUS_FILE"))
-			filter_calling_env_state = mysettings._filter_calling_env
-			if os.path.exists(os.path.join(mysettings["T"], "environment")):
-				mysettings._filter_calling_env = True
-			try:
-				qa_retval = spawn(mycommand, mysettings, debug=debug,
-					logfile=logfile, **kwargs)
-			finally:
-				mysettings._filter_calling_env = filter_calling_env_state
-			msg = _doebuild_exit_status_check(mydo, mysettings)
-			if msg:
-				qa_retval = 1
-				from textwrap import wrap
-				from portage.elog.messages import eerror
-				for l in wrap(msg, 72):
-					eerror(l, phase=mydo, key=mysettings.mycpv)
-			if qa_retval != os.EX_OK:
-				writemsg("!!! install_qa_check failed; exiting.\n",
-					noiselevel=-1)
-			return qa_retval
-	return phase_retval
+	if bash_command_not_found:
+		msg = ["QA Notice: command not found:"]
+		msg.append("")
+		msg.extend("\t" + line for line in bash_command_not_found)
+		_eqawarn(msg)
 
+	if configure_opts_warn:
+		msg = ["QA Notice: Unrecognized configure options:"]
+		msg.append("")
+		msg.extend("\t" + line for line in configure_opts_warn)
+		_eqawarn(msg)
 
+def _post_src_install_uid_fix(mysettings):
+	"""
+	Files in $D with user and group bits that match the "portage"
+	user or group are automatically mapped to PORTAGE_INST_UID and
+	PORTAGE_INST_GID if necessary. The chown system call may clear
+	S_ISUID and S_ISGID bits, so those bits are restored if
+	necessary.
+	"""
+	inst_uid = int(mysettings["PORTAGE_INST_UID"])
+	inst_gid = int(mysettings["PORTAGE_INST_GID"])
+	for parent, dirs, files in os.walk(mysettings["D"]):
+		for fname in chain(dirs, files):
+			fpath = os.path.join(parent, fname)
+			mystat = os.lstat(fpath)
+			if mystat.st_uid != portage_uid and \
+				mystat.st_gid != portage_gid:
+				continue
+			myuid = -1
+			mygid = -1
+			if mystat.st_uid == portage_uid:
+				myuid = inst_uid
+			if mystat.st_gid == portage_gid:
+				mygid = inst_gid
+			apply_secpass_permissions(fpath, uid=myuid, gid=mygid,
+				mode=mystat.st_mode, stat_cached=mystat,
+				follow_links=False)
+
+def _spawn_misc_sh(mysettings, commands, **kwargs):
+	"""
+	@param mysettings: the ebuild config
+	@type mysettings: config
+	@param commands: a list of function names to call in misc-functions.sh
+	@type commands: list
+	@rtype: int
+	@returns: the return value from the spawn() call
+	"""
+
+	# Note: PORTAGE_BIN_PATH may differ from the global
+	# constant when portage is reinstalling itself.
+	portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
+	misc_sh_binary = os.path.join(portage_bin_path,
+		os.path.basename(MISC_SH_BINARY))
+	mycommand = " ".join([_shell_quote(misc_sh_binary)] + commands)
+	_doebuild_exit_status_unlink(
+		mysettings.get("EBUILD_EXIT_STATUS_FILE"))
+	filter_calling_env_state = mysettings._filter_calling_env
+	if os.path.exists(os.path.join(mysettings["T"], "environment")):
+		mysettings._filter_calling_env = True
+	debug = mysettings.get("PORTAGE_DEBUG") == "1"
+	logfile = mysettings.get("PORTAGE_LOG_FILE")
+	mydo = mysettings["EBUILD_PHASE"]
+	try:
+		rval = spawn(mycommand, mysettings, debug=debug,
+			logfile=logfile, **kwargs)
+	finally:
+		mysettings._filter_calling_env = filter_calling_env_state
+	msg = _doebuild_exit_status_check(mydo, mysettings)
+	if msg:
+		rval = 1
+		from textwrap import wrap
+		from portage.elog.messages import eerror
+		for l in wrap(msg, 72):
+			eerror(l, phase=mydo, key=mysettings.mycpv)
+	return rval
+
 _eapi_prefix_re = re.compile("(^|\s*)%s($|\s*)" % portage.const.EAPIPREFIX)
 _eapi_num_re    = re.compile("(^|\s*)[0-9]+($|\s*)")
 
@@ -4793,8 +4840,9 @@
 
 def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
 	fetchonly=0, cleanup=0, dbkey=None, use_cache=1, fetchall=0, tree=None,
-	mydbapi=None, vartree=None, prev_mtimes=None):
-	
+	mydbapi=None, vartree=None, prev_mtimes=None,
+	fd_pipes=None, returnpid=False):
+
 	"""
 	Wrapper function that invokes specific ebuild phases through the spawning
 	of ebuild.sh
@@ -5206,7 +5254,10 @@
 		elif mydo == "setup":
 			retval = spawn(
 				_shell_quote(ebuild_sh_binary) + " " + mydo, mysettings,
-				debug=debug, free=1, logfile=logfile)
+				debug=debug, free=1, logfile=logfile, fd_pipes=fd_pipes,
+				returnpid=returnpid)
+			if returnpid:
+				return retval
 			retval = exit_status_check(retval)
 			if secpass >= 2:
 				""" Privileged phases may have left files that need to be made
@@ -5315,7 +5366,10 @@
 		# unpack compile install`, we will try and fetch 4 times :/
 		need_distfiles = (mydo in ("fetch", "unpack") or \
 			mydo not in ("digest", "manifest") and "noauto" not in features)
-		if need_distfiles and not fetch(
+		emerge_skip_distfiles = "EMERGE_FROM" in mysettings and \
+			mydo not in ("fetch", "unpack")
+		if not emerge_skip_distfiles and \
+			need_distfiles and not fetch(
 			fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
 			if have_build_dirs:
 				# Create an elog message for this fetch failure since the
@@ -5347,10 +5401,8 @@
 				return 1
 
 		# See above comment about fetching only when needed
-		if not digestcheck(checkme, mysettings, ("strict" in features),
-			(mydo not in ["digest","fetch","unpack"] and \
-			mysettings.get("PORTAGE_CALLER", None) == "ebuild" and \
-			"noauto" in features)):
+		if not emerge_skip_distfiles and \
+			not digestcheck(checkme, mysettings, "strict" in features):
 			return 1
 
 		if mydo == "fetch":
@@ -5435,7 +5487,8 @@
 					raise portage.exception.PermissionDenied(
 						"access('%s', os.W_OK)" % parent_dir)
 			retval = spawnebuild(mydo,
-				actionmap, mysettings, debug, logfile=logfile)
+				actionmap, mysettings, debug, logfile=logfile,
+				fd_pipes=fd_pipes, returnpid=returnpid)
 		elif mydo=="qmerge":
 			# check to ensure install was run.  this *only* pops up when users
 			# forget it and are using ebuild
@@ -5455,7 +5508,8 @@
 				mydbapi=mydbapi, vartree=vartree, prev_mtimes=prev_mtimes)
 		elif mydo=="merge":
 			retval = spawnebuild("install", actionmap, mysettings, debug,
-				alwaysdep=1, logfile=logfile)
+				alwaysdep=1, logfile=logfile, fd_pipes=fd_pipes,
+				returnpid=returnpid)
 			retval = exit_status_check(retval)
 			if retval != os.EX_OK:
 				# The merge phase handles this already.  Callers don't know how

-- 
gentoo-commits@lists.gentoo.org mailing list



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-07-01 17:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-01 17:09 [gentoo-commits] portage r10879 - in main/branches/prefix/pym: _emerge portage Fabian Groffen (grobian)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox