diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec index 012dde8..d13a996 100644 --- a/dnf-plugins-core.spec +++ b/dnf-plugins-core.spec @@ -58,7 +58,6 @@ Provides: dnf-command(debug-dump) Provides: dnf-command(debug-restore) Provides: dnf-command(debuginfo-install) Provides: dnf-command(download) -Provides: dnf-command(groups-manager) Provides: dnf-command(repoclosure) Provides: dnf-command(repograph) Provides: dnf-command(repomanage) @@ -74,7 +73,6 @@ Provides: dnf-plugin-debuginfo-install = %{version}-%{release} Provides: dnf-plugin-download = %{version}-%{release} Provides: dnf-plugin-generate_completion_cache = %{version}-%{release} Provides: dnf-plugin-needs_restarting = %{version}-%{release} -Provides: dnf-plugin-groups-manager = %{version}-%{release} Provides: dnf-plugin-repoclosure = %{version}-%{release} Provides: dnf-plugin-repodiff = %{version}-%{release} Provides: dnf-plugin-repograph = %{version}-%{release} @@ -89,7 +87,7 @@ Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} %description Core Plugins for DNF. This package enhances DNF with builddep, config-manager, -copr, debug, debuginfo-install, download, needs-restarting, groups-manager, repoclosure, +copr, debug, debuginfo-install, download, needs-restarting, repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. Additionally provides generate_completion_cache passive plugin. @@ -99,10 +97,8 @@ Summary: Core Plugins for DNF %{?python_provide:%python_provide python2-%{name}} BuildRequires: python2-dnf >= %{dnf_lowest_compatible} %if 0%{?rhel} && 0%{?rhel} <= 7 -BuildRequires: dbus-python BuildRequires: python-nose %else -BuildRequires: python2-dbus BuildRequires: python2-nose %endif BuildRequires: python2-devel @@ -112,10 +108,8 @@ Requires: python2-distro Requires: python2-dnf >= %{dnf_lowest_compatible} Requires: python2-hawkey >= %{hawkey_version} %if 0%{?rhel} && 0%{?rhel} <= 7 -Requires: dbus-python Requires: python-dateutil %else -Requires: python2-dbus Requires: python2-dateutil %endif Provides: python2-dnf-plugins-extras-debug = %{version}-%{release} @@ -135,8 +129,7 @@ Conflicts: python-%{name} < %{version}-%{release} %description -n python2-%{name} Core Plugins for DNF, Python 2 interface. This package enhances DNF with builddep, config-manager, copr, degug, debuginfo-install, download, needs-restarting, -groups-manager, repoclosure, repograph, repomanage, reposync, changelog -and repodiff commands. +repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. Additionally provides generate_completion_cache passive plugin. %endif @@ -144,14 +137,12 @@ Additionally provides generate_completion_cache passive plugin. %package -n python3-%{name} Summary: Core Plugins for DNF %{?python_provide:%python_provide python3-%{name}} -BuildRequires: python3-dbus BuildRequires: python3-devel BuildRequires: python3-dnf >= %{dnf_lowest_compatible} BuildRequires: python3-nose %if 0%{?fedora} Requires: python3-distro %endif -Requires: python3-dbus Requires: python3-dnf >= %{dnf_lowest_compatible} Requires: python3-hawkey >= %{hawkey_version} Requires: python3-dateutil @@ -172,8 +163,7 @@ Conflicts: python-%{name} < %{version}-%{release} %description -n python3-%{name} Core Plugins for DNF, Python 3 interface. This package enhances DNF with builddep, config-manager, copr, debug, debuginfo-install, download, needs-restarting, -groups-manager, repoclosure, repograph, repomanage, reposync, changelog -and repodiff commands. +repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. Additionally provides generate_completion_cache passive plugin. %endif @@ -200,8 +190,8 @@ Summary: Yum-utils CLI compatibility layer %description -n %{yum_utils_subpackage_name} As a Yum-utils CLI compatibility layer, supplies in CLI shims for debuginfo-install, repograph, package-cleanup, repoclosure, repomanage, -repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug, -download and yum-groups-manager that use new implementations using DNF. +repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug +and download that use new implementations using DNF. %endif %if 0%{?rhel} == 0 && %{with python2} @@ -468,7 +458,6 @@ ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-builddep ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-config-manager ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-dump ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-restore -ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-groups-manager ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yumdownloader # These commands don't have a dedicated man page, so let's just point them # to the utils page which contains their descriptions. @@ -494,7 +483,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{_mandir}/man8/dnf-debuginfo-install.* %{_mandir}/man8/dnf-download.* %{_mandir}/man8/dnf-generate_completion_cache.* -%{_mandir}/man8/dnf-groups-manager.* %{_mandir}/man8/dnf-needs-restarting.* %{_mandir}/man8/dnf-repoclosure.* %{_mandir}/man8/dnf-repodiff.* @@ -525,7 +513,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{python2_sitelib}/dnf-plugins/debuginfo-install.* %{python2_sitelib}/dnf-plugins/download.* %{python2_sitelib}/dnf-plugins/generate_completion_cache.* -%{python2_sitelib}/dnf-plugins/groups_manager.* %{python2_sitelib}/dnf-plugins/needs_restarting.* %{python2_sitelib}/dnf-plugins/repoclosure.* %{python2_sitelib}/dnf-plugins/repodiff.* @@ -551,7 +538,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{python3_sitelib}/dnf-plugins/debuginfo-install.py %{python3_sitelib}/dnf-plugins/download.py %{python3_sitelib}/dnf-plugins/generate_completion_cache.py -%{python3_sitelib}/dnf-plugins/groups_manager.py %{python3_sitelib}/dnf-plugins/needs_restarting.py %{python3_sitelib}/dnf-plugins/repoclosure.py %{python3_sitelib}/dnf-plugins/repodiff.py @@ -566,7 +552,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{python3_sitelib}/dnf-plugins/__pycache__/debuginfo-install.* %{python3_sitelib}/dnf-plugins/__pycache__/download.* %{python3_sitelib}/dnf-plugins/__pycache__/generate_completion_cache.* -%{python3_sitelib}/dnf-plugins/__pycache__/groups_manager.* %{python3_sitelib}/dnf-plugins/__pycache__/needs_restarting.* %{python3_sitelib}/dnf-plugins/__pycache__/repoclosure.* %{python3_sitelib}/dnf-plugins/__pycache__/repodiff.* @@ -594,7 +579,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{_bindir}/yum-config-manager %{_bindir}/yum-debug-dump %{_bindir}/yum-debug-restore -%{_bindir}/yum-groups-manager %{_bindir}/yumdownloader %{_mandir}/man1/debuginfo-install.* %{_mandir}/man1/needs-restarting.* @@ -607,7 +591,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{_mandir}/man1/yum-config-manager.* %{_mandir}/man1/yum-debug-dump.* %{_mandir}/man1/yum-debug-restore.* -%{_mandir}/man1/yum-groups-manager.* %{_mandir}/man1/yumdownloader.* %{_mandir}/man1/package-cleanup.* %{_mandir}/man1/dnf-utils.* @@ -629,7 +612,6 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %exclude %{_mandir}/man1/yum-config-manager.* %exclude %{_mandir}/man1/yum-debug-dump.* %exclude %{_mandir}/man1/yum-debug-restore.* -%exclude %{_mandir}/man1/yum-groups-manager.* %exclude %{_mandir}/man1/yumdownloader.* %exclude %{_mandir}/man1/package-cleanup.* %exclude %{_mandir}/man1/dnf-utils.* diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 3fb665d..dd97eb2 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -26,7 +26,6 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/dnf-builddep.8 ${CMAKE_CURRENT_BINARY_DIR}/dnf-debuginfo-install.8 ${CMAKE_CURRENT_BINARY_DIR}/dnf-download.8 ${CMAKE_CURRENT_BINARY_DIR}/dnf-generate_completion_cache.8 - ${CMAKE_CURRENT_BINARY_DIR}/dnf-groups-manager.8 ${CMAKE_CURRENT_BINARY_DIR}/dnf-leaves.8 ${CMAKE_CURRENT_BINARY_DIR}/dnf-needs-restarting.8 ${CMAKE_CURRENT_BINARY_DIR}/dnf-repoclosure.8 @@ -62,7 +61,6 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/debuginfo-install.1 ${CMAKE_CURRENT_BINARY_DIR}/yum-config-manager.1 ${CMAKE_CURRENT_BINARY_DIR}/yum-debug-dump.1 ${CMAKE_CURRENT_BINARY_DIR}/yum-debug-restore.1 - ${CMAKE_CURRENT_BINARY_DIR}/yum-groups-manager.1 ${CMAKE_CURRENT_BINARY_DIR}/yumdownloader.1 ${CMAKE_CURRENT_BINARY_DIR}/package-cleanup.1 ${CMAKE_CURRENT_BINARY_DIR}/dnf-utils.1 diff --git a/doc/conf.py b/doc/conf.py index 645185a..d760ef3 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -251,7 +251,6 @@ man_pages = [ ('download', 'dnf-download', u'DNF download Plugin', AUTHORS, 8), ('generate_completion_cache', 'dnf-generate_completion_cache', u'DNF generate_completion_cache Plugin', AUTHORS, 8), - ('groups-manager', 'dnf-groups-manager', u'DNF groups-manager Plugin', AUTHORS, 8), ('leaves', 'dnf-leaves', u'DNF leaves Plugin', AUTHORS, 8), ('local', 'dnf-local', u'DNF local Plugin', AUTHORS, 8), ('needs_restarting', 'dnf-needs-restarting', u'DNF needs_restarting Plugin', AUTHORS, 8), @@ -269,7 +268,6 @@ man_pages = [ ('copr', 'yum-copr', u'redirecting to DNF copr Plugin', AUTHORS, 8), ('debuginfo-install', 'debuginfo-install', u'redirecting to DNF debuginfo-install Plugin', AUTHORS, 1), - ('groups-manager', 'yum-groups-manager', u'redirecting to DNF groups-manager Plugin', AUTHORS, 1), ('needs_restarting', 'needs-restarting', u'redirecting to DNF needs-restarting Plugin', AUTHORS, 1), ('repoclosure', 'repoclosure', u'redirecting to DNF repoclosure Plugin', AUTHORS, 1), diff --git a/doc/groups-manager.rst b/doc/groups-manager.rst deleted file mode 100644 index f8f76a1..0000000 --- a/doc/groups-manager.rst +++ /dev/null @@ -1,94 +0,0 @@ -.. - Copyright (C) 2020 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. - -========================= -DNF groups-manager Plugin -========================= - -Create and edit groups repository metadata files. - --------- -Synopsis --------- - -``dnf groups-manager [options] [package-name-spec [package-name-spec ...]]`` - ------------ -Description ------------ -groups-manager plugin is used to create or edit a group metadata file for a repository. This is often much easier than writing/editing the XML by hand. The groups-manager can load an entire file of groups metadata and either create a new group or edit an existing group and then write all of the groups metadata back out. - ---------- -Arguments ---------- - -```` - Package to add to a group or remove from a group. - -------- -Options -------- - -All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for details. - -``--load=`` - Load the groups metadata information from the specified file before performing any operations. Metadata from all files are merged together if the option is specified multiple times. - -``--save=`` - Save the result to this file. You can specify the name of a file you are loading from as the data will only be saved when all the operations have been performed. This option can also be specified multiple times. - -``--merge=`` - This is the same as loading and saving a file, however the "merge" file is loaded before any others and saved last. - -``--print`` - Also print the result to stdout. - -``--id=`` - The id to lookup/use for the group. If you don't specify an ````, but do specify a name that doesn't refer to an existing group, then an id for the group is generated based on the name. - -``-n , --name=`` - The name to lookup/use for the group. If you specify an existing group id, then the group with that id will have it's name changed to this value. - -``--description=`` - The description to use for the group. - -``--display-order=`` - Change the integer which controls the order groups are presented in, for example in ``dnf grouplist``. - -``--translated-name=`` - A translation of the group name in the given language. The syntax is ``lang:text``. Eg. ``en:my-group-name-in-english`` - -``--translated-description=`` - A translation of the group description in the given language. The syntax is ``lang:text``. Eg. ``en:my-group-description-in-english``. - -``--user-visible`` - Make the group visible in ``dnf grouplist`` (this is the default). - -``--not-user-visible`` - Make the group not visible in ``dnf grouplist``. - -``--mandatory`` - Store the package names specified within the mandatory section of the specified group, the default is to use the default section. - -``--optional`` - Store the package names specified within the optional section of the specified group, the default is to use the default section. - -``--remove`` - Instead of adding packages remove them. Note that the packages are removed from all sections (default, mandatory and optional). - -``--dependencies`` - Also include the names of the direct dependencies for each package specified. diff --git a/doc/index.rst b/doc/index.rst index 7213253..91bb36e 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -33,7 +33,6 @@ This documents core plugins of DNF: debuginfo-install download generate_completion_cache - groups-manager leaves local migrate diff --git a/doc/needs_restarting.rst b/doc/needs_restarting.rst index 1a3fbbe..e79b43f 100644 --- a/doc/needs_restarting.rst +++ b/doc/needs_restarting.rst @@ -48,6 +48,3 @@ All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for det ``-r, --reboothint`` Only report whether a reboot is required (exit code 1) or not (exit code 0). - -``-s, --services`` - Only list the affected systemd services. diff --git a/doc/reposync.rst b/doc/reposync.rst index de40957..71a435d 100644 --- a/doc/reposync.rst +++ b/doc/reposync.rst @@ -39,40 +39,36 @@ Options All general DNF options are accepted. Namely, the ``--repoid`` option can be used to specify the repositories to synchronize. See `Options` in :manpage:`dnf(8)` for details. -``-a , --arch=`` - Download only packages of given architectures (default is all architectures). Can be used multiple times. - -``--delete`` - Delete local packages no longer present in repository. +``-p , --download-path=`` + Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path. + +``--norepopath`` + Don't add the reponame to the download path. Can only be used when syncing a single repository (default is to add the reponame). ``--download-metadata`` Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it. -``-g, --gpgcheck`` - Remove packages that fail GPG signature checking after downloading. Exit code is ``1`` if at least one package was removed. - Note that for repositories with ``gpgcheck=0`` set in their configuration the GPG signature is not checked even with this option used. +``-a , --arch=`` + Download only packages of given architectures (default is all architectures). Can be used multiple times. + +``--source`` + Operate on source packages. ``-m, --downloadcomps`` Also download and uncompress comps.xml. Consider using ``--download-metadata`` option which will download all available repository metadata. -``--metadata-path`` - Root path under which the downloaded metadata are stored. It defaults to ``--download-path`` value if not given. - ``-n, --newest-only`` Download only newest packages per-repo. -``--norepopath`` - Don't add the reponame to the download path. Can only be used when syncing a single repository (default is to add the reponame). +``--delete`` + Delete local packages no longer present in repository. -``-p , --download-path=`` - Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path. +``--metadata-path`` + Root path under which the downloaded metadata are stored. It defaults to ``--download-path`` value if not given. ``--remote-time`` Try to set the timestamps of the downloaded files to those on the remote side. -``--source`` - Operate on source packages. - ``-u, --urls`` Just print urls of what would be downloaded, don't download. diff --git a/libexec/dnf-utils.in b/libexec/dnf-utils.in index af1e893..667ce13 100644 --- a/libexec/dnf-utils.in +++ b/libexec/dnf-utils.in @@ -37,7 +37,6 @@ MAPPING = {'debuginfo-install': ['debuginfo-install'], 'yum-config-manager': ['config-manager'], 'yum-debug-dump': ['debug-dump'], 'yum-debug-restore': ['debug-restore'], - 'yum-groups-manager': ['groups-manager'], 'yumdownloader': ['download'] } diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index f66d3df..7465e53 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -6,7 +6,6 @@ INSTALL (FILES config_manager.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) INSTALL (FILES copr.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) INSTALL (FILES download.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) INSTALL (FILES generate_completion_cache.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) -INSTALL (FILES groups_manager.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) INSTALL (FILES leaves.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) if (${WITHOUT_LOCAL} STREQUAL "0") INSTALL (FILES local.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) diff --git a/plugins/groups_manager.py b/plugins/groups_manager.py deleted file mode 100644 index 382df37..0000000 --- a/plugins/groups_manager.py +++ /dev/null @@ -1,314 +0,0 @@ -# groups_manager.py -# DNF plugin for managing comps groups metadata files -# -# Copyright (C) 2020 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 - -import argparse -import gzip -import libcomps -import os -import re -import shutil -import tempfile - -from dnfpluginscore import _, logger -import dnf -import dnf.cli - - -RE_GROUP_ID_VALID = '-a-z0-9_.:' -RE_GROUP_ID = re.compile(r'^[{}]+$'.format(RE_GROUP_ID_VALID)) -RE_LANG = re.compile(r'^[-a-zA-Z0-9_.@]+$') -COMPS_XML_OPTIONS = { - 'default_explicit': True, - 'uservisible_explicit': True, - 'empty_groups': True} - - -def group_id_type(value): - '''group id validator''' - if not RE_GROUP_ID.match(value): - raise argparse.ArgumentTypeError(_('Invalid group id')) - return value - - -def translation_type(value): - '''translated texts validator''' - data = value.split(':', 2) - if len(data) != 2: - raise argparse.ArgumentTypeError( - _("Invalid translated data, should be in form 'lang:text'")) - lang, text = data - if not RE_LANG.match(lang): - raise argparse.ArgumentTypeError(_('Invalid/empty language for translated data')) - return lang, text - - -def text_to_id(text): - '''generate group id based on its name''' - group_id = text.lower() - group_id = re.sub('[^{}]'.format(RE_GROUP_ID_VALID), '', group_id) - if not group_id: - raise dnf.cli.CliError( - _("Can't generate group id from '{}'. Please specify group id using --id.").format( - text)) - return group_id - - -@dnf.plugin.register_command -class GroupsManagerCommand(dnf.cli.Command): - aliases = ('groups-manager',) - summary = _('create and edit groups metadata file') - - def __init__(self, cli): - super(GroupsManagerCommand, self).__init__(cli) - self.comps = libcomps.Comps() - - @staticmethod - def set_argparser(parser): - # input / output options - parser.add_argument('--load', action='append', default=[], - metavar='COMPS.XML', - help=_('load groups metadata from file')) - parser.add_argument('--save', action='append', default=[], - metavar='COMPS.XML', - help=_('save groups metadata to file')) - parser.add_argument('--merge', metavar='COMPS.XML', - help=_('load and save groups metadata to file')) - parser.add_argument('--print', action='store_true', default=False, - help=_('print the result metadata to stdout')) - # group options - parser.add_argument('--id', type=group_id_type, - help=_('group id')) - parser.add_argument('-n', '--name', help=_('group name')) - parser.add_argument('--description', - help=_('group description')) - parser.add_argument('--display-order', type=int, - help=_('group display order')) - parser.add_argument('--translated-name', action='append', default=[], - metavar='LANG:TEXT', type=translation_type, - help=_('translated name for the group')) - parser.add_argument('--translated-description', action='append', default=[], - metavar='LANG:TEXT', type=translation_type, - help=_('translated description for the group')) - visible = parser.add_mutually_exclusive_group() - visible.add_argument('--user-visible', dest='user_visible', action='store_true', - default=None, - help=_('make the group user visible (default)')) - visible.add_argument('--not-user-visible', dest='user_visible', action='store_false', - default=None, - help=_('make the group user invisible')) - - # package list options - section = parser.add_mutually_exclusive_group() - section.add_argument('--mandatory', action='store_true', - help=_('add packages to the mandatory section')) - section.add_argument('--optional', action='store_true', - help=_('add packages to the optional section')) - section.add_argument('--remove', action='store_true', default=False, - help=_('remove packages from the group instead of adding them')) - parser.add_argument('--dependencies', action='store_true', - help=_('include also direct dependencies for packages')) - - parser.add_argument("packages", nargs='*', metavar='PACKAGE', - help=_('package specification')) - - def configure(self): - demands = self.cli.demands - - if self.opts.packages: - demands.sack_activation = True - demands.available_repos = True - demands.load_system_repo = False - - # handle --merge option (shortcut to --load and --save the same file) - if self.opts.merge: - self.opts.load.insert(0, self.opts.merge) - self.opts.save.append(self.opts.merge) - - # check that group is specified when editing is attempted - if (self.opts.description - or self.opts.display_order - or self.opts.translated_name - or self.opts.translated_description - or self.opts.user_visible is not None - or self.opts.packages): - if not self.opts.id and not self.opts.name: - raise dnf.cli.CliError( - _("Can't edit group without specifying it (use --id or --name)")) - - def load_input_files(self): - """ - Loads all input xml files. - Returns True if at least one file was successfuly loaded - """ - for file_name in self.opts.load: - file_comps = libcomps.Comps() - try: - if file_name.endswith('.gz'): - # libcomps does not support gzipped files - decompress to temporary - # location - with gzip.open(file_name) as gz_file: - temp_file = tempfile.NamedTemporaryFile(delete=False) - try: - shutil.copyfileobj(gz_file, temp_file) - # close temp_file to ensure the content is flushed to disk - temp_file.close() - file_comps.fromxml_f(temp_file.name) - finally: - os.unlink(temp_file.name) - else: - file_comps.fromxml_f(file_name) - except (IOError, OSError, libcomps.ParserError) as err: - # gzip module raises OSError on reading from malformed gz file - # get_last_errors() output often contains duplicit lines, remove them - seen = set() - for error in file_comps.get_last_errors(): - if error in seen: - continue - logger.error(error.strip()) - seen.add(error) - raise dnf.exceptions.Error( - _("Can't load file \"{}\": {}").format(file_name, err)) - else: - self.comps += file_comps - - def save_output_files(self): - for file_name in self.opts.save: - try: - # xml_f returns a list of errors / log entries - errors = self.comps.xml_f(file_name, xml_options=COMPS_XML_OPTIONS) - except libcomps.XMLGenError as err: - errors = [err] - if errors: - # xml_f() method could return more than one error. In this case - # raise the latest of them and log the others. - for err in errors[:-1]: - logger.error(err.strip()) - raise dnf.exceptions.Error(_("Can't save file \"{}\": {}").format( - file_name, errors[-1].strip())) - - - def find_group(self, group_id, name): - ''' - Try to find group according to command line parameters - first by id - then by name. - ''' - group = None - if group_id: - for grp in self.comps.groups: - if grp.id == group_id: - group = grp - break - if group is None and name: - for grp in self.comps.groups: - if grp.name == name: - group = grp - break - return group - - def edit_group(self, group): - ''' - Set attributes and package lists for selected group - ''' - def langlist_to_strdict(lst): - str_dict = libcomps.StrDict() - for lang, text in lst: - str_dict[lang] = text - return str_dict - - # set group attributes - if self.opts.name: - group.name = self.opts.name - if self.opts.description: - group.desc = self.opts.description - if self.opts.display_order: - group.display_order = self.opts.display_order - if self.opts.user_visible is not None: - group.uservisible = self.opts.user_visible - if self.opts.translated_name: - group.name_by_lang = langlist_to_strdict(self.opts.translated_name) - if self.opts.translated_description: - group.desc_by_lang = langlist_to_strdict(self.opts.translated_description) - - # edit packages list - if self.opts.packages: - # find packages according to specifications from command line - packages = set() - for pkg_spec in self.opts.packages: - q = self.base.sack.query().filterm(name__glob=pkg_spec).latest() - if not q: - logger.warning(_("No match for argument: {}").format(pkg_spec)) - continue - packages.update(q) - if self.opts.dependencies: - # add packages that provide requirements - requirements = set() - for pkg in packages: - requirements.update(pkg.requires) - packages.update(self.base.sack.query().filterm(provides=requirements)) - - pkg_names = {pkg.name for pkg in packages} - - if self.opts.remove: - for pkg_name in pkg_names: - for pkg in group.packages_match(name=pkg_name, - type=libcomps.PACKAGE_TYPE_UNKNOWN): - group.packages.remove(pkg) - else: - if self.opts.mandatory: - pkg_type = libcomps.PACKAGE_TYPE_MANDATORY - elif self.opts.optional: - pkg_type = libcomps.PACKAGE_TYPE_OPTIONAL - else: - pkg_type = libcomps.PACKAGE_TYPE_DEFAULT - for pkg_name in sorted(pkg_names): - if not group.packages_match(name=pkg_name, type=pkg_type): - group.packages.append(libcomps.Package(name=pkg_name, type=pkg_type)) - - def run(self): - self.load_input_files() - - if self.opts.id or self.opts.name: - # we are adding / editing a group - group = self.find_group(group_id=self.opts.id, name=self.opts.name) - if group is None: - # create a new group - if self.opts.remove: - raise dnf.exceptions.Error(_("Can't remove packages from non-existent group")) - group = libcomps.Group() - if self.opts.id: - group.id = self.opts.id - group.name = self.opts.id - elif self.opts.name: - group_id = text_to_id(self.opts.name) - if self.find_group(group_id=group_id, name=None): - raise dnf.cli.CliError( - _("Group id '{}' generated from '{}' is duplicit. " - "Please specify group id using --id.").format( - group_id, self.opts.name)) - group.id = group_id - self.comps.groups.append(group) - self.edit_group(group) - - self.save_output_files() - if self.opts.print or (not self.opts.save): - print(self.comps.xml_str(xml_options=COMPS_XML_OPTIONS)) diff --git a/plugins/needs_restarting.py b/plugins/needs_restarting.py index f6bf525..69203f4 100644 --- a/plugins/needs_restarting.py +++ b/plugins/needs_restarting.py @@ -29,7 +29,6 @@ from dnfpluginscore import logger, _ import dnf import dnf.cli -import dbus import functools import os import re @@ -127,30 +126,6 @@ def print_cmd(pid): print('%d : %s' % (pid, command)) -def get_service_dbus(pid): - bus = dbus.SystemBus() - systemd_manager_object = bus.get_object( - 'org.freedesktop.systemd1', - '/org/freedesktop/systemd1' - ) - systemd_manager_interface = dbus.Interface( - systemd_manager_object, - 'org.freedesktop.systemd1.Manager' - ) - service_proxy = bus.get_object( - 'org.freedesktop.systemd1', - systemd_manager_interface.GetUnitByPID(pid) - ) - service_properties = dbus.Interface( - service_proxy, dbus_interface="org.freedesktop.DBus.Properties") - name = service_properties.Get( - "org.freedesktop.systemd1.Unit", - 'Id' - ) - if name.endswith(".service"): - return name - return - def smap2opened_file(pid, line): slash = line.find('/') if slash < 0: @@ -230,8 +205,6 @@ class NeedsRestartingCommand(dnf.cli.Command): parser.add_argument('-r', '--reboothint', action='store_true', help=_("only report whether a reboot is required " "(exit code 1) or not (exit code 0)")) - parser.add_argument('-s', '--services', action='store_true', - help=_("only report affected systemd services")) def configure(self): demands = self.cli.demands @@ -278,11 +251,5 @@ class NeedsRestartingCommand(dnf.cli.Command): if pkg.installtime > process_start(ofile.pid): stale_pids.add(ofile.pid) - if self.opts.services: - names = set([get_service_dbus(pid) for pid in sorted(stale_pids)]) - for name in names: - if name is not None: - print(name) - return 0 for pid in sorted(stale_pids): print_cmd(pid) diff --git a/plugins/reposync.py b/plugins/reposync.py index c891bfa..7556e7e 100644 --- a/plugins/reposync.py +++ b/plugins/reposync.py @@ -24,7 +24,6 @@ from __future__ import unicode_literals import hawkey import os import shutil -import types from dnfpluginscore import _, logger from dnf.cli.option_parser import OptionParser @@ -64,27 +63,24 @@ class RepoSyncCommand(dnf.cli.Command): help=_('download only packages for this ARCH')) parser.add_argument('--delete', default=False, action='store_true', help=_('delete local packages no longer present in repository')) - parser.add_argument('--download-metadata', default=False, action='store_true', - help=_('download all the metadata.')) - parser.add_argument('-g', '--gpgcheck', default=False, action='store_true', - help=_('Remove packages that fail GPG signature checking ' - 'after downloading')) parser.add_argument('-m', '--downloadcomps', default=False, action='store_true', help=_('also download and uncompress comps.xml')) - parser.add_argument('--metadata-path', - help=_('where to store downloaded repository metadata. ' - 'Defaults to the value of --download-path.')) + parser.add_argument('--download-metadata', default=False, action='store_true', + help=_('download all the metadata.')) parser.add_argument('-n', '--newest-only', default=False, action='store_true', help=_('download only newest packages per-repo')) - parser.add_argument('--norepopath', default=False, action='store_true', - help=_("Don't add the reponame to the download path.")) parser.add_argument('-p', '--download-path', default='./', help=_('where to store downloaded repositories')) + parser.add_argument('--norepopath', default=False, action='store_true', + help=_("Don't add the reponame to the download path.")) + parser.add_argument('--metadata-path', + help=_('where to store downloaded repository metadata. ' + 'Defaults to the value of --download-path.')) + parser.add_argument('--source', default=False, action='store_true', + help=_('operate on source packages')) parser.add_argument('--remote-time', default=False, action='store_true', help=_('try to set local timestamps of local files by ' 'the one on the server')) - parser.add_argument('--source', default=False, action='store_true', - help=_('operate on source packages')) parser.add_argument('-u', '--urls', default=False, action='store_true', help=_("Just list urls of what would be downloaded, " "don't download")) @@ -118,7 +114,6 @@ class RepoSyncCommand(dnf.cli.Command): def run(self): self.base.conf.keepcache = True - gpgcheck_ok = True for repo in self.base.repos.iter_enabled(): if self.opts.remote_time: repo._repo.setPreserveRemoteTime(True) @@ -155,24 +150,8 @@ class RepoSyncCommand(dnf.cli.Command): self.print_urls(pkglist) else: self.download_packages(pkglist) - if self.opts.gpgcheck: - for pkg in pkglist: - local_path = self.pkg_download_path(pkg) - # base.package_signature_check uses pkg.localPkg() to determine - # the location of the package rpm file on the disk. - # Set it to the correct download path. - pkg.localPkg = types.MethodType( - lambda s, local_path=local_path: local_path, pkg) - result, error = self.base.package_signature_check(pkg) - if result != 0: - logger.warning(_("Removing {}: {}").format( - os.path.basename(local_path), error)) - os.unlink(local_path) - gpgcheck_ok = False if self.opts.delete: self.delete_old_local_packages(repo, pkglist) - if not gpgcheck_ok: - raise dnf.exceptions.Error(_("GPG signature check failed.")) def repo_target(self, repo): return _pkgdir(self.opts.destdir or self.opts.download_path,