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
import sys
implicit_pattern = re.compile("([^:]*):(\d+): warning: implicit declaration "
- + "of function `([^']*)'")
+ + "of function [`']([^']*)'")
pointer_pattern = re.compile(
"([^:]*):(\d+): warning: "
+ "("
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',
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:
\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
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
have_eapi_mask = True
try:
missing_licenses = \
- pkgsettings.getMissingLicenses(
+ pkgsettings._getMissingLicenses(
cpv, metadata)
except portage.exception.InvalidDependString:
# This will have already been reported
# 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:
# 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:
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:
" 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:
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
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)
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
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 "*"
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
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
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] == "||":
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 []
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:
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"))
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
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)
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"] = ""
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
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)))
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"] = ""
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
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:]
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.
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
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):
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"]
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):
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)