From: Fabian Groffen Date: Sun, 22 Jun 2008 15:29:37 +0000 (-0000) Subject: Merged from trunk 10738:10759 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=5d15a003cee3bad7b927bca9e50f3e408a31a70b;p=portage.git Merged from trunk 10738:10759 | 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 --- diff --git a/NEWS b/NEWS index 09da35b30..45dc3798e 100644 --- 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 ` 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 diff --git a/bin/check-implicit-pointer-usage.py b/bin/check-implicit-pointer-usage.py index 93b9d6b96..a9f22a543 100755 --- a/bin/check-implicit-pointer-usage.py +++ b/bin/check-implicit-pointer-usage.py @@ -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: " + "(" diff --git a/bin/repoman b/bin/repoman index f015ab548..693c7a4a8 100755 --- a/bin/repoman +++ b/bin/repoman @@ -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: diff --git a/man/repoman.1 b/man/repoman.1 index 7f03365c2..1d4c24a2f 100644 --- a/man/repoman.1 +++ b/man/repoman.1 @@ -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 diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 7a1498671..0ee968931 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -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) diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 238af6cda..28161c1d9 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -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) diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index d6d5657c3..3c27c2d95 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -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 diff --git a/pym/portage/dep.py b/pym/portage/dep.py index df6bdfd3e..3d3b5d954 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -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 diff --git a/pym/portage/sets/files.py b/pym/portage/sets/files.py index 714915c6d..e30785621 100644 --- a/pym/portage/sets/files.py +++ b/pym/portage/sets/files.py @@ -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): diff --git a/pym/portage/sets/libs.py b/pym/portage/sets/libs.py index 774ef5ac4..b41653575 100644 --- a/pym/portage/sets/libs.py +++ b/pym/portage/sets/libs.py @@ -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): diff --git a/pym/portage/tests/sets/shell/testShell.py b/pym/portage/tests/sets/shell/testShell.py index b1f4aa46c..43d69599a 100644 --- a/pym/portage/tests/sets/shell/testShell.py +++ b/pym/portage/tests/sets/shell/testShell.py @@ -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)