Merged from trunk 10738:10759
authorFabian Groffen <grobian@gentoo.org>
Sun, 22 Jun 2008 15:29:37 +0000 (15:29 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sun, 22 Jun 2008 15:29:37 +0000 (15:29 -0000)
   | 10739    | Make the visibility related config methods such as          |
   | zmedico  | getMaskAtom() and getProfileMaskAtom() private since these  |
   |          | methods really should take Package instances before we      |
   |          | expose them as public api.                                  |

   | 10740    | Instead of having Atom inherit from str, just emulate the   |
   | zmedico  | interface. This allows us to define __slots__ (not allowed  |
   |          | when inheriting from str) and therefore should conserve     |
   |          | some memory by avoiding a __dict__ attribute on every Atom. |

   | 10741    | Use a metaclass to cache Atom instances transparently. This |
   | zmedico  | should improve performance and conserve memory in cases     |
   |          | when the same atom is more than once.                       |

   | 10742    | Make the Atom cache dict private and add a docstring for    |
   | zmedico  | _AtomCache.                                                 |

   | 10743    | Make Atom use str.__hash__.                                 |
   | zmedico  |                                                             |

   | 10744    | Make Atom use str.__eq__ and __ne__ also.                   |
   | zmedico  |                                                             |

   | 10745    | Make isvalidatom() use the Atom cache to avoid validating   |
   | zmedico  | the same atom twice.                                        |

   | 10746    | Bug #228595 - Use os.path.realpath() before comparing paths |
   | zmedico  | to those returned from portdbapi.getRepositoryPath() since  |
   |          | those paths are also cannonical.                            |

   | 10747    | Add subversion support for repoman. (thanks grobian)        |
   | zmedico  |                                                             |

   | 10748    | Remove unused Atom.string attribute.                        |
   | zmedico  |                                                             |

   | 10749    | Fix Atom -> str breakage in WorldSet.write().               |
   | zmedico  |                                                             |

   | 10750    | drop old -i,--include-masked option #226429 by Tobias       |
   | SpankMan | Klausmann                                                   |

   | 10751    | Use bash's built-in echo instead of the actual echo binary  |
   | zmedico  | since it has compatibility issues on FreeBSD systems.       |
   |          | Thanks to aballier for reporting the issue and testing this |
   |          | patch.                                                      |

   | 10752    | Exclude calls to autoheader and makeinfo from the automake  |
   | zmedico  | "maintainer mode" check (filter some false positives).      |
   |          | Thanks to Flameeyes.                                        |

   | 10753    | Fix implicit_pattern to match different quote character     |
   | zmedico  | found in warnings generated by gcc-4.3. Thanks to aballier  |
   |          | for reporting with sample log.                              |

   | 10754    | Make LibraryConsumerSet.mapPathsToAtoms() use the contents  |
   | zmedico  | index for more efficient owner lookups.                     |

   | 10755    | Fix Atom -> str breakage in depgraph.display_problems().    |
   | zmedico  |                                                             |

   | 10756    | Bug #228489 - Restore the "ci" alias for "commit" mode.     |
   | zmedico  | Thanks to grobian for the patch.                            |

   | 10757    | Implement Atom.__cmp__() so that things like list.sort()    |
   | zmedico  | work correctly for Atom instances.                          |

   | 10758    | Fix Atom -> str breakage in                                 |
   | zmedico  | depgraph._show_slot_collision_notice(). Thanks to Arfrever  |
   |          | for reporting.                                              |

   | 10759    | Fix broken path handling wrt $ROOT in                       |
   | zmedico  | LibraryConsumerSet.mapPathsToAtoms().                       |

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

NEWS
bin/check-implicit-pointer-usage.py
bin/repoman
man/repoman.1
pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/dbapi/porttree.py
pym/portage/dep.py
pym/portage/sets/files.py
pym/portage/sets/libs.py
pym/portage/tests/sets/shell/testShell.py

diff --git a/NEWS b/NEWS
index 09da35b309f275eaf84e72101ce0531a4d53a44c..45dc3798ecae3933c324a2d915cd9f1684ec67f0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ News (mainly features/major bug fixes)
 portage-2.2
 -------------
 
+* Add subversion support for repoman.
 * It is now possible to use `emerge <file>` to reinstall the package that
   installed a particular file. Package contents entries are indexed to
   improve performance. A command such as `emerge /lib/modules` can serve
index 93b9d6b968b24216e8f4a668858ef1907357f102..a9f22a543327c539b9a8bb1e4546978d15140ebd 100755 (executable)
@@ -17,7 +17,7 @@ import re
 import sys
 
 implicit_pattern = re.compile("([^:]*):(\d+): warning: implicit declaration "
-                              + "of function `([^']*)'")
+                              + "of function [`']([^']*)'")
 pointer_pattern = re.compile(
     "([^:]*):(\d+): warning: "
     + "("
index f015ab5485f92b8c2589273fee11b72d8ce6d089..693c7a4a80b23610220c068821957e88bcdb9601 100755 (executable)
@@ -145,6 +145,7 @@ def ParseArgs(args, qahelp):
 
        modes = {
                'commit' : 'Run a scan then commit changes',
+               'ci' : 'Run a scan then commit changes',
                'fix' : 'Fix simple QA issues (stray digests, missing digests)',
                'full' : 'Scan directory tree and print all issues (not a summary)',
                'help' : 'Show this screen',
@@ -223,6 +224,9 @@ def ParseArgs(args, qahelp):
 
        if not opts.mode:
                opts.mode = 'full'      #default to full
+       
+       if opts.mode == 'ci':
+               opts.mode = 'commit'  # backwards compat shortcut
 
        if opts.mode == 'commit' and not (opts.force or opts.pretend):
                if opts.ignore_masked:
index 7f03365c206840e6978eed9bf676508c9aa019f4..1d4c24a2fa092c12f566d2b388d329c3282548d6 100644 (file)
@@ -25,9 +25,6 @@ Be less verbose about extraneous info
 \fB-p\fR, \fB--pretend\fR
 Don't commit or fix anything; just show what would be done
 .TP
-\fB-i\fR, \fB--include-masked\fR
-Include masked packages in scans at category or tree level
-.TP
 \fB-x\fR, \fB--xmlparse\fR
 Forces the metadata.xml parse check to be carried out
 .TP
index 7a14986718655d69f4f5f2844eb6f6bf9df20753..0ee96893149c165dc86841c162d19093a03f45a6 100644 (file)
@@ -1141,14 +1141,14 @@ def visible(pkgsettings, pkg):
        if not portage.eapi_is_supported(pkg.metadata["EAPI"]):
                return False
        if not pkg.installed and \
-               pkgsettings.getMissingKeywords(pkg.cpv, pkg.metadata):
+               pkgsettings._getMissingKeywords(pkg.cpv, pkg.metadata):
                return False
-       if pkgsettings.getMaskAtom(pkg.cpv, pkg.metadata):
+       if pkgsettings._getMaskAtom(pkg.cpv, pkg.metadata):
                return False
-       if pkgsettings.getProfileMaskAtom(pkg.cpv, pkg.metadata):
+       if pkgsettings._getProfileMaskAtom(pkg.cpv, pkg.metadata):
                return False
        try:
-               if pkgsettings.getMissingLicenses(pkg.cpv, pkg.metadata):
+               if pkgsettings._getMissingLicenses(pkg.cpv, pkg.metadata):
                        return False
        except portage.exception.InvalidDependString:
                return False
@@ -1221,7 +1221,7 @@ def show_masked_packages(masked_packages):
                                have_eapi_mask = True
                        try:
                                missing_licenses = \
-                                       pkgsettings.getMissingLicenses(
+                                       pkgsettings._getMissingLicenses(
                                                cpv, metadata)
                        except portage.exception.InvalidDependString:
                                # This will have already been reported
@@ -2076,7 +2076,7 @@ class depgraph(object):
                # Max number of parents shown, to avoid flooding the display.
                max_parents = 3
                for slot_atom, root in self._slot_collision_info:
-                       msg.append(slot_atom)
+                       msg.append(str(slot_atom))
                        msg.append("\n\n")
                        slot_nodes = []
                        for node in self._slot_collision_nodes:
@@ -3227,7 +3227,7 @@ class depgraph(object):
                                                # reinstall the same exact version only due
                                                # to a KEYWORDS mask.
                                                if installed and matched_packages and \
-                                                       pkgsettings.getMissingKeywords(
+                                                       pkgsettings._getMissingKeywords(
                                                        pkg.cpv, pkg.metadata):
                                                        different_version = None
                                                        for avail_pkg in matched_packages:
@@ -3576,7 +3576,7 @@ class depgraph(object):
                                                if pkg_in_graph and not visible(pkgsettings, pkg):
                                                        self._masked_installed.add(pkg)
                                                elif graph_complete_for_root and \
-                                                       pkgsettings.getMissingKeywords(
+                                                       pkgsettings._getMissingKeywords(
                                                        pkg.cpv, pkg.metadata) and \
                                                        pkg.metadata["KEYWORDS"].split() and \
                                                        not pkg_in_graph:
@@ -5212,7 +5212,7 @@ class depgraph(object):
                                " Ebuilds for the following packages are either all\n")
                        sys.stderr.write(colorize("BAD", "!!!") + \
                                " masked or don't exist:\n")
-                       sys.stderr.write(" ".join(atom for arg, atom in \
+                       sys.stderr.write(" ".join(str(atom) for arg, atom in \
                                self._missing_args) + "\n")
 
                if self._pprovided_args:
@@ -5710,7 +5710,7 @@ class depgraph(object):
                        try:
                                if visible(root_config.settings, v) and \
                                        not (v.installed and \
-                                       v.root_config.settings.getMissingKeywords(v.cpv, v.metadata)):
+                                       v.root_config.settings._getMissingKeywords(v.cpv, v.metadata)):
                                        root_config.visible_pkgs.cpv_inject(v)
                        except portage.exception.InvalidDependString:
                                pass
@@ -9166,6 +9166,7 @@ def emerge_main():
                        if "porttree" in trees[root]:
                                db = trees[root]["porttree"].dbapi
                                paths = (db.mysettings["PORTDIR"]+" "+db.mysettings["PORTDIR_OVERLAY"]).split()
+                               paths = [os.path.realpath(p) for p in paths]
                                repos = db.getRepositories()
                                for r in repos:
                                        p = db.getRepositoryPath(r)
index 238af6cda0f090d32b4449768ef621e3016d837a..28161c1d9a3970f5742c40a2b989fc5c769b60d6 100644 (file)
@@ -2211,7 +2211,7 @@ class config(object):
 
                return iuse_implicit
 
-       def getMaskAtom(self, cpv, metadata):
+       def _getMaskAtom(self, cpv, metadata):
                """
                Take a package and return a matching package.mask atom, or None if no
                such atom exists or it has been cancelled by package.unmask. PROVIDE
@@ -2240,7 +2240,7 @@ class config(object):
                                return x
                return None
 
-       def getProfileMaskAtom(self, cpv, metadata):
+       def _getProfileMaskAtom(self, cpv, metadata):
                """
                Take a package and return a matching profile atom, or None if no
                such atom exists. Note that a profile atom may or may not have a "*"
@@ -2265,7 +2265,7 @@ class config(object):
                                return x
                return None
 
-       def getMissingKeywords(self, cpv, metadata):
+       def _getMissingKeywords(self, cpv, metadata):
                """
                Take a package and return a list of any KEYWORDS that the user may
                may need to accept for the given package. If the KEYWORDS are empty
@@ -2342,7 +2342,7 @@ class config(object):
                        missing = mygroups
                return missing
 
-       def getMissingLicenses(self, cpv, metadata):
+       def _getMissingLicenses(self, cpv, metadata):
                """
                Take a LICENSE string and return a list any licenses that the user may
                may need to accept for the given package.  The returned list will not
@@ -2369,9 +2369,9 @@ class config(object):
                license_struct = portage.dep.use_reduce(
                        license_struct, uselist=metadata["USE"].split())
                license_struct = portage.dep.dep_opconvert(license_struct)
-               return self._getMissingLicenses(license_struct, acceptable_licenses)
+               return self._getMaskedLicenses(license_struct, acceptable_licenses)
 
-       def _getMissingLicenses(self, license_struct, acceptable_licenses):
+       def _getMaskedLicenses(self, license_struct, acceptable_licenses):
                if not license_struct:
                        return []
                if license_struct[0] == "||":
@@ -2379,7 +2379,7 @@ class config(object):
                        for element in license_struct[1:]:
                                if isinstance(element, list):
                                        if element:
-                                               ret.append(self._getMissingLicenses(
+                                               ret.append(self._getMaskedLicenses(
                                                        element, acceptable_licenses))
                                                if not ret[-1]:
                                                        return []
@@ -2395,7 +2395,7 @@ class config(object):
                for element in license_struct:
                        if isinstance(element, list):
                                if element:
-                                       ret.extend(self._getMissingLicenses(element,
+                                       ret.extend(self._getMaskedLicenses(element,
                                                acceptable_licenses))
                        else:
                                if element not in acceptable_licenses:
@@ -4217,9 +4217,12 @@ def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None):
                                configure_opts_warn_re = re.compile(
                                        r'^configure: WARNING: Unrecognized options: .*')
                                am_maintainer_mode_re = re.compile(r'.*/missing --run .*')
+                               am_maintainer_mode_exclude_re = \
+                                       re.compile(r'.*/missing --run (autoheader|makeinfo)')
                                try:
                                        for line in f:
-                                               if am_maintainer_mode_re.search(line) is not None:
+                                               if am_maintainer_mode_re.search(line) is not None and \
+                                                       am_maintainer_mode_exclude_re.search(line) is None:
                                                        am_maintainer_mode.append(line.rstrip("\n"))
                                                if configure_opts_warn_re.match(line) is not None:
                                                        configure_opts_warn.append(line.rstrip("\n"))
@@ -6398,11 +6401,11 @@ def getmaskingstatus(mycpv, settings=None, portdb=None):
        rValue = []
 
        # profile checking
-       if settings.getProfileMaskAtom(mycpv, metadata):
+       if settings._getProfileMaskAtom(mycpv, metadata):
                rValue.append("profile")
 
        # package.mask checking
-       if settings.getMaskAtom(mycpv, metadata):
+       if settings._getMaskAtom(mycpv, metadata):
                rValue.append("package.mask")
 
        # keywords checking
@@ -6467,7 +6470,7 @@ def getmaskingstatus(mycpv, settings=None, portdb=None):
                                break
 
        try:
-               missing_licenses = settings.getMissingLicenses(mycpv, metadata)
+               missing_licenses = settings._getMissingLicenses(mycpv, metadata)
                if missing_licenses:
                        allowed_tokens = set(["||", "(", ")"])
                        allowed_tokens.update(missing_licenses)
index d6d5657c346dc2d7ae966521ca47f34dab2264f2..3c27c2d95892e492b4c04fea28e67023ed8134c8 100644 (file)
@@ -654,11 +654,11 @@ class portdbapi(dbapi):
                                        continue
                                if mydep.slot and mydep.slot != metadata["SLOT"]:
                                        continue
-                               if settings.getMissingKeywords(cpv, metadata):
+                               if settings._getMissingKeywords(cpv, metadata):
                                        continue
-                               if settings.getMaskAtom(cpv, metadata):
+                               if settings._getMaskAtom(cpv, metadata):
                                        continue
-                               if settings.getProfileMaskAtom(cpv, metadata):
+                               if settings._getProfileMaskAtom(cpv, metadata):
                                        continue
                                if local_config:
                                        metadata["USE"] = ""
@@ -666,7 +666,7 @@ class portdbapi(dbapi):
                                                self.doebuild_settings.setcpv(cpv, mydb=metadata)
                                                metadata["USE"] = self.doebuild_settings.get("USE", "")
                                        try:
-                                               if settings.getMissingLicenses(cpv, metadata):
+                                               if settings._getMissingLicenses(cpv, metadata):
                                                        continue
                                        except InvalidDependString:
                                                continue
@@ -721,8 +721,8 @@ class portdbapi(dbapi):
 
                db_keys = ["SLOT"]
                visible = []
-               getMaskAtom = self.mysettings.getMaskAtom
-               getProfileMaskAtom = self.mysettings.getProfileMaskAtom
+               getMaskAtom = self.mysettings._getMaskAtom
+               getProfileMaskAtom = self.mysettings._getProfileMaskAtom
                for cpv in mylist:
                        try:
                                metadata = dict(izip(db_keys, self.aux_get(cpv, db_keys)))
@@ -761,7 +761,7 @@ class portdbapi(dbapi):
                                continue
                        if not eapi_is_supported(metadata["EAPI"]):
                                continue
-                       if self.mysettings.getMissingKeywords(mycpv, metadata):
+                       if self.mysettings._getMissingKeywords(mycpv, metadata):
                                continue
                        if local_config:
                                metadata["USE"] = ""
@@ -769,7 +769,7 @@ class portdbapi(dbapi):
                                        self.doebuild_settings.setcpv(mycpv, mydb=metadata)
                                        metadata["USE"] = self.doebuild_settings.get("USE", "")
                                try:
-                                       if self.mysettings.getMissingLicenses(mycpv, metadata):
+                                       if self.mysettings._getMissingLicenses(mycpv, metadata):
                                                continue
                                except InvalidDependString:
                                        continue
index df6bdfd3e2d39b9bd2f3963e7f0ad41216398362..3d3b5d954d1f4e80f325cf37b7a10d6ab18441e8 100644 (file)
@@ -392,12 +392,40 @@ class _use_dep(object):
                tokens.extend(self.conditional_disabled.difference(use))
                return _use_dep(tokens)
 
-class Atom(str):
+class _AtomCache(type):
+       """
+       Cache Atom instances from constructor calls and reuse
+       identical instances when available.
+       """
+       def __call__(cls, s):
+               instance = cls._atoms.get(s)
+               if instance is None:
+                       instance = super(_AtomCache, cls).__call__(s)
+                       cls._atoms[s] = instance
+               return instance
+
+class Atom(object):
+
+       """
+       For compatibility with existing atom string manipulation code, this
+       class emulates most of the str methods that are useful with atoms.
+       """
+
+       __metaclass__ = _AtomCache
+       _atoms = {}
+
+       _str_methods = ("endswith", "find", "index", "lstrip", "replace",
+               "startswith", "strip", "rindex", "rfind", "rstrip", "__getitem__",
+               "__eq__", "__hash__", "__len__", "__ne__", "__repr__", "__str__")
+
+       __slots__ = ("__weakref__", "blocker", "cp", "cpv", "operator",
+               "slot", "use") + _str_methods
 
        def __init__(self, s):
-               str.__init__(self, s)
                if not isvalidatom(s, allow_blockers=True):
                        raise InvalidAtom(s)
+               for x in self._str_methods:
+                       setattr(self, x, getattr(s, x))
                self.blocker = "!" == s[:1]
                if self.blocker:
                        s = s[1:]
@@ -412,6 +440,15 @@ class Atom(str):
                else:
                        self.use = None
 
+       def __cmp__(self, other):
+               self_str = str(self)
+               other_str = str(other)
+               if self_str == other_str:
+                       return 0
+               if self_str > other_str:
+                       return 1
+               return -1
+
 def get_operator(mydep):
        """
        Return the operator used in a depstring.
@@ -583,6 +620,9 @@ def isvalidatom(atom, allow_blockers=False):
                1) 0 if the atom is invalid
                2) 1 if the atom is valid
        """
+       existing_atom = Atom._atoms.get(atom)
+       if existing_atom is not None:
+               atom = existing_atom
        if isinstance(atom, Atom):
                if atom.blocker and not allow_blockers:
                        return 0
index 714915c6d94d1fc3581dea2f6094253b33586a61..e30785621343af96e55ff1f75d76e456df813a76 100644 (file)
@@ -184,7 +184,8 @@ class WorldSet(EditablePackageSet):
                return setname.startswith(SETPREFIX)
 
        def write(self):
-               write_atomic(self._filename, "\n".join(sorted(self._atoms))+"\n")
+               write_atomic(self._filename,
+                       "".join(sorted("%s\n" % x for x in self._atoms)))
                write_atomic(self._filename2, "\n".join(sorted(self._nonatoms))+"\n")
        
        def load(self):
index 774ef5ac4b11a6c7efc5dfa13f251f6db5840045..b4165357562a69813faab6457137aa122933c51b 100644 (file)
@@ -4,10 +4,7 @@
 
 from portage.sets.base import PackageSet
 from portage.sets import get_boolean
-from portage.dbapi.vartree import dblink
-from portage.versions import catsplit, catpkgsplit
-
-import os
+from portage.versions import catpkgsplit
 
 class LibraryConsumerSet(PackageSet):
        _operations = ["merge", "unmerge"]
@@ -19,17 +16,11 @@ class LibraryConsumerSet(PackageSet):
 
        def mapPathsToAtoms(self, paths):
                rValue = set()
-               for cpv in self.dbapi.cpv_all():
-                       mysplit = catsplit(cpv)
-                       link = dblink(mysplit[0], mysplit[1], myroot=self.dbapi.root, \
-                                       mysettings=self.dbapi.settings, treetype='vartree', \
-                                       vartree=self.dbapi.vartree)
-                       if paths.intersection(link.getcontents()):
-                               cat, pn = catpkgsplit(cpv)[:2]
-                               slot = self.dbapi.aux_get(cpv, ["SLOT"])[0]
-                               rValue.add("%s/%s:%s" % (cat, pn, slot))
+               for link, p in self.dbapi._owners.iter_owners(paths):
+                       cat, pn = catpkgsplit(link.mycpv)[:2]
+                       slot = self.dbapi.aux_get(link.mycpv, ["SLOT"])[0]
+                       rValue.add("%s/%s:%s" % (cat, pn, slot))
                return rValue
-       
 
 class PreservedLibraryConsumerSet(LibraryConsumerSet):
        def load(self):
index b1f4aa46c6c9aa8370e006d9326bca286063e5c5..43d69599a13a3b387319d5c007214cba839cc3c2 100644 (file)
@@ -19,10 +19,11 @@ class CommandOutputSetTestCase(TestCase):
        def testCommand(self):
                
                input = set(test_cps)
-               command = find_binary("echo")
-               command += " -e "
+               command = find_binary("bash")
+               command += " -c '"
                for a in input:
-                 command += "\"%s\n\"" % a
+                 command += " echo -e \"%s\" ; " % a
+               command += "'"
                s = CommandOutputSet(command)
                atoms = s.getAtoms()
                self.assertEqual(atoms, input)