diff options
author | Alexander Sulfrian <asulfrian@zedat.fu-berlin.de> | 2022-01-16 08:40:09 +0100 |
---|---|---|
committer | Alexander Sulfrian <asulfrian@zedat.fu-berlin.de> | 2022-01-17 16:41:32 +0100 |
commit | 3842939e7d94373a8a4d4214072c9b24b1e32b6d (patch) | |
tree | bb5f8844df88d5eac3dda931004cafb1b3622846 /src/lib/Bcfg2/Server/Plugins/Packages/Pyapt.py | |
parent | 000a832751563cfe571363a27e293fd3d9db31a4 (diff) | |
download | bcfg2-3842939e7d94373a8a4d4214072c9b24b1e32b6d.tar.gz bcfg2-3842939e7d94373a8a4d4214072c9b24b1e32b6d.tar.bz2 bcfg2-3842939e7d94373a8a4d4214072c9b24b1e32b6d.zip |
Packages: Add "pyapt" source type
Pyapt is a new source that is using the apt python bindings to parse the
Packages files from debian repositories. Compared to the python implementation
it is faster and more robust. It will use the dependencies of the newest
version of a package from a specific source (because it can use the python
bindings to compare the version numbers).
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/Packages/Pyapt.py')
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/Pyapt.py | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Pyapt.py b/src/lib/Bcfg2/Server/Plugins/Packages/Pyapt.py new file mode 100644 index 000000000..5e0eb55be --- /dev/null +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Pyapt.py @@ -0,0 +1,93 @@ +""" +APT backend for :mod:`Bcfg2.Server.Plugins.Packages` using +apt_pkg python bindings. +""" + +import apt_pkg +from Bcfg2.Server.Plugins.Packages.Apt import AptCollection, AptSource + + +class PyaptCollection(AptCollection): + """ Handle collections of PyAPT sources. This is a no-op object + that simply inherits from + :class:`Bcfg2.Server.Plugins.Packages.Apt.AptCollection` and + overrides nothing. + """ + pass + + +class PyaptSource(AptSource): + """ Handle PyAPT sources """ + + def read_files(self): # pylint: disable=R0912 + bdeps = dict() + brecs = dict() + bprov = dict() + bvers = dict() + self.pkgnames = set() + self.essentialpkgs = set() + for fname in self.files: + barch = self._get_arch(fname) + if barch not in bdeps: + bdeps[barch] = dict() + brecs[barch] = dict() + bprov[barch] = dict() + + apt_pkg.init_system() + with apt_pkg.TagFile(fname) as tagfile: + for section in tagfile: + pkgname = section['Package'] + + if pkgname in bvers: + new = section['Version'] + old = bvers[pkgname] + if apt_pkg.version_compare(new, old) <= 0: + continue + + self.pkgnames.add(pkgname) + bvers[pkgname] = section['Version'] + bdeps[barch][pkgname] = [] + brecs[barch][pkgname] = [] + + if section.find_flag('Essential'): + self.essentialpkgs.add(pkgname) + + for dep_type in ['Depends', 'Pre-Depends', 'Recommends']: + dep_str = section.find(dep_type) + if dep_str is None: + continue + + vindex = 0 + for dep in apt_pkg.parse_depends(dep_str): + if len(dep) > 1: + cdeps = [cdep for (cdep, _, _) in dep] + dyn_dname = "choice-%s-%s-%s" % (pkgname, + barch, + vindex) + vindex += 1 + + if dep_type == 'Recommends': + brecs[barch][pkgname].append(dyn_dname) + else: + bdeps[barch][pkgname].append(dyn_dname) + bprov[barch][dyn_dname] = set(cdeps) + else: + (raw_dep, _, _) = dep[0] + if dep_type == 'Recommends': + brecs[barch][pkgname].append(raw_dep) + else: + bdeps[barch][pkgname].append(raw_dep) + + provides = section.find('Provides') + if provides is not None: + provided_packages = [ + pkg + for group in apt_pkg.parse_depends(provides) + for (pkg, _, _) in group] + for dname in provided_packages: + if dname not in bprov[barch]: + bprov[barch][dname] = set() + bprov[barch][dname].add(pkgname) + + self.process_files(bdeps, bprov, brecs) + read_files.__doc__ = AptSource.read_files.__doc__ |