public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] portage r15483 - in main/branches/prefix/pym/portage: . dbapi package/ebuild util
@ 2010-02-27 19:32 Fabian Groffen (grobian)
  0 siblings, 0 replies; only message in thread
From: Fabian Groffen (grobian) @ 2010-02-27 19:32 UTC (permalink / raw
  To: gentoo-commits

Author: grobian
Date: 2010-02-27 19:32:48 +0000 (Sat, 27 Feb 2010)
New Revision: 15483

Added:
   main/branches/prefix/pym/portage/dep/
   main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py
   main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py
   main/branches/prefix/pym/portage/util/movefile.py
Removed:
   main/branches/prefix/pym/portage/dep.py
Modified:
   main/branches/prefix/pym/portage/__init__.py
   main/branches/prefix/pym/portage/dbapi/__init__.py
   main/branches/prefix/pym/portage/dbapi/vartree.py
Log:
   Merged from trunk -r15460:15465

   | 15461   | Move dep.py to dep/__init__.py, for splitting into smaller   |
   | zmedico | files.                                                       |
   
   | 15462   | Move portage.dep_check and related functions to              |
   | zmedico | portage.dep.dep_check.                                       |
   
   | 15463   | Split getmaskingstatus and getmaskingreason info             |
   | zmedico | portage.package.ebuild submodules.                           |
   
   | 15464   | Move portage.movefile to portage.util.movefile.              |
   | zmedico |                                                              |
   
   | 15465   | Avoid name collision with dep_expand submodule so epydoc     |
   | zmedico | won't crash.                                                 |


Modified: main/branches/prefix/pym/portage/__init__.py
===================================================================
--- main/branches/prefix/pym/portage/__init__.py	2010-02-27 19:26:00 UTC (rev 15482)
+++ main/branches/prefix/pym/portage/__init__.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -92,6 +92,7 @@
 		'portage.dep:best_match_to_list,dep_getcpv,dep_getkey,' + \
 			'flatten,get_operator,isjustname,isspecific,isvalidatom,' + \
 			'match_from_list,match_to_list',
+		'portage.dep.dep_check:dep_check,dep_eval,dep_wordreduce,dep_zapdeps',
 		'portage.eclass_cache',
 		'portage.env.loaders',
 		'portage.exception',
@@ -109,6 +110,8 @@
 		'portage.package.ebuild.digestcheck:digestcheck',
 		'portage.package.ebuild.digestgen:digestgen',
 		'portage.package.ebuild.fetch:fetch',
+		'portage.package.ebuild.getmaskingreason:getmaskingreason',
+		'portage.package.ebuild.getmaskingstatus:getmaskingstatus',
 		'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
 		'portage.process',
 		'portage.process:atexit_register,run_exitfuncs',
@@ -127,6 +130,7 @@
 		'portage.util.env_update:env_update',
 		'portage.util.ExtractKernelVersion:ExtractKernelVersion',
 		'portage.util.listdir:cacheddir,listdir',
+		'portage.util.movefile:movefile',
 		'portage.versions',
 		'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \
 			'cpv_getkey@getCPFromCPV,endversion_keys,' + \
@@ -634,223 +638,6 @@
 		raise portage.exception.PortageException(
 			"mv '%s' '%s'" % (src, dest))
 
-def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
-		hardlink_candidates=None, encoding=_encodings['fs']):
-	"""moves a file from src to dest, preserving all permissions and attributes; mtime will
-	be preserved even when moving across filesystems.  Returns true on success and false on
-	failure.  Move is atomic."""
-	#print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
-
-	if mysettings is None:
-		global settings
-		mysettings = settings
-
-	selinux_enabled = mysettings.selinux_enabled()
-	if selinux_enabled:
-		selinux = _unicode_module_wrapper(_selinux, encoding=encoding)
-
-	lchown = _unicode_func_wrapper(data.lchown, encoding=encoding)
-	os = _unicode_module_wrapper(_os,
-		encoding=encoding, overrides=_os_overrides)
-	shutil = _unicode_module_wrapper(_shutil, encoding=encoding)
-
-	try:
-		if not sstat:
-			sstat=os.lstat(src)
-
-	except SystemExit as e:
-		raise
-	except Exception as e:
-		print(_("!!! Stating source file failed... movefile()"))
-		print("!!!",e)
-		return None
-
-	destexists=1
-	try:
-		dstat=os.lstat(dest)
-	except (OSError, IOError):
-		dstat=os.lstat(os.path.dirname(dest))
-		destexists=0
-
-	if bsd_chflags:
-		if destexists and dstat.st_flags != 0:
-			bsd_chflags.lchflags(dest, 0)
-		# Use normal stat/chflags for the parent since we want to
-		# follow any symlinks to the real parent directory.
-		pflags = os.stat(os.path.dirname(dest)).st_flags
-		if pflags != 0:
-			bsd_chflags.chflags(os.path.dirname(dest), 0)
-
-	if destexists:
-		if stat.S_ISLNK(dstat[stat.ST_MODE]):
-			try:
-				os.unlink(dest)
-				destexists=0
-			except SystemExit as e:
-				raise
-			except Exception as e:
-				pass
-
-	if stat.S_ISLNK(sstat[stat.ST_MODE]):
-		try:
-			target=os.readlink(src)
-			if mysettings and mysettings["D"]:
-				if target.find(mysettings["D"])==0:
-					target=target[len(mysettings["D"]):]
-			if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
-				os.unlink(dest)
-			if selinux_enabled:
-				selinux.symlink(target, dest, src)
-			else:
-				os.symlink(target,dest)
-			lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
-			# utime() only works on the target of a symlink, so it's not
-			# possible to perserve mtime on symlinks.
-			return os.lstat(dest)[stat.ST_MTIME]
-		except SystemExit as e:
-			raise
-		except Exception as e:
-			print(_("!!! failed to properly create symlink:"))
-			print("!!!",dest,"->",target)
-			print("!!!",e)
-			return None
-
-	hardlinked = False
-	# Since identical files might be merged to multiple filesystems,
-	# so os.link() calls might fail for some paths, so try them all.
-	# For atomic replacement, first create the link as a temp file
-	# and them use os.rename() to replace the destination.
-	if hardlink_candidates:
-		head, tail = os.path.split(dest)
-		hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
-			(tail, os.getpid()))
-		try:
-			os.unlink(hardlink_tmp)
-		except OSError as e:
-			if e.errno != errno.ENOENT:
-				writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
-					(hardlink_tmp,), noiselevel=-1)
-				writemsg("!!! %s\n" % (e,), noiselevel=-1)
-				return None
-			del e
-		for hardlink_src in hardlink_candidates:
-			try:
-				os.link(hardlink_src, hardlink_tmp)
-			except OSError:
-				continue
-			else:
-				try:
-					os.rename(hardlink_tmp, dest)
-				except OSError as e:
-					writemsg(_("!!! Failed to rename %s to %s\n") % \
-						(hardlink_tmp, dest), noiselevel=-1)
-					writemsg("!!! %s\n" % (e,), noiselevel=-1)
-					return None
-				hardlinked = True
-				break
-
-	renamefailed=1
-	if hardlinked:
-		renamefailed = False
-	if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
-		try:
-			if selinux_enabled:
-				ret = selinux.rename(src, dest)
-			else:
-				ret=os.rename(src,dest)
-			renamefailed=0
-		except OSError as e:
-			if e.errno != errno.EXDEV:
-				# Some random error.
-				print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest})
-				print("!!!",e)
-				return None
-			# Invalid cross-device-link 'bind' mounted or actually Cross-Device
-	if renamefailed:
-		didcopy=0
-		if stat.S_ISREG(sstat[stat.ST_MODE]):
-			try: # For safety copy then move it over.
-				if selinux_enabled:
-					selinux.copyfile(src, dest + "#new")
-					selinux.rename(dest + "#new", dest)
-				else:
-					shutil.copyfile(src,dest+"#new")
-					os.rename(dest+"#new",dest)
-				didcopy=1
-			except SystemExit as e:
-				raise
-			except Exception as e:
-				print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest})
-				print("!!!",e)
-				return None
-		else:
-			#we don't yet handle special, so we need to fall back to /bin/mv
-			a = process.spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
-			if a != os.EX_OK:
-				writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1)
-				writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
-					{"src": _unicode_decode(src, encoding=encoding),
-					"dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
-				writemsg("!!! %s\n" % a, noiselevel=-1)
-				return None # failure
-		try:
-			if didcopy:
-				if stat.S_ISLNK(sstat[stat.ST_MODE]):
-					lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
-				else:
-					os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
-				os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
-				os.unlink(src)
-		except SystemExit as e:
-			raise
-		except Exception as e:
-			print(_("!!! Failed to chown/chmod/unlink in movefile()"))
-			print("!!!",dest)
-			print("!!!",e)
-			return None
-
-	# Always use stat_obj[stat.ST_MTIME] for the integral timestamp which
-	# is returned, since the stat_obj.st_mtime float attribute rounds *up*
-	# if the nanosecond part of the timestamp is 999999881 ns or greater.
-	try:
-		if hardlinked:
-			newmtime = os.stat(dest)[stat.ST_MTIME]
-		else:
-			# Note: It is not possible to preserve nanosecond precision
-			# (supported in POSIX.1-2008 via utimensat) with the IEEE 754
-			# double precision float which only has a 53 bit significand.
-			if newmtime is not None:
-				os.utime(dest, (newmtime, newmtime))
-			else:
-				newmtime = sstat[stat.ST_MTIME]
-				if renamefailed:
-					# If rename succeeded then timestamps are automatically
-					# preserved with complete precision because the source
-					# and destination inode are the same. Otherwise, round
-					# down to the nearest whole second since python's float
-					# st_mtime cannot be used to preserve the st_mtim.tv_nsec
-					# field with complete precision. Note that we have to use
-					# stat_obj[stat.ST_MTIME] here because the float
-					# stat_obj.st_mtime rounds *up* sometimes.
-					os.utime(dest, (newmtime, newmtime))
-	except OSError:
-		# The utime can fail here with EPERM even though the move succeeded.
-		# Instead of failing, use stat to return the mtime if possible.
-		try:
-			newmtime = os.stat(dest)[stat.ST_MTIME]
-		except OSError as e:
-			writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
-			writemsg("!!! %s\n" % dest, noiselevel=-1)
-			writemsg("!!! %s\n" % str(e), noiselevel=-1)
-			return None
-
-	if bsd_chflags:
-		# Restore the flags we saved before moving
-		if pflags:
-			bsd_chflags.chflags(os.path.dirname(dest), pflags)
-
-	return newmtime
-
 def merge(mycat, mypkg, pkgloc, infloc, myroot, mysettings, myebuild=None,
 	mytree=None, mydbapi=None, vartree=None, prev_mtimes=None, blockers=None,
 	scheduler=None):
@@ -911,835 +698,6 @@
 				newsplit.append(x)
 	return newsplit
 
-def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
-	trees=None, use_mask=None, use_force=None, **kwargs):
-	"""
-	In order to solve bug #141118, recursively expand new-style virtuals so
-	as to collapse one or more levels of indirection, generating an expanded
-	search space. In dep_zapdeps, new-style virtuals will be assigned
-	zero cost regardless of whether or not they are currently installed. Virtual
-	blockers are supported but only when the virtual expands to a single
-	atom because it wouldn't necessarily make sense to block all the components
-	of a compound virtual.  When more than one new-style virtual is matched,
-	the matches are sorted from highest to lowest versions and the atom is
-	expanded to || ( highest match ... lowest match )."""
-	newsplit = []
-	mytrees = trees[myroot]
-	portdb = mytrees["porttree"].dbapi
-	atom_graph = mytrees.get("atom_graph")
-	parent = mytrees.get("parent")
-	virt_parent = mytrees.get("virt_parent")
-	graph_parent = None
-	eapi = None
-	if parent is not None:
-		if virt_parent is not None:
-			graph_parent = virt_parent
-			eapi = virt_parent[0].metadata['EAPI']
-		else:
-			graph_parent = parent
-			eapi = parent.metadata["EAPI"]
-	repoman = not mysettings.local_config
-	if kwargs["use_binaries"]:
-		portdb = trees[myroot]["bintree"].dbapi
-	myvirtuals = mysettings.getvirtuals()
-	pprovideddict = mysettings.pprovideddict
-	myuse = kwargs["myuse"]
-	for x in mysplit:
-		if x == "||":
-			newsplit.append(x)
-			continue
-		elif isinstance(x, list):
-			newsplit.append(_expand_new_virtuals(x, edebug, mydbapi,
-				mysettings, myroot=myroot, trees=trees, use_mask=use_mask,
-				use_force=use_force, **kwargs))
-			continue
-
-		if not isinstance(x, portage.dep.Atom):
-			try:
-				x = portage.dep.Atom(x)
-			except portage.exception.InvalidAtom:
-				if portage.dep._dep_check_strict:
-					raise portage.exception.ParseError(
-						_("invalid atom: '%s'") % x)
-				else:
-					# Only real Atom instances are allowed past this point.
-					continue
-			else:
-				if x.blocker and x.blocker.overlap.forbid and \
-					eapi in ("0", "1") and portage.dep._dep_check_strict:
-					raise portage.exception.ParseError(
-						_("invalid atom: '%s'") % (x,))
-				if x.use and eapi in ("0", "1") and \
-					portage.dep._dep_check_strict:
-					raise portage.exception.ParseError(
-						_("invalid atom: '%s'") % (x,))
-
-		if repoman and x.use and x.use.conditional:
-			evaluated_atom = portage.dep.remove_slot(x)
-			if x.slot:
-				evaluated_atom += ":%s" % x.slot
-			evaluated_atom += str(x.use._eval_qa_conditionals(
-				use_mask, use_force))
-			x = portage.dep.Atom(evaluated_atom)
-
-		if not repoman and \
-			myuse is not None and isinstance(x, portage.dep.Atom) and x.use:
-			if x.use.conditional:
-				x = x.evaluate_conditionals(myuse)
-
-		mykey = x.cp
-		if not mykey.startswith("virtual/"):
-			newsplit.append(x)
-			if atom_graph is not None:
-				atom_graph.add(x, graph_parent)
-			continue
-		mychoices = myvirtuals.get(mykey, [])
-		if x.blocker:
-			# Virtual blockers are no longer expanded here since
-			# the un-expanded virtual atom is more useful for
-			# maintaining a cache of blocker atoms.
-			newsplit.append(x)
-			if atom_graph is not None:
-				atom_graph.add(x, graph_parent)
-			continue
-
-		if repoman or not hasattr(portdb, 'match_pkgs'):
-			if portdb.cp_list(x.cp):
-				newsplit.append(x)
-			else:
-				# TODO: Add PROVIDE check for repoman.
-				a = []
-				for y in mychoices:
-					a.append(dep.Atom(x.replace(x.cp, y.cp, 1)))
-				if not a:
-					newsplit.append(x)
-				elif len(a) == 1:
-					newsplit.append(a[0])
-				else:
-					newsplit.append(['||'] + a)
-			continue
-
-		pkgs = []
-		# Ignore USE deps here, since otherwise we might not
-		# get any matches. Choices with correct USE settings
-		# will be preferred in dep_zapdeps().
-		matches = portdb.match_pkgs(x.without_use)
-		# Use descending order to prefer higher versions.
-		matches.reverse()
-		for pkg in matches:
-			# only use new-style matches
-			if pkg.cp.startswith("virtual/"):
-				pkgs.append(pkg)
-		if not (pkgs or mychoices):
-			# This one couldn't be expanded as a new-style virtual.  Old-style
-			# virtuals have already been expanded by dep_virtual, so this one
-			# is unavailable and dep_zapdeps will identify it as such.  The
-			# atom is not eliminated here since it may still represent a
-			# dependency that needs to be satisfied.
-			newsplit.append(x)
-			if atom_graph is not None:
-				atom_graph.add(x, graph_parent)
-			continue
-
-		a = []
-		for pkg in pkgs:
-			virt_atom = '=' + pkg.cpv
-			if x.use:
-				virt_atom += str(x.use)
-			virt_atom = dep.Atom(virt_atom)
-			# According to GLEP 37, RDEPEND is the only dependency
-			# type that is valid for new-style virtuals. Repoman
-			# should enforce this.
-			depstring = pkg.metadata['RDEPEND']
-			pkg_kwargs = kwargs.copy()
-			pkg_kwargs["myuse"] = pkg.use.enabled
-			if edebug:
-				util.writemsg_level(_("Virtual Parent:      %s\n") \
-					% (pkg,), noiselevel=-1, level=logging.DEBUG)
-				util.writemsg_level(_("Virtual Depstring:   %s\n") \
-					% (depstring,), noiselevel=-1, level=logging.DEBUG)
-
-			# Set EAPI used for validation in dep_check() recursion.
-			mytrees["virt_parent"] = (pkg, virt_atom)
-
-			try:
-				mycheck = dep_check(depstring, mydbapi, mysettings,
-					myroot=myroot, trees=trees, **pkg_kwargs)
-			finally:
-				# Restore previous EAPI after recursion.
-				if virt_parent is not None:
-					mytrees["virt_parent"] = virt_parent
-				else:
-					del mytrees["virt_parent"]
-
-			if not mycheck[0]:
-				raise portage.exception.ParseError(
-					"%s: %s '%s'" % (y[0], mycheck[1], depstring))
-
-			# pull in the new-style virtual
-			mycheck[1].append(virt_atom)
-			a.append(mycheck[1])
-			if atom_graph is not None:
-				atom_graph.add(virt_atom, graph_parent)
-		# Plain old-style virtuals.  New-style virtuals are preferred.
-		if not pkgs:
-				for y in mychoices:
-					new_atom = dep.Atom(x.replace(x.cp, y.cp, 1))
-					matches = portdb.match(new_atom)
-					# portdb is an instance of depgraph._dep_check_composite_db, so
-					# USE conditionals are already evaluated.
-					if matches and mykey in \
-						portdb.aux_get(matches[-1], ['PROVIDE'])[0].split():
-						a.append(new_atom)
-						if atom_graph is not None:
-							atom_graph.add(new_atom, graph_parent)
-
-		if not a and mychoices:
-			# Check for a virtual package.provided match.
-			for y in mychoices:
-				new_atom = dep.Atom(x.replace(x.cp, y.cp, 1))
-				if match_from_list(new_atom,
-					pprovideddict.get(new_atom.cp, [])):
-					a.append(new_atom)
-					if atom_graph is not None:
-						atom_graph.add(new_atom, graph_parent)
-
-		if not a:
-			newsplit.append(x)
-			if atom_graph is not None:
-				atom_graph.add(x, graph_parent)
-		elif len(a) == 1:
-			newsplit.append(a[0])
-		else:
-			newsplit.append(['||'] + a)
-
-	return newsplit
-
-def dep_eval(deplist):
-	if not deplist:
-		return 1
-	if deplist[0]=="||":
-		#or list; we just need one "1"
-		for x in deplist[1:]:
-			if isinstance(x, list):
-				if dep_eval(x)==1:
-					return 1
-			elif x==1:
-					return 1
-		#XXX: unless there's no available atoms in the list
-		#in which case we need to assume that everything is
-		#okay as some ebuilds are relying on an old bug.
-		if len(deplist) == 1:
-			return 1
-		return 0
-	else:
-		for x in deplist:
-			if isinstance(x, list):
-				if dep_eval(x)==0:
-					return 0
-			elif x==0 or x==2:
-				return 0
-		return 1
-
-def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
-	"""Takes an unreduced and reduced deplist and removes satisfied dependencies.
-	Returned deplist contains steps that must be taken to satisfy dependencies."""
-	if trees is None:
-		global db
-		trees = db
-	writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
-	if not reduced or unreduced == ["||"] or dep_eval(reduced):
-		return []
-
-	if unreduced[0] != "||":
-		unresolved = []
-		for x, satisfied in zip(unreduced, reduced):
-			if isinstance(x, list):
-				unresolved += dep_zapdeps(x, satisfied, myroot,
-					use_binaries=use_binaries, trees=trees)
-			elif not satisfied:
-				unresolved.append(x)
-		return unresolved
-
-	# We're at a ( || atom ... ) type level and need to make a choice
-	deps = unreduced[1:]
-	satisfieds = reduced[1:]
-
-	# Our preference order is for an the first item that:
-	# a) contains all unmasked packages with the same key as installed packages
-	# b) contains all unmasked packages
-	# c) contains masked installed packages
-	# d) is the first item
-
-	preferred_installed = []
-	preferred_in_graph = []
-	preferred_any_slot = []
-	preferred_non_installed = []
-	unsat_use_in_graph = []
-	unsat_use_installed = []
-	unsat_use_non_installed = []
-	other = []
-
-	# unsat_use_* must come after preferred_non_installed
-	# for correct ordering in cases like || ( foo[a] foo[b] ).
-	choice_bins = (
-		preferred_in_graph,
-		preferred_installed,
-		preferred_any_slot,
-		preferred_non_installed,
-		unsat_use_in_graph,
-		unsat_use_installed,
-		unsat_use_non_installed,
-		other,
-	)
-
-	# Alias the trees we'll be checking availability against
-	parent   = trees[myroot].get("parent")
-	priority = trees[myroot].get("priority")
-	graph_db = trees[myroot].get("graph_db")
-	vardb = None
-	if "vartree" in trees[myroot]:
-		vardb = trees[myroot]["vartree"].dbapi
-	if use_binaries:
-		mydbapi = trees[myroot]["bintree"].dbapi
-	else:
-		mydbapi = trees[myroot]["porttree"].dbapi
-
-	# Sort the deps into installed, not installed but already 
-	# in the graph and other, not installed and not in the graph
-	# and other, with values of [[required_atom], availablility]
-	for x, satisfied in zip(deps, satisfieds):
-		if isinstance(x, list):
-			atoms = dep_zapdeps(x, satisfied, myroot,
-				use_binaries=use_binaries, trees=trees)
-		else:
-			atoms = [x]
-		if vardb is None:
-			# When called by repoman, we can simply return the first choice
-			# because dep_eval() handles preference selection.
-			return atoms
-
-		all_available = True
-		all_use_satisfied = True
-		slot_map = {}
-		cp_map = {}
-		for atom in atoms:
-			if atom.blocker:
-				continue
-			# Ignore USE dependencies here since we don't want USE
-			# settings to adversely affect || preference evaluation.
-			avail_pkg = mydbapi.match(atom.without_use)
-			if avail_pkg:
-				avail_pkg = avail_pkg[-1] # highest (ascending order)
-				avail_slot = dep.Atom("%s:%s" % (atom.cp,
-					mydbapi.aux_get(avail_pkg, ["SLOT"])[0]))
-			if not avail_pkg:
-				all_available = False
-				all_use_satisfied = False
-				break
-
-			if atom.use:
-				avail_pkg_use = mydbapi.match(atom)
-				if not avail_pkg_use:
-					all_use_satisfied = False
-				else:
-					# highest (ascending order)
-					avail_pkg_use = avail_pkg_use[-1]
-					if avail_pkg_use != avail_pkg:
-						avail_pkg = avail_pkg_use
-						avail_slot = dep.Atom("%s:%s" % (atom.cp,
-							mydbapi.aux_get(avail_pkg, ["SLOT"])[0]))
-
-			slot_map[avail_slot] = avail_pkg
-			pkg_cp = cpv_getkey(avail_pkg)
-			highest_cpv = cp_map.get(pkg_cp)
-			if highest_cpv is None or \
-				pkgcmp(catpkgsplit(avail_pkg)[1:],
-				catpkgsplit(highest_cpv)[1:]) > 0:
-				cp_map[pkg_cp] = avail_pkg
-
-		this_choice = (atoms, slot_map, cp_map, all_available)
-		if all_available:
-			# The "all installed" criterion is not version or slot specific.
-			# If any version of a package is already in the graph then we
-			# assume that it is preferred over other possible packages choices.
-			all_installed = True
-			for atom in set(dep.Atom(atom.cp) for atom in atoms \
-				if not atom.blocker):
-				# New-style virtuals have zero cost to install.
-				if not vardb.match(atom) and not atom.startswith("virtual/"):
-					all_installed = False
-					break
-			all_installed_slots = False
-			if all_installed:
-				all_installed_slots = True
-				for slot_atom in slot_map:
-					# New-style virtuals have zero cost to install.
-					if not vardb.match(slot_atom) and \
-						not slot_atom.startswith("virtual/"):
-						all_installed_slots = False
-						break
-			if graph_db is None:
-				if all_use_satisfied:
-					if all_installed:
-						if all_installed_slots:
-							preferred_installed.append(this_choice)
-						else:
-							preferred_any_slot.append(this_choice)
-					else:
-						preferred_non_installed.append(this_choice)
-				else:
-					if all_installed_slots:
-						unsat_use_installed.append(this_choice)
-					else:
-						unsat_use_non_installed.append(this_choice)
-			else:
-				all_in_graph = True
-				for slot_atom in slot_map:
-					# New-style virtuals have zero cost to install.
-					if not graph_db.match(slot_atom) and \
-						not slot_atom.startswith("virtual/"):
-						all_in_graph = False
-						break
-				circular_atom = None
-				if all_in_graph:
-					if parent is None or priority is None:
-						pass
-					elif priority.buildtime:
-						# Check if the atom would result in a direct circular
-						# dependency and try to avoid that if it seems likely
-						# to be unresolvable. This is only relevant for
-						# buildtime deps that aren't already satisfied by an
-						# installed package.
-						cpv_slot_list = [parent]
-						for atom in atoms:
-							if atom.blocker:
-								continue
-							if vardb.match(atom):
-								# If the atom is satisfied by an installed
-								# version then it's not a circular dep.
-								continue
-							if atom.cp != parent.cp:
-								continue
-							if match_from_list(atom, cpv_slot_list):
-								circular_atom = atom
-								break
-				if circular_atom is not None:
-					other.append(this_choice)
-				else:
-					if all_use_satisfied:
-						if all_in_graph:
-							preferred_in_graph.append(this_choice)
-						elif all_installed:
-							if all_installed_slots:
-								preferred_installed.append(this_choice)
-							else:
-								preferred_any_slot.append(this_choice)
-						else:
-							preferred_non_installed.append(this_choice)
-					else:
-						if all_in_graph:
-							unsat_use_in_graph.append(this_choice)
-						elif all_installed_slots:
-							unsat_use_installed.append(this_choice)
-						else:
-							unsat_use_non_installed.append(this_choice)
-		else:
-			other.append(this_choice)
-
-	# Prefer choices which contain upgrades to higher slots. This helps
-	# for deps such as || ( foo:1 foo:2 ), where we want to prefer the
-	# atom which matches the higher version rather than the atom furthest
-	# to the left. Sorting is done separately for each of choice_bins, so
-	# as not to interfere with the ordering of the bins. Because of the
-	# bin separation, the main function of this code is to allow
-	# --depclean to remove old slots (rather than to pull in new slots).
-	for choices in choice_bins:
-		if len(choices) < 2:
-			continue
-		for choice_1 in choices[1:]:
-			atoms_1, slot_map_1, cp_map_1, all_available_1 = choice_1
-			cps = set(cp_map_1)
-			for choice_2 in choices:
-				if choice_1 is choice_2:
-					# choice_1 will not be promoted, so move on
-					break
-				atoms_2, slot_map_2, cp_map_2, all_available_2 = choice_2
-				intersecting_cps = cps.intersection(cp_map_2)
-				if not intersecting_cps:
-					continue
-				has_upgrade = False
-				has_downgrade = False
-				for cp in intersecting_cps:
-					version_1 = cp_map_1[cp]
-					version_2 = cp_map_2[cp]
-					difference = pkgcmp(catpkgsplit(version_1)[1:],
-						catpkgsplit(version_2)[1:])
-					if difference != 0:
-						if difference > 0:
-							has_upgrade = True
-						else:
-							has_downgrade = True
-							break
-				if has_upgrade and not has_downgrade:
-					# promote choice_1 in front of choice_2
-					choices.remove(choice_1)
-					index_2 = choices.index(choice_2)
-					choices.insert(index_2, choice_1)
-					break
-
-	for allow_masked in (False, True):
-		for choices in choice_bins:
-			for atoms, slot_map, cp_map, all_available in choices:
-				if all_available or allow_masked:
-					return atoms
-
-	assert(False) # This point should not be reachable
-
-def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
-	use_cache=1, use_binaries=0, myroot="/", trees=None):
-	"""Takes a depend string and parses the condition."""
-	edebug = mysettings.get("PORTAGE_DEBUG", None) == "1"
-	#check_config_instance(mysettings)
-	if trees is None:
-		trees = globals()["db"]
-	if use=="yes":
-		if myuse is None:
-			#default behavior
-			myusesplit = mysettings["PORTAGE_USE"].split()
-		else:
-			myusesplit = myuse
-			# We've been given useflags to use.
-			#print "USE FLAGS PASSED IN."
-			#print myuse
-			#if "bindist" in myusesplit:
-			#	print "BINDIST is set!"
-			#else:
-			#	print "BINDIST NOT set."
-	else:
-		#we are being run by autouse(), don't consult USE vars yet.
-		# WE ALSO CANNOT USE SETTINGS
-		myusesplit=[]
-
-	#convert parenthesis to sublists
-	try:
-		mysplit = portage.dep.paren_reduce(depstring)
-	except portage.exception.InvalidDependString as e:
-		return [0, str(e)]
-
-	mymasks = set()
-	useforce = set()
-	useforce.add(mysettings["ARCH"])
-	if use == "all":
-		# This masking/forcing is only for repoman.  In other cases, relevant
-		# masking/forcing should have already been applied via
-		# config.regenerate().  Also, binary or installed packages may have
-		# been built with flags that are now masked, and it would be
-		# inconsistent to mask them now.  Additionally, myuse may consist of
-		# flags from a parent package that is being merged to a $ROOT that is
-		# different from the one that mysettings represents.
-		mymasks.update(mysettings.usemask)
-		mymasks.update(mysettings.archlist())
-		mymasks.discard(mysettings["ARCH"])
-		useforce.update(mysettings.useforce)
-		useforce.difference_update(mymasks)
-	try:
-		mysplit = portage.dep.use_reduce(mysplit, uselist=myusesplit,
-			masklist=mymasks, matchall=(use=="all"), excludeall=useforce)
-	except portage.exception.InvalidDependString as e:
-		return [0, str(e)]
-
-	# Do the || conversions
-	mysplit=portage.dep.dep_opconvert(mysplit)
-
-	if mysplit == []:
-		#dependencies were reduced to nothing
-		return [1,[]]
-
-	# Recursively expand new-style virtuals so as to
-	# collapse one or more levels of indirection.
-	try:
-		mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings,
-			use=use, mode=mode, myuse=myuse,
-			use_force=useforce, use_mask=mymasks, use_cache=use_cache,
-			use_binaries=use_binaries, myroot=myroot, trees=trees)
-	except portage.exception.ParseError as e:
-		return [0, str(e)]
-
-	mysplit2=mysplit[:]
-	mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache)
-	if mysplit2 is None:
-		return [0, _("Invalid token")]
-
-	writemsg("\n\n\n", 1)
-	writemsg("mysplit:  %s\n" % (mysplit), 1)
-	writemsg("mysplit2: %s\n" % (mysplit2), 1)
-
-	try:
-		selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot,
-			use_binaries=use_binaries, trees=trees)
-	except portage.exception.InvalidAtom as e:
-		if portage.dep._dep_check_strict:
-			raise # This shouldn't happen.
-		# dbapi.match() failed due to an invalid atom in
-		# the dependencies of an installed package.
-		return [0, _("Invalid atom: '%s'") % (e,)]
-
-	return [1, selected_atoms]
-
-def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
-	"Reduces the deplist to ones and zeros"
-	deplist=mydeplist[:]
-	for mypos, token in enumerate(deplist):
-		if isinstance(deplist[mypos], list):
-			#recurse
-			deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
-		elif deplist[mypos]=="||":
-			pass
-		elif token[:1] == "!":
-			deplist[mypos] = False
-		else:
-			mykey = deplist[mypos].cp
-			if mysettings and mykey in mysettings.pprovideddict and \
-			        match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
-				deplist[mypos]=True
-			elif mydbapi is None:
-				# Assume nothing is satisfied.  This forces dep_zapdeps to
-				# return all of deps the deps that have been selected
-				# (excluding those satisfied by package.provided).
-				deplist[mypos] = False
-			else:
-				if mode:
-					x = mydbapi.xmatch(mode, deplist[mypos])
-					if mode.startswith("minimum-"):
-						mydep = []
-						if x:
-							mydep.append(x)
-					else:
-						mydep = x
-				else:
-					mydep=mydbapi.match(deplist[mypos],use_cache=use_cache)
-				if mydep!=None:
-					tmp=(len(mydep)>=1)
-					if deplist[mypos][0]=="!":
-						tmp=False
-					deplist[mypos]=tmp
-				else:
-					#encountered invalid string
-					return None
-	return deplist
-
-def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False):
-	from portage.util import grablines
-	if settings is None:
-		settings = globals()["settings"]
-	if portdb is None:
-		portdb = globals()["portdb"]
-	mysplit = catpkgsplit(mycpv)
-	if not mysplit:
-		raise ValueError(_("invalid CPV: %s") % mycpv)
-	if metadata is None:
-		db_keys = list(portdb._aux_cache_keys)
-		try:
-			metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
-		except KeyError:
-			if not portdb.cpv_exists(mycpv):
-				raise
-	if metadata is None:
-		# Can't access SLOT due to corruption.
-		cpv_slot_list = [mycpv]
-	else:
-		cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
-	mycp=mysplit[0]+"/"+mysplit[1]
-
-	# XXX- This is a temporary duplicate of code from the config constructor.
-	locations = [os.path.join(settings["PORTDIR"], "profiles")]
-	locations.extend(settings.profiles)
-	for ov in settings["PORTDIR_OVERLAY"].split():
-		profdir = os.path.join(normalize_path(ov), "profiles")
-		if os.path.isdir(profdir):
-			locations.append(profdir)
-	locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
-		USER_CONFIG_PATH))
-	locations.reverse()
-	pmasklists = [(x, grablines(os.path.join(x, "package.mask"), recursive=1)) for x in locations]
-
-	if mycp in settings.pmaskdict:
-		for x in settings.pmaskdict[mycp]:
-			if match_from_list(x, cpv_slot_list):
-				for pmask in pmasklists:
-					comment = ""
-					comment_valid = -1
-					pmask_filename = os.path.join(pmask[0], "package.mask")
-					for i in range(len(pmask[1])):
-						l = pmask[1][i].strip()
-						if l == "":
-							comment = ""
-							comment_valid = -1
-						elif l[0] == "#":
-							comment += (l+"\n")
-							comment_valid = i + 1
-						elif l == x:
-							if comment_valid != i:
-								comment = ""
-							if return_location:
-								return (comment, pmask_filename)
-							else:
-								return comment
-						elif comment_valid != -1:
-							# Apparently this comment applies to muliple masks, so
-							# it remains valid until a blank line is encountered.
-							comment_valid += 1
-	if return_location:
-		return (None, None)
-	else:
-		return None
-
-def getmaskingstatus(mycpv, settings=None, portdb=None):
-	if settings is None:
-		settings = config(clone=globals()["settings"])
-	if portdb is None:
-		portdb = globals()["portdb"]
-
-	metadata = None
-	installed = False
-	if not isinstance(mycpv, basestring):
-		# emerge passed in a Package instance
-		pkg = mycpv
-		mycpv = pkg.cpv
-		metadata = pkg.metadata
-		installed = pkg.installed
-
-	mysplit = catpkgsplit(mycpv)
-	if not mysplit:
-		raise ValueError(_("invalid CPV: %s") % mycpv)
-	if metadata is None:
-		db_keys = list(portdb._aux_cache_keys)
-		try:
-			metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
-		except KeyError:
-			if not portdb.cpv_exists(mycpv):
-				raise
-			return ["corruption"]
-		if "?" in metadata["LICENSE"]:
-			settings.setcpv(mycpv, mydb=metadata)
-			metadata["USE"] = settings["PORTAGE_USE"]
-		else:
-			metadata["USE"] = ""
-	mycp=mysplit[0]+"/"+mysplit[1]
-
-	rValue = []
-
-	# profile checking
-	if settings._getProfileMaskAtom(mycpv, metadata):
-		rValue.append("profile")
-
-	# package.mask checking
-	if settings._getMaskAtom(mycpv, metadata):
-		rValue.append("package.mask")
-
-	# keywords checking
-	eapi = metadata["EAPI"]
-	mygroups = settings._getKeywords(mycpv, metadata)
-	licenses = metadata["LICENSE"]
-	properties = metadata["PROPERTIES"]
-	slot = metadata["SLOT"]
-	if eapi.startswith("-"):
-		eapi = eapi[1:]
-	if not eapi_is_supported(eapi):
-		return ["EAPI %s" % eapi]
-	elif _eapi_is_deprecated(eapi) and not installed:
-		return ["EAPI %s" % eapi]
-	egroups = settings.configdict["backupenv"].get(
-		"ACCEPT_KEYWORDS", "").split()
-	pgroups = settings["ACCEPT_KEYWORDS"].split()
-	myarch = settings["ARCH"]
-	if pgroups and myarch not in pgroups:
-		"""For operating systems other than Linux, ARCH is not necessarily a
-		valid keyword."""
-		myarch = pgroups[0].lstrip("~")
-
-	cp = cpv_getkey(mycpv)
-	pkgdict = settings.pkeywordsdict.get(cp)
-	matches = False
-	if pkgdict:
-		cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
-		for atom, pkgkeywords in pkgdict.items():
-			if match_from_list(atom, cpv_slot_list):
-				matches = True
-				pgroups.extend(pkgkeywords)
-	if matches or egroups:
-		pgroups.extend(egroups)
-		inc_pgroups = set()
-		for x in pgroups:
-			if x.startswith("-"):
-				if x == "-*":
-					inc_pgroups.clear()
-				else:
-					inc_pgroups.discard(x[1:])
-			else:
-				inc_pgroups.add(x)
-		pgroups = inc_pgroups
-		del inc_pgroups
-
-	kmask = "missing"
-
-	if '**' in pgroups:
-		kmask = None
-	else:
-		for keyword in pgroups:
-			if keyword in mygroups:
-				kmask = None
-				break
-
-	if kmask:
-		fallback = None
-		for gp in mygroups:
-			if gp=="*":
-				kmask=None
-				break
-			elif gp=="-"+myarch and myarch in pgroups:
-				kmask="-"+myarch
-				break
-			elif gp=="~"+myarch and myarch in pgroups:
-				kmask="~"+myarch
-				break
-
-	try:
-		missing_licenses = settings._getMissingLicenses(mycpv, metadata)
-		if missing_licenses:
-			allowed_tokens = set(["||", "(", ")"])
-			allowed_tokens.update(missing_licenses)
-			license_split = licenses.split()
-			license_split = [x for x in license_split \
-				if x in allowed_tokens]
-			msg = license_split[:]
-			msg.append("license(s)")
-			rValue.append(" ".join(msg))
-	except portage.exception.InvalidDependString as e:
-		rValue.append("LICENSE: "+str(e))
-
-	try:
-		missing_properties = settings._getMissingProperties(mycpv, metadata)
-		if missing_properties:
-			allowed_tokens = set(["||", "(", ")"])
-			allowed_tokens.update(missing_properties)
-			properties_split = properties.split()
-			properties_split = [x for x in properties_split \
-					if x in allowed_tokens]
-			msg = properties_split[:]
-			msg.append("properties")
-			rValue.append(" ".join(msg))
-	except portage.exception.InvalidDependString as e:
-		rValue.append("PROPERTIES: "+str(e))
-
-	# Only show KEYWORDS masks for installed packages
-	# if they're not masked for any other reason.
-	if kmask and (not installed or not rValue):
-		rValue.append(kmask+" keyword")
-
-	return rValue
-
 auxdbkeys = (
   'DEPEND',    'RDEPEND',   'SLOT',      'SRC_URI',
 	'RESTRICT',  'HOMEPAGE',  'LICENSE',   'DESCRIPTION',

Modified: main/branches/prefix/pym/portage/dbapi/__init__.py
===================================================================
--- main/branches/prefix/pym/portage/dbapi/__init__.py	2010-02-27 19:26:00 UTC (rev 15482)
+++ main/branches/prefix/pym/portage/dbapi/__init__.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -8,7 +8,7 @@
 
 import portage
 portage.proxy.lazyimport.lazyimport(globals(),
-	'portage.dbapi.dep_expand:dep_expand',
+	'portage.dbapi.dep_expand:_dep_expand',
 	'portage.dep:match_from_list',
 	'portage.locks:unlockfile',
 	'portage.output:colorize',
@@ -122,7 +122,7 @@
 		Returns:
 			a list of packages that match origdep
 		"""
-		mydep = dep_expand(origdep, mydb=self, settings=self.settings)
+		mydep = _dep_expand(origdep, mydb=self, settings=self.settings)
 		return list(self._iter_match(mydep,
 			self.cp_list(mydep.cp, use_cache=use_cache)))
 

Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
===================================================================
--- main/branches/prefix/pym/portage/dbapi/vartree.py	2010-02-27 19:26:00 UTC (rev 15482)
+++ main/branches/prefix/pym/portage/dbapi/vartree.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -40,8 +40,9 @@
 	InvalidData, InvalidPackageName, \
 	FileNotFound, PermissionDenied, UnsupportedAPIException
 from portage.localization import _
+from portage.util.movefile import movefile
 
-from portage import abssymlink, movefile, _movefile, bsd_chflags
+from portage import abssymlink, _movefile, bsd_chflags
 
 # This is a special version of the os module, wrapped for unicode support.
 from portage import os

Deleted: main/branches/prefix/pym/portage/dep.py
===================================================================
--- main/branches/prefix/pym/portage/dep.py	2010-02-27 19:26:00 UTC (rev 15482)
+++ main/branches/prefix/pym/portage/dep.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -1,1203 +0,0 @@
-# deps.py -- Portage dependency resolution functions
-# Copyright 2003-2004 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Id$
-
-__all__ = [
-	'Atom', 'best_match_to_list', 'cpvequal',
-	'dep_getcpv', 'dep_getkey', 'dep_getslot',
-	'dep_getusedeps', 'dep_opconvert', 'flatten',
-	'get_operator', 'isjustname', 'isspecific',
-	'isvalidatom', 'match_from_list', 'match_to_list',
-	'paren_enclose', 'paren_normalize', 'paren_reduce',
-	'remove_slot', 'strip_empty', 'use_reduce'
-]
-
-# DEPEND SYNTAX:
-#
-# 'use?' only affects the immediately following word!
-# Nesting is the only legal way to form multiple '[!]use?' requirements.
-#
-# Where: 'a' and 'b' are use flags, and 'z' is a depend atom.
-#
-# "a? z"           -- If 'a' in [use], then b is valid.
-# "a? ( z )"       -- Syntax with parenthesis.
-# "a? b? z"        -- Deprecated.
-# "a? ( b? z )"    -- Valid
-# "a? ( b? ( z ) ) -- Valid
-#
-
-import re, sys
-import warnings
-from itertools import chain
-import portage.exception
-from portage.exception import InvalidData, InvalidAtom
-from portage.localization import _
-from portage.versions import catpkgsplit, catsplit, \
-	pkgcmp, pkgsplit, ververify, _cp, _cpv
-import portage.cache.mappings
-
-if sys.hexversion >= 0x3000000:
-	basestring = str
-
-def cpvequal(cpv1, cpv2):
-	"""
-	
-	@param cpv1: CategoryPackageVersion (no operators) Example: "sys-apps/portage-2.1"
-	@type cpv1: String
-	@param cpv2: CategoryPackageVersion (no operators) Example: "sys-apps/portage-2.1"
-	@type cpv2: String
-	@rtype: Boolean
-	@returns:
-	1.  True if cpv1 = cpv2
-	2.  False Otherwise
-	3.  Throws PortageException if cpv1 or cpv2 is not a CPV
-
-	Example Usage:
-	>>> from portage.dep import cpvequal
-	>>> cpvequal("sys-apps/portage-2.1","sys-apps/portage-2.1")
-	>>> True
-
-	"""
-
-	split1 = catpkgsplit(cpv1)
-	split2 = catpkgsplit(cpv2)
-	
-	if not split1 or not split2:
-		raise portage.exception.PortageException(_("Invalid data '%s, %s', parameter was not a CPV") % (cpv1, cpv2))
-	
-	if split1[0] != split2[0]:
-		return False
-	
-	return (pkgcmp(split1[1:], split2[1:]) == 0)
-
-def strip_empty(myarr):
-	"""
-	Strip all empty elements from an array
-
-	@param myarr: The list of elements
-	@type myarr: List
-	@rtype: Array
-	@return: The array with empty elements removed
-	"""
-	return [x for x in myarr if x]
-
-_paren_whitespace_re = re.compile(r'\S(\(|\))|(\(|\))\S')
-
-def paren_reduce(mystr,tokenize=1):
-	"""
-	Take a string and convert all paren enclosed entities into sublists, optionally
-	futher splitting the list elements by spaces.
-
-	Example usage:
-		>>> paren_reduce('foobar foo ( bar baz )',1)
-		['foobar', 'foo', ['bar', 'baz']]
-		>>> paren_reduce('foobar foo ( bar baz )',0)
-		['foobar foo ', [' bar baz ']]
-
-	@param mystr: The string to reduce
-	@type mystr: String
-	@param tokenize: Split on spaces to produces further list breakdown
-	@type tokenize: Integer
-	@rtype: Array
-	@return: The reduced string in an array
-	"""
-	global _dep_check_strict, _paren_whitespace_re
-	if _dep_check_strict:
-		m = _paren_whitespace_re.search(mystr)
-		if m is not None:
-			raise portage.exception.InvalidDependString(
-				_("missing space by parenthesis: '%s'") % m.group(0))
-	mylist = []
-	while mystr:
-		left_paren = mystr.find("(")
-		has_left_paren = left_paren != -1
-		right_paren = mystr.find(")")
-		has_right_paren = right_paren != -1
-		if not has_left_paren and not has_right_paren:
-			freesec = mystr
-			subsec = None
-			tail = ""
-		elif mystr[0] == ")":
-			return [mylist,mystr[1:]]
-		elif has_left_paren and not has_right_paren:
-			raise portage.exception.InvalidDependString(
-				_("missing right parenthesis: '%s'") % mystr)
-		elif has_left_paren and left_paren < right_paren:
-			freesec,subsec = mystr.split("(",1)
-			sublist = paren_reduce(subsec, tokenize=tokenize)
-			if len(sublist) != 2:
-				raise portage.exception.InvalidDependString(
-					_("malformed syntax: '%s'") % mystr)
-			subsec, tail = sublist
-		else:
-			subsec,tail = mystr.split(")",1)
-			if tokenize:
-				subsec = strip_empty(subsec.split(" "))
-				return [mylist+subsec,tail]
-			return mylist+[subsec],tail
-		if not isinstance(tail, basestring):
-			raise portage.exception.InvalidDependString(
-				_("malformed syntax: '%s'") % mystr)
-		mystr = tail
-		if freesec:
-			if tokenize:
-				mylist = mylist + strip_empty(freesec.split(" "))
-			else:
-				mylist = mylist + [freesec]
-		if subsec is not None:
-			mylist = mylist + [subsec]
-	return mylist
-
-class paren_normalize(list):
-	"""Take a dependency structure as returned by paren_reduce or use_reduce
-	and generate an equivalent structure that has no redundant lists."""
-	def __init__(self, src):
-		list.__init__(self)
-		self._zap_parens(src, self)
-
-	def _zap_parens(self, src, dest, disjunction=False):
-		if not src:
-			return dest
-		i = iter(src)
-		for x in i:
-			if isinstance(x, basestring):
-				if x == '||':
-					x = self._zap_parens(next(i), [], disjunction=True)
-					if len(x) == 1:
-						dest.append(x[0])
-					else:
-						dest.append("||")
-						dest.append(x)
-				elif x.endswith("?"):
-					dest.append(x)
-					dest.append(self._zap_parens(next(i), []))
-				else:
-					dest.append(x)
-			else:
-				if disjunction:
-					x = self._zap_parens(x, [])
-					if len(x) == 1:
-						dest.append(x[0])
-					else:
-						dest.append(x)
-				else:
-					self._zap_parens(x, dest)
-		return dest
-
-def paren_enclose(mylist):
-	"""
-	Convert a list to a string with sublists enclosed with parens.
-
-	Example usage:
-		>>> test = ['foobar','foo',['bar','baz']]
-		>>> paren_enclose(test)
-		'foobar foo ( bar baz )'
-
-	@param mylist: The list
-	@type mylist: List
-	@rtype: String
-	@return: The paren enclosed string
-	"""
-	mystrparts = []
-	for x in mylist:
-		if isinstance(x, list):
-			mystrparts.append("( "+paren_enclose(x)+" )")
-		else:
-			mystrparts.append(x)
-	return " ".join(mystrparts)
-
-# This is just for use by emerge so that it can enable a backward compatibility
-# mode in order to gracefully deal with installed packages that have invalid
-# atoms or dep syntax.  For backward compatibility with api consumers, strict
-# behavior will be explicitly enabled as necessary.
-_dep_check_strict = False
-
-def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]):
-	"""
-	Takes a paren_reduce'd array and reduces the use? conditionals out
-	leaving an array with subarrays
-
-	@param deparray: paren_reduce'd list of deps
-	@type deparray: List
-	@param uselist: List of use flags
-	@type uselist: List
-	@param masklist: List of masked flags
-	@type masklist: List
-	@param matchall: Resolve all conditional deps unconditionally.  Used by repoman
-	@type matchall: Integer
-	@rtype: List
-	@return: The use reduced depend array
-	"""
-	# Quick validity checks
-	for x, y in enumerate(deparray):
-		if y == '||':
-			if len(deparray) - 1 == x or not isinstance(deparray[x+1], list):
-				raise portage.exception.InvalidDependString(_('%(dep)s missing atom list in "%(deparray)s"') % {"dep": deparray[x], "deparray": paren_enclose(deparray)})
-	if deparray and deparray[-1] and deparray[-1][-1] == "?":
-		raise portage.exception.InvalidDependString(_('Conditional without target in "%s"') % paren_enclose(deparray))
-
-	global _dep_check_strict
-
-	mydeparray = deparray[:]
-	rlist = []
-	while mydeparray:
-		head = mydeparray.pop(0)
-
-		if not isinstance(head, basestring):
-			additions = use_reduce(head, uselist, masklist, matchall, excludeall)
-			if additions:
-				rlist.append(additions)
-			elif rlist and rlist[-1] == "||":
-			#XXX: Currently some DEPEND strings have || lists without default atoms.
-			#	raise portage.exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"")
-				rlist.append([])
-
-		else:
-			if head[-1:] == "?": # Use reduce next group on fail.
-				# Pull any other use conditions and the following atom or list into a separate array
-				newdeparray = [head]
-				while isinstance(newdeparray[-1], basestring) and \
-					newdeparray[-1][-1:] == "?":
-					if mydeparray:
-						newdeparray.append(mydeparray.pop(0))
-					else:
-						raise ValueError(_("Conditional with no target."))
-
-				# Deprecation checks
-				warned = 0
-				if len(newdeparray[-1]) == 0:
-					sys.stderr.write(_("Note: Empty target in string. (Deprecated)\n"))
-					warned = 1
-				if len(newdeparray) != 2:
-					sys.stderr.write(_("Note: Nested use flags without parenthesis (Deprecated)\n"))
-					warned = 1
-				if warned:
-					sys.stderr.write("  --> "+" ".join(map(str,[head]+newdeparray))+"\n")
-
-				# Check that each flag matches
-				ismatch = True
-				missing_flag = False
-				for head in newdeparray[:-1]:
-					head = head[:-1]
-					if not head:
-						missing_flag = True
-						break
-					if head.startswith("!"):
-						head_key = head[1:]
-						if not head_key:
-							missing_flag = True
-							break
-						if not matchall and head_key in uselist or \
-							head_key in excludeall:
-							ismatch = False
-							break
-					elif head not in masklist:
-						if not matchall and head not in uselist:
-							ismatch = False
-							break
-					else:
-						ismatch = False
-				if missing_flag:
-					raise portage.exception.InvalidDependString(
-						_('Conditional without flag: "') + \
-						paren_enclose([head+"?", newdeparray[-1]])+"\"")
-
-				# If they all match, process the target
-				if ismatch:
-					target = newdeparray[-1]
-					if isinstance(target, list):
-						additions = use_reduce(target, uselist, masklist, matchall, excludeall)
-						if additions:
-							rlist.append(additions)
-					elif not _dep_check_strict:
-						# The old deprecated behavior.
-						rlist.append(target)
-					else:
-						raise portage.exception.InvalidDependString(
-							_("Conditional without parenthesis: '%s?'") % head)
-
-			else:
-				rlist += [head]
-
-	return rlist
-
-def dep_opconvert(deplist):
-	"""
-	Iterate recursively through a list of deps, if the
-	dep is a '||' or '&&' operator, combine it with the
-	list of deps that follows..
-
-	Example usage:
-		>>> test = ["blah", "||", ["foo", "bar", "baz"]]
-		>>> dep_opconvert(test)
-		['blah', ['||', 'foo', 'bar', 'baz']]
-
-	@param deplist: A list of deps to format
-	@type mydep: List
-	@rtype: List
-	@return:
-		The new list with the new ordering
-	"""
-
-	retlist = []
-	x = 0
-	while x != len(deplist):
-		if isinstance(deplist[x], list):
-			retlist.append(dep_opconvert(deplist[x]))
-		elif deplist[x] == "||" or deplist[x] == "&&":
-			retlist.append([deplist[x]] + dep_opconvert(deplist[x+1]))
-			x += 1
-		else:
-			retlist.append(deplist[x])
-		x += 1
-	return retlist
-
-def flatten(mylist):
-	"""
-	Recursively traverse nested lists and return a single list containing
-	all non-list elements that are found.
-
-	Example usage:
-		>>> flatten([1, [2, 3, [4]]])
-		[1, 2, 3, 4]
-
-	@param mylist: A list containing nested lists and non-list elements.
-	@type mylist: List
-	@rtype: List
-	@return: A single list containing only non-list elements.
-	"""
-	newlist = []
-	for x in mylist:
-		if isinstance(x, list):
-			newlist.extend(flatten(x))
-		else:
-			newlist.append(x)
-	return newlist
-
-class _use_dep(object):
-
-	__slots__ = ("__weakref__", "conditional",
-		"disabled", "enabled", "tokens", "required")
-
-	_conditionals_class = portage.cache.mappings.slot_dict_class(
-		("disabled", "enabled", "equal", "not_equal"), prefix="")
-
-	_valid_use_re = re.compile(r'^[^-?!=][^?!=]*$')
-
-	def __init__(self, use):
-		enabled_flags = []
-		disabled_flags = []
-		conditional = self._conditionals_class()
-		for k in conditional.allowed_keys:
-			conditional[k] = []
-
-		for x in use:
-			last_char = x[-1:]
-			first_char = x[:1]
-
-			if "?" == last_char:
-				if "!" == first_char:
-					conditional.disabled.append(
-						self._validate_flag(x, x[1:-1]))
-				else:
-					conditional.enabled.append(
-						self._validate_flag(x, x[:-1]))
-
-			elif "=" == last_char:
-				if "!" == first_char:
-					conditional.not_equal.append(
-						self._validate_flag(x, x[1:-1]))
-				else:
-					conditional.equal.append(
-						self._validate_flag(x, x[:-1]))
-
-			else:
-				if "-" == first_char:
-					disabled_flags.append(self._validate_flag(x, x[1:]))
-				else:
-					enabled_flags.append(self._validate_flag(x, x))
-
-		self.tokens = use
-		if not isinstance(self.tokens, tuple):
-			self.tokens = tuple(self.tokens)
-
-		self.required = frozenset(chain(
-			enabled_flags,
-			disabled_flags,
-			*conditional.values()
-		))
-
-		self.enabled = frozenset(enabled_flags)
-		self.disabled = frozenset(disabled_flags)
-		self.conditional = None
-
-		for v in conditional.values():
-			if v:
-				for k, v in conditional.items():
-					conditional[k] = frozenset(v)
-				self.conditional = conditional
-				break
-
-	def _validate_flag(self, token, flag):
-		if self._valid_use_re.match(flag) is None:
-			raise InvalidAtom(_("Invalid use dep: '%s'") % (token,))
-		return flag
-
-	def __bool__(self):
-		return bool(self.tokens)
-
-	if sys.hexversion < 0x3000000:
-		__nonzero__ = __bool__
-
-	def __str__(self):
-		if not self.tokens:
-			return ""
-		return "[%s]" % (",".join(self.tokens),)
-
-	def __repr__(self):
-		return "portage.dep._use_dep(%s)" % repr(self.tokens)
-
-	def evaluate_conditionals(self, use):
-		"""
-		Create a new instance with conditionals evaluated.
-
-		Conditional evaluation behavior:
-
-			parent state   conditional   result
-
-			 x              x?            x
-			-x              x?
-			 x             !x?
-			-x             !x?           -x
-
-			 x              x=            x
-			-x              x=           -x
-			 x             !x=           -x
-			-x             !x=            x
-
-		Conditional syntax examples:
-
-			Compact Form        Equivalent Expanded Form
-
-			foo[bar?]           bar? ( foo[bar]  ) !bar? ( foo       )
-			foo[!bar?]          bar? ( foo       ) !bar? ( foo[-bar] )
-			foo[bar=]           bar? ( foo[bar]  ) !bar? ( foo[-bar] )
-			foo[!bar=]          bar? ( foo[-bar] ) !bar? ( foo[bar]  )
-
-		"""
-		tokens = []
-
-		conditional = self.conditional
-		tokens.extend(self.enabled)
-		tokens.extend("-" + x for x in self.disabled)
-		tokens.extend(x for x in conditional.enabled if x in use)
-		tokens.extend("-" + x for x in conditional.disabled if x not in use)
-
-		tokens.extend(x for x in conditional.equal if x in use)
-		tokens.extend("-" + x for x in conditional.equal if x not in use)
-		tokens.extend("-" + x for x in conditional.not_equal if x in use)
-		tokens.extend(x for x in conditional.not_equal if x not in use)
-
-		return _use_dep(tokens)
-
-	def _eval_qa_conditionals(self, use_mask, use_force):
-		"""
-		For repoman, evaluate all possible combinations within the constraints
-		of the given use.force and use.mask settings. The result may seem
-		ambiguous in the sense that the same flag can be in both the enabled
-		and disabled sets, but this is useful within the context of how its
-		intended to be used by repoman. It is assumed that the caller has
-		already ensured that there is no intersection between the given
-		use_mask and use_force sets when necessary.
-		"""
-		tokens = []
-
-		conditional = self.conditional
-		tokens.extend(self.enabled)
-		tokens.extend("-" + x for x in self.disabled)
-		tokens.extend(x for x in conditional.enabled if x not in use_mask)
-		tokens.extend("-" + x for x in conditional.disabled if x not in use_force)
-
-		tokens.extend(x for x in conditional.equal if x not in use_mask)
-		tokens.extend("-" + x for x in conditional.equal if x not in use_force)
-		tokens.extend("-" + x for x in conditional.not_equal if x not in use_mask)
-		tokens.extend(x for x in conditional.not_equal if x not in use_force)
-
-		return _use_dep(tokens)
-
-if sys.hexversion < 0x3000000:
-	_atom_base = unicode
-else:
-	_atom_base = str
-
-class Atom(_atom_base):
-
-	"""
-	For compatibility with existing atom string manipulation code, this
-	class emulates most of the str methods that are useful with atoms.
-	"""
-
-	class _blocker(object):
-		__slots__ = ("overlap",)
-
-		class _overlap(object):
-			__slots__ = ("forbid",)
-
-			def __init__(self, forbid=False):
-				self.forbid = forbid
-
-		def __init__(self, forbid_overlap=False):
-			self.overlap = self._overlap(forbid=forbid_overlap)
-
-	def __init__(self, s):
-		if isinstance(s, Atom):
-			# This is an efficiency assertion, to ensure that the Atom
-			# constructor is not called redundantly.
-			raise TypeError(_("Expected %s, got %s") % \
-				(_atom_base, type(s)))
-
-		_atom_base.__init__(s)
-
-		if "!" == s[:1]:
-			blocker = self._blocker(forbid_overlap=("!" == s[1:2]))
-			if blocker.overlap.forbid:
-				s = s[2:]
-			else:
-				s = s[1:]
-		else:
-			blocker = False
-		self.__dict__['blocker'] = blocker
-		m = _atom_re.match(s)
-		if m is None:
-			raise InvalidAtom(self)
-
-		if m.group('op') is not None:
-			base = _atom_re.groupindex['op']
-			op = m.group(base + 1)
-			cpv = m.group(base + 2)
-			cp = m.group(base + 3)
-			if m.group(base + 4) is not None:
-				raise InvalidAtom(self)
-		elif m.group('star') is not None:
-			base = _atom_re.groupindex['star']
-			op = '=*'
-			cpv = m.group(base + 1)
-			cp = m.group(base + 2)
-			if m.group(base + 3) is not None:
-				raise InvalidAtom(self)
-		elif m.group('simple') is not None:
-			op = None
-			cpv = cp = m.group(_atom_re.groupindex['simple'] + 1)
-			if m.group(_atom_re.groupindex['simple'] + 2) is not None:
-				raise InvalidAtom(self)
-		else:
-			raise AssertionError(_("required group not found in atom: '%s'") % self)
-		self.__dict__['cp'] = cp
-		self.__dict__['cpv'] = cpv
-		self.__dict__['slot'] = m.group(_atom_re.groups - 1)
-		self.__dict__['operator'] = op
-
-		use_str = m.group(_atom_re.groups)
-		if use_str is not None:
-			use = _use_dep(dep_getusedeps(s))
-			without_use = Atom(m.group('without_use'))
-		else:
-			use = None
-			without_use = self
-
-		self.__dict__['use'] = use
-		self.__dict__['without_use'] = without_use
-
-	def __setattr__(self, name, value):
-		raise AttributeError("Atom instances are immutable",
-			self.__class__, name, value)
-
-	def intersects(self, other):
-		"""
-		Atoms with different cpv, operator or use attributes cause this method
-		to return False even though there may actually be some intersection.
-		TODO: Detect more forms of intersection.
-		@param other: The package atom to match
-		@type other: Atom
-		@rtype: Boolean
-		@return: True if this atom and the other atom intersect,
-			False otherwise.
-		"""
-		if not isinstance(other, Atom):
-			raise TypeError("expected %s, got %s" % \
-				(Atom, type(other)))
-
-		if self == other:
-			return True
-
-		if self.cp != other.cp or \
-			self.use != other.use or \
-			self.operator != other.operator or \
-			self.cpv != other.cpv:
-			return False
-
-		if self.slot is None or \
-			other.slot is None or \
-			self.slot == other.slot:
-			return True
-
-		return False
-
-	def evaluate_conditionals(self, use):
-		"""
-		Create an atom instance with any USE conditionals evaluated.
-		@param use: The set of enabled USE flags
-		@type use: set
-		@rtype: Atom
-		@return: an atom instance with any USE conditionals evaluated
-		"""
-		if not (self.use and self.use.conditional):
-			return self
-		atom = remove_slot(self)
-		if self.slot:
-			atom += ":%s" % self.slot
-		atom += str(self.use.evaluate_conditionals(use))
-		return Atom(atom)
-
-	def __copy__(self):
-		"""Immutable, so returns self."""
-		return self
-
-	def __deepcopy__(self, memo=None):
-		"""Immutable, so returns self."""
-		memo[id(self)] = self
-		return self
-
-def get_operator(mydep):
-	"""
-	Return the operator used in a depstring.
-
-	Example usage:
-		>>> from portage.dep import *
-		>>> get_operator(">=test-1.0")
-		'>='
-
-	@param mydep: The dep string to check
-	@type mydep: String
-	@rtype: String
-	@return: The operator. One of:
-		'~', '=', '>', '<', '=*', '>=', or '<='
-	"""
-	if isinstance(mydep, Atom):
-		return mydep.operator
-	try:
-		return Atom(mydep).operator
-	except InvalidAtom:
-		pass
-
-	# Fall back to legacy code for backward compatibility.
-	warnings.warn(_("%s is deprecated, use %s instead") % \
-		('portage.dep.get_operator()', 'portage.dep.Atom.operator'),
-		DeprecationWarning)
-	operator = None
-	if mydep:
-		mydep = remove_slot(mydep)
-	if not mydep:
-		return None
-	if mydep[0] == "~":
-		operator = "~"
-	elif mydep[0] == "=":
-		if mydep[-1] == "*":
-			operator = "=*"
-		else:
-			operator = "="
-	elif mydep[0] in "><":
-		if len(mydep) > 1 and mydep[1] == "=":
-			operator = mydep[0:2]
-		else:
-			operator = mydep[0]
-	else:
-		operator = None
-
-	return operator
-
-def dep_getcpv(mydep):
-	"""
-	Return the category-package-version with any operators/slot specifications stripped off
-
-	Example usage:
-		>>> dep_getcpv('>=media-libs/test-3.0')
-		'media-libs/test-3.0'
-
-	@param mydep: The depstring
-	@type mydep: String
-	@rtype: String
-	@return: The depstring with the operator removed
-	"""
-	if isinstance(mydep, Atom):
-		return mydep.cpv
-	try:
-		return Atom(mydep).cpv
-	except InvalidAtom:
-		pass
-
-	# Fall back to legacy code for backward compatibility.
-	warnings.warn(_("%s is deprecated, use %s instead") % \
-		('portage.dep.dep_getcpv()', 'portage.dep.Atom.cpv'),
-		DeprecationWarning, stacklevel=2)
-	mydep_orig = mydep
-	if mydep:
-		mydep = remove_slot(mydep)
-	if mydep and mydep[0] == "*":
-		mydep = mydep[1:]
-	if mydep and mydep[-1] == "*":
-		mydep = mydep[:-1]
-	if mydep and mydep[0] == "!":
-		if mydep[1:2] == "!":
-			mydep = mydep[2:]
-		else:
-			mydep = mydep[1:]
-	if mydep[:2] in [">=", "<="]:
-		mydep = mydep[2:]
-	elif mydep[:1] in "=<>~":
-		mydep = mydep[1:]
-	return mydep
-
-def dep_getslot(mydep):
-	"""
-	Retrieve the slot on a depend.
-
-	Example usage:
-		>>> dep_getslot('app-misc/test:3')
-		'3'
-
-	@param mydep: The depstring to retrieve the slot of
-	@type mydep: String
-	@rtype: String
-	@return: The slot
-	"""
-	slot = getattr(mydep, "slot", False)
-	if slot is not False:
-		return slot
-	colon = mydep.find(":")
-	if colon != -1:
-		bracket = mydep.find("[", colon)
-		if bracket == -1:
-			return mydep[colon+1:]
-		else:
-			return mydep[colon+1:bracket]
-	return None
-
-def remove_slot(mydep):
-	"""
-	Removes dep components from the right side of an atom:
-		* slot
-		* use
-		* repo
-	"""
-	colon = mydep.find(":")
-	if colon != -1:
-		mydep = mydep[:colon]
-	else:
-		bracket = mydep.find("[")
-		if bracket != -1:
-			mydep = mydep[:bracket]
-	return mydep
-
-def dep_getusedeps( depend ):
-	"""
-	Pull a listing of USE Dependencies out of a dep atom.
-	
-	Example usage:
-		>>> dep_getusedeps('app-misc/test:3[foo,-bar]')
-		('foo', '-bar')
-	
-	@param depend: The depstring to process
-	@type depend: String
-	@rtype: List
-	@return: List of use flags ( or [] if no flags exist )
-	"""
-	use_list = []
-	open_bracket = depend.find('[')
-	# -1 = failure (think c++ string::npos)
-	comma_separated = False
-	bracket_count = 0
-	while( open_bracket != -1 ):
-		bracket_count += 1
-		if bracket_count > 1:
-			raise InvalidAtom(_("USE Dependency with more "
-				"than one set of brackets: %s") % (depend,))
-		close_bracket = depend.find(']', open_bracket )
-		if close_bracket == -1:
-			raise InvalidAtom(_("USE Dependency with no closing bracket: %s") % depend )
-		use = depend[open_bracket + 1: close_bracket]
-		# foo[1:1] may return '' instead of None, we don't want '' in the result
-		if not use:
-			raise InvalidAtom(_("USE Dependency with "
-				"no use flag ([]): %s") % depend )
-		if not comma_separated:
-			comma_separated = "," in use
-
-		if comma_separated and bracket_count > 1:
-			raise InvalidAtom(_("USE Dependency contains a mixture of "
-				"comma and bracket separators: %s") % depend )
-
-		if comma_separated:
-			for x in use.split(","):
-				if x:
-					use_list.append(x)
-				else:
-					raise InvalidAtom(_("USE Dependency with no use "
-						"flag next to comma: %s") % depend )
-		else:
-			use_list.append(use)
-
-		# Find next use flag
-		open_bracket = depend.find( '[', open_bracket+1 )
-	return tuple(use_list)
-
-# \w is [a-zA-Z0-9_]
-
-# 2.1.3 A slot name may contain any of the characters [A-Za-z0-9+_.-].
-# It must not begin with a hyphen or a dot.
-_slot = r'([\w+][\w+.-]*)'
-_slot_re = re.compile('^' + _slot + '$', re.VERBOSE)
-
-_use = r'\[.*\]'
-_op = r'([=~]|[><]=?)'
-
-_atom_re = re.compile('^(?P<without_use>(?:' +
-	'(?P<op>' + _op + _cpv + ')|' +
-	'(?P<star>=' + _cpv + r'\*)|' +
-	'(?P<simple>' + _cp + '))(:' + _slot + ')?)(' + _use + ')?$', re.VERBOSE)
-
-def isvalidatom(atom, allow_blockers=False):
-	"""
-	Check to see if a depend atom is valid
-
-	Example usage:
-		>>> isvalidatom('media-libs/test-3.0')
-		False
-		>>> isvalidatom('>=media-libs/test-3.0')
-		True
-
-	@param atom: The depend atom to check against
-	@type atom: String or Atom
-	@rtype: Boolean
-	@return: One of the following:
-		1) False if the atom is invalid
-		2) True if the atom is valid
-	"""
-	try:
-		if not isinstance(atom, Atom):
-			atom = Atom(atom)
-		if not allow_blockers and atom.blocker:
-			return False
-		return True
-	except InvalidAtom:
-		return False
-
-def isjustname(mypkg):
-	"""
-	Checks to see if the atom is only the package name (no version parts).
-
-	Example usage:
-		>>> isjustname('=media-libs/test-3.0')
-		False
-		>>> isjustname('media-libs/test')
-		True
-
-	@param mypkg: The package atom to check
-	@param mypkg: String or Atom
-	@rtype: Integer
-	@return: One of the following:
-		1) False if the package string is not just the package name
-		2) True if it is
-	"""
-	try:
-		if not isinstance(mypkg, Atom):
-			mypkg = Atom(mypkg)
-		return mypkg == mypkg.cp
-	except InvalidAtom:
-		pass
-
-	for x in mypkg.split('-')[-2:]:
-		if ververify(x):
-			return False
-	return True
-
-def isspecific(mypkg):
-	"""
-	Checks to see if a package is in =category/package-version or
-	package-version format.
-
-	Example usage:
-		>>> isspecific('media-libs/test')
-		False
-		>>> isspecific('=media-libs/test-3.0')
-		True
-
-	@param mypkg: The package depstring to check against
-	@type mypkg: String
-	@rtype: Boolean
-	@return: One of the following:
-		1) False if the package string is not specific
-		2) True if it is
-	"""
-	try:
-		if not isinstance(mypkg, Atom):
-			mypkg = Atom(mypkg)
-		return mypkg != mypkg.cp
-	except InvalidAtom:
-		pass
-
-	# Fall back to legacy code for backward compatibility.
-	return not isjustname(mypkg)
-
-def dep_getkey(mydep):
-	"""
-	Return the category/package-name of a depstring.
-
-	Example usage:
-		>>> dep_getkey('=media-libs/test-3.0')
-		'media-libs/test'
-
-	@param mydep: The depstring to retrieve the category/package-name of
-	@type mydep: String
-	@rtype: String
-	@return: The package category/package-name
-	"""
-	if isinstance(mydep, Atom):
-		return mydep.cp
-	try:
-		return Atom(mydep).cp
-	except InvalidAtom:
-		try:
-			atom = Atom('=' + mydep)
-		except InvalidAtom:
-			pass
-		else:
-			warnings.warn(_("invalid input to %s: '%s', use %s instead") % \
-				('portage.dep.dep_getkey()', mydep, 'portage.cpv_getkey()'),
-				DeprecationWarning, stacklevel=2)
-			return atom.cp
-
-	# Fall back to legacy code for backward compatibility.
-	warnings.warn(_("%s is deprecated, use %s instead") % \
-		('portage.dep.dep_getkey()', 'portage.dep.Atom.cp'),
-		DeprecationWarning, stacklevel=2)
-	mydep = dep_getcpv(mydep)
-	if mydep and isspecific(mydep):
-		mysplit = catpkgsplit(mydep)
-		if not mysplit:
-			return mydep
-		return mysplit[0] + "/" + mysplit[1]
-	else:
-		return mydep
-
-def match_to_list(mypkg, mylist):
-	"""
-	Searches list for entries that matches the package.
-
-	@param mypkg: The package atom to match
-	@type mypkg: String
-	@param mylist: The list of package atoms to compare against
-	@param mylist: List
-	@rtype: List
-	@return: A unique list of package atoms that match the given package atom
-	"""
-	return [ x for x in set(mylist) if match_from_list(x, [mypkg]) ]
-
-def best_match_to_list(mypkg, mylist):
-	"""
-	Returns the most specific entry that matches the package given.
-
-	@param mypkg: The package atom to check
-	@type mypkg: String
-	@param mylist: The list of package atoms to check against
-	@type mylist: List
-	@rtype: String
-	@return: The package atom which best matches given the following ordering:
-		- =cpv      6
-		- ~cpv      5
-		- =cpv*     4
-		- cp:slot   3
-		- >cpv      2
-		- <cpv      2
-		- >=cpv     2
-		- <=cpv     2
-		- cp        1
-	"""
-	operator_values = {'=':6, '~':5, '=*':4,
-		'>':2, '<':2, '>=':2, '<=':2, None:1}
-	maxvalue = 0
-	bestm  = None
-	for x in match_to_list(mypkg, mylist):
-		if dep_getslot(x) is not None:
-			if maxvalue < 3:
-				maxvalue = 3
-				bestm = x
-		op_val = operator_values[x.operator]
-		if op_val > maxvalue:
-			maxvalue = op_val
-			bestm  = x
-	return bestm
-
-def match_from_list(mydep, candidate_list):
-	"""
-	Searches list for entries that matches the package.
-
-	@param mydep: The package atom to match
-	@type mydep: String
-	@param candidate_list: The list of package atoms to compare against
-	@param candidate_list: List
-	@rtype: List
-	@return: A list of package atoms that match the given package atom
-	"""
-
-	if not candidate_list:
-		return []
-
-	from portage.util import writemsg
-	if "!" == mydep[:1]:
-		mydep = mydep[1:]
-	if not isinstance(mydep, Atom):
-		mydep = Atom(mydep)
-
-	mycpv     = mydep.cpv
-	mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
-	slot      = mydep.slot
-
-	if not mycpv_cps:
-		cat, pkg = catsplit(mycpv)
-		ver      = None
-		rev      = None
-	else:
-		cat, pkg, ver, rev = mycpv_cps
-		if mydep == mycpv:
-			raise KeyError(_("Specific key requires an operator"
-				" (%s) (try adding an '=')") % (mydep))
-
-	if ver and rev:
-		operator = mydep.operator
-		if not operator:
-			writemsg(_("!!! Invalid atom: %s\n") % mydep, noiselevel=-1)
-			return []
-	else:
-		operator = None
-
-	mylist = []
-
-	if operator is None:
-		for x in candidate_list:
-			cp = getattr(x, "cp", None)
-			if cp is None:
-				mysplit = catpkgsplit(remove_slot(x))
-				if mysplit is not None:
-					cp = mysplit[0] + '/' + mysplit[1]
-			if cp != mycpv:
-				continue
-			mylist.append(x)
-
-	elif operator == "=": # Exact match
-		for x in candidate_list:
-			xcpv = getattr(x, "cpv", None)
-			if xcpv is None:
-				xcpv = remove_slot(x)
-			if not cpvequal(xcpv, mycpv):
-				continue
-			mylist.append(x)
-
-	elif operator == "=*": # glob match
-		# XXX: Nasty special casing for leading zeros
-		# Required as =* is a literal prefix match, so can't 
-		# use vercmp
-		mysplit = catpkgsplit(mycpv)
-		myver = mysplit[2].lstrip("0")
-		if not myver or not myver[0].isdigit():
-			myver = "0"+myver
-		mycpv = mysplit[0]+"/"+mysplit[1]+"-"+myver
-		for x in candidate_list:
-			xs = getattr(x, "cpv_split", None)
-			if xs is None:
-				xs = catpkgsplit(remove_slot(x))
-			myver = xs[2].lstrip("0")
-			if not myver or not myver[0].isdigit():
-				myver = "0"+myver
-			xcpv = xs[0]+"/"+xs[1]+"-"+myver
-			if xcpv.startswith(mycpv):
-				mylist.append(x)
-
-	elif operator == "~": # version, any revision, match
-		for x in candidate_list:
-			xs = getattr(x, "cpv_split", None)
-			if xs is None:
-				xs = catpkgsplit(remove_slot(x))
-			if xs is None:
-				raise InvalidData(x)
-			if not cpvequal(xs[0]+"/"+xs[1]+"-"+xs[2], mycpv_cps[0]+"/"+mycpv_cps[1]+"-"+mycpv_cps[2]):
-				continue
-			if xs[2] != ver:
-				continue
-			mylist.append(x)
-
-	elif operator in [">", ">=", "<", "<="]:
-		mysplit = ["%s/%s" % (cat, pkg), ver, rev]
-		for x in candidate_list:
-			xs = getattr(x, "cpv_split", None)
-			if xs is None:
-				xs = catpkgsplit(remove_slot(x))
-			xcat, xpkg, xver, xrev = xs
-			xs = ["%s/%s" % (xcat, xpkg), xver, xrev]
-			try:
-				result = pkgcmp(xs, mysplit)
-			except ValueError: # pkgcmp may return ValueError during int() conversion
-				writemsg(_("\nInvalid package name: %s\n") % x, noiselevel=-1)
-				raise
-			if result is None:
-				continue
-			elif operator == ">":
-				if result > 0:
-					mylist.append(x)
-			elif operator == ">=":
-				if result >= 0:
-					mylist.append(x)
-			elif operator == "<":
-				if result < 0:
-					mylist.append(x)
-			elif operator == "<=":
-				if result <= 0:
-					mylist.append(x)
-			else:
-				raise KeyError(_("Unknown operator: %s") % mydep)
-	else:
-		raise KeyError(_("Unknown operator: %s") % mydep)
-
-	if slot is not None:
-		candidate_list = mylist
-		mylist = []
-		for x in candidate_list:
-			xslot = getattr(x, "slot", False)
-			if xslot is False:
-				xslot = dep_getslot(x)
-			if xslot is not None and xslot != slot:
-				continue
-			mylist.append(x)
-
-	if mydep.use:
-		candidate_list = mylist
-		mylist = []
-		for x in candidate_list:
-			use = getattr(x, "use", None)
-			if use is not None:
-				regex = x.iuse.regex
-				missing_iuse = False
-				for y in mydep.use.required:
-					if regex.match(y) is None:
-						missing_iuse = True
-						break
-				if missing_iuse:
-					continue
-				if mydep.use.enabled.difference(use.enabled):
-					continue
-				if mydep.use.disabled.intersection(use.enabled):
-					continue
-			mylist.append(x)
-
-	return mylist

Copied: main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py (from rev 15465, main/trunk/pym/portage/package/ebuild/getmaskingreason.py)
===================================================================
--- main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py	                        (rev 0)
+++ main/branches/prefix/pym/portage/package/ebuild/getmaskingreason.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -0,0 +1,78 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+__all__ = ['getmaskingreason']
+
+import portage
+from portage import os
+from portage.const import USER_CONFIG_PATH
+from portage.dep import match_from_list
+from portage.localization import _
+from portage.util import grablines, normalize_path
+from portage.versions import catpkgsplit
+
+def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False):
+	if settings is None:
+		settings = portage.settings
+	if portdb is None:
+		portdb = portage.portdb
+	mysplit = catpkgsplit(mycpv)
+	if not mysplit:
+		raise ValueError(_("invalid CPV: %s") % mycpv)
+	if metadata is None:
+		db_keys = list(portdb._aux_cache_keys)
+		try:
+			metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
+		except KeyError:
+			if not portdb.cpv_exists(mycpv):
+				raise
+	if metadata is None:
+		# Can't access SLOT due to corruption.
+		cpv_slot_list = [mycpv]
+	else:
+		cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
+	mycp=mysplit[0]+"/"+mysplit[1]
+
+	# XXX- This is a temporary duplicate of code from the config constructor.
+	locations = [os.path.join(settings["PORTDIR"], "profiles")]
+	locations.extend(settings.profiles)
+	for ov in settings["PORTDIR_OVERLAY"].split():
+		profdir = os.path.join(normalize_path(ov), "profiles")
+		if os.path.isdir(profdir):
+			locations.append(profdir)
+	locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
+		USER_CONFIG_PATH))
+	locations.reverse()
+	pmasklists = [(x, grablines(os.path.join(x, "package.mask"), recursive=1)) for x in locations]
+
+	if mycp in settings.pmaskdict:
+		for x in settings.pmaskdict[mycp]:
+			if match_from_list(x, cpv_slot_list):
+				for pmask in pmasklists:
+					comment = ""
+					comment_valid = -1
+					pmask_filename = os.path.join(pmask[0], "package.mask")
+					for i in range(len(pmask[1])):
+						l = pmask[1][i].strip()
+						if l == "":
+							comment = ""
+							comment_valid = -1
+						elif l[0] == "#":
+							comment += (l+"\n")
+							comment_valid = i + 1
+						elif l == x:
+							if comment_valid != i:
+								comment = ""
+							if return_location:
+								return (comment, pmask_filename)
+							else:
+								return comment
+						elif comment_valid != -1:
+							# Apparently this comment applies to muliple masks, so
+							# it remains valid until a blank line is encountered.
+							comment_valid += 1
+	if return_location:
+		return (None, None)
+	else:
+		return None

Copied: main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py (from rev 15465, main/trunk/pym/portage/package/ebuild/getmaskingstatus.py)
===================================================================
--- main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py	                        (rev 0)
+++ main/branches/prefix/pym/portage/package/ebuild/getmaskingstatus.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -0,0 +1,154 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+__all__ = ['getmaskingstatus']
+
+import portage
+from portage import eapi_is_supported, _eapi_is_deprecated
+from portage.dep import match_from_list
+from portage.localization import _
+from portage.package.ebuild.config import config
+from portage.versions import catpkgsplit, cpv_getkey
+
+def getmaskingstatus(mycpv, settings=None, portdb=None):
+	if settings is None:
+		settings = config(clone=portage.settings)
+	if portdb is None:
+		portdb = portage.portdb
+
+	metadata = None
+	installed = False
+	if not isinstance(mycpv, basestring):
+		# emerge passed in a Package instance
+		pkg = mycpv
+		mycpv = pkg.cpv
+		metadata = pkg.metadata
+		installed = pkg.installed
+
+	mysplit = catpkgsplit(mycpv)
+	if not mysplit:
+		raise ValueError(_("invalid CPV: %s") % mycpv)
+	if metadata is None:
+		db_keys = list(portdb._aux_cache_keys)
+		try:
+			metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys)))
+		except KeyError:
+			if not portdb.cpv_exists(mycpv):
+				raise
+			return ["corruption"]
+		if "?" in metadata["LICENSE"]:
+			settings.setcpv(mycpv, mydb=metadata)
+			metadata["USE"] = settings["PORTAGE_USE"]
+		else:
+			metadata["USE"] = ""
+
+	rValue = []
+
+	# profile checking
+	if settings._getProfileMaskAtom(mycpv, metadata):
+		rValue.append("profile")
+
+	# package.mask checking
+	if settings._getMaskAtom(mycpv, metadata):
+		rValue.append("package.mask")
+
+	# keywords checking
+	eapi = metadata["EAPI"]
+	mygroups = settings._getKeywords(mycpv, metadata)
+	licenses = metadata["LICENSE"]
+	properties = metadata["PROPERTIES"]
+	if eapi.startswith("-"):
+		eapi = eapi[1:]
+	if not eapi_is_supported(eapi):
+		return ["EAPI %s" % eapi]
+	elif _eapi_is_deprecated(eapi) and not installed:
+		return ["EAPI %s" % eapi]
+	egroups = settings.configdict["backupenv"].get(
+		"ACCEPT_KEYWORDS", "").split()
+	pgroups = settings["ACCEPT_KEYWORDS"].split()
+	myarch = settings["ARCH"]
+	if pgroups and myarch not in pgroups:
+		"""For operating systems other than Linux, ARCH is not necessarily a
+		valid keyword."""
+		myarch = pgroups[0].lstrip("~")
+
+	cp = cpv_getkey(mycpv)
+	pkgdict = settings.pkeywordsdict.get(cp)
+	matches = False
+	if pkgdict:
+		cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]
+		for atom, pkgkeywords in pkgdict.items():
+			if match_from_list(atom, cpv_slot_list):
+				matches = True
+				pgroups.extend(pkgkeywords)
+	if matches or egroups:
+		pgroups.extend(egroups)
+		inc_pgroups = set()
+		for x in pgroups:
+			if x.startswith("-"):
+				if x == "-*":
+					inc_pgroups.clear()
+				else:
+					inc_pgroups.discard(x[1:])
+			else:
+				inc_pgroups.add(x)
+		pgroups = inc_pgroups
+		del inc_pgroups
+
+	kmask = "missing"
+
+	if '**' in pgroups:
+		kmask = None
+	else:
+		for keyword in pgroups:
+			if keyword in mygroups:
+				kmask = None
+				break
+
+	if kmask:
+		for gp in mygroups:
+			if gp=="*":
+				kmask=None
+				break
+			elif gp=="-"+myarch and myarch in pgroups:
+				kmask="-"+myarch
+				break
+			elif gp=="~"+myarch and myarch in pgroups:
+				kmask="~"+myarch
+				break
+
+	try:
+		missing_licenses = settings._getMissingLicenses(mycpv, metadata)
+		if missing_licenses:
+			allowed_tokens = set(["||", "(", ")"])
+			allowed_tokens.update(missing_licenses)
+			license_split = licenses.split()
+			license_split = [x for x in license_split \
+				if x in allowed_tokens]
+			msg = license_split[:]
+			msg.append("license(s)")
+			rValue.append(" ".join(msg))
+	except portage.exception.InvalidDependString as e:
+		rValue.append("LICENSE: "+str(e))
+
+	try:
+		missing_properties = settings._getMissingProperties(mycpv, metadata)
+		if missing_properties:
+			allowed_tokens = set(["||", "(", ")"])
+			allowed_tokens.update(missing_properties)
+			properties_split = properties.split()
+			properties_split = [x for x in properties_split \
+					if x in allowed_tokens]
+			msg = properties_split[:]
+			msg.append("properties")
+			rValue.append(" ".join(msg))
+	except portage.exception.InvalidDependString as e:
+		rValue.append("PROPERTIES: "+str(e))
+
+	# Only show KEYWORDS masks for installed packages
+	# if they're not masked for any other reason.
+	if kmask and (not installed or not rValue):
+		rValue.append(kmask+" keyword")
+
+	return rValue

Copied: main/branches/prefix/pym/portage/util/movefile.py (from rev 15465, main/trunk/pym/portage/util/movefile.py)
===================================================================
--- main/branches/prefix/pym/portage/util/movefile.py	                        (rev 0)
+++ main/branches/prefix/pym/portage/util/movefile.py	2010-02-27 19:32:48 UTC (rev 15483)
@@ -0,0 +1,234 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+__all__ = ['movefile']
+
+import errno
+import os as _os
+import shutil as _shutil
+import stat
+
+import portage
+from portage import bsd_chflags, _encodings, _os_overrides, _selinux, \
+	_unicode_decode, _unicode_func_wrapper, _unicode_module_wrapper
+from portage.const import MOVE_BINARY
+from portage.localization import _
+from portage.process import spawn
+from portage.util import writemsg
+
+def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
+		hardlink_candidates=None, encoding=_encodings['fs']):
+	"""moves a file from src to dest, preserving all permissions and attributes; mtime will
+	be preserved even when moving across filesystems.  Returns true on success and false on
+	failure.  Move is atomic."""
+	#print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
+
+	if mysettings is None:
+		mysettings = portage.settings
+
+	selinux_enabled = mysettings.selinux_enabled()
+	if selinux_enabled:
+		selinux = _unicode_module_wrapper(_selinux, encoding=encoding)
+
+	lchown = _unicode_func_wrapper(portage.data.lchown, encoding=encoding)
+	os = _unicode_module_wrapper(_os,
+		encoding=encoding, overrides=_os_overrides)
+	shutil = _unicode_module_wrapper(_shutil, encoding=encoding)
+
+	try:
+		if not sstat:
+			sstat=os.lstat(src)
+
+	except SystemExit as e:
+		raise
+	except Exception as e:
+		print(_("!!! Stating source file failed... movefile()"))
+		print("!!!",e)
+		return None
+
+	destexists=1
+	try:
+		dstat=os.lstat(dest)
+	except (OSError, IOError):
+		dstat=os.lstat(os.path.dirname(dest))
+		destexists=0
+
+	if bsd_chflags:
+		if destexists and dstat.st_flags != 0:
+			bsd_chflags.lchflags(dest, 0)
+		# Use normal stat/chflags for the parent since we want to
+		# follow any symlinks to the real parent directory.
+		pflags = os.stat(os.path.dirname(dest)).st_flags
+		if pflags != 0:
+			bsd_chflags.chflags(os.path.dirname(dest), 0)
+
+	if destexists:
+		if stat.S_ISLNK(dstat[stat.ST_MODE]):
+			try:
+				os.unlink(dest)
+				destexists=0
+			except SystemExit as e:
+				raise
+			except Exception as e:
+				pass
+
+	if stat.S_ISLNK(sstat[stat.ST_MODE]):
+		try:
+			target=os.readlink(src)
+			if mysettings and mysettings["D"]:
+				if target.find(mysettings["D"])==0:
+					target=target[len(mysettings["D"]):]
+			if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
+				os.unlink(dest)
+			if selinux_enabled:
+				selinux.symlink(target, dest, src)
+			else:
+				os.symlink(target,dest)
+			lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+			# utime() only works on the target of a symlink, so it's not
+			# possible to perserve mtime on symlinks.
+			return os.lstat(dest)[stat.ST_MTIME]
+		except SystemExit as e:
+			raise
+		except Exception as e:
+			print(_("!!! failed to properly create symlink:"))
+			print("!!!",dest,"->",target)
+			print("!!!",e)
+			return None
+
+	hardlinked = False
+	# Since identical files might be merged to multiple filesystems,
+	# so os.link() calls might fail for some paths, so try them all.
+	# For atomic replacement, first create the link as a temp file
+	# and them use os.rename() to replace the destination.
+	if hardlink_candidates:
+		head, tail = os.path.split(dest)
+		hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
+			(tail, os.getpid()))
+		try:
+			os.unlink(hardlink_tmp)
+		except OSError as e:
+			if e.errno != errno.ENOENT:
+				writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
+					(hardlink_tmp,), noiselevel=-1)
+				writemsg("!!! %s\n" % (e,), noiselevel=-1)
+				return None
+			del e
+		for hardlink_src in hardlink_candidates:
+			try:
+				os.link(hardlink_src, hardlink_tmp)
+			except OSError:
+				continue
+			else:
+				try:
+					os.rename(hardlink_tmp, dest)
+				except OSError as e:
+					writemsg(_("!!! Failed to rename %s to %s\n") % \
+						(hardlink_tmp, dest), noiselevel=-1)
+					writemsg("!!! %s\n" % (e,), noiselevel=-1)
+					return None
+				hardlinked = True
+				break
+
+	renamefailed=1
+	if hardlinked:
+		renamefailed = False
+	if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
+		try:
+			if selinux_enabled:
+				selinux.rename(src, dest)
+			else:
+				os.rename(src,dest)
+			renamefailed=0
+		except OSError as e:
+			if e.errno != errno.EXDEV:
+				# Some random error.
+				print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest})
+				print("!!!",e)
+				return None
+			# Invalid cross-device-link 'bind' mounted or actually Cross-Device
+	if renamefailed:
+		didcopy=0
+		if stat.S_ISREG(sstat[stat.ST_MODE]):
+			try: # For safety copy then move it over.
+				if selinux_enabled:
+					selinux.copyfile(src, dest + "#new")
+					selinux.rename(dest + "#new", dest)
+				else:
+					shutil.copyfile(src,dest+"#new")
+					os.rename(dest+"#new",dest)
+				didcopy=1
+			except SystemExit as e:
+				raise
+			except Exception as e:
+				print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest})
+				print("!!!",e)
+				return None
+		else:
+			#we don't yet handle special, so we need to fall back to /bin/mv
+			a = spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
+			if a != os.EX_OK:
+				writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1)
+				writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
+					{"src": _unicode_decode(src, encoding=encoding),
+					"dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
+				writemsg("!!! %s\n" % a, noiselevel=-1)
+				return None # failure
+		try:
+			if didcopy:
+				if stat.S_ISLNK(sstat[stat.ST_MODE]):
+					lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+				else:
+					os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+				os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
+				os.unlink(src)
+		except SystemExit as e:
+			raise
+		except Exception as e:
+			print(_("!!! Failed to chown/chmod/unlink in movefile()"))
+			print("!!!",dest)
+			print("!!!",e)
+			return None
+
+	# Always use stat_obj[stat.ST_MTIME] for the integral timestamp which
+	# is returned, since the stat_obj.st_mtime float attribute rounds *up*
+	# if the nanosecond part of the timestamp is 999999881 ns or greater.
+	try:
+		if hardlinked:
+			newmtime = os.stat(dest)[stat.ST_MTIME]
+		else:
+			# Note: It is not possible to preserve nanosecond precision
+			# (supported in POSIX.1-2008 via utimensat) with the IEEE 754
+			# double precision float which only has a 53 bit significand.
+			if newmtime is not None:
+				os.utime(dest, (newmtime, newmtime))
+			else:
+				newmtime = sstat[stat.ST_MTIME]
+				if renamefailed:
+					# If rename succeeded then timestamps are automatically
+					# preserved with complete precision because the source
+					# and destination inode are the same. Otherwise, round
+					# down to the nearest whole second since python's float
+					# st_mtime cannot be used to preserve the st_mtim.tv_nsec
+					# field with complete precision. Note that we have to use
+					# stat_obj[stat.ST_MTIME] here because the float
+					# stat_obj.st_mtime rounds *up* sometimes.
+					os.utime(dest, (newmtime, newmtime))
+	except OSError:
+		# The utime can fail here with EPERM even though the move succeeded.
+		# Instead of failing, use stat to return the mtime if possible.
+		try:
+			newmtime = os.stat(dest)[stat.ST_MTIME]
+		except OSError as e:
+			writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
+			writemsg("!!! %s\n" % dest, noiselevel=-1)
+			writemsg("!!! %s\n" % str(e), noiselevel=-1)
+			return None
+
+	if bsd_chflags:
+		# Restore the flags we saved before moving
+		if pflags:
+			bsd_chflags.chflags(os.path.dirname(dest), pflags)
+
+	return newmtime




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

only message in thread, other threads:[~2010-02-27 19:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-27 19:32 [gentoo-commits] portage r15483 - in main/branches/prefix/pym/portage: . dbapi package/ebuild util 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