Mini Shell
# repolist.py
# repolist CLI command.
#
# Copyright (C) 2014-2016 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
from __future__ import absolute_import
from __future__ import unicode_literals
from dnf.cli import commands
from dnf.i18n import _, ucd, fill_exact_width, exact_width
from dnf.cli.option_parser import OptionParser
import dnf.cli.format
import dnf.pycomp
import dnf.util
import fnmatch
import hawkey
import logging
import operator
logger = logging.getLogger('dnf')
def _expire_str(repo, md):
last = dnf.util.normalize_time(repo._repo.getTimestamp()) if md else _("unknown")
if repo.metadata_expire <= -1:
return _("Never (last: %s)") % last
elif not repo.metadata_expire:
return _("Instant (last: %s)") % last
else:
num = _num2ui_num(repo.metadata_expire)
return _("%s second(s) (last: %s)") % (num, last)
def _num2ui_num(num):
return ucd(dnf.pycomp.format("%d", num, True))
def _repo_match(repo, patterns):
rid = repo.id.lower()
rnm = repo.name.lower()
for pat in patterns:
if fnmatch.fnmatch(rid, pat):
return True
if fnmatch.fnmatch(rnm, pat):
return True
return False
def _repo_size(sack, repo):
ret = 0
for pkg in sack.query(flags=hawkey.IGNORE_EXCLUDES).filterm(reponame__eq=repo.id):
ret += pkg._size
return dnf.cli.format.format_number(ret)
class RepoListCommand(commands.Command):
"""A class containing methods needed by the cli to execute the
repolist command.
"""
aliases = ('repolist', 'repoinfo')
summary = _('display the configured software repositories')
@staticmethod
def set_argparser(parser):
repolimit = parser.add_mutually_exclusive_group()
repolimit.add_argument('--all', dest='_repos_action',
action='store_const', const='all', default=None,
help=_("show all repos"))
repolimit.add_argument('--enabled', dest='_repos_action',
action='store_const', const='enabled',
help=_("show enabled repos (default)"))
repolimit.add_argument('--disabled', dest='_repos_action',
action='store_const', const='disabled',
help=_("show disabled repos"))
parser.add_argument('repos', nargs='*', default='enabled-default', metavar="REPOSITORY",
choices=['all', 'enabled', 'disabled'],
action=OptionParser.PkgNarrowCallback,
help=_("Repository specification"))
def pre_configure(self):
if not self.opts.quiet:
self.cli.redirect_logger(stdout=logging.WARNING, stderr=logging.INFO)
def configure(self):
if not self.opts.quiet:
self.cli.redirect_repo_progress()
demands = self.cli.demands
if self.base.conf.verbose or self.opts.command == 'repoinfo':
demands.available_repos = True
demands.sack_activation = True
if self.opts._repos_action:
self.opts.repos_action = self.opts._repos_action
def run(self):
arg = self.opts.repos_action
extcmds = [x.lower() for x in self.opts.repos]
verbose = self.base.conf.verbose
repos = list(self.base.repos.values())
repos.sort(key=operator.attrgetter('id'))
term = self.output.term
on_ehibeg = term.FG_COLOR['green'] + term.MODE['bold']
on_dhibeg = term.FG_COLOR['red']
on_hiend = term.MODE['normal']
tot_num = 0
cols = []
if not repos:
logger.warning(_('No repositories available'))
return
include_status = arg == 'all' or (arg == 'enabled-default' and extcmds)
repoinfo_output = []
for repo in repos:
if len(extcmds) and not _repo_match(repo, extcmds):
continue
(ehibeg, dhibeg, hiend) = '', '', ''
ui_enabled = ''
ui_endis_wid = 0
ui_excludes_num = ''
if include_status:
(ehibeg, dhibeg, hiend) = (on_ehibeg, on_dhibeg, on_hiend)
if repo.enabled:
enabled = True
if arg == 'disabled':
continue
if include_status or verbose or self.opts.command == 'repoinfo':
ui_enabled = ehibeg + _('enabled') + hiend
ui_endis_wid = exact_width(_('enabled'))
if verbose or self.opts.command == 'repoinfo':
ui_size = _repo_size(self.base.sack, repo)
else:
enabled = False
if arg == 'enabled' or (arg == 'enabled-default' and not extcmds):
continue
ui_enabled = dhibeg + _('disabled') + hiend
ui_endis_wid = exact_width(_('disabled'))
if not (verbose or self.opts.command == 'repoinfo'):
rid = ucd(repo.id)
cols.append((rid, repo.name, (ui_enabled, ui_endis_wid)))
else:
if enabled:
md = repo.metadata
else:
md = None
out = [self.output.fmtKeyValFill(_("Repo-id : "), repo.id),
self.output.fmtKeyValFill(_("Repo-name : "), repo.name)]
if include_status:
out += [self.output.fmtKeyValFill(_("Repo-status : "),
ui_enabled)]
if md and repo._repo.getRevision():
out += [self.output.fmtKeyValFill(_("Repo-revision : "),
repo._repo.getRevision())]
if md and repo._repo.getContentTags():
tags = repo._repo.getContentTags()
out += [self.output.fmtKeyValFill(_("Repo-tags : "),
", ".join(sorted(tags)))]
if md and repo._repo.getDistroTags():
distroTagsDict = {k: v for (k, v) in repo._repo.getDistroTags()}
for (distro, tags) in distroTagsDict.items():
out += [self.output.fmtKeyValFill(
_("Repo-distro-tags : "),
"[%s]: %s" % (distro, ", ".join(sorted(tags))))]
if md:
num = len(self.base.sack.query(flags=hawkey.IGNORE_EXCLUDES).filterm(
reponame__eq=repo.id))
num_available = len(self.base.sack.query().filterm(reponame__eq=repo.id))
ui_num = _num2ui_num(num)
ui_num_available = _num2ui_num(num_available)
tot_num += num
out += [
self.output.fmtKeyValFill(
_("Repo-updated : "),
dnf.util.normalize_time(repo._repo.getMaxTimestamp())),
self.output.fmtKeyValFill(_("Repo-pkgs : "), ui_num),
self.output.fmtKeyValFill(_("Repo-available-pkgs: "), ui_num_available),
self.output.fmtKeyValFill(_("Repo-size : "), ui_size)]
if repo.metalink:
out += [self.output.fmtKeyValFill(_("Repo-metalink : "),
repo.metalink)]
if enabled:
ts = repo._repo.getTimestamp()
out += [self.output.fmtKeyValFill(
_(" Updated : "), dnf.util.normalize_time(ts))]
elif repo.mirrorlist:
out += [self.output.fmtKeyValFill(_("Repo-mirrors : "),
repo.mirrorlist)]
baseurls = repo.baseurl
if baseurls:
out += [self.output.fmtKeyValFill(_("Repo-baseurl : "),
", ".join(baseurls))]
elif enabled:
mirrors = repo._repo.getMirrors()
if mirrors:
url = "%s (%d more)" % (mirrors[0], len(mirrors) - 1)
out += [self.output.fmtKeyValFill(_("Repo-baseurl : "), url)]
expire = _expire_str(repo, md)
out += [self.output.fmtKeyValFill(_("Repo-expire : "), expire)]
if repo.excludepkgs:
# TRANSLATORS: Packages that are excluded - their names like (dnf systemd)
out += [self.output.fmtKeyValFill(_("Repo-exclude : "),
", ".join(repo.excludepkgs))]
if repo.includepkgs:
out += [self.output.fmtKeyValFill(_("Repo-include : "),
", ".join(repo.includepkgs))]
if ui_excludes_num:
# TRANSLATORS: Number of packages that where excluded (5)
out += [self.output.fmtKeyValFill(_("Repo-excluded : "),
ui_excludes_num)]
if repo.repofile:
out += [self.output.fmtKeyValFill(_("Repo-filename : "),
repo.repofile)]
repoinfo_output.append("\n".join(map(ucd, out)))
if repoinfo_output:
print("\n\n".join(repoinfo_output))
if not verbose and cols:
# Work out the first (id) and last (enabled/disabled/count),
# then chop the middle (name)...
id_len = exact_width(_('repo id'))
nm_len = 0
st_len = 0
for (rid, rname, (ui_enabled, ui_endis_wid)) in cols:
if id_len < exact_width(rid):
id_len = exact_width(rid)
if nm_len < exact_width(rname):
nm_len = exact_width(rname)
if st_len < ui_endis_wid:
st_len = ui_endis_wid
# Need this as well as above for: fill_exact_width()
if include_status:
if exact_width(_('status')) > st_len:
left = term.columns - (id_len + len(_('status')) + 2)
else:
left = term.columns - (id_len + st_len + 2)
else: # Don't output a status column.
left = term.columns - (id_len + 1)
if left < nm_len: # Name gets chopped
nm_len = left
else: # Share the extra...
left -= nm_len
id_len += left // 2
nm_len += left - (left // 2)
txt_rid = fill_exact_width(_('repo id'), id_len)
if include_status:
txt_rnam = fill_exact_width(_('repo name'), nm_len, nm_len)
else:
txt_rnam = _('repo name')
if not include_status: # Don't output a status column.
print("%s %s" % (txt_rid, txt_rnam))
else:
print("%s %s %s" % (txt_rid, txt_rnam, _('status')))
for (rid, rname, (ui_enabled, ui_endis_wid)) in cols:
if not include_status: # Don't output a status column.
print("%s %s" % (fill_exact_width(rid, id_len), rname))
continue
print("%s %s %s" % (fill_exact_width(rid, id_len),
fill_exact_width(rname, nm_len, nm_len),
ui_enabled))
if verbose or self.opts.command == 'repoinfo':
msg = _('Total packages: {}')
print(msg.format(_num2ui_num(tot_num)))
Zerion Mini Shell 1.0