Skip to content

Instantly share code, notes, and snippets.

@ssato
Created June 8, 2016 01:27
Show Gist options
  • Save ssato/df2ac6b7610f7ae8a003b7f0e45c97aa to your computer and use it in GitHub Desktop.
Save ssato/df2ac6b7610f7ae8a003b7f0e45c97aa to your computer and use it in GitHub Desktop.
An experimental DNF plugin to report statistics and changes will be made instead of performing actual operations like install/update/erase/etc.
# report.py
# DNF Plugin to report summary of RPMs to install, update and remove.
#
# It implicitly assume the come back of --enableplugin option to dnf although
# it was removed as 'it's questionalbe use':
# http://dnf.readthedocs.io/en/latest/cli_vs_yum.html#enableplugin-not-recognized
#
# Copyright (C) 2016 Satoru SATOH <satoru.satoh@gmail.com>
#
# 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
import dnf
import json
import operator
import sys
_TS_TYPES = "install upgrade reinstall erase downgrade fail".split()
# :see: dnf.cli.output._active_pkg
def _active_pkg(tsi):
"""
Return the package from tsi that takes the active role in the transaction.
:return: :class:`dnf.package.Package`
"""
attr = "erased" if tsi.op_type == dnf.transaction.ERASE else "installed"
return operator.attrgetter(attr)(tsi)
def _to_pkg(tsi):
"""
:param tsi: An instance of :class:`dnf.transaction.TransactionItem`
:return: A dict gives basic package info
"""
apo = _active_pkg(tsi)
# It's not permitted (apo.arch is read-only property) actually.
# apo.arch = "noarch" if apo.a is None else apo.a # gpg-pubkey cases
return dict(naevr="%s.%s %s:%s-%s" % apo.pkgtup,
name=apo.name, arch=apo.arch, epoch=apo.epoch,
version=apo.version, release=apo.release,
repoid=apo.from_repo)
# :see:`dnf.cli.output._make_lists`
def _make_lists(transaction, ts_types=None):
"""
:param transaction: An instance of :class:`dnf.transaction.Transaction`
"""
if ts_types is None:
ts_types = _TS_TYPES
pkgs = {t: [] for t in ts_types}
for tsi in transaction:
for ttype in ts_types:
if tsi.op_type == getattr(dnf.transaction, ttype.upper(), None):
pkgs[ttype].append(tsi)
for ttype in ts_types:
pkgs[ttype].sort(key=lambda tsi: str(tsi.active))
return pkgs
class ReportPlugin(dnf.Plugin):
name = 'report'
def __init__(self, base, cli):
super(ReportPlugin, self).__init__(base, cli)
self.base = base
def resolved_itr(self):
"""
:see: dnf.cli.output.Output.list_transaction
"""
ts_types = _TS_TYPES
pkgs = _make_lists(self.base.transaction)
for ttype in ts_types:
yield (ttype, sorted((_to_pkg(tsi) for tsi in pkgs[ttype]),
key=operator.itemgetter("naevr")))
def resolved(self):
"""
:see: dnf.cli.output.Output.list_transaction
"""
pkgs = dict(self.resolved_itr())
print(json.dumps(pkgs, indent=2))
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment