Blame dnf/cli/commands/clean.py

Packit Service 21c75c
# clean.py
Packit Service 21c75c
# Clean CLI command.
Packit Service 21c75c
#
Packit Service 21c75c
# Copyright (C) 2014-2016 Red Hat, Inc.
Packit Service 21c75c
#
Packit Service 21c75c
# This copyrighted material is made available to anyone wishing to use,
Packit Service 21c75c
# modify, copy, or redistribute it subject to the terms and conditions of
Packit Service 21c75c
# the GNU General Public License v.2, or (at your option) any later version.
Packit Service 21c75c
# This program is distributed in the hope that it will be useful, but WITHOUT
Packit Service 21c75c
# ANY WARRANTY expressed or implied, including the implied warranties of
Packit Service 21c75c
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit Service 21c75c
# Public License for more details.  You should have received a copy of the
Packit Service 21c75c
# GNU General Public License along with this program; if not, write to the
Packit Service 21c75c
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 21c75c
# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
Packit Service 21c75c
# source code or documentation are not subject to the GNU General Public
Packit Service 21c75c
# License and may only be used or replicated with the express permission of
Packit Service 21c75c
# Red Hat, Inc.
Packit Service 21c75c
#
Packit Service 21c75c
Packit Service 21c75c
from __future__ import absolute_import
Packit Service 21c75c
from __future__ import unicode_literals
Packit Service 21c75c
from dnf.cli import commands
Packit Service 21c75c
from dnf.i18n import _, P_
Packit Service 21c75c
from dnf.yum import misc
Packit Service 21c75c
Packit Service 21c75c
import dnf.cli
Packit Service 21c75c
import dnf.exceptions
Packit Service 21c75c
import dnf.lock
Packit Service 21c75c
import dnf.logging
Packit Service 21c75c
import dnf.repo
Packit Service 21c75c
import logging
Packit Service 21c75c
import os
Packit Service 21c75c
import re
Packit Service 21c75c
import time
Packit Service 21c75c
Packit Service 21c75c
logger = logging.getLogger("dnf")
Packit Service 21c75c
Packit Service 21c75c
# Dict mapping cmdline arguments to actual data types to be cleaned up
Packit Service 21c75c
_CACHE_TYPES = {
Packit Service 21c75c
    'metadata': ['metadata', 'dbcache', 'expire-cache'],
Packit Service 21c75c
    'packages': ['packages'],
Packit Service 21c75c
    'dbcache': ['dbcache'],
Packit Service 21c75c
    'expire-cache': ['expire-cache'],
Packit Service 21c75c
    'all': ['metadata', 'packages', 'dbcache'],
Packit Service 21c75c
}
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _tree(dirpath):
Packit Service 21c75c
    """Traverse dirpath recursively and yield relative filenames."""
Packit Service 21c75c
    for root, dirs, files in os.walk(dirpath):
Packit Service 21c75c
        base = os.path.relpath(root, dirpath)
Packit Service 21c75c
        for f in files:
Packit Service 21c75c
            path = os.path.join(base, f)
Packit Service 21c75c
            yield os.path.normpath(path)
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _filter(files, patterns):
Packit Service 21c75c
    """Yield those filenames that match any of the patterns."""
Packit Service 21c75c
    return (f for f in files for p in patterns if re.match(p, f))
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _clean(dirpath, files):
Packit Service 21c75c
    """Remove the given filenames from dirpath."""
Packit Service 21c75c
    count = 0
Packit Service 21c75c
    for f in files:
Packit Service 21c75c
        path = os.path.join(dirpath, f)
Packit Service 21c75c
        logger.log(dnf.logging.DDEBUG, _('Removing file %s'), path)
Packit Service 21c75c
        misc.unlink_f(path)
Packit Service 21c75c
        count += 1
Packit Service 21c75c
    return count
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
def _cached_repos(files):
Packit Service 21c75c
    """Return the repo IDs that have some cached metadata around."""
Packit Service 21c75c
    metapat = dnf.repo.CACHE_FILES['metadata']
Packit Service 21c75c
    matches = (re.match(metapat, f) for f in files)
Packit Service 21c75c
    return set(m.group('repoid') for m in matches if m)
Packit Service 21c75c
Packit Service 21c75c
Packit Service 21c75c
class CleanCommand(commands.Command):
Packit Service 21c75c
    """A class containing methods needed by the cli to execute the
Packit Service 21c75c
    clean command.
Packit Service 21c75c
    """
Packit Service 21c75c
Packit Service 21c75c
    aliases = ('clean',)
Packit Service 21c75c
    summary = _('remove cached data')
Packit Service 21c75c
Packit Service 21c75c
    @staticmethod
Packit Service 21c75c
    def set_argparser(parser):
Packit Service 21c75c
        parser.add_argument('type', nargs='+',
Packit Service 21c75c
                           choices=_CACHE_TYPES.keys(),
Packit Service 21c75c
                           help=_('Metadata type to clean'))
Packit Service 21c75c
Packit Service 21c75c
    def run(self):
Packit Service 21c75c
        cachedir = self.base.conf.cachedir
Packit Service 21c75c
        md_lock = dnf.lock.build_metadata_lock(cachedir, True)
Packit Service 21c75c
        download_lock = dnf.lock.build_download_lock(cachedir, True)
Packit Service 21c75c
        rpmdb_lock = dnf.lock.build_rpmdb_lock(self.base.conf.persistdir, True)
Packit Service 21c75c
        while True:
Packit Service 21c75c
            try:
Packit Service 21c75c
                with md_lock and download_lock and rpmdb_lock:
Packit Service 21c75c
                    types = set(t for c in self.opts.type for t in _CACHE_TYPES[c])
Packit Service 21c75c
                    files = list(_tree(cachedir))
Packit Service 21c75c
                    logger.debug(_('Cleaning data: ' + ' '.join(types)))
Packit Service 21c75c
Packit Service 21c75c
                    if 'expire-cache' in types:
Packit Service 21c75c
                        expired = _cached_repos(files)
Packit Service 21c75c
                        self.base._repo_persistor.expired_to_add.update(expired)
Packit Service 21c75c
                        types.remove('expire-cache')
Packit Service 21c75c
                        logger.info(_('Cache was expired'))
Packit Service 21c75c
Packit Service 21c75c
                    patterns = [dnf.repo.CACHE_FILES[t] for t in types]
Packit Service 21c75c
                    count = _clean(cachedir, _filter(files, patterns))
Packit Service 21c75c
                    logger.info(P_('%d file removed', '%d files removed', count) % count)
Packit Service 21c75c
                    return
Packit Service 21c75c
            except dnf.exceptions.LockError as e:
Packit Service 21c75c
                if not self.base.conf.exit_on_lock:
Packit Service 21c75c
                    msg = _('Waiting for process with pid %d to finish.') % (e.pid)
Packit Service 21c75c
                    logger.info(msg)
Packit Service 21c75c
                    time.sleep(3)
Packit Service 21c75c
                else:
Packit Service 21c75c
                    raise e