summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2010-08-19 21:28:10 -0700
committerZac Medico <zmedico@gentoo.org>2010-08-19 21:28:10 -0700
commitc0ee69585bf87e09c237668531127e79e0cd1c46 (patch)
tree12789d04012a72e171bc509ef9582a223f5cf33b
parent133bdfe6d497d3e138512a777ddfee2c3aff1393 (diff)
downloadportage-c0ee69585bf87e09c237668531127e79e0cd1c46.tar.gz
portage-c0ee69585bf87e09c237668531127e79e0cd1c46.tar.bz2
portage-c0ee69585bf87e09c237668531127e79e0cd1c46.zip
Add experimental EPREFIX/EROOT support to the config and vartree
classes, and use it in ResolverPlayground to emulate a prefix-like environment. This fixes ResolverPlayground so that it doesn't have to abuse the --root and --root-deps options in order to create a testing environment. Instead it simply creates a temporary EPREFIX. WARNING: EPREFIX/EROOT support is experimental and may be incomplete for cases in which EPREFIX is non-empty.
-rw-r--r--pym/_emerge/depgraph.py5
-rw-r--r--pym/portage/dbapi/porttree.py25
-rw-r--r--pym/portage/dbapi/vartree.py106
-rw-r--r--pym/portage/package/ebuild/config.py27
-rw-r--r--pym/portage/tests/resolver/ResolverPlayground.py36
5 files changed, 114 insertions, 85 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index ed64e49e0..704686567 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -72,10 +72,7 @@ class _frozen_depgraph_config(object):
if settings.get("PORTAGE_DEBUG", "") == "1":
self.edebug = 1
self.spinner = spinner
- if "_test_" in myopts and "/" not in trees:
- self._running_root = trees[self.target_root]["root_config"]
- else:
- self._running_root = trees["/"]["root_config"]
+ self._running_root = trees["/"]["root_config"]
self._opts_no_restart = frozenset(["--buildpkgonly",
"--fetchonly", "--fetch-all-uri", "--pretend"])
self.pkgsettings = {}
diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
index 043adc642..c925d9bf8 100644
--- a/pym/portage/dbapi/porttree.py
+++ b/pym/portage/dbapi/porttree.py
@@ -1056,7 +1056,7 @@ def close_portdbapi_caches():
i.close_caches()
class portagetree(object):
- def __init__(self, root="/", virtual=None, settings=None):
+ def __init__(self, root=None, virtual=None, settings=None):
"""
Constructor for a PortageTree
@@ -1068,14 +1068,21 @@ class portagetree(object):
@type settings: Instance of portage.config
"""
- if True:
- self.root = root
- if settings is None:
- from portage import settings
- self.settings = settings
- self.portroot = settings["PORTDIR"]
- self.virtual = virtual
- self.dbapi = portdbapi(mysettings=settings)
+ if settings is None:
+ settings = portage.settings
+ self.settings = settings
+
+ self.root = settings['ROOT']
+ if root is not None and root != self.root:
+ warnings.warn("The root parameter of the " + \
+ "portage.dbapi.porttree.portagetree" + \
+ " constructor is now unused. Use " + \
+ "settings['ROOT'] instead.",
+ DeprecationWarning, stacklevel=2)
+
+ self.portroot = settings["PORTDIR"]
+ self.virtual = virtual
+ self.dbapi = portdbapi(mysettings=settings)
def dep_bestmatch(self,mydep):
"compatibility method"
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 80057e2dd..c406f5b48 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -61,6 +61,7 @@ import stat
import sys
import tempfile
import time
+import warnings
try:
import cPickle as pickle
@@ -815,16 +816,12 @@ class vardbapi(dbapi):
_aux_cache_keys_re = re.compile(r'^NEEDED\..*$')
_aux_multi_line_re = re.compile(r'^(CONTENTS|NEEDED\..*)$')
- def __init__(self, root, categories=None, settings=None, vartree=None):
+ def __init__(self, _unused_param=None, categories=None, settings=None, vartree=None):
"""
The categories parameter is unused since the dbapi class
now has a categories property that is generated from the
available packages.
"""
- self.root = _unicode_decode(root,
- encoding=_encodings['content'], errors='strict')
- if self.root[-1] != '/':
- self.root += '/'
# Used by emerge to check whether any packages
# have been added or removed.
@@ -841,11 +838,20 @@ class vardbapi(dbapi):
self.blockers = None
if settings is None:
- from portage import settings
+ settings = portage.settings
self.settings = settings
+ self.root = settings['ROOT']
+
+ if _unused_param is not None and _unused_param != self.root:
+ warnings.warn("The first parameter of the " + \
+ "portage.dbapi.vartree.vardbapi" + \
+ " constructor is now unused. Use " + \
+ "settings['ROOT'] instead.",
+ DeprecationWarning, stacklevel=2)
+
+ self._eroot = settings['EROOT']
if vartree is None:
- from portage import db
- vartree = db[root]["vartree"]
+ vartree = portage.db[self.root]["vartree"]
self.vartree = vartree
self._aux_cache_keys = set(
["BUILD_TIME", "CHOST", "COUNTER", "DEPEND", "DESCRIPTION",
@@ -854,14 +860,14 @@ class vardbapi(dbapi):
"repository", "RESTRICT" , "SLOT", "USE", "DEFINED_PHASES",
"REQUIRED_USE"])
self._aux_cache_obj = None
- self._aux_cache_filename = os.path.join(self.root,
+ self._aux_cache_filename = os.path.join(self._eroot,
CACHE_PATH, "vdb_metadata.pickle")
- self._counter_path = os.path.join(root,
+ self._counter_path = os.path.join(self._eroot,
CACHE_PATH, "counter")
try:
- self.plib_registry = PreservedLibsRegistry(self.root,
- os.path.join(self.root, PRIVATE_PATH, "preserved_libs_registry"))
+ self.plib_registry = PreservedLibsRegistry(self._eroot,
+ os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry"))
except PermissionDenied:
# apparently this user isn't allowed to access PRIVATE_PATH
self.plib_registry = None
@@ -872,7 +878,7 @@ class vardbapi(dbapi):
def getpath(self, mykey, filename=None):
# This is an optimized hotspot, so don't use unicode-wrapped
# os module and don't use os.path.join().
- rValue = self.root + VDB_PATH + _os.sep + mykey
+ rValue = self._eroot + VDB_PATH + _os.sep + mykey
if filename is not None:
# If filename is always relative, we can do just
# rValue += _os.sep + filename
@@ -884,7 +890,7 @@ class vardbapi(dbapi):
This is called before an after any modifications, so that consumers
can use directory mtimes to validate caches. See bug #290428.
"""
- base = self.root + VDB_PATH
+ base = self._eroot + VDB_PATH
cat = catsplit(cpv)[0]
catdir = base + _os.sep + cat
t = time.time()
@@ -1025,7 +1031,7 @@ class vardbapi(dbapi):
involve merge or unmerge of packages).
"""
returnme = []
- basepath = os.path.join(self.root, VDB_PATH) + os.path.sep
+ basepath = os.path.join(self._eroot, VDB_PATH) + os.path.sep
if use_cache:
from portage import listdir
@@ -1117,7 +1123,7 @@ class vardbapi(dbapi):
return list(self._iter_match(mydep,
self.cp_list(mydep.cp, use_cache=use_cache)))
try:
- curmtime = os.stat(os.path.join(self.root, VDB_PATH, mycat)).st_mtime
+ curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime
except (IOError, OSError):
curmtime=0
@@ -1760,26 +1766,23 @@ class vardbapi(dbapi):
class vartree(object):
"this tree will scan a var/db/pkg database located at root (passed to init)"
- def __init__(self, root="/", virtual=None, clone=None, categories=None,
+ def __init__(self, root=None, virtual=None, clone=None, categories=None,
settings=None):
- if clone:
- writemsg("vartree.__init__(): deprecated " + \
- "use of clone parameter\n", noiselevel=-1)
- self.root = clone.root[:]
- self.dbapi = copy.deepcopy(clone.dbapi)
- self.populated = 1
- from portage import config
- self.settings = config(clone=clone.settings)
- else:
- self.root = root[:]
- if settings is None:
- from portage import settings
- self.settings = settings
- if categories is None:
- categories = settings.categories
- self.dbapi = vardbapi(self.root, categories=categories,
- settings=settings, vartree=self)
- self.populated = 1
+
+ if settings is None:
+ settings = portage.settings
+ self.root = settings['ROOT']
+
+ if root is not None and root != self.root:
+ warnings.warn("The 'root' parameter of the " + \
+ "portage.dbapi.vartree.vartree" + \
+ " constructor is now unused. Use " + \
+ "settings['ROOT'] instead.",
+ DeprecationWarning, stacklevel=2)
+
+ self.settings = settings
+ self.dbapi = vardbapi(settings=settings, vartree=self)
+ self.populated = 1
def getpath(self, mykey, filename=None):
return self.dbapi.getpath(mykey, filename=filename)
@@ -1807,7 +1810,7 @@ class vartree(object):
except SystemExit as e:
raise
except Exception as e:
- mydir = os.path.join(self.root, VDB_PATH, mycpv)
+ mydir = os.path.join(self._eroot, VDB_PATH, mycpv)
writemsg(_("\nParse Error reading PROVIDE and USE in '%s'\n") % mydir,
noiselevel=-1)
if mylines:
@@ -1926,7 +1929,10 @@ class dblink(object):
self._blockers = blockers
self._scheduler = scheduler
- self.dbroot = normalize_path(os.path.join(myroot, VDB_PATH))
+ # WARNING: EROOT support is experimental and may be incomplete
+ # for cases in which EPREFIX is non-empty.
+ self._eroot = mysettings['EROOT']
+ self.dbroot = normalize_path(os.path.join(self._eroot, VDB_PATH))
self.dbcatdir = self.dbroot+"/"+cat
self.dbpkgdir = self.dbcatdir+"/"+pkg
self.dbtmpdir = self.dbcatdir+"/-MERGING-"+pkg
@@ -2039,7 +2045,7 @@ class dblink(object):
obj_index = contents_re.groupindex['obj']
dir_index = contents_re.groupindex['dir']
sym_index = contents_re.groupindex['sym']
- myroot = self.myroot
+ myroot = self._eroot
if myroot == os.path.sep:
myroot = None
pos = 0
@@ -2666,7 +2672,7 @@ class dblink(object):
#remove self from vartree database so that our own virtual gets zapped if we're the last node
self.vartree.zap(self.mycpv)
- def isowner(self, filename, destroot):
+ def isowner(self, filename, destroot=None):
"""
Check if a file belongs to this package. This may
result in a stat call for the parent directory of
@@ -2685,9 +2691,17 @@ class dblink(object):
1. True if this package owns the file.
2. False if this package does not own the file.
"""
- return bool(self._match_contents(filename, destroot))
- def _match_contents(self, filename, destroot):
+ if destroot is not None and destroot != self._eroot:
+ warnings.warn("The second parameter of the " + \
+ "portage.dbapi.vartree.dblink.isowner()" + \
+ " is now unused. Instead " + \
+ "self.settings['EROOT'] will be used.",
+ DeprecationWarning, stacklevel=2)
+
+ return bool(self._match_contents(filename))
+
+ def _match_contents(self, filename, destroot=None):
"""
The matching contents entry is returned, which is useful
since the path may differ from the one given by the caller,
@@ -2701,8 +2715,14 @@ class dblink(object):
filename = _unicode_decode(filename,
encoding=_encodings['content'], errors='strict')
- destroot = _unicode_decode(destroot,
- encoding=_encodings['content'], errors='strict')
+ if destroot is not None and destroot != self._eroot:
+ warnings.warn("The second parameter of the " + \
+ "portage.dbapi.vartree.dblink._match_contents()" + \
+ " is now unused. Instead " + \
+ "self.settings['EROOT'] will be used.",
+ DeprecationWarning, stacklevel=2)
+
+ destroot = self._eroot
# The given filename argument might have a different encoding than the
# the filenames contained in the contents, so use separate wrapped os
diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
index 4893cfbb4..46cac3b49 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -317,7 +317,7 @@ class config(object):
def __init__(self, clone=None, mycpv=None, config_profile_path=None,
config_incrementals=None, config_root=None, target_root=None,
- local_config=True, env=None):
+ _eprefix=None, local_config=True, env=None):
"""
@param clone: If provided, init will use deepcopy to copy by value the instance.
@type clone: Instance of config class.
@@ -333,6 +333,8 @@ class config(object):
@type config_root: String
@param target_root: __init__ override of $ROOT env variable.
@type target_root: String
+ @param _eprefix: set the EPREFIX variable (private, used by internal tests)
+ @type _eprefix: String
@param local_config: Enables loading of local config (/etc/portage); used most by repoman to
ignore local config (keywording and unmasking)
@type local_config: Boolean
@@ -341,6 +343,10 @@ class config(object):
@type env: dict
"""
+ # rename local _eprefix variable for convenience
+ eprefix = _eprefix
+ del _eprefix
+
# When initializing the global portage.settings instance, avoid
# raising exceptions whenever possible since exceptions thrown
# from 'import portage' or 'import portage.exceptions' statements
@@ -458,8 +464,10 @@ class config(object):
noiselevel=-1)
raise DirectoryNotFound(var)
+ if eprefix is None:
+ eprefix = ""
if config_root is None:
- config_root = "/"
+ config_root = eprefix + os.sep
config_root = normalize_path(os.path.abspath(
config_root)).rstrip(os.path.sep) + os.path.sep
@@ -664,6 +672,8 @@ class config(object):
ensure_dirs(target_root)
check_var_directory("ROOT", target_root)
+ eroot = target_root.rstrip(os.sep) + eprefix + os.sep
+
# The expand_map is used for variable substitution
# in getconfig() calls, and the getconfig() calls
# update expand_map with the value of each variable
@@ -681,7 +691,7 @@ class config(object):
# lead to unexpected results.
expand_map = {}
- env_d = getconfig(os.path.join(target_root, "etc", "profile.env"),
+ env_d = getconfig(os.path.join(eroot, "etc", "profile.env"),
expand=expand_map)
# env_d will be None if profile.env doesn't exist.
if env_d:
@@ -798,10 +808,9 @@ class config(object):
self["ROOT"] = target_root
self.backup_changes("ROOT")
- # Prefix forward compatability, set EPREFIX to the empty string
- self["EPREFIX"] = ''
+ self["EPREFIX"] = eprefix
self.backup_changes("EPREFIX")
- self["EROOT"] = target_root
+ self["EROOT"] = eroot
self.backup_changes("EROOT")
self.pusedict = portage.dep.ExtendedAtomDict(dict)
@@ -1078,7 +1087,7 @@ class config(object):
"""
Create a few directories that are critical to portage operation
"""
- if not os.access(self["ROOT"], os.W_OK):
+ if not os.access(self["EROOT"], os.W_OK):
return
# gid, mode, mask, preserve_perms
@@ -1091,7 +1100,7 @@ class config(object):
for mypath, (gid, mode, modemask, preserve_perms) \
in dir_mode_map.items():
- mydir = os.path.join(self["ROOT"], mypath)
+ mydir = os.path.join(self["EROOT"], mypath)
if preserve_perms and os.path.isdir(mydir):
# Only adjust permissions on some directories if
# they don't exist yet. This gives freedom to the
@@ -2185,7 +2194,7 @@ class config(object):
def reload(self):
"""Reload things like /etc/profile.env that can change during runtime."""
- env_d_filename = os.path.join(self["ROOT"], "etc", "profile.env")
+ env_d_filename = os.path.join(self["EROOT"], "etc", "profile.env")
self.configdict["env.d"].clear()
env_d = getconfig(env_d_filename, expand=False)
if env_d:
diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py
index fb691ba63..1ce371d9b 100644
--- a/pym/portage/tests/resolver/ResolverPlayground.py
+++ b/pym/portage/tests/resolver/ResolverPlayground.py
@@ -35,9 +35,11 @@ class ResolverPlayground(object):
profile: settings defined by the profile.
"""
self.debug = debug
- self.root = tempfile.mkdtemp() + os.path.sep
- self.portdir = os.path.join(self.root, "usr/portage")
- self.vdbdir = os.path.join(self.root, "var/db/pkg")
+ self.root = "/"
+ self.eprefix = tempfile.mkdtemp()
+ self.eroot = self.root + self.eprefix.lstrip(os.sep) + os.sep
+ self.portdir = os.path.join(self.eroot, "usr/portage")
+ self.vdbdir = os.path.join(self.eroot, "var/db/pkg")
os.makedirs(self.portdir)
os.makedirs(self.vdbdir)
@@ -182,12 +184,12 @@ class ResolverPlayground(object):
raise NotImplentedError()
#Create profile symlink
- os.makedirs(os.path.join(self.root, "etc"))
- os.symlink(sub_profile_dir, os.path.join(self.root, "etc", "make.profile"))
+ os.makedirs(os.path.join(self.eroot, "etc"))
+ os.symlink(sub_profile_dir, os.path.join(self.eroot, "etc", "make.profile"))
def _create_world(self, world):
#Create /var/lib/portage/world
- var_lib_portage = os.path.join(self.root, "var", "lib", "portage")
+ var_lib_portage = os.path.join(self.eroot, "var", "lib", "portage")
os.makedirs(var_lib_portage)
world_file = os.path.join(var_lib_portage, "world")
@@ -201,8 +203,7 @@ class ResolverPlayground(object):
env = {
"ACCEPT_KEYWORDS": "x86",
"PORTDIR": self.portdir,
- "ROOT": self.root,
- 'PORTAGE_TMPDIR' : os.path.join(self.root, 'var/tmp'),
+ 'PORTAGE_TMPDIR' : os.path.join(self.eroot, 'var/tmp'),
}
# Pass along PORTAGE_USERNAME and PORTAGE_GRPNAME since they
@@ -212,15 +213,16 @@ class ResolverPlayground(object):
if 'PORTAGE_GRPNAME' in os.environ:
env['PORTAGE_GRPNAME'] = os.environ['PORTAGE_GRPNAME']
- settings = config(config_root=self.root, target_root=self.root, env=env)
+ settings = config(_eprefix=self.eprefix, env=env)
settings.lock()
trees = {
self.root: {
- "virtuals": settings.getvirtuals(),
- "vartree": vartree(self.root, categories=settings.categories, settings=settings),
+ "vartree": vartree(settings=settings),
"porttree": portagetree(self.root, settings=settings),
- "bintree": binarytree(self.root, os.path.join(self.root, "usr/portage/packages"), settings=settings)
+ "bintree": binarytree(self.root,
+ os.path.join(self.eroot, "usr/portage/packages"),
+ settings=settings)
}
}
@@ -237,14 +239,8 @@ class ResolverPlayground(object):
options = options.copy()
options["--pretend"] = True
options["--quiet"] = True
- options["--root"] = self.root
- options["--config-root"] = self.root
- options["--root-deps"] = True
if self.debug:
options["--debug"] = True
- # Add a fake _test_ option that can be used for
- # conditional test code.
- options["_test_"] = True
if not self.debug:
portage.util.noiselimit = -2
@@ -267,9 +263,9 @@ class ResolverPlayground(object):
def cleanup(self):
if self.debug:
- print("\nROOT=%s" % self.root)
+ print("\nEROOT=%s" % self.eroot)
else:
- shutil.rmtree(self.root)
+ shutil.rmtree(self.eroot)
class ResolverPlaygroundTestCase(object):