Hola. Attached is a patch that A) adds EAPI awareness to portage; mainly, if >0, complain and be unwilling to merge the package B) tweaks to portage_db_flat, addition of portage_db_metadata, and portage_db_flat_hash
Flat_hash is the replacement cache format for metadata/cache; assuming nobody does anything stupid with EAPI, it will allow us to deploy new metadata in the tree without forcing a breakage every time we do so. portage_db_metadata.py is a compability implementation; basically detects if it's flat_list (portage_db_flat), or flat_hash and calls accordingly. Aside from that, tried to keep changes as minimal as possible. The patch isn't complete due to the fact we need to add an EAPI cache compatibility check for --metadata transfer, but can't do that till I get some feedback from -dev ml regarding a bit of tree cleanup that will go along with it. Please test this out; if you want to test the EAPI checking, tag EAPI=1 into an ebuild, and try making emerge bail. If you're less adventurous, please test the compatibility cache testing; in /etc/portage/modules portdbapi.metadbmodule=portage_db_metadata.database Will enable the autodetection. Additionally, portdbapi.auxdbmodule=portage_db_flat_hash.database being flipped on would be appreciated, although you will have to wipe your cache and run emerge --metadata; with the settings above, you're testing the auto-detect functionality, and the new format. Thanks, ~harring
diff -urN portage-old/bin/emerge portage/bin/emerge
--- portage-old/bin/emerge 2005-08-27 05:28:09.000000000 -0500
+++ portage/bin/emerge 2005-08-27 05:27:17.000000000 -0500
@@ -612,7 +612,7 @@
help()
sys.exit(0)
elif portage.secpass!=2:
- if myaction in ["search", "info", "regen"]:
+ if myaction in ["search", "info", "regen", "metadata"]:
pass
elif (not myaction) and (not myfiles):
pass
@@ -1497,7 +1497,7 @@
myfetchlist=[]
for x in mylist:
fetch=" "
-
+ stupid_if_logic_hack = True
if x[0]=="blocks":
addl=""+red("B")+" "+fetch+" "
resolved=portage.db[x[1]]["vartree"].resolve_key(x[2])
@@ -1512,7 +1512,22 @@
print red("(is blocking
"+x[3]+")")
else:
print
+ stupid_if_logic_hack = False
+
else:
+ if x[0] == "ebuild": source = "porttree"
+ elif x[0] == "binary": source = "bintree"
+ elif x[0] == ("nomerge", "blocker"): source
= None
+ else:
+ print "EAPI check, unknown source
"+str(x[0])+" for "+x[2]+", this shouldn't occur",mylist
+ sys.exit(1)
+ if source:
+ needed =
portage.db[x[1]][source].dbapi.aux_get(x[2], ["EAPI"])[0]
+ if needed > portage.EAPI:
+ print '[%s] %s %s, EAPI:%i
installed portage EAPI:%i' % (x[0].ljust(13), x[2], red("UNMERGABLE"),needed,
portage.EAPI)
+ stupid_if_logic_hack = True
+
+ if stupid_if_logic_hack:
if (x[0]!="binary") and ("fetch" in
string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])):
fetch = red("F")
if portage.portdb.fetch_check(x[2],
portage.settings):
@@ -1830,6 +1845,34 @@
self.pkgsettings["FEATURES"]=string.join(myfeat)
mergecount=0
+
+ unmergable = []
+ for source, root, cpv, action in mymergelist:
+ if source == "ebuild": source = "porttree"
+ elif source == "binary": source = "bintree"
+ elif source in ("nomerge", "blocks"):
+ continue
+ else:
+ print "EAPI check, unknown source
"+str(source)+" for "+cpv+", this shouldn't occur",mymergelist
+ sys.exit(1)
+ needed = portage.db[root][source].dbapi.aux_get(cpv,
["EAPI"])[0]
+ if portage.EAPI < needed:
+ unmergable.append((needed, cpv))
+
+ if len(unmergable):
+ print
+ print red("!!!")
+ print red("!!!")+" %s" % red("Ebuild API
incompatibility")
+ print red("!!!")+" installed portage EAPI is %i, the
following packages require a higher version" % portage.EAPI
+ print red("!!!")+" This version of portage is incapable
of installing the higher version"
+ print red("!!!")+" A portage upgrade should solve this"
+ print red("!!!")
+ for needed, cpv in unmergable:
+ print ">>> %s requires EAPI %s" % (cpv,
red(str(needed)))
+ print
+ if not ("--fetchonly" in myopts or "--fetch-all-uri" in
myopts or "--pretend" in myopts):
+ sys.exit(1)
+
for x in mymergelist:
mergecount+=1
myroot=x[1]
diff -urN portage-old/pym/portage.py portage/pym/portage.py
--- portage-old/pym/portage.py 2005-08-27 05:28:02.000000000 -0500
+++ portage/pym/portage.py 2005-08-27 05:27:26.000000000 -0500
@@ -81,7 +81,7 @@
MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE,
MAKE_DEFAULTS_FILE, \
DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, SANDBOX_PIDS_FILE,
CONFIG_MEMORY_FILE,\
- INCREMENTALS, STICKIES
+ INCREMENTALS, STICKIES, EAPI
from portage_data import ostype, lchown, userland, secpass, uid,
wheelgid, \
portage_uid, portage_gid
@@ -5077,9 +5071,9 @@
'DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
'RESTRICT', 'HOMEPAGE', 'LICENSE', 'DESCRIPTION',
'KEYWORDS', 'INHERITED', 'IUSE', 'CDEPEND',
- 'PDEPEND', 'PROVIDE',
+ 'PDEPEND', 'PROVIDE', 'EAPI',
'UNUSED_01', 'UNUSED_02', 'UNUSED_03', 'UNUSED_04',
- 'UNUSED_05', 'UNUSED_06', 'UNUSED_07', 'UNUSED_08',
+ 'UNUSED_05', 'UNUSED_06', 'UNUSED_07',
]
auxdbkeylen=len(auxdbkeys)
@@ -5373,10 +5367,15 @@
mydata = self.auxdb[mylocation][cat][pkg]
returnme = []
for x in mylist:
- if mydata.has_key(x):
- returnme.append(mydata[x])
- else:
- returnme.append("")
+ returnme.append(mydata.get(x,""))
+
+ if "EAPI" in mylist:
+ idx = mylist.index("EAPI")
+ try:
+ returnme[idx] = int(returnme[idx])
+ except ValueError:
+ # string
+ returnme[idx] = 0
return returnme
diff -urN portage-old/pym/portage_db_flat.py portage/pym/portage_db_flat.py
--- portage-old/pym/portage_db_flat.py 2005-08-27 05:27:59.000000000 -0500
+++ portage/pym/portage_db_flat.py 2005-08-27 05:27:43.000000000 -0500
@@ -9,6 +9,10 @@
import portage_db_template
+# since this format is massively deprecated,
+# we're hardcoding the previously weird line count
+magic_line_count = 22
+
class database(portage_db_template.database):
def module_init(self):
self.lastkey = None # Cache
@@ -42,39 +46,39 @@
mykeys += [x]
return mykeys
- def get_values(self,key):
+ def get_values(self,key, data=None):
+ """ do not use data unless you know what it does."""
+
if not key:
raise KeyError, "key is not set to a valid value"
- try:
- # give buffering a hint of the pretty much maximal
cache size we deal with
- myf = open(self.fullpath+key, "r", 8192)
- except OSError, oe:
- # either the file didn't exist, or it was removed under
our feet.
- return None
-
+ mydict = {}
+ if data == None:
+ try:
+ # give buffering a hint of the pretty much
maximal cache size we deal with
+ myf = open(self.fullpath+key, "r", 8192)
+ except OSError:
+ # either the file didn't exist, or it was
removed under our feet.
+ raise KeyError("failed reading key")
+
+ # nuke the newlines right off the batt.
+ data = myf.read().splitlines()
+ mydict["_mtime_"] = os.fstat(myf.fileno()).st_mtime
+ myf.close()
+ else:
+ mydict["_mtime_"] = data.pop(-1)
- # nuke the newlines right off the batt.
- data = myf.read().splitlines()
- mdict = {}
-
# rely on exceptions to note differing line counts.
try:
- for x in range(0, len(self.dbkeys)):
- mdict[self.dbkeys[x]] = data[x]
-
- # do this now, rather then earlier- possible that
earlier it might have been wasted
- # if key count mismatched
- mdict["_mtime_"] = os.fstat(myf.fileno()).st_mtime
+ for x in range(magic_line_count):
+ mydict[self.dbkeys[x]] = data[x]
except IndexError:
- myf.close()
raise ValueError, "Key count mistmatch"
- myf.close()
- return mdict
+ return mydict
- def set_values(self,key,val):
+ def set_values(self,key, val, raw=False):
if not key:
raise KeyError, "No key provided. key:%s val:%s" %
(key,val)
if not val:
@@ -86,12 +90,19 @@
update_fp = self.fullpath + ".update." + str(os.getpid()) + "."
+ key
myf = open(update_fp,"w")
- myf.writelines( [ val[x] +"\n" for x in self.dbkeys] )
+ if not raw:
+ myf.writelines( [ val[x] +"\n" for x in self.dbkeys] )
+ if len(self.dbkeys) != magic_line_count:
+ myf.writelines(["\n"] * len(self.dbkeys) -
magic_line_count)
+ mtime = val["_mtime_"]
+ else:
+ mtime = val.pop(-1)
+ myf.writelines(val)
myf.close()
os.chown(update_fp, self.uid, self.gid)
os.chmod(update_fp, 0664)
- os.utime(update_fp, (-1,long(val["_mtime_"])))
+ os.utime(update_fp, (-1,long(mtime)))
os.rename(update_fp, self.fullpath+key)
def del_key(self,key):
diff -urN portage-old/pym/portage_db_flat_hash.py
portage/pym/portage_db_flat_hash.py
--- portage-old/pym/portage_db_flat_hash.py 1969-12-31 18:00:00.000000000
-0600
+++ portage/pym/portage_db_flat_hash.py 2005-08-27 05:27:43.000000000 -0500
@@ -0,0 +1,38 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_flat.py,v
1.13.2.6 2005/04/19 07:14:17 ferringb Exp $
+cvs_id_string="$Id: portage_db_flat.py,v 1.13.2.6 2005/04/19 07:14:17 ferringb
Exp $"[5:-2]
+
+import portage_db_flat, os
+
+class database(portage_db_flat.database):
+
+ def get_values(self, key, data=None):
+ """ do not specify data unless you know what it does"""
+ if not key:
+ raise KeyError("key is not valid")
+
+ if data == None:
+ try:
+ myf = open(self.fullpath + key, "r")
+ except OSError:
+ raise KeyError("failed pulling key")
+
+ data = dict(map(lambda x: x.split("=",1),
myf.read().splitlines()))
+ data["_mtime_"] = os.fstat(myf.fileno()).st_mtime
+ myf.close()
+
+ mydict = {}
+ for x in self.dbkeys:
+ mydict[x] = data.get(x, "")
+ mydict["_mtime_"] = long(data["_mtime_"])
+ return mydict
+
+ def set_values(self, key, values):
+ l = []
+ for x in values.keys():
+ if values[x] and x != "_mtime_":
+ l.append("%s=%s\n" % (x, values[x]))
+ l.append(values["_mtime_"])
+ portage_db_flat.database.set_values(self, key, l, raw=True)
+
diff -urN portage-old/pym/portage_db_metadata.py
portage/pym/portage_db_metadata.py
--- portage-old/pym/portage_db_metadata.py 1969-12-31 18:00:00.000000000
-0600
+++ portage/pym/portage_db_metadata.py 2005-08-27 05:27:43.000000000 -0500
@@ -0,0 +1,49 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_flat.py,v
1.13.2.6 2005/04/19 07:14:17 ferringb Exp $
+cvs_id_string="$Id: portage_db_flat.py,v 1.13.2.6 2005/04/19 07:14:17 ferringb
Exp $"[5:-2]
+
+import os, portage_db_flat_hash, portage_db_flat
+
+class database(portage_db_flat_hash.database):
+
+ def get_values(self, key):
+ if not key:
+ raise KeyError("key is not valid")
+
+ try:
+ myf = open(self.fullpath + key, "r")
+ except OSError:
+ raise KeyError("key is not valid")
+ mtime = os.fstat(myf.fileno()).st_mtime
+ data = myf.read().splitlines()
+
+ # easy attempt first.
+ if len(data) != portage_db_flat.magic_line_count:
+ d = dict(map(lambda x: x.split("=",1), data))
+ d["_mtime_"] = mtime
+ return portage_db_flat_hash.database.get_values(self,
key, d)
+ # this one's interesting.
+ d = {}
+
+ for line in data:
+ # yes, meant to iterate over a string.
+ hashed = False
+ for idx, c in enumerate(line):
+ if not c.isalpha():
+ if c == "=" and idx > 0:
+ hashed = True
+ d[line[:idx]] = line[idx + 1:]
+ elif c == "_" or c.isdigit():
+ continue
+ break
+ elif not c.isupper():
+ break
+
+ if not hashed:
+ # non hashed.
+ data.append(mtime)
+ return
portage_db_flat.database.get_values(self, key, data=data)
+
+ d["_mtime_"] = mtime
+ return portage_db_flat_hash.database.get_values(self, key,
data=d)
--- portage-old/pym/portage_const.py 2005-04-28 23:56:35.000000000 -0500
+++ portage/pym/portage_const.py 2005-08-27 03:59:09.000000000 -0500
@@ -43,6 +43,9 @@
INCREMENTALS=["USE","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","PRELINK_PATH","PRELINK_PATH_MASK"]
STICKIES=["KEYWORDS_ACCEPT","USE","CFLAGS","CXXFLAGS","MAKEOPTS","EXTRA_ECONF","EXTRA_EINSTALL","EXTRA_EMAKE"]
+# supported EBUILD api versions.
+EAPI = 0
+
# ===========================================================================
# END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANT
# ===========================================================================
pgpHVzeEVHT1x.pgp
Description: PGP signature
