Source code for Bcfg2.Server.Plugins.Packages.Apt
""" APT backend for :mod:`Bcfg2.Server.Plugins.Packages` """
import re
import gzip
from Bcfg2.Server.Plugins.Packages.Collection import Collection
from Bcfg2.Server.Plugins.Packages.Source import Source
[docs]def strip_suffix(pkgname):
""" Remove the ':any' suffix from a dependency name if it is present.
"""
if pkgname.endswith(':any'):
return pkgname[:-4]
else:
return pkgname
[docs]class AptCollection(Collection):
""" Handle collections of APT sources. This is a no-op object
that simply inherits from
:class:`Bcfg2.Server.Plugins.Packages.Collection.Collection`,
overrides nothing, and defers all operations to :class:`PacSource`
"""
def __init__(self, metadata, sources, cachepath, basepath, debug=False):
# we define an __init__ that just calls the parent __init__,
# so that we can set the docstring on __init__ to something
# different from the parent __init__ -- namely, the parent
# __init__ docstring, minus everything after ``.. -----``,
# which we use to delineate the actual docs from the
# .. autoattribute hacks we have to do to get private
# attributes included in sphinx 1.0 """
Collection.__init__(self, metadata, sources, cachepath, basepath,
debug=debug)
__init__.__doc__ = Collection.__init__.__doc__.split(".. -----")[0]
[docs] def get_config(self):
""" Get an APT configuration file (i.e., ``sources.list``).
:returns: string """
lines = ["# This config was generated automatically by the Bcfg2 "
"Packages plugin", '']
for source in self:
if source.rawurl:
if source.rawurl[-1] != '/':
source.rawurl = source.rawurl + "/"
index = source.rawurl.rfind("/", 0, -1)
lines.append("deb %s %s" %
(source.rawurl[:index],
source.rawurl[index + 1:]))
else:
lines.append("deb %s %s %s" % (source.url, source.version,
" ".join(source.components)))
if source.debsrc:
lines.append("deb-src %s %s %s" %
(source.url,
source.version,
" ".join(source.components)))
lines.append("")
return "\n".join(lines)
[docs]class AptSource(Source):
""" Handle APT sources """
#: AptSource sets the ``type`` on Package entries to "deb"
ptype = 'deb'
@property
def urls(self):
""" A list of URLs to the base metadata file for each
repository described by this source. """
if not self.rawurl:
rv = []
for part in self.components:
for arch in self.arches:
rv.append("%sdists/%s/%s/binary-%s/Packages.gz" %
(self.url, self.version, part, arch))
return rv
else:
return ["%sPackages.gz" % self.rawurl]
[docs] def read_files(self): # pylint: disable=R0912
bdeps = dict()
brecs = dict()
bprov = dict()
self.pkgnames = set()
self.essentialpkgs = set()
for fname in self.files:
if not self.rawurl:
barch = [x
for x in fname.split('@')
if x.startswith('binary-')][0][7:]
else:
# RawURL entries assume that they only have one <Arch></Arch>
# element and that it is the architecture of the source.
barch = self.arches[0]
if barch not in bdeps:
bdeps[barch] = dict()
brecs[barch] = dict()
bprov[barch] = dict()
try:
reader = gzip.GzipFile(fname)
except IOError:
self.logger.error("Packages: Failed to read file %s" % fname)
raise
for line in reader.readlines():
if not isinstance(line, str):
line = line.decode('utf-8')
words = str(line.strip()).split(':', 1)
if words[0] == 'Package':
pkgname = words[1].strip().rstrip()
self.pkgnames.add(pkgname)
bdeps[barch][pkgname] = []
brecs[barch][pkgname] = []
elif words[0] == 'Essential' and self.essential:
if words[1].strip() == 'yes':
self.essentialpkgs.add(pkgname)
elif words[0] in ['Depends', 'Pre-Depends', 'Recommends']:
vindex = 0
for dep in words[1].split(','):
if '|' in dep:
cdeps = [re.sub(r'\s+', '',
re.sub(r'\(.*\)', '', cdep))
for cdep in dep.split('|')]
cdeps = [strip_suffix(cdep) for cdep in cdeps]
dyn_dname = "choice-%s-%s-%s" % (pkgname,
barch,
vindex)
vindex += 1
if words[0] == 'Recommends':
brecs[barch][pkgname].append(dyn_dname)
else:
bdeps[barch][pkgname].append(dyn_dname)
bprov[barch][dyn_dname] = set(cdeps)
else:
raw_dep = re.sub(r'\(.*\)', '', dep)
raw_dep = raw_dep.rstrip().strip()
raw_dep = strip_suffix(raw_dep)
if words[0] == 'Recommends':
brecs[barch][pkgname].append(raw_dep)
else:
bdeps[barch][pkgname].append(raw_dep)
elif words[0] == 'Provides':
for pkg in words[1].split(','):
dname = pkg.rstrip().strip()
if dname not in bprov[barch]:
bprov[barch][dname] = set()
bprov[barch][dname].add(pkgname)
self.process_files(bdeps, bprov, brecs)
read_files.__doc__ = Source.read_files.__doc__