Blame plugins/local.py

Packit Service 27f74b
# local.py
Packit Service 27f74b
# Automatically copy all downloaded packages to a repository on the local
Packit Service 27f74b
# filesystem and generating repo metadata.
Packit Service 27f74b
#
Packit Service 27f74b
# Copyright (C) 2015 Igor Gnatenko
Packit Service 27f74b
#
Packit Service 27f74b
# This copyrighted material is made available to anyone wishing to use,
Packit Service 27f74b
# modify, copy, or redistribute it subject to the terms and conditions of
Packit Service 27f74b
# the GNU General Public License v.2, or (at your option) any later version.
Packit Service 27f74b
# This program is distributed in the hope that it will be useful, but WITHOUT
Packit Service 27f74b
# ANY WARRANTY expressed or implied, including the implied warranties of
Packit Service 27f74b
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit Service 27f74b
# Public License for more details.  You should have received a copy of the
Packit Service 27f74b
# GNU General Public License along with this program; if not, write to the
Packit Service 27f74b
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 27f74b
# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
Packit Service 27f74b
# source code or documentation are not subject to the GNU General Public
Packit Service 27f74b
# License and may only be used or replicated with the express permission of
Packit Service 27f74b
# Red Hat, Inc.
Packit Service 27f74b
#
Packit Service 27f74b
Packit Service 27f74b
from __future__ import absolute_import
Packit Service 27f74b
from __future__ import unicode_literals
Packit Service 27f74b
from dnf.i18n import ucd
Packit Service 27f74b
from dnfpluginscore import _, logger
Packit Service 27f74b
Packit Service 27f74b
import dnf
Packit Service 27f74b
import dnf.cli
Packit Service 27f74b
import os
Packit Service 27f74b
import shutil
Packit Service 27f74b
import subprocess
Packit Service 27f74b
Packit Service 27f74b
Packit Service 27f74b
class LocalConfParse(object):
Packit Service 27f74b
    """Parsing config
Packit Service 27f74b
Packit Service 27f74b
    Args:
Packit Service 27f74b
      conf (libdnf.conf.ConfigParser): Config to parse
Packit Service 27f74b
Packit Service 27f74b
    """
Packit Service 27f74b
    def __init__(self, conf):
Packit Service 27f74b
        self.conf = conf
Packit Service 27f74b
Packit Service 27f74b
    def get_value(self, section, key, default=None):
Packit Service 27f74b
        if self.conf.has_section(section) and self.conf.has_option(section, key):
Packit Service 27f74b
            return self.conf.get(section, key)
Packit Service 27f74b
        return default
Packit Service 27f74b
Packit Service 27f74b
    def parse_config(self):
Packit Service 27f74b
        conf = self.conf
Packit Service 27f74b
        main = {}
Packit Service 27f74b
        crepo = {}
Packit Service 27f74b
Packit Service 27f74b
        if not conf.has_section("main") or not conf.has_section("createrepo") or \
Packit Service 27f74b
           not conf.has_option("main", "enabled") or not conf.has_option("createrepo", "enabled"):
Packit Service 27f74b
            raise KeyError("Missing key")
Packit Service 27f74b
        main["enabled"] = conf.getboolean("main", "enabled")
Packit Service 27f74b
        crepo["enabled"] = conf.getboolean("createrepo", "enabled")
Packit Service 27f74b
Packit Service 27f74b
        if main["enabled"]:
Packit Service 27f74b
            main["repodir"] = self.get_value("main", "repodir",
Packit Service 27f74b
                                             default="/var/lib/dnf/plugins/local")
Packit Service 27f74b
        else:
Packit Service 27f74b
            raise KeyError("Disabled")
Packit Service 27f74b
Packit Service 27f74b
        if crepo["enabled"]:
Packit Service 27f74b
            crepo["cachedir"] = self.get_value("createrepo", "cachedir")
Packit Service 27f74b
Packit Service 27f74b
            if conf.has_option("createrepo", "quiet"):
Packit Service 27f74b
                crepo["quiet"] = conf.getboolean("createrepo", "quiet")
Packit Service 27f74b
            else:
Packit Service 27f74b
                crepo["quiet"] = True
Packit Service 27f74b
Packit Service 27f74b
            if conf.has_option("createrepo", "verbose"):
Packit Service 27f74b
                crepo["verbose"] = conf.getboolean("createrepo", "verbose")
Packit Service 27f74b
            else:
Packit Service 27f74b
                crepo["verbose"] = False
Packit Service 27f74b
Packit Service 27f74b
        return main, crepo
Packit Service 27f74b
Packit Service 27f74b
Packit Service 27f74b
class Local(dnf.Plugin):
Packit Service 27f74b
Packit Service 27f74b
    name = "local"
Packit Service 27f74b
Packit Service 27f74b
    def __init__(self, base, cli):
Packit Service 27f74b
        super(Local, self).__init__(base, cli)
Packit Service 27f74b
        self.base = base
Packit Service 27f74b
        self.main = {}
Packit Service 27f74b
        self.crepo = {}
Packit Service 27f74b
        self.logger = logger
Packit Service 27f74b
Packit Service 27f74b
    def pre_config(self):
Packit Service 27f74b
        conf = self.read_config(self.base.conf)
Packit Service 27f74b
Packit Service 27f74b
        parser = LocalConfParse(conf)
Packit Service 27f74b
        try:
Packit Service 27f74b
            self.main, self.crepo = parser.parse_config()
Packit Service 27f74b
        except KeyError:
Packit Service 27f74b
            self.main["enabled"] = False
Packit Service 27f74b
            self.crepo["enabled"] = False
Packit Service 27f74b
            return
Packit Service 27f74b
Packit Service 27f74b
        local_repo = dnf.repo.Repo("_dnf_local", self.base.conf)
Packit Service 27f74b
        local_repo.baseurl = "file://{}".format(self.main["repodir"])
Packit Service 27f74b
        local_repo.cost = 500
Packit Service 27f74b
        local_repo.skip_if_unavailable = True
Packit Service 27f74b
        self.base.repos.add(local_repo)
Packit Service 27f74b
Packit Service 27f74b
    def transaction(self):
Packit Service 27f74b
        main, crepo = self.main, self.crepo
Packit Service 27f74b
Packit Service 27f74b
        if not main["enabled"] or not self.transaction:
Packit Service 27f74b
            return
Packit Service 27f74b
Packit Service 27f74b
        repodir = main["repodir"]
Packit Service 27f74b
        if not os.path.exists(repodir):
Packit Service 27f74b
            try:
Packit Service 27f74b
                os.makedirs(repodir, mode=0o755)
Packit Service 27f74b
            except OSError as e:
Packit Service 27f74b
                self.logger.error("local: " + _(
Packit Service 27f74b
                    "Unable to create a directory '{}' due to '{}'").format(repodir, ucd(e)))
Packit Service 27f74b
                return
Packit Service 27f74b
        elif not os.path.isdir(repodir):
Packit Service 27f74b
            self.logger.error(
Packit Service 27f74b
                "local: " + _("'{}' is not a directory").format(repodir))
Packit Service 27f74b
            return
Packit Service 27f74b
Packit Service 27f74b
        needs_rebuild = False
Packit Service 27f74b
        for pkg in self.base.transaction.install_set:
Packit Service 27f74b
            path = pkg.localPkg()
Packit Service 27f74b
            if os.path.dirname(path) == repodir:
Packit Service 27f74b
                continue
Packit Service 27f74b
            self.logger.debug(
Packit Service 27f74b
                "local: " + _("Copying '{}' to local repo").format(path))
Packit Service 27f74b
            try:
Packit Service 27f74b
                shutil.copy2(path, repodir)
Packit Service 27f74b
                needs_rebuild = True
Packit Service 27f74b
            except IOError:
Packit Service 27f74b
                self.logger.error(
Packit Service 27f74b
                    "local: " + _("Can't write file '{}'").format(os.path.join(
Packit Service 27f74b
                        repodir, os.path.basename(path))))
Packit Service 27f74b
Packit Service 27f74b
        if not crepo["enabled"] or not needs_rebuild:
Packit Service 27f74b
            return
Packit Service 27f74b
Packit Service 27f74b
        args = ["createrepo_c", "--update", "--unique-md-filenames"]
Packit Service 27f74b
        if crepo["verbose"]:
Packit Service 27f74b
            args.append("--verbose")
Packit Service 27f74b
        elif crepo["quiet"]:
Packit Service 27f74b
            args.append("--quiet")
Packit Service 27f74b
        if crepo["cachedir"] is not None:
Packit Service 27f74b
            args.append("--cachedir")
Packit Service 27f74b
            args.append(crepo["cachedir"])
Packit Service 27f74b
        args.append(repodir)
Packit Service 27f74b
        self.logger.debug("local: " + _("Rebuilding local repo"))
Packit Service 27f74b
        p = subprocess.Popen(args, stdout=subprocess.PIPE,
Packit Service 27f74b
                             stderr=subprocess.STDOUT)
Packit Service 27f74b
        for line in p.stdout:
Packit Service 27f74b
            print(line.decode().rstrip("\n"))