From: Michael Tremer Date: Fri, 12 Feb 2021 17:11:45 +0000 (+0000) Subject: packages: Drop old code that read archives and installed packages X-Git-Tag: 0.9.28~1285^2~747 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42dfd369427b4e39540b7edcd5ea449383f7af92;p=pakfire.git packages: Drop old code that read archives and installed packages Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 8c6dada76..8f16add31 100644 --- a/Makefile.am +++ b/Makefile.am @@ -143,8 +143,6 @@ pakfiredir = $(pythondir)/pakfire pakfire_packages_PYTHON = \ src/pakfire/packages/__init__.py \ src/pakfire/packages/base.py \ - src/pakfire/packages/file.py \ - src/pakfire/packages/installed.py \ src/pakfire/packages/lexer.py \ src/pakfire/packages/make.py \ src/pakfire/packages/packager.py \ diff --git a/src/pakfire/packages/__init__.py b/src/pakfire/packages/__init__.py index 916f64b06..d90bbdef8 100644 --- a/src/pakfire/packages/__init__.py +++ b/src/pakfire/packages/__init__.py @@ -19,32 +19,6 @@ # # ############################################################################### -import tarfile - -from . import file - from .base import Package -from .installed import DatabasePackage from .make import Makefile - -from pakfire.constants import * - -def open(pakfire, repo, filename): - """ - Function to open all packages and return the right object. - - Abstractly, this detects if a package is a source package or - not. - """ - # XXX We should make this check much better... - - # Simply check if the given file is a tarfile. - if tarfile.is_tarfile(filename): - if filename.endswith(".src.%s" % PACKAGE_EXTENSION): - return file.SourcePackage(pakfire, repo, filename) - - return file.BinaryPackage(pakfire, repo, filename) - - elif filename.endswith(".%s" % MAKEFILE_EXTENSION): - return Makefile(pakfire, filename) diff --git a/src/pakfire/packages/file.py b/src/pakfire/packages/file.py deleted file mode 100644 index bd961edcc..000000000 --- a/src/pakfire/packages/file.py +++ /dev/null @@ -1,1038 +0,0 @@ -#!/usr/bin/python -############################################################################### -# # -# Pakfire - The IPFire package management system # -# Copyright (C) 2011 Pakfire development team # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -############################################################################### - -import hashlib -import lzma -import os -import re -import shutil -import tarfile -import tempfile - -import logging -log = logging.getLogger("pakfire") - -from ..constants import * -from ..i18n import _ - -from .. import compress -from .. import filelist - -from . import base -from . import lexer -from . import make -from . import tar - -class FilePackage(base.Package): - """ - This class is a wrapper that reads package data from the (outer) - tarball and should never be used solely. - """ - _type = None - - def __init__(self, pakfire, repo, filename): - base.Package.__init__(self, pakfire, repo) - self.filename = os.path.abspath(filename) - - # Place to cache the metadata - self._metadata = {} - - # Place to cache the filelist and payload compression algorithm. - self._filelist = None - self.__payload_compression = None - - # Store the format of this package file. - self.format = self.get_format() - - # XXX need to make this much better. - self.check() - - # Read the info file. - if self.format >= 1: - a = self.open_archive() - f = a.extractfile("info") - - self.lexer = lexer.FileLexer(f.readlines()) - - f.close() - a.close() - - elif self.format == 0: - pass - - else: - raise PackageFormatUnsupportedError(_("Filename: %s") % self.filename) - - def check(self): - """ - Initially check if the given file is of the correct type and - can be opened. - """ - if not tarfile.is_tarfile(self.filename): - raise FileError("Given file is not of correct format: %s" % self.filename) - - assert self.format in PACKAGE_FORMATS_SUPPORTED, self.format - - def get_format(self): - a = self.open_archive() - try: - f = a.extractfile("pakfire-format") - except KeyError: - return 0 - - format = f.read() - try: - format = int(format) - except TypeError: - format = 0 - - f.close() - a.close() - - return format - - def __repr__(self): - return "<%s %s>" % (self.__class__.__name__, self.filename) - - @property - def local(self): - # A file package is always local. - return True - - def open_archive(self, mode="r"): - return tarfile.open(self.filename, mode=mode, format=tarfile.PAX_FORMAT) - - def open_payload_archive(self): - a = self.open_archive() - - # Find the payload data. - payload = a.extractfile("data.img") - - # Decompress the payload if needed. - if self.payload_compression == "xz": - payload_archive = tar.InnerTarFileXz.open(fileobj=payload) - - elif self.payload_compression == "none": - payload_archive = tar.InnerTarFile.open(fileobj=payload) - - else: - raise Exception("Unhandled payload compression type: %s" % \ - self.payload_compression) - - return payload_archive - - def extract(self, message=None, prefix=None): - log.debug("Extracting package %s" % self.friendly_name) - - if prefix is None: - prefix = "" - - # Open package data for read. - payload_archive = self.open_payload_archive() - - # Load progressbar. - pb = None - if message: - message = "%-10s : %s" % (message, self.friendly_name) - - from . import util - pb = util.make_progress(message, len(self.filelist), eta=False) - - # Collect messages with errors and warnings, that are passed to - # the user. - messages = [] - - name2file = {} - for file in self.filelist: - if file.is_dir() and file.name.endswith("/"): - name = file.name[:-1] - else: - name = file.name - - name2file[name] = file - - i = 0 - while True: - member = next(payload_archive) - if not member: - break - - # Check if file is also known in metadata. - name = member.name - if not name.startswith("/"): - name = "/%s" % name - - try: - file = name2file[name] - except KeyError: - log.warning(_("File in archive is missing in file metadata: %s. Skipping.") % name) - continue - - # Update progress. - if pb: - i += 1 - pb.update(i) - - target = os.path.join(prefix, member.name) - - # Check if a configuration file is already present. We don't want to - # overwrite that. - if file.is_config(): - config_save = "%s%s" % (target, CONFIG_FILE_SUFFIX_SAVE) - config_new = "%s%s" % (target, CONFIG_FILE_SUFFIX_NEW) - - if os.path.exists(config_save) and not os.path.exists(target): - # Extract new configuration file, save it as CONFIG_FILE_SUFFIX_NEW, - # and reuse _SAVE. - payload_archive.extract(member, path=prefix) - - shutil.move(target, config_new) - shutil.move(config_save, target) - continue - - elif os.path.exists(target): - # If the files are identical, we skip the extraction of a - # new configuration file. We also do that when the new configuration file - # is a dummy file. - if file.size == 0: - continue - - # Calc hash of the current configuration file. - config_hash1 = hashlib.new("sha512") - f = open(target) - while True: - buf = f.read(BUFFER_SIZE) - if not buf: - break - config_hash1.update(buf) - f.close() - - if file.hash1 == config_hash1.hexdigest(): - continue - - # Backup old configuration file and extract new one. - shutil.move(target, config_save) - payload_archive.extract(member, path=prefix) - - # Save new configuration file as CONFIG_FILE_SUFFIX_NEW and - # restore old configuration file. - shutil.move(target, config_new) - shutil.move(config_save, target) - - if prefix: - config_new = os.path.relpath(config_new, prefix) - messages.append(_("Config file created as %s") % config_new) - continue - - # Don't overwrite target files if they already exist. - if file.is_datafile() and os.path.exists(target): - log.debug(_("Don't overwrite already existing datafile '/%s'") % member.name) - continue - - # If the member is a directory and if it already exists, we - # don't need to create it again. - if os.path.exists(target): - if member.isdir(): - continue - - else: - # Remove file if it has been existant - try: - os.unlink(target) - except OSError: - messages.append(_("Could not remove file: /%s") % member.name) - - #if self.pakfire.config.get("debug"): - # msg = "Creating file (%s:%03d:%03d) " % \ - # (tarfile.filemode(member.mode), member.uid, member.gid) - # if member.issym(): - # msg += "/%s -> %s" % (member.name, member.linkname) - # elif member.islnk(): - # msg += "/%s link to /%s" % (member.name, member.linkname) - # else: - # msg += "/%s" % member.name - # log.debug(msg) - - payload_archive.extract(member, path=prefix) - - # Close all open files. - payload_archive.close() - - if pb: - pb.finish() - - # Print messages. - for msg in messages: - log.warning(msg) - - def open_file(self, filename): - payload_archive = self.open_payload_archive() - - # Search for filename. - while True: - member = next(payload_archive) - if not member: - break - - # Skip non-matching files. - if not filename in (member.name, "/%s" % member.name): - continue - - return payload_archive.extractfile(member) - - def open_makefile(self): - """ - Opens the makefile inside the package. - """ - f = self.open_file("%s.%s" % (self.name, MAKEFILE_EXTENSION)) - if not f: - return - - return make.Makefile(self.pakfire, lines=f.readlines()) - - @property - def metadata(self): - """ - Read-in the metadata from the "info" file and cache it in _metadata. - """ - assert self.format == 0, self - - if not self._metadata: - a = self.open_archive() - f = a.extractfile("info") - - for line in f.readlines(): - m = re.match(r"^(\w+)=(.*)$", line) - if m is None: - continue - - key, val = m.groups() - self._metadata[key] = val.strip("\"") - - f.close() - a.close() - - return self._metadata - - @property - def size(self): - """ - Return the size of the package file. - """ - return os.path.getsize(self.filename) - - @property - def inst_size(self): - inst_size = 0 - - if self.format >= 1: - inst_size = self.lexer.package.get_var("size") - try: - inst_size = int(inst_size) - except TypeError: - inst_size = 0 - - return inst_size - - def read_plain_filelist(self, filename): - a = self.open_archive() - files = [] - - try: - f = a.extractfile(filename) - for line in f.readlines(): - # Strip newline at end of line. - file = line.rstrip() - - # Add a leading / is not present. - if not file.startswith("/"): - file = "/%s" % file - - files.append(file) - f.close() - - # Ignore if 'filename' does not exist. - except KeyError: - pass - - finally: - a.close() - - return files - - def get_filelist(self): - """ - Return a list of the files that are contained in the package - payload. - """ - ret = [] - - a = self.open_archive() - - # Cache configfiles. - if self.format >= 5: - filename = "configfiles" - else: - filename = "configs" - configfiles = self.read_plain_filelist(filename) - - # Cache datafiles. - datafiles = self.read_plain_filelist("datafiles") - - f = a.extractfile("filelist") - for line in f.readlines(): - line = line.strip() - - file = pakfire.filelist.File(self.pakfire) - - if self.format >= 1: - line = line.split(None, 8) - - # Check if fields do have the correct length. - if self.format >= 3 and len(line) <= 7: - continue - elif len(line) <= 6: - continue - - # Switch the first and last argument in the line. - if self.format < 4: - line.append(line.pop(0)) - - name = line[-1] - - if not name.startswith("/"): - name = "/%s" % name - - # Check if configfiles. - if name in configfiles: - file.config = True - - # Check if this is a datafile. - if name in datafiles: - file.datafile = True - - # Parse file type. - try: - file.type = int(line[0]) - except ValueError: - file.type = 0 - - # Parse the size information. - try: - file.size = int(line[1]) - except ValueError: - file.size = 0 - - # Parse user and group. - file.user, file.group = line[2], line[3] - - # Parse mode. - try: - file.mode = int(line[4]) - except ValueError: - file.mode = 0 - - # Parse time. - try: - file.mtime = line[5] - except ValueError: - file.mtime = 0 - - # Parse hash1 (sha512). - if not line[6] == "-": - file.hash1 = line[6] - - if self.format >= 3 and len(line) >= 9 and not line[7] == "-": - file.capabilities = line[7] - - else: - name = line - - if not name.startswith("/"): - name = "/%s" % name - - file.name = name - file.pkg = self - - ret.append(file) - - f.close() - a.close() - - return ret - - @property - def filelist(self): - if self._filelist is None: - self._filelist = self.get_filelist() - - return self._filelist - - @property - def configfiles(self): - return [f for f in self.filelist if f.is_config()] - - @property - def datafiles(self): - return [f for f in self.filelist if f.is_datafile()] - - @property - def payload_compression(self): - """ - Return the (guessed) compression type of the payload. - """ - # We cache that because this is costly. - if self.__payload_compression is None: - a = self.open_archive() - f = a.extractfile("data.img") - - # Go and guess what we do have here. - self.__payload_compression = compress.guess_algo(fileobj=f) - - f.close() - a.close() - - return self.__payload_compression or "none" - - ### SIGNATURE STUFF - - @property - def signatures(self): - """ - Read the signatures from the archive. - """ - ret = {} - - # Open the archive for reading. - a = self.open_archive() - - for member in a.getmembers(): - # Skip all files that are not a signature. - if not member.name.startswith("signatures/"): - continue - - # Get the ID of the key. - key_id = os.path.basename(member.name) - - # Get the content of the signature file. - f = a.extractfile(member.name) - signature = f.read() - f.close() - - if signature: - ret[key_id] = signature - - # Close the archive. - a.close() - - return ret - - def has_signature(self, key_id): - """ - Check if the file a signature of the given key. - """ - f = self.open_file("signatures/%s" % key_id) - if f: - f.close() - - return True - - return False - - def __has_hardlinks(self): - """ - Returns True when a file has a hardlink. - """ - res = os.stat(self.filename) - - return res.st_nlink > 1 - - def __remove_hardlinks(self): - """ - Remove all hardlinks from this file that we can alter it in place. - """ - if not self.__has_hardlinks(): - return - - # Open a file descriptor to the old file and remove the link from - # the filesystem. - f = open(self.filename, "rb") - os.unlink(self.filename) - - # Create a new file with the exact same name for copying the data - # to. - g = open(self.filename, "wb") - - # Copy the data. - while True: - buf = f.read(BUFFER_SIZE) - if not buf: - break - - g.write(buf) - - # Close all files. - f.close() - g.close() - - # Make sure the whole process above worked fine. - assert self.__has_hardlinks() is False - - def sign(self, key_id): - """ - Sign the package with the given key. - """ - # First check if the package has already been signed with this key. - # If true, we do not have anything to do here. - if self.has_signature(key_id): - return False - - # Remove all hardlinks. - self.__remove_hardlinks() - - # XXX verify the content of the file here. - - # Open the archive and read the checksum file. - a = self.open_archive() - - f = a.extractfile("chksums") - cleartext = f.read() - - f.close() - a.close() - - # Create the signature. - signature = self.pakfire.keyring.sign(key_id, cleartext) - - try: - # Write the signature to a temporary file. - f = tempfile.NamedTemporaryFile(mode="w", delete=False) - f.write(signature) - f.close() - - # Reopen the outer tarfile in write mode and append - # the new signature. - a = self.open_archive("a") - a.add(f.name, "signatures/%s" % key_id) - a.close() - - finally: - os.unlink(f.name) - - return True - - def verify(self): - """ - Verify the tarball against the given key. - - If not key is given, only the checksums are compared to - the actual data. - """ - # TODO use new key code from libpakfire - - # XXX replace Exception - - # Read the data of the checksum file. - a = self.open_archive() - f = a.extractfile("chksums") - chksums = f.read() - f.close() - a.close() - - sigs = [] - for signature in list(self.signatures.values()): - sigs += self.pakfire.keyring.verify(signature, chksums) - - # Open the archive to access all files we will need. - a = self.open_archive() - - # Read the chksums file. - chksums = {} - f = a.extractfile("chksums") - for line in f.readlines(): - filename, chksum = line.split() - chksums[filename] = chksum - f.close() - a.close() - - for filename, chksum in list(chksums.items()): - ret = self.check_chksum(filename, chksum) - - if ret: - log.debug("Checksum of %s matches." % filename) - continue - else: - log.debug("Checksum of %s does not match." % filename) - - raise Exception("Checksum does not match: %s" % filename) - - return sigs - - def check_chksum(self, filename, chksum, algo="sha512"): - a = self.open_archive() - f = a.extractfile(filename) - - h = hashlib.new(algo) - while True: - buf = f.read(BUFFER_SIZE) - if not buf: - break - - h.update(buf) - - f.close() - a.close() - - return h.hexdigest() == chksum - - @property - def hash1(self): - """ - Calculate the hash1 of this package. - """ - from . import util - return util.calc_hash1(self.filename) - - @property - def type(self): - if self.format >= 2: - type = self.lexer.package.get_var("type") - elif self.format == 1: - type = self._type - else: - type = self.metadata.get("type") - - assert type, self - return type - - @property - def name(self): - if self.format >= 1: - name = self.lexer.package.get_var("name") - elif self.format == 0: - name = self.metadata.get("PKG_NAME") - - assert name, self - return name - - @property - def epoch(self): - if self.format >= 1: - epoch = self.lexer.package.get_var("epoch", 0) - elif self.format == 0: - epoch = self.metadata.get("PKG_EPOCH") - - try: - epoch = int(epoch) - except TypeError: - epoch = 0 - - return epoch - - @property - def version(self): - if self.format >= 1: - version = self.lexer.package.get_var("version") - elif self.format == 0: - version = self.metadata.get("PKG_VER") - - assert version, self - return version - - @property - def release(self): - if self.format >= 1: - release = self.lexer.package.get_var("release") - elif self.format == 0: - release = self.metadata.get("PKG_REL") - - assert release, self - return release - - @property - def arch(self): - if self.format >= 1: - arch = self.lexer.package.get_var("arch") - elif self.format == 0: - arch = self.metadata.get("PKG_ARCH") - - assert arch, self - return arch - - @property - def vendor(self): - if self.format >= 1: - vendor = self.lexer.distro.get_var("vendor") - elif self.format == 0: - vendor = self.metadata.get("PKG_VENDOR") - - return vendor - - @property - def summary(self): - if self.format >= 1: - summary = self.lexer.package.get_var("summary") - elif self.format == 0: - summary = self.metadata.get("PKG_SUMMARY") - - assert summary, self - return summary - - @property - def description(self): - if self.format >= 1: - description = self.lexer.package.get_var("description") - elif self.format == 0: - description = self.metadata.get("PKG_DESC") - - return description - - @property - def groups(self): - if self.format >= 1: - groups = self.lexer.package.get_var("groups") - elif self.format == 0: - groups = self.metadata.get("PKG_GROUPS") - - if groups: - return groups.split() - - return [] - - @property - def license(self): - if self.format >= 1: - license = self.lexer.package.get_var("license") - elif self.format == 0: - license = self.metadata.get("PKG_LICENSE") - - return license - - @property - def url(self): - if self.format >= 1: - url = self.lexer.package.get_var("url") - elif self.format == 0: - url = self.metadata.get("PKG_URL") - - return url - - @property - def maintainer(self): - if self.format >= 1: - maintainer = self.lexer.package.get_var("maintainer") - elif self.format == 0: - maintainer = self.metadata.get("PKG_MAINTAINER") - - return maintainer - - @property - def uuid(self): - if self.format >= 1: - uuid = self.lexer.package.get_var("uuid") - elif self.format == 0: - uuid = self.metadata.get("PKG_UUID") - - assert uuid, self - return uuid - - @property - def build_id(self): - if self.format >= 1: - build_id = self.lexer.build.get_var("id") - elif self.format == 0: - build_id = self.metadata.get("BUILD_ID") - - assert build_id, self - return build_id - - @property - def build_host(self): - if self.format >= 1: - build_host = self.lexer.build.get_var("host") - elif self.format == 0: - build_host = self.metadata.get("BUILD_HOST") - - assert build_host, self - return build_host - - @property - def build_time(self): - if self.format >= 1: - build_time = self.lexer.build.get_var("time") - elif self.format == 0: - build_time = self.metadata.get("BUILD_TIME") - - # XXX re-enable this later - #assert build_time, self - - try: - build_time = int(build_time) - except TypeError: - build_time = 0 - - return build_time - - @property - def provides(self): - if self.format >= 1: - provides = self.lexer.deps.get_var("provides") - elif self.format == 0: - provides = self.metadata.get("PKG_PROVIDES") - - if not provides: - return [] - - provides = provides.splitlines() - return self.filter_deps(provides) - - @property - def requires(self): - if self.format >= 1: - requires = self.lexer.deps.get_var("requires") - elif self.format == 0: - requires = self.metadata.get("PKG_REQUIRES") - - if not requires: - return [] - - requires = requires.splitlines() - return self.filter_deps(requires) - - @property - def prerequires(self): - if self.format >= 1: - prerequires = self.lexer.deps.get_var("prerequires") - elif self.format == 0: - prerequires = self.metadata.get("PKG_PREREQUIRES") - - if not prerequires: - return [] - - prerequires = prerequires.splitlines() - return self.filter_deps(prerequires) - - @property - def obsoletes(self): - if self.format >= 1: - obsoletes = self.lexer.deps.get_var("obsoletes") - elif self.format == 0: - obsoletes = self.metadata.get("PKG_OBSOLETES") - - if not obsoletes: - return [] - - obsoletes = obsoletes.splitlines() - return self.filter_deps(obsoletes) - - @property - def conflicts(self): - if self.format >= 1: - conflicts = self.lexer.deps.get_var("conflicts") - elif self.format == 0: - conflicts = self.metadata.get("PKG_CONFLICTS") - - if not conflicts: - return [] - - conflicts = conflicts.splitlines() - return self.filter_deps(conflicts) - - @property - def recommends(self): - if self.format < 4: - return [] - - recommends = self.lexer.deps.get_var("recommends") - - if not recommends: - return [] - - recommends = recommends.splitlines() - return self.filter_deps(recommends) - - @property - def suggests(self): - if self.format < 4: - return [] - - suggests = self.lexer.deps.get_var("suggests") - - if not suggests: - return [] - - suggests = suggests.splitlines() - return self.filter_deps(suggests) - - -class SourcePackage(FilePackage): - _type = "source" - - @property - def arch(self): - return "src" - - @property - def supported_arches(self): - if self.format >= 2: - arches = self.lexer.package.get_var("arch", "all") - elif self.format == 1: - # Format 1 did not support "supported_arches", so we assume "all". - arches = "all" - else: - arches = self.metadata.get("PKG_SUPPORTED_ARCHES", "all") - - assert arches, self - return arches - - @property - def requires(self): - m = self.open_makefile() - if not m: - return [] - - requires = m.lexer.build.get_var("requires") - requires = requires.splitlines() - - return self.filter_deps(requires) - - -class BinaryPackage(FilePackage): - _type = "binary" - - def get_scriptlet(self, type): - a = self.open_archive() - - # Path of the scriptlet in the tarball. - path = "scriptlets/%s" % type - - try: - f = a.extractfile(path) - except KeyError: - # If the scriptlet is not available, we just return. - return - - scriptlet = f.read() - - f.close() - a.close() - - return scriptlet diff --git a/src/pakfire/packages/installed.py b/src/pakfire/packages/installed.py deleted file mode 100644 index 06619a580..000000000 --- a/src/pakfire/packages/installed.py +++ /dev/null @@ -1,355 +0,0 @@ -#!/usr/bin/python -############################################################################### -# # -# Pakfire - The IPFire package management system # -# Copyright (C) 2011 Pakfire development team # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -############################################################################### - -import os - -import pakfire.filelist - -from .. import http - -from .base import Package -from .file import BinaryPackage - -import pakfire.util as util -from pakfire.constants import * - -class DatabasePackage(Package): - type = "db" - - def __init__(self, pakfire, repo, db, data): - Package.__init__(self, pakfire, repo) - - self.db = db - - self._data = {} - self._filelist = None - - for key in list(data.keys()): - self._data[key] = data[key] - - def __repr__(self): - return "<%s %s>" % (self.__class__.__name__, self.friendly_name) - - @property - def metadata(self): - return self._data - - @property - def id(self): - id = self.metadata.get("id") - if not id: - id = 0 - - return id - - @property - def name(self): - return self.metadata.get("name") - - @property - def version(self): - return self.metadata.get("version") - - @property - def release(self): - return self.metadata.get("release") - - @property - def epoch(self): - epoch = self.metadata.get("epoch", 0) - - return int(epoch) - - @property - def arch(self): - return self.metadata.get("arch") - - @property - def maintainer(self): - return self.metadata.get("maintainer") - - @property - def license(self): - return self.metadata.get("license") - - @property - def summary(self): - return self.metadata.get("summary") - - @property - def description(self): - return self.metadata.get("description") - - @property - def groups(self): - groups = self.metadata.get("groups", "") - - if groups: - return groups.split() - - return [] - - @property - def build_date(self): - return self.metadata.get("build_date") - - @property - def build_time(self): - build_time = self.metadata.get("build_time", 0) - - try: - return int(build_time) - except TypeError: - return 0 - - @property - def build_host(self): - return self.metadata.get("build_host") - - @property - def build_id(self): - return self.metadata.get("build_id") - - @property - def vendor(self): - return self.metadata.get("vendor") - - @property - def uuid(self): - return self.metadata.get("uuid") - - @property - def size(self): - return self.metadata.get("size", 0) - - @property - def inst_size(self): - inst_size = self.metadata.get("inst_size", None) - - # As install size has not always been saved in the database - # use the package size instead. - if inst_size is None: - return self.size - - return inst_size - - @property - def dependencies(self): - if not hasattr(self, "__dependencies"): - self.__dependencies = {} - - c = self.db.cursor() - c.execute("SELECT type, dependency FROM dependencies WHERE pkg = ?", (self.id,)) - - for type, dependency in c.fetchall(): - try: - self.__dependencies[type].append(dependency) - except KeyError: - self.__dependencies[type] = [dependency,] - - return self.__dependencies - - @property - def provides(self): - return self.dependencies.get("provides", []) - - @property - def requires(self): - return self.dependencies.get("requires", []) - - @property - def conflicts(self): - return self.dependencies.get("conflicts", []) - - @property - def obsoletes(self): - return self.dependencies.get("obsoletes", []) - - @property - def recommends(self): - return self.dependencies.get("recommends", []) - - @property - def suggests(self): - return self.dependencies.get("suggests", []) - - @property - def hash1(self): - return self.metadata.get("hash1") - - @property - def scriptlet(self): - return self.metadata.get("scriptlet") - - def get_scriptlet(self, action): - c = self.db.cursor() - c.execute("SELECT scriptlet FROM scriptlets WHERE pkg = ? AND action = ? LIMIT 1", (self.id, action,)) - - try: - row = c.fetchone() - - # If no row was returned, no scriptlet for this action - # does exist. - if row: - return row["scriptlet"] - - finally: - c.close() - - @property - def filename(self): - return self.metadata.get("filename") - - @property - def filelist(self): - if self._filelist is None: - self._filelist = [] - - c = self.db.cursor() - c.execute("SELECT * FROM files WHERE pkg = ?", (self.id,)) - - for row in c.fetchall(): - file = pakfire.filelist.FileDatabase(self.pakfire, self.db, row["id"], row) - self._filelist.append(file) - - return self._filelist - - @property - def configfiles(self): - ret = [] - - for file in self.filelist: - if not file.is_config(): - continue - - ret.append(file) - - return ret - - @property - def datafiles(self): - ret = [] - - for file in self.filelist: - if not file.is_datafile(): - continue - - ret.append(file) - - return ret - - def _does_provide_file(self, requires): - """ - A faster version to find a file in the database. - """ - c = self.db.cursor() - c.execute("SELECT * FROM files WHERE name GLOB ? AND pkg = ?", - (requires.requires, self.id)) - - ret = False - for pkg in c: - ret = True - break - - c.close() - - return ret - - def download(self, text=""): - """ - Downloads the package from repository and returns a new instance - of BinaryPackage. - """ - - # XXX a bit hacky, but InstalledRepository has no cache. - if self.repo.name == "installed": - return self - - # Marker, if we need to download the package. - download = True - - # Add shortcut for cache. - cache = self.repo.cache - - cache_filename = "packages/%s" % os.path.basename(self.filename) - - # Check if file already exists in cache. - if cache.exists(cache_filename): - # If the file does already exist, we check if the hash1 matches. - if cache.verify(cache_filename, self.hash1): - # We already got the right file. Skip download. - download = False - else: - # The file in cache has a wrong hash. Remove it and repeat download. - cache.remove(cache_filename) - - if download: - downloader = http.Client() - for mirror in self.repo.mirrors.all: - downloader.add_mirror(mirror.url) - - downloader.retrieve(filename, filename=cache_filename) - - # Verify if the download was okay. - if not cache.verify(cache_filename, self.hash1): - raise Exception("XXX this should never happen...") - - filename = os.path.join(cache.path, cache_filename) - return BinaryPackage(self.pakfire, self.repo, filename) - - def cleanup(self, message, prefix): - c = self.db.cursor() - - # Get all files, that are in this package and check for all of - # them if they need to be removed. - files = self.filelist - - # Fetch the whole filelist of the system from the database and create - # a diff. Exclude files from this package - of course. - c.execute("SELECT DISTINCT name FROM files WHERE pkg != ?", (self.id,)) - - installed_files = set() - for row in c: - installed_files.add(row["name"]) - c.close() - - # List with files to be removed. - remove_files = [] - - for f in files: - # Try to find the if an other package owns the file. - # Handles packages that move files from / to /usr. - try: - filename = os.path.abspath(f.name) - except OSError: - filename = f.name - - if filename in installed_files: - continue - - remove_files.append(f) - - self._remove_files(remove_files, message, prefix) - - @property - def signatures(self): - # Database packages do not have any signatures. - return [] diff --git a/src/pakfire/packages/packager.py b/src/pakfire/packages/packager.py index 80d5319fb..16b2143d7 100644 --- a/src/pakfire/packages/packager.py +++ b/src/pakfire/packages/packager.py @@ -632,11 +632,6 @@ class BinaryPackager(Packager): except OSError: shutil.copy2(tempfile, resultfile) - # XXX to resolve a cyclic dependency - from . import file - - return file.BinaryPackage(self.pakfire, self.pakfire.repos.dummy, resultfile) - class SourcePackager(Packager): payload_compression = None