+changes
+depgraph
+Ebuild changes:
+ - Add:
+ src_test() {
+ "${python}" setup.py test || die "testing returned non zero"
+ }
+ - Add:
+ DEPEND on python 2.5 (needed for 'from __future__ import with' and others)
+
For Next Release:
- - find all commits to main gentoolkit svn after rc7 push and merge where
- appropriate
+ - write NEWS file
- write a docstring for Package which details especially the change in have
cpv as an object, not a string.
import os
import sys
import codecs
-try:
- import portage
-except ImportError:
- sys.path.insert(0, "/usr/lib/portage/pym")
- import portage
-try:
- from portage.output import *
-except ImportError:
- from output import *
+import portage
+from portage.output import *
from getopt import getopt, GetoptError
__program__ = "glsa-check"
__author__ = "Marius Mauch <genone@gentoo.org>"
-__version__ = open("/usr/share/gentoolkit/VERSION").read().strip()
+__version__ = "svn"
optionmap = [
["-l", "--list", "list the GLSAs"],
args, params = getopt(sys.argv[1:], "".join([o[0][1] for o in optionmap]), \
[x[2:] for x in reduce(lambda x,y: x+y, [z[1:-1] for z in optionmap])])
args = [a for a,b in args]
-
+
for option in ["--nocolor", "-n"]:
if option in args:
nocolor()
args.remove(option)
-
+
verbose = False
for option in ["--verbose", "-v"]:
if option in args:
if option in args:
list_cve = True
args.remove(option)
-
+
least_change = True
for option in ["--emergelike", "-e"]:
if option in args:
mode = "HELP"
elif len(params) <= 0 and mode == "list":
params.append("affected")
-
+
# show help message
if mode == "help" or mode == "HELP":
msg = "Syntax: glsa-check <option> [glsa-list]\n\n"
params.remove("new")
sys.stderr.write("Warning: The 'new' glsa-list target has been removed, using 'affected'.\n")
params.append("affected")
-
+
if "all" in params:
glsalist = completelist
params.remove("all")
mergedict = {}
for (vuln, update) in myglsa.getAffectionTable(least_change=least_change):
mergedict.setdefault(update, []).append(vuln)
-
+
# first, extract the atoms that cannot be upgraded (where key == "")
no_upgrades = []
if "" in mergedict:
import portage.mail as portage_mail
except ImportError:
import portage_mail
-
+
import socket
from StringIO import StringIO
try:
myrecipient = glsaconfig["PORTAGE_ELOG_MAILURI"].split()[0]
else:
myrecipient = "root@localhost"
-
+
if "PORTAGE_ELOG_MAILFROM" in glsaconfig:
myfrom = glsaconfig["PORTAGE_ELOG_MAILFROM"]
else:
if glsalist or not quiet:
mymessage = portage_mail.create_message(myfrom, myrecipient, mysubject, summary, myattachments)
portage_mail.send_mail(glsaconfig, mymessage)
-
+
sys.exit(0)
-
+
# something wrong here, all valid paths are covered with sys.exit()
sys.stderr.write("nothing more to do\n")
sys.exit(2)
.EX
$ equery list binutils
* Searching for binutils ...
- [I--] [XX] sys-devel/binutils-2.18-r1 (i686-pc-linux-gnu-2.18)
- [IP-] [ ~] sys-devel/binutils-2.19.1-r1 (i686-pc-linux-gnu-2.19.1)
+ [I--] [XX] sys-devel/binutils-2.18-r1:i686-pc-linux-gnu-2.18
+ [IP-] [ ~] sys-devel/binutils-2.19.1-r1:i686-pc-linux-gnu-2.19.1
.EE
.HP
Location field (\fB[IPO-]\fP):
.HP
Slot:
.br
-The fourth field, in parentheses, is the package's slot. \fB0\fP is the default slot. To find all packages with multiple slots installed, use \fB--duplicates\fP.
+The fourth field, after the colon, is the package's slot. \fB0\fP is the default slot. To find all packages with multiple slots installed, use \fB--duplicates\fP.
.P
\fBNote:\fP Because it takes extra processing time to determine the location, mask status and slot, you can speed up output by passing the \fB--quiet\fP global option to \fBequery\fP when you don't care about the extra information.
#
# $Header$
-"""The functions in this module have been deprecated and are not even
-guaranteed to work. Improved functions can be found in helpers2.py"""
-
import warnings
import portage
def print_verbose(self, pkg, cfile):
"Format for full output."
- file_str = pp.path(format_filetype(cfile, pkg.get_contents()[cfile]))
+ file_str = pp.path(format_filetype(cfile, pkg.parsed_contents()[cfile]))
if self.name_only:
name = pkg.cpv.cp
else:
#
# $Header: $
-"""Display the Gentoo ChangeLog entry for the latest installable version of a
-given package.
-"""
+"""Displays the ChangeLog entry for the latest installable version of a package"""
# Move to Imports sections when Python 2.6 is stable
from __future__ import with_statement
print
match = get_match(query)
- changelog_path = os.path.join(match.get_package_path(), 'ChangeLog')
+ changelog_path = os.path.join(match.package_path(), 'ChangeLog')
changelog = ChangeLog(changelog_path)
#
#
# $Header: $
-"""Check timestamps and MD5 sums for files owned by a given installed package"""
+"""Checks timestamps and MD5 sums for files owned by a given installed package"""
__docformat__ = 'epytext'
result = {}
for pkg in pkgs:
# _run_checks returns tuple(n_passed, n_checked, err)
- check_results = self._run_checks(pkg.get_contents())
+ check_results = self._run_checks(pkg.parsed_contents())
result[pkg.cpv] = check_results
if self.printer_fn is not None:
self.printer_fn(pkg.cpv, check_results)
def display_files(contents):
"""Display the content of an installed package.
- @see: gentoolkit.package.Package.get_contents
+ @see: gentoolkit.package.Package.parsed_contents
@type contents: dict
@param contents: {'path': ['filetype', ...], ...}
"""
def filter_contents(contents):
"""Filter files by type if specified by the user.
- @see: gentoolkit.package.Package.get_contents
+ @see: gentoolkit.package.Package.parsed_contents
@type contents: dict
@param contents: {'path': ['filetype', ...], ...}
@rtype: dict
if CONFIG['verbose']:
print " * Contents of %s:" % pp.cpv(str(pkg.cpv))
- contents = pkg.get_contents()
+ contents = pkg.parsed_contents()
display_files(filter_contents(contents))
first_run = False
# ms_int is a number representation of mask level.
# Only 2 and above are "hard masked" and have reasons.
continue
- mask_reason = pkg.get_mask_reason()
+ mask_reason = pkg.mask_reason()
if not mask_reason:
# Package not on system or not masked
continue
for kw in sorted(keywords):
if kw.startswith(('~', '-')):
- # keyword (~) or arch (-) masked, color red
- kw = pp.useflag(kw, enabled=True)
- else:
- # unmasked, color blue
+ # keyword (~) or arch (-) masked
kw = pp.useflag(kw, enabled=False)
+ else:
+ # unmasked
+ kw = pp.useflag(kw, enabled=True)
result.append(kw)
return ' '.join(result)
-def format_keywords_line(pkg, fmtd_keywords):
+def format_keywords_line(pkg, fmtd_keywords, slot, verstr_len):
"""Format the entire keywords line for display."""
- slot = pkg.environment('SLOT')
ver = pkg.cpv.fullversion
- verstr_len = len(ver) + 1 + len(slot) # +1 for ':'
-
- if CONFIG['verbose']:
- result = format_line(
- fmtd_keywords, "%s:%s: " % (pp.cpv(ver), pp.slot(slot)),
- " " * (verstr_len + 2)
- )
- else:
- result = "%s:%s: %s" % (ver, slot, fmtd_keywords)
+ result = "%s:%s: %s" % (ver, pp.slot(slot), fmtd_keywords)
+ if CONFIG['verbose'] and fmtd_keywords:
+ result = format_line(fmtd_keywords, "%s:%s: " % (ver, pp.slot(slot)),
+ " " * (verstr_len + 2))
return result
ref_pkg = get_reference_pkg(matches)
if CONFIG['verbose']:
- repo = ref_pkg.get_repo_name()
+ repo = ref_pkg.repo_id()
print " * %s [%s]" % (pp.cpv(ref_pkg.cpv.cp), pp.section(repo))
got_opts = False
# Specific information requested, less formatting
got_opts = True
- if not got_opts:
- pkg_loc = ref_pkg.get_package_path()
- print format_line(pkg_loc, "Location: ", " " * 13)
-
if QUERY_OPTS["herd"] or not got_opts:
- herds = format_herds(ref_pkg.metadata.get_herds(include_email=True))
+ herds = format_herds(ref_pkg.metadata.herds(include_email=True))
if QUERY_OPTS["herd"]:
print_sequence(format_list(herds))
else:
print format_line(herd, "Herd: ", " " * 13)
if QUERY_OPTS["maintainer"] or not got_opts:
- maints = format_maintainers(ref_pkg.metadata.get_maintainers())
+ maints = format_maintainers(ref_pkg.metadata.maintainers())
if QUERY_OPTS["maintainer"]:
print_sequence(format_list(maints))
else:
print format_line(maint, "Maintainer: ", " " * 13)
if QUERY_OPTS["upstream"] or not got_opts:
- upstream = format_upstream(ref_pkg.metadata.get_upstream())
+ upstream = format_upstream(ref_pkg.metadata.upstream())
if QUERY_OPTS["upstream"]:
upstream = format_list(upstream)
else:
upstream = format_list(upstream, "Upstream: ", " " * 13)
print_sequence(upstream)
+ if not got_opts:
+ pkg_loc = ref_pkg.package_path()
+ print format_line(pkg_loc, "Location: ", " " * 13)
+
if QUERY_OPTS["keywords"] or not got_opts:
# Get {<Package 'dev-libs/glib-2.20.5'>: [u'ia64', u'm68k', ...], ...}
keyword_map = filter_keywords(matches)
for match in matches:
+ slot = match.environment('SLOT')
+ verstr_len = len(match.cpv.fullversion) + len(slot)
fmtd_keywords = format_keywords(keyword_map[match])
- keywords_line = format_keywords_line(match, fmtd_keywords)
+ keywords_line = format_keywords_line(
+ match, fmtd_keywords, slot, verstr_len
+ )
if QUERY_OPTS["keywords"]:
print keywords_line
else:
- # FIXME: duplicate code
- slot = match.environment('SLOT')
- verstr_len = len(match.cpv.fullversion) + len(slot)
indent = " " * (16 + verstr_len)
print format_line(keywords_line, "Keywords: ", indent)
if QUERY_OPTS["description"]:
- desc = ref_pkg.metadata.get_descriptions()
+ desc = ref_pkg.metadata.descriptions()
print_sequence(format_list(desc))
if QUERY_OPTS["useflags"]:
- useflags = format_useflags(ref_pkg.metadata.get_useflags())
+ useflags = format_useflags(ref_pkg.metadata.use())
print_sequence(format_list(useflags))
if QUERY_OPTS["xml"]:
- print_file(os.path.join(ref_pkg.get_package_path(), 'metadata.xml'))
+ print_file(os.path.join(ref_pkg.package_path(), 'metadata.xml'))
def format_line(line, first="", subsequent="", force_quiet=False):
"""
for pkg in match_set:
- size, files, uncounted = pkg.get_size()
+ size, files, uncounted = pkg.size()
if CONFIG['verbose']:
print " * %s" % pp.cpv(str(pkg.cpv))
twrap.subsequent_indent = " " * (maxflag_len + 8)
markers = ("-", "+")
- color = [pp.useflag, partial(pp.useflag, enabled=True)]
+ color = (
+ partial(pp.useflag, enabled=False), partial(pp.useflag, enabled=True)
+ )
for in_makeconf, in_installed, flag, desc, restrict in output:
if CONFIG['verbose']:
flag_name = ""
def get_output_descriptions(pkg, global_usedesc):
"""Prepare descriptions and usage information for each USE flag."""
- local_usedesc = pkg.metadata.get_useflags()
+ local_usedesc = pkg.metadata.use()
iuse = pkg.environment("IUSE")
if iuse:
usevar = []
if pkg.is_installed():
- used_flags = pkg.get_use_flags().split()
+ used_flags = pkg.use().split()
else:
used_flags = settings["USE"].split()
except AttributeError:
restrict = ""
- if flag in pkg.get_settings("USE").split():
+ if flag in pkg.settings("USE").split():
inuse = True
if flag in used_flags:
inused = True
#
first_run = True
+ legend_printed = False
for query in queries:
if not first_run:
print
output = get_output_descriptions(pkg, global_usedesc)
if output:
if CONFIG['verbose']:
- print_legend()
+ if not legend_printed:
+ print_legend()
+ legend_printed = True
print (" * Found these USE flags for %s:" %
pp.cpv(str(pkg.cpv)))
print pp.emph(" U I")
matches = find_packages(query, QUERY_OPTS['includeMasked'])
if matches:
pkg = sorted(matches).pop()
- ebuild_path = pkg.get_ebuild_path()
+ ebuild_path = pkg.ebuild_path()
if ebuild_path:
print os.path.normpath(ebuild_path)
else:
sys.stderr.write(
- pp.warn("No ebuilds to satisfy %s" % pkg.name)
+ pp.warn("No ebuilds to satisfy %s" % pkg.cpv.name)
)
else:
raise errors.GentoolkitNoMatches(query)
# Process the ChangeLog:
self.entries = self._split_changelog()
self.indexed_entries = self._index_changelog()
+ self.full = self.entries
+ self.latest = self.entries[0]
def __repr__(self):
return "<%s %r>" % (self.__class__.__name__, self.changelog_path)
- @property
- def full(self):
- """Return the output of L{self._split_changelog}."""
- return self.entries
-
- @property
- def latest(self):
- """Return the newest ChangeLog entry."""
- return self.entries[0]
-
def entries_matching_atom(self, atom):
"""Return entries whose header versions match atom's version.
# we can use re.match, else use re.search.
use_match = True
- return self.find_owners(query_re, use_match=use_match)
+ pkgset = get_installed_cpvs()
+
+ return self.find_owners(query_re, use_match=use_match, pkgset=pkgset)
def find_owners(self, query_re, use_match=False, pkgset=None):
"""Find owners and feed data to supplied output function.
results = []
found_match = False
- if pkgset is None:
- pkgset = get_installed_cpvs()
for pkg in sorted([Package(x) for x in pkgset]):
- files = pkg.get_contents()
+ files = pkg.parsed_contents()
for cfile in files:
match = query_fn(cfile)
if match:
"""Similar to the builtin cmp, but for package strings. Usually called
as: package_list.sort(compare_package_strings)
- An alternative is to use the Package descriptor from gentoolkit.package
- >>> pkgs = [Package(x) for x in package_list]
- >>> pkgs.sort()
+ An alternative is to use the CPV descriptor from gentoolkit.cpv:
+ >>> cpvs = sorted(CPV(x) for x in package_list)
@see: >>> help(cmp)
"""
>>> pkg_md = MetaData('/usr/portage/app-misc/gourmet/metadata.xml')
>>> pkg_md
<MetaData '/usr/portage/app-misc/gourmet/metadata.xml'>
- >>> pkg_md.get_herds()
+ >>> pkg_md.herds()
['no-herd']
- >>> for maint in pkg_md.get_maintainers():
+ >>> for maint in pkg_md.maintainers():
... print "{0} ({1})".format(maint.email, maint.name)
...
nixphoeni@gentoo.org (Joe Sapp)
- >>> for flag in pkg_md.get_useflags():
+ >>> for flag in pkg_md.use():
... print flag.name, "->", flag.description
...
rtf -> Enable export to RTF
gnome-print -> Enable printing support using gnome-print
- >>> upstream = pkg_md.get_upstream()
+ >>> upstream = pkg_md.upstream()
>>> upstream
[<_Upstream {'docs': [], 'remoteid': [], 'maintainer':
[<_Maintainer 'Thomas_Hinkle@alumni.brown.edu'>], 'bugtracker': [],
def __init__(self, node):
self.node = node
- self.maintainers = self.get_upstream_maintainers()
- self.changelogs = self.get_upstream_changelogs()
- self.docs = self.get_upstream_documentation()
- self.bugtrackers = self.get_upstream_bugtrackers()
- self.remoteids = self.get_upstream_remoteids()
+ self.maintainers = self.upstream_maintainers()
+ self.changelogs = self.upstream_changelogs()
+ self.docs = self.upstream_documentation()
+ self.bugtrackers = self.upstream_bugtrackers()
+ self.remoteids = self.upstream_remoteids()
def __repr__(self):
return "<%s %r>" % (self.__class__.__name__, self.__dict__)
- def get_upstream_bugtrackers(self):
+ def upstream_bugtrackers(self):
"""Retrieve upstream bugtracker location from xml node."""
return [e.text for e in self.node.findall('bugs-to')]
- def get_upstream_changelogs(self):
+ def upstream_changelogs(self):
"""Retrieve upstream changelog location from xml node."""
return [e.text for e in self.node.findall('changelog')]
- def get_upstream_documentation(self):
+ def upstream_documentation(self):
"""Retrieve upstream documentation location from xml node."""
result = []
for elem in self.node.findall('doc'):
result.append((elem.text, lang))
return result
- def get_upstream_maintainers(self):
+ def upstream_maintainers(self):
"""Retrieve upstream maintainer information from xml node."""
return [_Maintainer(m) for m in self.node.findall('maintainer')]
- def get_upstream_remoteids(self):
+ def upstream_remoteids(self):
"""Retrieve upstream remote ID from xml node."""
return [(e.text, e.get('type')) for e in self.node.findall('remote-id')]
if node.findtext('name') == herd:
return node.findtext('email')
- def get_herds(self, include_email=False):
+ def herds(self, include_email=False):
"""Return a list of text nodes for <herd>.
@type include_email: bool
return result
- def get_descriptions(self):
+ def descriptions(self):
"""Return a list of text nodes for <longdescription>.
@rtype: list
self._descriptions = [e.text for e in long_descriptions]
return self._descriptions
- def get_maintainers(self):
+ def maintainers(self):
"""Get maintainers' name, email and description.
@rtype: list
return self._maintainers
- def get_useflags(self):
+ def use(self):
"""Get names and descriptions for USE flags defined in metadata.
@rtype: list
return self._useflags
- def get_upstream(self):
+ def upstream(self):
"""Get upstream contact information.
@rtype: list
#
# $Header$
-"""Provides classes for accessing Portage db information for a given package."""
+"""Provides an interface to package information stored by package managers.
+
+The package class is the heart of much of Gentoolkit. Given a CPV
+(category/package-version string),
+TODO: finish this docstring
+"""
__all__ = (
'Package',
if self._metadata is None:
metadata_path = os.path.join(
- self.get_package_path(), 'metadata.xml'
+ self.package_path(), 'metadata.xml'
)
self._metadata = MetaData(metadata_path)
def environment(self, envvars, tree=None):
"""Returns one or more of the predefined environment variables.
+ Available envvars are:
+ ----------------------
+ BINPKGMD5 COUNTER FEATURES LICENSE SRC_URI
+ CATEGORY CXXFLAGS HOMEPAGE PDEPEND USE
+ CBUILD DEFINED_PHASES INHERITED PF
+ CFLAGS DEPEND IUSE PROVIDE
+ CHOST DESCRIPTION KEYWORDS RDEPEND
+ CONTENTS EAPI LDFLAGS SLOT
+
Example usage:
>>> pkg = Package('sys-apps/portage-2.1.6.13')
>>> pkg.environment('USE')
return result[0]
return result
- # Namespace compatibility 2009, djanderson
- get_env_var = environment
-
def exists(self):
"""Return True if package exists in the Portage tree, else False"""
return bool(PORTDB.cpv_exists(str(self.cpv)))
@staticmethod
- def get_settings(key):
+ def settings(key):
"""Returns the value of the given key for this package (useful
for package.* files."""
settings.lock()
return result
- def get_mask_status(self):
+ def mask_status(self):
"""Shortcut to L{portage.getmaskingstatus}.
@rtype: None or list
return result
- def get_mask_reason(self):
+ def mask_reason(self):
"""Shortcut to L{portage.getmaskingreason}.
@rtype: None or tuple
try:
result = portage.getmaskingreason(str(self.cpv),
settings=settings,
- PORTDB=PORTDB,
+ portdb=PORTDB,
return_location=True)
if result is None:
result = tuple()
return result
- def get_ebuild_path(self, in_vartree=False):
+ def ebuild_path(self, in_vartree=False):
"""Returns the complete path to the .ebuild file.
Example usage:
- >>> pkg.get_ebuild_path()
+ >>> pkg.ebuild_path()
'/usr/portage/sys-apps/portage/portage-2.1.6.13.ebuild'
- >>> pkg.get_ebuild_path(in_vartree=True)
+ >>> pkg.ebuild_path(in_vartree=True)
'/var/db/pkg/sys-apps/portage-2.1.6.13/portage-2.1.6.13.ebuild'
"""
return VARDB.findname(str(self.cpv))
return PORTDB.findname(str(self.cpv))
- def get_package_path(self):
+ def package_path(self):
"""Return the path to where the ebuilds and other files reside."""
if self._package_path is None:
- path_split = self.get_ebuild_path().split(os.sep)
+ path_split = self.ebuild_path().split(os.sep)
self._package_path = os.sep.join(path_split[:-1])
return self._package_path
- def get_repo_name(self):
- """Using the package path, determine the repo name.
+ def repo_id(self):
+ """Using the package path, determine the repository id.
@rtype: str
- @return: /usr/<THIS>portage</THIS>/cat-egory/name/
+ @return: /usr/<THIS>portage</THIS>/category/name/
"""
- return self.get_package_path().split(os.sep)[-3]
+ return self.package_path().split(os.sep)[-3]
- def get_use_flags(self):
+ def use(self):
"""Returns the USE flags active at time of installation."""
return self.dblink.getstring("USE")
- def get_contents(self):
+ def parsed_contents(self):
"""Returns the parsed CONTENTS file.
@rtype: dict
return self.dblink.getcontents()
- def get_size(self):
+ def size(self):
"""Estimates the installed size of the contents of this package.
@rtype: tuple
@return: (size, number of files in total, number of uncounted files)
"""
- contents = self.get_contents()
+ contents = self.parsed_contents()
size = n_uncounted = n_files = 0
for cfile in contents:
try:
def __str__(self):
if self.do_format:
maskmodes = [' ', ' ~', ' -', 'M ', 'M~', 'M-', 'XX']
- return "[%(location)s] [%(mask)s] %(package)s (%(slot)s)" % {
+ return "[%(location)s] [%(mask)s] %(package)s:%(slot)s" % {
'location': self.location,
'mask': pp.maskflag(maskmodes[self.format_mask_status()[0]]),
'package': pp.cpv(str(self.pkg.cpv)),
- 'slot': self.pkg.environment("SLOT")
+ 'slot': pp.slot(self.pkg.environment("SLOT"))
}
else:
return str(self.pkg.cpv)
"""
result = 0
- masking_status = self.pkg.get_mask_status()
+ masking_status = self.pkg.mask_status()
if masking_status is None:
return (6, [])
- if ("~%s keyword" % self.pkg.get_settings("ARCH")) in masking_status:
+ if ("~%s keyword" % self.pkg.settings("ARCH")) in masking_status:
result += 1
if "missing keyword" in masking_status:
result += 2
"""Print a string as a subsection header."""
return output.turquoise(string)
-def useflag(string, enabled=False):
+def useflag(string, enabled=True):
"""Print a USE flag string"""
- return output.red(string) if enabled else output.blue(string)
+ return output.green(string) if enabled else output.blue(string)
def warn(string):
"""Print a warning string to stderr."""
#!/usr/bin/env python
+from __future__ import with_statement
+
import os
import re
import sys