Convert PackageIndex.packages from a dict to a list so that in the future
it will be possible to support multiple packages with the same cpv.

svn path=/main/trunk/; revision=9452
diff --git a/bin/emaint b/bin/emaint
index 8464d13..e0baa13 100755
--- a/bin/emaint
+++ b/bin/emaint
@@ -129,14 +129,17 @@
 			onProgress(maxval, 0)
 		pkgindex = self._pkgindex
 		missing = []
+		metadata = {}
+		for d in pkgindex.packages:
+			metadata[d["CPV"]] = d
 		for i, cpv in enumerate(cpv_all):
-			d = pkgindex.packages.get(cpv)
+			d = metadata.get(cpv)
 			if not d or "MD5" not in d:
 				missing.append(cpv)
 			if onProgress:
 				onProgress(maxval, i+1)
 		errors = ["'%s' is not in Packages" % cpv for cpv in missing]
-		stale = set(pkgindex.packages).difference(cpv_all)
+		stale = set(metadata).difference(cpv_all)
 		for cpv in stale:
 			errors.append("'%s' is not in the repository" % cpv)
 		return errors
@@ -151,13 +154,16 @@
 			onProgress(maxval, 0)
 		pkgindex = self._pkgindex
 		missing = []
+		metadata = {}
+		for d in pkgindex.packages:
+			metadata[d["CPV"]] = d
 		for i, cpv in enumerate(cpv_all):
-			d = pkgindex.packages.get(cpv)
+			d = metadata.get(cpv)
 			if not d or "MD5" not in d:
 				bintree.inject(cpv)
 			if onProgress:
 				onProgress(maxval, i+1)
-		stale = set(pkgindex.packages).difference(cpv_all)
+		stale = set(metadata).difference(cpv_all)
 		if stale:
 			from portage import locks
 			pkgindex_lock = locks.lockfile(
@@ -177,9 +183,11 @@
 				del bintree
 				portage.db[self._bintree.root]["bintree"] = self._bintree
 				self._bintree._populate()
-				for cpv in set(self._pkgindex.packages).difference(
+				for cpv in set(metadata).difference(
 					self._bintree.dbapi.cpv_all()):
-					del self._pkgindex.packages[cpv]
+					del metadata[cpv]
+				del pkgindex.packages[:]
+				pkgindex.packages.extend(metadata.itervalues())
 				from portage.util import atomic_ofstream
 				f = atomic_ofstream(self._pkgindex_file)
 				try:
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
index ba0809f..79a792e 100644
--- a/pym/portage/dbapi/bintree.py
+++ b/pym/portage/dbapi/bintree.py
@@ -382,7 +382,9 @@
 			if not self._pkgindex_version_supported(pkgindex):
 				pkgindex = self._new_pkgindex()
 			header = pkgindex.header
-			metadata = pkgindex.packages
+			metadata = {}
+			for d in pkgindex.packages:
+				metadata[d["CPV"]] = d
 			update_pkgindex = False
 			for mydir in dirs:
 				for myfile in listdir(os.path.join(self.pkgdir, mydir)):
@@ -554,7 +556,8 @@
 				stale = [cpv for cpv in metadata if cpv not in self._pkg_paths]
 				for cpv in stale:
 					del metadata[cpv]
-				#
+				del pkgindex.packages[:]
+				pkgindex.packages.extend(metadata.itervalues())
 				self._update_pkgindex_header(pkgindex.header)
 				from portage.util import atomic_ofstream
 				f = atomic_ofstream(self._pkgindex_file)
@@ -625,7 +628,9 @@
 				finally:
 					f.close()
 			if pkgindex:
-				self._remotepkgs = pkgindex.packages
+				self._remotepkgs = {}
+				for d in pkgindex.packages:
+					self._remotepkgs[d["CPV"]] = d
 				self._remote_has_index = True
 				self._remote_base_uri = pkgindex.header.get("URI", base_url)
 				self.remotepkgs = {}
@@ -768,7 +773,14 @@
 				self.dbapi.cpv_remove(cpv)
 				del self._pkg_paths[cpv]
 				return
-			pkgindex.packages[cpv] = d
+			# If found, remove package(s) with duplicate path.
+			for i in xrange(len(pkgindex.packages) - 1, -1, -1):
+				d2 = pkgindex.packages[i]
+				if d2["CPV"] != cpv:
+					continue
+				if d2.get("PATH") == d.get("PATH"):
+					del pkgindex.packages[i]
+			pkgindex.packages.append(d)
 			self._update_pkgindex_header(pkgindex.header)
 			from portage.util import atomic_ofstream
 			f = atomic_ofstream(os.path.join(self.pkgdir, "Packages"))
diff --git a/pym/portage/getbinpkg.py b/pym/portage/getbinpkg.py
index d2d1f75..e3f97e7 100644
--- a/pym/portage/getbinpkg.py
+++ b/pym/portage/getbinpkg.py
@@ -675,13 +675,23 @@
 		pkgfile.write("%s: %s\n" % (k, v))
 	pkgfile.write("\n")
 
+def _cmp_cpv(d1, d2):
+	cpv1 = d1["CPV"]
+	cpv2 = d2["CPV"]
+	if cpv1 > cpv2:
+		return 1
+	elif cpv1 == cpv2:
+		return 0
+	else:
+		return -1
+
 class PackageIndex(object):
 
 	def __init__(self, default_pkg_data=None, inherited_keys=None):
 		self._default_pkg_data = default_pkg_data
 		self._inherited_keys = inherited_keys
 		self.header = {}
-		self.packages = {}
+		self.packages = []
 		self.modified = True
 
 	def read(self, pkgfile):
@@ -707,19 +717,18 @@
 					v = self.header.get(k)
 					if v is not None:
 						d.setdefault(k, v)
-			self.packages[mycpv] = d
+			self.packages.append(d)
 
 	def write(self, pkgfile):
-		cpv_all = self.packages.keys()
-		cpv_all.sort()
 		if self.modified:
 			self.header["TIMESTAMP"] = str(long(time.time()))
-			self.header["PACKAGES"] = str(len(cpv_all))
+			self.header["PACKAGES"] = str(len(self.packages))
 		keys = self.header.keys()
 		keys.sort()
 		writepkgindex(pkgfile, [(k, self.header[k]) for k in keys])
-		for cpv in cpv_all:
-			metadata = self.packages[cpv].copy()
+		for metadata in sorted(self.packages, _cmp_cpv):
+			metadata = metadata.copy()
+			cpv = metadata["CPV"]
 			if self._inherited_keys:
 				for k in self._inherited_keys:
 					v = self.header.get(k)