Merged from trunk -r13677:13688
authorFabian Groffen <grobian@gentoo.org>
Sat, 27 Jun 2009 14:32:58 +0000 (14:32 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sat, 27 Jun 2009 14:32:58 +0000 (14:32 -0000)
   | 13678   | Fix imports for _emerge submodules.                          |
   | zmedico |                                                              |

   | 13679   | Bug #275237 - If a directory exists in a location where a    |
   | zmedico | normal file is to be merged, generate a config-protect       |
   |         | filename for the file and merge it that way. Thanks to Jonas |
   |         | Bernoulli <jonas@bernoulli.cc> for this patch.               |

   | 13680   | In binarytree.inject(), when a symlink is created for the    |
   | zmedico | current package and it overwrites another package, delete    |
   |         | the corresponding metadata from the Packages file. Thanks to |
   |         | Eitan Mosenkis <eitan@mosenkis.net> for reporting.           |

   | 13681   | Add support to `portageq owners` for querying paths matching |
   | zmedico | a given basename. It is natural to support this since the    |
   |         | vartree already maintains a basename -> owner index anyway.  |
   |         | There are plans for the packagekit backend is to support     |
   |         | this type of search.                                         |

   | 13685   | Bug #275217 - Part 3 - Splits depgraph.select_files into     |
   | zmedico | select_files and _resolve. Thanks to Sebastian Mingramm      |
   |         | (few) <s.mingramm@gmx.de> for this patch.                    |

   | 13686   | * Make Package.metadata['USE'] access trigger USE            |
   | zmedico | calculation for unbuilt ebuilds. * Make                      |
   |         | Package.metadata['LICENSE'] access trigger USE conditional   |
   |         | evaluation. * Make Package.metadata['PROVIDE'] access        |
   |         | trigger USE conditional evaluation. * Initialize             |
   |         | Package.metadata['CHOST'] in the Package constructor for     |
   |         | unbuilt ebuilds.                                             |

   | 13687   | Remove obsolete Package.metadata['CHOST'] initialization.    |
   | zmedico |                                                              |

   | 13688   | Use depgraph._pkg() to construct Package instances inside    |
   | zmedico | _select_pkg_highest_available_imp().                         |

svn path=/main/branches/prefix/; revision=13714

bin/portageq
bin/repoman
pym/_emerge/Package.py
pym/_emerge/Scheduler.py
pym/_emerge/depgraph.py
pym/portage/dbapi/bintree.py
pym/portage/dbapi/vartree.py

index 2c87ac7042746519ce6b34bbb94593eb4eed85ac..38d797639d32a1e2cab2a2803dd0dd715a18796a 100755 (executable)
@@ -161,8 +161,8 @@ def owners(argv):
        Given a list of files, print the packages that own the files and which
        files belong to each package. Files owned by a package are listed on
        the lines below it, indented by a single tab character (\\t). All file
-       paths must start with <root>. Returns 1 if no owners could be found,
-       and 0 otherwise.
+       paths must either start with <root> or be a basename alone.
+       Returns 1 if no owners could be found, and 0 otherwise.
        """
        if len(argv) < 2:
                sys.stderr.write("ERROR: insufficient parameters!\n")
@@ -183,18 +183,22 @@ def owners(argv):
        files = []
        for f in argv[1:]:
                f = portage.normalize_path(f)
-               if not f.startswith(os.path.sep):
+               is_basename = os.sep not in f
+               if not is_basename and f[:1] != os.sep:
                        if cwd is None:
                                sys.stderr.write("ERROR: cwd does not exist!\n")
                                sys.stderr.flush()
                                return 2
                        f = os.path.join(cwd, f)
                        f = portage.normalize_path(f)
-               if not f.startswith(root):
+               if not is_basename and not f.startswith(root):
                        sys.stderr.write("ERROR: file paths must begin with <root>!\n")
                        sys.stderr.flush()
                        return 2
-               files.append(f[len(root):])
+               if is_basename:
+                       files.append(f)
+               else:
+                       files.append(f[len(root):])
 
        owners = vardb._owners.get_owners(files)
 
index bcde969de62be3f71649ad73675c71b47f23aa49..213da7e6fb97ac93c02487967e86a782f0f400de 100755 (executable)
@@ -48,7 +48,8 @@ portage._disable_legacy_globals()
 from repoman.checks import run_checks
 from repoman import utilities
 
-from _emerge import Package, RootConfig
+from _emerge.Package import Package
+from _emerge.RootConfig import RootConfig
 from portage.sets import load_default_config
 
 import portage.checksum
index 66ba5bc6c43c1c9654b56fe44ee498709e7a8d8f..e1283bbf4e4233774c8dbfaaf4371c71735c58fb 100644 (file)
@@ -11,7 +11,8 @@ else:
 import portage
 
 from portage.cache.mappings import slot_dict_class
-
+from portage.dep import paren_reduce, use_reduce, \
+       paren_normalize, paren_enclose
 from _emerge.Task import Task
 
 class Package(Task):
@@ -22,7 +23,8 @@ class Package(Task):
                "root_config", "type_name",
                "category", "counter", "cp", "cpv_split",
                "inherited", "iuse", "mtime",
-               "pf", "pv_split", "root", "slot", "slot_atom", "use")
+               "pf", "pv_split", "root", "slot", "slot_atom",) + \
+       ("_use",)
 
        metadata_keys = [
                "CHOST", "COUNTER", "DEPEND", "EAPI",
@@ -35,6 +37,8 @@ class Package(Task):
                Task.__init__(self, **kwargs)
                self.root = self.root_config.root
                self.metadata = _PackageMetadataWrapper(self, self.metadata)
+               if not self.built:
+                       self.metadata['CHOST'] = self.root_config.settings.get('CHOST', '')
                self.cp = portage.cpv_getkey(self.cpv)
                slot = self.slot
                if not slot:
@@ -46,13 +50,19 @@ class Package(Task):
                self.cpv_split = portage.catpkgsplit(self.cpv)
                self.pv_split = self.cpv_split[1:]
 
-       class _use(object):
+       class _use_class(object):
 
                __slots__ = ("__weakref__", "enabled")
 
                def __init__(self, use):
                        self.enabled = frozenset(use)
 
+       @property
+       def use(self):
+               if self._use is None:
+                       self._use = self._use_class(self.metadata['USE'].split())
+               return self._use
+
        class _iuse(object):
 
                __slots__ = ("__weakref__", "all", "enabled", "disabled", "iuse_implicit", "regex", "tokens")
@@ -143,13 +153,38 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
 
        __slots__ = ("_pkg",)
        _wrapped_keys = frozenset(
-               ["COUNTER", "INHERITED", "IUSE", "SLOT", "USE", "_mtime_"])
+               ["COUNTER", "INHERITED", "IUSE", "SLOT", "_mtime_"])
 
        def __init__(self, pkg, metadata):
                _PackageMetadataWrapperBase.__init__(self)
                self._pkg = pkg
+               """LICENSE with USE conditionals evaluated."""
+
+               if not pkg.built:
+                       # USE is lazy, but we want it to show up in self.keys().
+                       self['USE'] = ''
+
                self.update(metadata)
 
+       def __getitem__(self, k):
+               v = _PackageMetadataWrapperBase.__getitem__(self, k)
+               if k in ('PROVIDE', 'LICENSE',):
+                       if '?' in v:
+                               v = paren_enclose(paren_normalize(use_reduce(
+                                       paren_reduce(v), uselist=self._pkg.use.enabled)))
+                               self[k] = v
+
+               elif k == 'USE' and not self._pkg.built:
+                       if not v:
+                               # This is lazy because it's expensive.
+                               pkgsettings = self._pkg.root_config.trees[
+                                       'porttree'].dbapi.doebuild_settings
+                               pkgsettings.setcpv(self._pkg)
+                               v = pkgsettings["PORTAGE_USE"]
+                               self['USE'] = v
+
+               return v
+
        def __setitem__(self, k, v):
                _PackageMetadataWrapperBase.__setitem__(self, k, v)
                if k in self._wrapped_keys:
@@ -167,9 +202,6 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
        def _set_slot(self, k, v):
                self._pkg.slot = v
 
-       def _set_use(self, k, v):
-               self._pkg.use = self._pkg._use(v.split())
-
        def _set_counter(self, k, v):
                if isinstance(v, basestring):
                        try:
index 800e81cdcf6c59074c77fcbd9bc5c29d4c835b49..d103363371420dfc1c58efb130d2b205356a59d7 100644 (file)
@@ -1627,12 +1627,6 @@ class Scheduler(PollScheduler):
                db_keys = list(self.trees[root_config.root][
                        tree_type].dbapi._aux_cache_keys)
                metadata = izip(db_keys, db.aux_get(cpv, db_keys))
-               pkg = Package(cpv=cpv, metadata=metadata,
+               return Package(built=(type_name != 'ebuild'),
+                       cpv=cpv, metadata=metadata,
                        root_config=root_config, installed=installed)
-               if type_name == "ebuild":
-                       settings = self.pkgsettings[root_config.root]
-                       settings.setcpv(pkg)
-                       pkg.metadata["USE"] = settings["PORTAGE_USE"]
-                       pkg.metadata['CHOST'] = settings.get('CHOST', '')
-
-               return pkg
index 14e0552eb1835855d142d95f541ea45d98d3dfe2..a7d3243701b98cb15c07d4aaa968bca889fdbb2a 100644 (file)
@@ -176,6 +176,8 @@ class depgraph(object):
                                        "--getbinpkgonly" in self.myopts)
                del trees
 
+               #contains the args created by select_files
+               self._initial_arg_list = []
                self.digraph=portage.digraph()
                # contains all sets added to the graph
                self._sets = {}
@@ -1067,7 +1069,8 @@ class depgraph(object):
                                yield arg, atom
 
        def select_files(self, myfiles):
-               """Given a list of .tbz2s, .ebuilds sets, and deps, create the
+               """Given a list of .tbz2s, .ebuilds sets, and deps, populate
+               self._initial_arg_list and call self._resolve to create the 
                appropriate depgraph and return a favorite list."""
                debug = "--debug" in self.myopts
                root_config = self.roots[self.target_root]
@@ -1146,9 +1149,6 @@ class depgraph(object):
                                metadata = izip(db_keys, portdb.aux_get(mykey, db_keys))
                                pkg = Package(type_name="ebuild", root_config=root_config,
                                        cpv=mykey, metadata=metadata, onlydeps=onlydeps)
-                               pkgsettings.setcpv(pkg)
-                               pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
-                               pkg.metadata['CHOST'] = pkgsettings.get('CHOST', '')
                                self._pkg_cache[pkg] = pkg
                                args.append(PackageArg(arg=x, package=pkg,
                                        root_config=root_config))
@@ -1325,14 +1325,25 @@ class depgraph(object):
                                myfavorites.add(arg.arg)
                myfavorites = list(myfavorites)
 
-               pprovideddict = pkgsettings.pprovideddict
                if debug:
                        portage.writemsg("\n", noiselevel=-1)
                # Order needs to be preserved since a feature of --nodeps
                # is to allow the user to force a specific merge order.
                args.reverse()
-               while args:
-                       arg = args.pop()
+               self._initial_arg_list = args[:]
+       
+               return self._resolve(myfavorites)
+       
+       def _resolve(self, myfavorites):
+               """Given self._initial_arg_list, pull in the root nodes, 
+               call self._creategraph to process theier deps and return 
+               a favorite list."""
+               debug = "--debug" in self.myopts
+               onlydeps = "--onlydeps" in self.myopts
+               myroot = self.target_root
+               pkgsettings = self.pkgsettings[myroot]
+               pprovideddict = pkgsettings.pprovideddict
+               for arg in self._initial_arg_list:
                        for atom in arg.set:
                                self.spinner.update()
                                dep = Dependency(atom=atom, onlydeps=onlydeps,
@@ -1866,9 +1877,7 @@ class depgraph(object):
 
                                if not cpv_list:
                                        continue
-                               pkg_status = "merge"
-                               if installed or onlydeps:
-                                       pkg_status = "nomerge"
+
                                # descending order
                                cpv_list.reverse()
                                for cpv in cpv_list:
@@ -1880,31 +1889,11 @@ class depgraph(object):
                                                # in case there is a visible downgrade.
                                                continue
                                        reinstall_for_flags = None
-                                       cache_key = (pkg_type, root, cpv, pkg_status)
-                                       calculated_use = True
-                                       pkg = self._pkg_cache.get(cache_key)
-                                       if pkg is None:
-                                               calculated_use = False
-                                               try:
-                                                       metadata = izip(db_keys, db.aux_get(cpv, db_keys))
-                                               except KeyError:
-                                                       continue
-                                               pkg = Package(built=built, cpv=cpv,
-                                                       installed=installed, metadata=metadata,
-                                                       onlydeps=onlydeps, root_config=root_config,
-                                                       type_name=pkg_type)
-                                               metadata = pkg.metadata
-                                               if not built:
-                                                       metadata['CHOST'] = pkgsettings.get('CHOST', '')
-                                               if not built and ("?" in metadata["LICENSE"] or \
-                                                       "?" in metadata["PROVIDE"]):
-                                                       # This is avoided whenever possible because
-                                                       # it's expensive. It only needs to be done here
-                                                       # if it has an effect on visibility.
-                                                       pkgsettings.setcpv(pkg)
-                                                       metadata["USE"] = pkgsettings["PORTAGE_USE"]
-                                                       calculated_use = True
-                                               self._pkg_cache[pkg] = pkg
+                                       try:
+                                               pkg = self._pkg(cpv, pkg_type, root_config,
+                                                       installed=installed, onlydeps=onlydeps)
+                                       except portage.exception.PackageNotFound:
+                                               continue
 
                                        if not installed or (built and matched_packages):
                                                # Only enforce visibility on installed packages
@@ -1955,11 +1944,9 @@ class depgraph(object):
                                                                                if not visible(pkgsettings, pkg_eb):
                                                                                        continue
 
-                                       if not pkg.built and not calculated_use:
-                                               # This is avoided whenever possible because
-                                               # it's expensive.
-                                               pkgsettings.setcpv(pkg)
-                                               pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
+                                       # Calculation of USE for unbuilt ebuilds is relatively
+                                       # expensive, so it is only performed lazily, after the
+                                       # above visibility checks are complete.
 
                                        if pkg.cp != atom.cp:
                                                # A cpv can be returned from dbapi.match() as an
@@ -1972,8 +1959,6 @@ class depgraph(object):
                                        myarg = None
                                        if root == self.target_root:
                                                try:
-                                                       # Ebuild USE must have been calculated prior
-                                                       # to this point, in case atoms have USE deps.
                                                        myarg = self._iter_atoms_for_pkg(pkg).next()
                                                except StopIteration:
                                                        pass
@@ -2202,18 +2187,24 @@ class depgraph(object):
                                        return 0
                return 1
 
-       def _pkg(self, cpv, type_name, root_config, installed=False):
+       def _pkg(self, cpv, type_name, root_config, installed=False, 
+               onlydeps=False):
                """
                Get a package instance from the cache, or create a new
-               one if necessary. Raises KeyError from aux_get if it
+               one if necessary. Raises PackageNotFound from aux_get if it
                failures for some reason (package does not exist or is
                corrupt).
                """
                operation = "merge"
-               if installed:
+               if installed or onlydeps:
                        operation = "nomerge"
                pkg = self._pkg_cache.get(
                        (type_name, root_config.root, cpv, operation))
+               if pkg is None and onlydeps and not installed:
+                       # Maybe it already got pulled in as a "merge" node.
+                       pkg = self.mydbapi[root_config.root].get(
+                               (type_name, root_config.root, cpv, 'merge'))
+
                if pkg is None:
                        tree_type = self.pkg_tree_map[type_name]
                        db = root_config.trees[tree_type].dbapi
@@ -2223,13 +2214,9 @@ class depgraph(object):
                                metadata = izip(db_keys, db.aux_get(cpv, db_keys))
                        except KeyError:
                                raise portage.exception.PackageNotFound(cpv)
-                       pkg = Package(cpv=cpv, metadata=metadata,
-                               root_config=root_config, installed=installed)
-                       if type_name == "ebuild":
-                               settings = self.pkgsettings[root_config.root]
-                               settings.setcpv(pkg)
-                               pkg.metadata["USE"] = settings["PORTAGE_USE"]
-                               pkg.metadata['CHOST'] = settings.get('CHOST', '')
+                       pkg = Package(built=(type_name != "ebuild"), cpv=cpv,
+                               installed=installed, metadata=metadata,
+                               root_config=root_config, type_name=type_name)
                        self._pkg_cache[pkg] = pkg
                return pkg
 
@@ -4369,11 +4356,6 @@ class depgraph(object):
                                installed=installed, metadata=metadata,
                                operation=action, root_config=root_config,
                                type_name=pkg_type)
-                       if pkg_type == "ebuild":
-                               pkgsettings = self.pkgsettings[myroot]
-                               pkgsettings.setcpv(pkg)
-                               pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
-                               pkg.metadata['CHOST'] = pkgsettings.get('CHOST', '')
                        self._pkg_cache[pkg] = pkg
 
                        root_config = self.roots[pkg.root]
@@ -4815,10 +4797,7 @@ def get_mask_info(root_config, cpv, pkgsettings,
                        db.aux_get(cpv, db_keys)))
        except KeyError:
                metadata = None
-       if metadata and not built:
-               pkgsettings.setcpv(cpv, mydb=metadata)
-               metadata["USE"] = pkgsettings["PORTAGE_USE"]
-               metadata['CHOST'] = pkgsettings.get('CHOST', '')
+
        if metadata is None:
                mreasons = ["corruption"]
        else:
index a9abaf309a03840893c534050c17debeb65e88cc..071cc4a63539355f660f560c8c01ef1d16e42625 100644 (file)
@@ -836,6 +836,7 @@ class binarytree(object):
                # process) and then updated it, all while holding a lock.
                from portage.locks import lockfile, unlockfile
                pkgindex_lock = None
+               created_symlink = False
                try:
                        pkgindex_lock = lockfile(self._pkgindex_file,
                                wantnewlockfile=1)
@@ -846,6 +847,7 @@ class binarytree(object):
                        if self._all_directory and \
                                self.getname(cpv).split(os.path.sep)[-2] == "All":
                                self._create_symlink(cpv)
+                               created_symlink = True
                        pkgindex = self._new_pkgindex()
                        try:
                                f = open(self._pkgindex_file)
@@ -877,8 +879,14 @@ class binarytree(object):
                                        # Handle path collisions in $PKGDIR/All
                                        # when CPV is not identical.
                                        del pkgindex.packages[i]
-                               elif cpv == d2.get("CPV") and path == d2.get("PATH", ""):
-                                       del pkgindex.packages[i]
+                               elif cpv == d2.get("CPV"):
+                                       if path == d2.get("PATH", ""):
+                                               del pkgindex.packages[i]
+                                       elif created_symlink and not d2.get("PATH", ""):
+                                               # Delete entry for the package that was just
+                                               # overwritten by a symlink to this package.
+                                               del pkgindex.packages[i]
+
                        pkgindex.packages.append(d)
 
                        self._update_pkgindex_header(pkgindex.header)
index b1c6c086e2862137eb8a65eed6b5e608a6cafe7c..76d2b5d8a94f4acf74c5a73924f343e78274c1ba 100644 (file)
@@ -2053,7 +2053,12 @@ class vardbapi(dbapi):
                                return x
 
                        for path in path_iter:
-                               name = os.path.basename(path.rstrip(os.path.sep))
+                               is_basename = os.sep != path[:1]
+                               if is_basename:
+                                       name = path
+                               else:
+                                       name = os.path.basename(path.rstrip(os.path.sep))
+
                                if not name:
                                        continue
 
@@ -2074,8 +2079,14 @@ class vardbapi(dbapi):
 
                                                if current_hash != hash_value:
                                                        continue
-                                               if dblink(cpv).isowner(path, root):
-                                                       yield dblink(cpv), path
+
+                                               if is_basename:
+                                                       for p in dblink(cpv).getcontents():
+                                                               if os.path.basename(p) == name:
+                                                                       yield dblink(cpv), p[len(root):]
+                                               else:
+                                                       if dblink(cpv).isowner(path, root):
+                                                               yield dblink(cpv), path
 
 class vartree(object):
        "this tree will scan a var/db/pkg database located at root (passed to init)"
@@ -4357,7 +4368,7 @@ class dblink(object):
                                        # destination file exists
                                        if stat.S_ISDIR(mydmode):
                                                # install of destination is blocked by an existing directory with the same name
-                                               moveme = 0
+                                               cfgprot = 1
                                                showMessage("!!! %s\n" % mydest,
                                                        level=logging.ERROR, noiselevel=-1)
                                        elif stat.S_ISREG(mydmode) or (stat.S_ISLNK(mydmode) and os.path.exists(mydest) and stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])):
@@ -4392,8 +4403,8 @@ class dblink(object):
                                                                """A previously remembered update has been
                                                                accepted, so it is removed from confmem."""
                                                                del cfgfiledict[myrealdest]
-                                               if cfgprot:
-                                                       mydest = new_protect_filename(mydest, newmd5=mymd5)
+                                       if cfgprot:
+                                               mydest = new_protect_filename(mydest, newmd5=mymd5)
 
                                # whether config protection or not, we merge the new file the
                                # same way.  Unless moveme=0 (blocking directory)