move: respect EAPI wrt dots_in_PN, bug #426476
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
index e3de50f..8072542 100644
--- a/pym/portage/dbapi/bintree.py
+++ b/pym/portage/dbapi/bintree.py
@@ -8,6 +8,7 @@
 	'portage.checksum:hashfunc_map,perform_multiple_checksums,verify_all',
 	'portage.dbapi.dep_expand:dep_expand',
 	'portage.dep:dep_getkey,isjustname,match_from_list',
+	'portage.eapi:_get_eapi_attrs',
 	'portage.output:EOutput,colorize',
 	'portage.locks:lockfile,unlockfile',
 	'portage.package.ebuild.fetch:_check_distfile,_hide_url_passwd',
@@ -386,8 +387,10 @@
 				# Ignore PROVIDE virtual match.
 				continue
 			if repo_match is not None \
-				and not repo_match(self.dbapi.aux_get(mycpv,
-					['repository'])[0]):
+				and not repo_match(mycpv.repo):
+				continue
+			eapi_attrs = _get_eapi_attrs(mycpv.eapi)
+			if not eapi_attrs.dots_in_PN and "." in catsplit(newcp)[1]:
 				continue
 			mynewcpv = mycpv.replace(mycpv_cp, str(newcp), 1)
 			myoldpkg = catsplit(mycpv)[1]
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 264790a..0ae7dc5 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -330,7 +330,10 @@
 				# Ignore PROVIDE virtual match.
 				continue
 			if repo_match is not None \
-				and not repo_match(self.aux_get(mycpv, ['repository'])[0]):
+				and not repo_match(mycpv.repo):
+				continue
+			eapi_attrs = _get_eapi_attrs(mycpv.eapi)
+			if not eapi_attrs.dots_in_PN and "." in catsplit(newcp)[1]:
 				continue
 			mynewcpv = mycpv.replace(mycpv_cp, str(newcp), 1)
 			mynewcat = catsplit(newcp)[0]
diff --git a/pym/portage/tests/update/test_update_dbentry.py b/pym/portage/tests/update/test_update_dbentry.py
new file mode 100644
index 0000000..e13cfed
--- /dev/null
+++ b/pym/portage/tests/update/test_update_dbentry.py
@@ -0,0 +1,184 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import re
+import textwrap
+
+import portage
+from portage import os
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import ensure_dirs
+from portage._global_updates import _do_global_updates
+
+class UpdateDbentryTestCase(TestCase):
+
+	def testUpdateDbentryTestCase(self):
+
+		ebuilds = {
+
+			"dev-libs/A-2::dont_apply_updates" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4",
+				"SLOT": "2",
+			},
+
+			"dev-libs/B-2::dont_apply_updates" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4",
+				"SLOT": "2",
+			},
+
+		}
+
+		installed = {
+
+			"dev-libs/A-1::test_repo" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4",
+			},
+
+			"dev-libs/A-2::dont_apply_updates" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4",
+				"SLOT": "2",
+			},
+
+			"dev-libs/B-1::test_repo" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4-python",
+			},
+
+			"dev-libs/M-1::test_repo" : {
+				"EAPI": "4",
+			},
+
+			"dev-libs/N-1::test_repo" : {
+				"EAPI": "4",
+			},
+
+			"dev-libs/N-2::test_repo" : {
+				"EAPI": "4-python",
+			},
+
+		}
+
+		binpkgs = {
+
+			"dev-libs/A-1::test_repo" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4",
+			},
+
+			"dev-libs/A-2::dont_apply_updates" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4",
+				"SLOT": "2",
+			},
+
+			"dev-libs/B-1::test_repo" : {
+				"RDEPEND" : "dev-libs/M dev-libs/N dev-libs/P",
+				"EAPI": "4-python",
+			},
+
+		}
+
+		world = ["dev-libs/M", "dev-libs/N"]
+
+		updates = textwrap.dedent("""
+			move dev-libs/M dev-libs/M-moved
+			move dev-libs/N dev-libs/N.moved
+		""")
+
+		playground = ResolverPlayground(binpkgs=binpkgs,
+			ebuilds=ebuilds, installed=installed, world=world)
+
+		settings = playground.settings
+		trees = playground.trees
+		eroot = settings["EROOT"]
+		portdir = settings["PORTDIR"]
+		portdb = trees[eroot]["porttree"].dbapi
+		vardb = trees[eroot]["vartree"].dbapi
+		bindb = trees[eroot]["bintree"].dbapi
+		setconfig = trees[eroot]["root_config"].setconfig
+		selected_set = setconfig.getSets()["selected"]
+
+		updates_dir = os.path.join(portdir, "profiles", "updates")
+
+		try:
+			ensure_dirs(updates_dir)
+			with open(os.path.join(updates_dir, "1Q-2010"), 'w') as f:
+				f.write(updates)
+
+			# Create an empty updates directory, so that this
+			# repo doesn't inherit updates from the main repo.
+			ensure_dirs(os.path.join(
+				portdb.getRepositoryPath("dont_apply_updates"),
+				"profiles", "updates"))
+
+			global_noiselimit = portage.util.noiselimit
+			portage.util.noiselimit = -2
+			try:
+				_do_global_updates(trees, {})
+			finally:
+				portage.util.noiselimit = global_noiselimit
+
+			# Workaround for cache validation not working
+			# correctly when filesystem has timestamp precision
+			# of 1 second.
+			vardb._clear_cache()
+
+			# M -> M-moved
+			old_pattern = re.compile(r"\bdev-libs/M(\s|$)")
+			rdepend = vardb.aux_get("dev-libs/A-1", ["RDEPEND"])[0]
+			self.assertTrue(old_pattern.search(rdepend) is None)
+			self.assertTrue("dev-libs/M-moved" in rdepend)
+			rdepend = bindb.aux_get("dev-libs/A-1", ["RDEPEND"])[0]
+			self.assertTrue(old_pattern.search(rdepend) is None)
+			self.assertTrue("dev-libs/M-moved" in rdepend)
+			rdepend = vardb.aux_get("dev-libs/B-1", ["RDEPEND"])[0]
+			self.assertTrue(old_pattern.search(rdepend) is None)
+			self.assertTrue("dev-libs/M-moved" in rdepend)
+			rdepend = vardb.aux_get("dev-libs/B-1", ["RDEPEND"])[0]
+			self.assertTrue(old_pattern.search(rdepend) is None)
+			self.assertTrue("dev-libs/M-moved" in rdepend)
+
+			# EAPI 4-python N -> N.moved
+			rdepend = vardb.aux_get("dev-libs/B-1", ["RDEPEND"])[0]
+			old_pattern = re.compile(r"\bdev-libs/N(\s|$)")
+			self.assertTrue(old_pattern.search(rdepend) is None)
+			self.assertTrue("dev-libs/N.moved" in rdepend)
+			rdepend = bindb.aux_get("dev-libs/B-1", ["RDEPEND"])[0]
+			self.assertTrue(old_pattern.search(rdepend) is None)
+			self.assertTrue("dev-libs/N.moved" in rdepend)
+			self.assertRaises(KeyError,
+				vardb.aux_get, "dev-libs/N-2", ["EAPI"])
+			vardb.aux_get("dev-libs/N.moved-2", ["RDEPEND"])[0]
+
+			# EAPI 4 does not allow dots in package names for N -> N.moved
+			rdepend = vardb.aux_get("dev-libs/A-1", ["RDEPEND"])[0]
+			self.assertTrue("dev-libs/N" in rdepend)
+			self.assertTrue("dev-libs/N.moved" not in rdepend)
+			rdepend = bindb.aux_get("dev-libs/A-1", ["RDEPEND"])[0]
+			self.assertTrue("dev-libs/N" in rdepend)
+			self.assertTrue("dev-libs/N.moved" not in rdepend)
+			vardb.aux_get("dev-libs/N-1", ["RDEPEND"])[0]
+			self.assertRaises(KeyError,
+				vardb.aux_get, "dev-libs/N.moved-1", ["EAPI"])
+
+			# dont_apply_updates
+			rdepend = vardb.aux_get("dev-libs/A-2", ["RDEPEND"])[0]
+			self.assertTrue("dev-libs/M" in rdepend)
+			self.assertTrue("dev-libs/M-moved" not in rdepend)
+			rdepend = bindb.aux_get("dev-libs/A-2", ["RDEPEND"])[0]
+			self.assertTrue("dev-libs/M" in rdepend)
+			self.assertTrue("dev-libs/M-moved" not in rdepend)
+
+			selected_set.load()
+			self.assertTrue("dev-libs/M" not in selected_set)
+			self.assertTrue("dev-libs/M-moved" in selected_set)
+			self.assertTrue("dev-libs/N" not in selected_set)
+			self.assertTrue("dev-libs/N.moved" in selected_set)
+
+		finally:
+			playground.cleanup()
diff --git a/pym/portage/update.py b/pym/portage/update.py
index a66c60b..c9c2af9 100644
--- a/pym/portage/update.py
+++ b/pym/portage/update.py
@@ -18,7 +18,7 @@
 	'portage.util:ConfigProtect,new_protect_filename,' + \
 		'normalize_path,write_atomic,writemsg',
 	'portage.util.listdir:_ignorecvs_dirs',
-	'portage.versions:ververify'
+	'portage.versions:catsplit,ververify'
 )
 
 from portage.const import USER_CONFIG_PATH
@@ -29,14 +29,20 @@
 
 if sys.hexversion >= 0x3000000:
 	long = int
+	_unicode = str
+else:
+	_unicode = unicode
 
 ignored_dbentries = ("CONTENTS", "environment.bz2")
 
 def update_dbentry(update_cmd, mycontent, eapi=None):
+	eapi_attrs = _get_eapi_attrs(eapi)
 	if update_cmd[0] == "move":
-		old_value = str(update_cmd[1])
-		if old_value in mycontent:
-			new_value = str(update_cmd[2])
+		avoid_dots_in_PN = (not eapi_attrs.dots_in_PN and
+			"." in catsplit(update_cmd[2].cp)[1])
+		if not avoid_dots_in_PN and _unicode(update_cmd[1]) in mycontent:
+			old_value = _unicode(update_cmd[1])
+			new_value = _unicode(update_cmd[2])
 			old_value = re.escape(old_value);
 			mycontent = re.sub(old_value+"(:|$|\\s)", new_value+"\\1", mycontent)
 			def myreplace(matchobj):