diff --git a/AUTHORS b/AUTHORS
index 88003d1..c8ce939 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,6 +1,7 @@
Ales Kozumplik <ales@redhat.com>
Igor Gnatenko <i.gnatenko.brain@gmail.com>
Jan Silhan <jsilhan@redhat.com>
+Michal Mraka <michael.mraka@redhat.com>
Miroslav Suchý <msuchy@redhat.com>
Parag Nemade <pnemade@redhat.com>
Petr Špaček <pspacek@redhat.com>
diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec
new file mode 100644
index 0000000..b9e0a38
--- /dev/null
+++ b/dnf-plugins-core.spec
@@ -0,0 +1,329 @@
+%{?!dnf_version: %global dnf_version 0.6.4}
+
+Name: dnf-plugins-core
+Version: 0.1.5
+Release: 2%{?dist}
+Summary: Core Plugins for DNF
+Group: System Environment/Base
+License: GPLv2+
+URL: https://github.com/rpm-software-management/dnf-plugins-core
+
+# source archive is created by running package/archive from a git checkout
+Source0: dnf-plugins-core-%{version}.tar.gz
+
+BuildArch: noarch
+BuildRequires: cmake
+BuildRequires: dnf = %{dnf_version}
+BuildRequires: gettext
+BuildRequires: pykickstart
+BuildRequires: python-nose
+BuildRequires: python-sphinx
+BuildRequires: python2-devel
+Requires: dnf = %{dnf_version}
+Requires: pykickstart
+Requires: python-requests
+
+%description
+Core Plugins for DNF. This package enhance DNF with builddep, config-manager,
+copr, debuginfo-install, download, kickstart, needs-restarting, repoquery and
+reposync commands. Additionally provides generate_completion_cache, noroot and
+protected_packages passive plugins.
+
+%package -n python3-dnf-plugins-core
+Summary: Core Plugins for DNF
+Group: System Environment/Base
+BuildRequires: python3-devel
+BuildRequires: python3-dnf = %{dnf_version}
+BuildRequires: python3-nose
+BuildRequires: python3-sphinx
+Requires: python3-dnf = %{dnf_version}
+
+%description -n python3-dnf-plugins-core
+Core Plugins for DNF, Python 3 version. This package enhance DNF with builddep,
+config-manager, copr, debuginfo-install, download, kickstart, needs-restarting,
+repoquery and reposync commands. Additionally provides generate_completion_cache,
+noroot and protected_packages passive plugins.
+
+%prep
+%setup -q -n dnf-plugins-core-%{version}
+rm -rf py3
+mkdir ../py3
+cp -a . ../py3/
+mv ../py3 ./
+
+%build
+%cmake .
+make %{?_smp_mflags}
+make doc-man
+pushd py3
+%cmake -DPYTHON_DESIRED:str=3 .
+make %{?_smp_mflags}
+make doc-man
+popd
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+%find_lang %{name}
+pushd py3
+make install DESTDIR=$RPM_BUILD_ROOT
+popd
+
+%check
+PYTHONPATH=./plugins /usr/bin/nosetests-2.* -s tests/
+PYTHONPATH=./plugins /usr/bin/nosetests-3.* -s tests/
+
+%files -f %{name}.lang
+%doc AUTHORS COPYING README.rst
+%dir %{_sysconfdir}/dnf/protected.d
+%ghost %{_var}/cache/dnf/packages.db
+%{python_sitelib}/dnf-plugins/*
+%{python_sitelib}/dnfpluginscore/
+%{_mandir}/man8/dnf.plugin.*
+
+%files -n python3-dnf-plugins-core -f %{name}.lang
+%doc AUTHORS COPYING README.rst
+%dir %{_sysconfdir}/dnf/protected.d
+%ghost %{_var}/cache/dnf/packages.db
+%exclude %{python3_sitelib}/dnf-plugins/__pycache__/
+%{python3_sitelib}/dnf-plugins/*
+%{python3_sitelib}/dnf-plugins/__pycache__/*
+%{python3_sitelib}/dnfpluginscore/
+%{_mandir}/man8/dnf.plugin.*
+
+%changelog
+* Mon Apr 13 2015 Michal Luscon <mluscon@redhat.com> 0.1.5-2
+- prepare repo for tito build system (Michal Luscon)
+- migrate raw_input() to Python3 (RhBug:1208399) (Miroslav Suchý)
+- create --destdir if not exist (Michael Mraka)
+- repoquery: Added -s/--source switch, test case and documentation for querying source rpm name (Parag Nemade)
+- repoquery: Added documentation and test case for file switch (Parag Nemade)
+- debuginfo-install: support cases where src.rpm name != binary package name (Petr Spacek)
+- use dnfpluginscore.lib.urlopen() (RhBug:1193047) (Miroslav Suchý)
+- implemented functionality of yum-config-manager (Michael Mraka)
+- repoquery: Added --file switch to show who owns the given file (RhBug:1196952) (Parag Nemade)
+- debuginfo-install: accept packages names specified as NEVRA (RhBug:1171046) (Petr Spacek)
+- repoquery: accept package names specified as NEVRA (RhBug:1179366) (Petr Spacek)
+- download: fix typo in 'No source rpm definded' (Petr Spacek)
+- download: accept package names ending with .src too (Petr Spacek)
+- cosmetic: download: pylint fixes (Jan Silhan)
+- download: Do not disable user-enabled repos (thanks Spacekpe) (Jan Silhan)
+- let pylint ignore unused variables starting with _ (Michael Mraka)
+- updated copyright (Michael Mraka)
+- fixed pylint warning Redefining name from outer scope (Michael Mraka)
+- fixed pylint warning Invalid constant name (Michael Mraka)
+- fixed pylint warnings Line too long (Michael Mraka)
+- pylint fix for Wrong continued indentation (Michael Mraka)
+- updated copyright (Michael Mraka)
+- pylint fix for Specify string format arguments as logging function parameters (Michael Mraka)
+- pylint fix for Method could be a function (Michael Mraka)
+- pylint fix for __init__ method from base class is not called (Michael Mraka)
+- pylint fix for Attribute defined outside __init__ (Michael Mraka)
+- updated copyright (Michael Mraka)
+- pylint fix for __init__ method from base class is not called (Michael Mraka)
+- pylint fix for Wrong continued indentation (Michael Mraka)
+- updated copyright (Michael Mraka)
+- pylint fix for Method could be a function (Michael Mraka)
+- pylint fix for __init__ method from base class is not called (Michael Mraka)
+- updated copyright (Michael Mraka)
+- pylint fix for Unused import (Michael Mraka)
+- pylint fix for __init__ method from base class is not called (Michael Mraka)
+- updated copyright (Michael Mraka)
+- pylint fix for Unused import (Michael Mraka)
+- Add README to tests/ directory (Petr Spacek)
+- AUTHORS: updated (Jan Silhan)
+- download: fix package download on Python 3 (Petr Spacek)
+
+* Thu Feb 5 2015 Jan Silhan <jsilhan@redhat.com> - 0.1.5-1
+- updated package url (Michael Mraka)
+- also dnf_version could be specified on rpmbuild commandline (Michael Mraka)
+- simple script to build test package (Michael Mraka)
+- let gitrev be specified on rpmbuild commandline (Michael Mraka)
+- assign default GITREV value (Michael Mraka)
+- standard way to find out latest commit (Michael Mraka)
+- debuginfo-install: fix handling of subpackages with non-zero epoch (Petr Spacek)
+- debuginfo-install: Make laywers happier by assigning copyright to Red Hat (Petr Spacek)
+- debuginfo-install: remove dead code uncovered by variable renaming (Petr Spacek)
+- debuginfo-install: clearly separate source and debug package names (Petr Spacek)
+- debuginfo-install: use descriptive parameter name in _is_available() (Petr Spacek)
+- repoquery: add -l option to list files contained in the package (Petr Spacek)
+- 1187773 - replace undefined variable (Miroslav Suchý)
+- download: fixed unicode location error (RhBug:1178239) (Jan Silhan)
+- builddep recognizes nosrc.rpm pkgs (RhBug:1166126) (Jan Silhan)
+- builddep: added nosignatures flag to rpm transaction set (Jan Silhan)
+- builddep: more verbose output of non-matching packages (RhBug:1155211) (Jan Silhan)
+- package: archive script is the same as in dnf (Jan Silhan)
+- spec: exclude __pycache__ dir (Igor Gnatenko)
+
+* Fri Dec 5 2014 Jan Silhan <jsilhan@redhat.com> - 0.1.4-1
+- revert of commit 80ae3f4 (Jan Silhan)
+- transifex update (Jan Silhan)
+- spec: binded to current dnf version (Jan Silhan)
+- generate_completion_cache: use sqlite instead of text files (Igor Gnatenko)
+- logging: renamed log file (Related:RhBug:1074715) (Jan Silhan)
+- Add reposync. (RhBug:1139738) (Ales Kozumplik)
+- download: fix traceback if rpm package has no defined sourcerpm (RhBug: 1144003) (Tim Lauridsen)
+- lint: ignore warnings of a test accessing protected attribute. (Ales Kozumplik)
+- repoquery lint: logger is not used. (Ales Kozumplik)
+- repoquery: support querying of weak deps. (Ales Kozumplik)
+- needs_restarting: fix typo (Miroslav Suchý)
+- copr: migrate copr plugin form urlgrabber to python-request (Miroslav Suchý)
+- Add needs-restarting command. (Ales Kozumplik)
+
+* Thu Sep 4 2014 Jan Silhan <jsilhan@redhat.com> - 0.1.3-1
+- repoquery: output times in UTC. (Ales Kozumplik)
+- repoquery: missing help messages. (Ales Kozumplik)
+- repoquery: add --info. (RhBug:1135984) (Ales Kozumplik)
+- add Jan to AUTHORS. (Ales Kozumplik)
+- spec: extended package description with plugin names and commands (Related:RhBug:1132335) (Jan Silhan)
+- copr: check for 'ok' in 'output' for json data (RhBug:1134378) (Igor Gnatenko)
+- README: changed references to new repo location (Jan Silhan)
+- transifex update (Jan Silhan)
+- copr: convert key to unicode before guessing lenght (Miroslav Suchý)
+- Add pnemade to AUTHORS (Ales Kozumplik)
+- debuginfo-install: Use logger as module level variable and not instance attribute since dnf-0.6.0 release (RhBug:1130559) (Parag Nemade)
+- copr: Use logger as module level variable and not instance attribute since dnf-0.6.0 release (RhBug:1130559) (Parag Nemade)
+- copr: implement help command (Igor Gnatenko)
+- debuginfo-install: fix indenting (Igor Gnatenko)
+- debuginfo-install: use srpm basename for debuginfo (Igor Gnatenko)
+
+* Mon Jul 28 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.2-1
+- BashCompletionCache: error strings are unicoded (RhBug:1118809) (Jan Silhan)
+- transifex update (Jan Silhan)
+- debuginfo-install: remove some pylint warnings (Igor Gnatenko)
+- debuginfo-install: fix installing when installed version not found in repos, optimize performance (RhBug: 1108321) (Ig
+- fix: copr plugin message for repo without builds (RhBug:1116389) (Adam Samalik)
+- logging: remove messages about initialization. (Ales Kozumplik)
+
+* Thu Jul 3 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.1-2
+- packaging: add protected_packages.py to the package. (Ales Kozumplik)
+
+* Thu Jul 3 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.1-1
+- protected_packages: prevent removal of the running kernel. (RhBug:1049310) (Ales Kozumplik)
+- packaging: create and own /etc/dnf/protected.d. (Ales Kozumplik)
+- doc: add documentation for protected_packages. (Ales Kozumplik)
+- doc: rename: generate-completion-cache -> generate_completion_cache. (Ales Kozumplik)
+- add protected_packages (RhBug:1111855) (Ales Kozumplik)
+- build: add python-requests to requires (RHBZ: 1104088) (Miroslav Suchý)
+- doc: typo: fix double 'plugin' in release notes. (Ales Kozumplik)
+
+* Wed Jun 4 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.0-1
+- pylint: fix all pylint builddep problems. (Ales Kozumplik)
+- builddep: better error reporting on deps that actually don't exist. (Ales Kozumplik)
+- builddep: load available repos. (RhBug:1103906) (Ales Kozumplik)
+- tests: stop argparse from printing to stdout when tests run. (Ales Kozumplik)
+- packaging: all the manual pages with a glob. (Ales Kozumplik)
+- fix: packaging problem with query.py. (Ales Kozumplik)
+- doc: add reference documentation for repoquery. (Ales Kozumplik)
+- repoquery: support --provides, --requires etc. (Ales Kozumplik)
+- repoquery: make the CLI more compatible with Yum's repoquery. (Ales Kozumplik)
+- repoquery: some cleanups in the plugin and the tests. (Ales Kozumplik)
+- rename: query->repoquery. (RhBug:1045078) (Ales Kozumplik)
+- add pylint script for dnf-core-plugins. (Ales Kozumplik)
+- tests: repoquery: fix unit tests. (Ales Kozumplik)
+- add query tool (Tim Lauridsen)
+
+* Wed May 28 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.8-1
+- build: add sphinx to build requires. (Ales Kozumplik)
+- doc: packaging: add license block to each .rst. (Ales Kozumplik)
+- tests: stray print() in test_download.py. (Ales Kozumplik)
+- doc: put each synopsis on new line (Miroslav Suchý)
+- doc: cosmetic: project name in the documentation. (Ales Kozumplik)
+- doc: cleanups, form, style. (Ales Kozumplik)
+- doc: add documentation and man pages (Tim Lauridsen)
+- copr: remove repofile if failed to enable repo (Igor Gnatenko)
+- copr: honor -y and --assumeno (Miroslav Suchý)
+- py3: absolute imports and unicode literals everywhere. (Ales Kozumplik)
+- debuginfo-install: doesn't install latest pkgs (RhBug: 1096507) (Igor Gnatenko)
+- debuginfo-install: fix description (Igor Gnatenko)
+- debuginfo-install: fix logger debug messages (Igor Gnatenko)
+- build: install the download plugin (Tim Lauridsen)
+- download: update the download plugin with --source, --destdir & --resolve options (Tim Lauridsen)
+- Add a special ArgumentParser to parsing plugin cmd arguments and options (Tim Lauridsen)
+- tests: add __init__.py to make tests a module and use abs imports (Tim Lauridsen)
+- build: simplify plugins/CMakeLists.txt. (Ales Kozumplik)
+- dnf.cli.commands.err_mini_usage() changed name. (Ales Kozumplik)
+- kickstart: do not include kickstart errors into own messages. (Radek Holy)
+
+* Wed Apr 23 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.7-1
+- build: gettext is also needed as a buildreq (Tim Lauridsen)
+- copr: use usage & summary class attributes, to work with dnf 0.5.0 use shared lib dnfpluginscore for translation wrapp
+- build: add cmake as buildreq (Tim Lauridsen)
+- generate-completion-cache: fix shared lib name (Tim Lauridsen)
+- make .spec use gitrev in the source file add helper script for building source archive (Tim Lauridsen)
+- Added transifex config (Tim Lauridsen)
+- tests: use cli logger in kickstart test (Tim Lauridsen)
+- Added translation .pot file Added da translation files so we have something to build & install (Tim Lauridsen)
+- Added CMake files Added CMake build to .spec & and added translation files handling (Tim Lauridsen)
+- make plugins use shared lib added translation wrappers added missing usage & summary PEP8 fixes (Tim Lauridsen)
+- added shared dnfpluginscore lib (Tim Lauridsen)
+- copr: C:139, 0: Unnecessary parens after 'print' keyword (superfluous-parens) (Miroslav Suchý)
+- copr: W: 23, 0: Unused import gettext (unused-import) (Miroslav Suchý)
+- copr: C: 33, 0: No space allowed before : (Miroslav Suchý)
+- copr: some python3 migration (Miroslav Suchý)
+- copr: get rid of dnf i18n imports (Miroslav Suchý)
+- remove dnf.yum.i18n imports. (Ales Kozumplik)
+- copr: Fix the playground upgrade command. (Tadej Janež)
+- copr: implement search function (Igor Gnatenko)
+- better format output (Miroslav Suchý)
+- implement playground plugin (Miroslav Suchý)
+- move removing of repo into method (Miroslav Suchý)
+- check root only for actions which really need root (Miroslav Suchý)
+- move repo downloading into separate method (Miroslav Suchý)
+- define copr url as class attribute (Miroslav Suchý)
+- better wording of warning (Miroslav Suchý)
+- move question to function argument (Miroslav Suchý)
+- move guessing chroot into function (Miroslav Suchý)
+- copr: use common lib use Command.usage & summary cleanup imports & PEP8 fixes (Tim Lauridsen)
+- builddep: added usage & summary & fix some PEP8 issues (Tim Lauridsen)
+- kickstart: use new public Command.usage & Command.summary api (Tim Lauridsen)
+- fix resource leak in builddep.py. (Ales Kozumplik)
+- refactor: command plugins use demands mechanism. (Ales Kozumplik)
+- noroot: move to the new 'demands' mechanism to check the need of root. (Ales Kozumplik)
+- tests: fix locale independence. (Radek Holy)
+- [copr] correctly specify chroot when it should be guessed (Miroslav Suchý)
+
+* Mon Mar 17 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.6-1
+- clenaup: remove commented out code (Miroslav Suchý)
+- copr: list: print description (Igor Gnatenko)
+- builddep: rpm error messages sink. (Ales Kozumplik)
+- builddep: improve error handling on an command argument (RhBug:1074436) (Ales Kozumplik)
+- copr: handling case when no argument is passed on cli (Miroslav Suchý)
+- copr: delete excess argument (Igor Gnatenko)
+- add copr plugin (Miroslav Suchý)
+- debuginfo-install: check for root with dnf api (Igor Gnatenko)
+- packaging: fix bogus dates. (Ales Kozumplik)
+
+* Wed Feb 26 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.5-2
+- packaging: add debuginfo-install.py (Ales Kozumplik)
+
+* Wed Feb 26 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.5-1
+- packaging: add builddep.py to the RPM. (Ales Kozumplik)
+
+* Tue Feb 25 2014 Radek Holý <rholy@redhat.com> - 0.0.4-1
+- refactor: use Base.install instead of installPkgs in kickstart plugin. (Radek Holy)
+- refactor: move kickstart arguments parsing to standalone method. (Radek Holy)
+- tests: test effects instead of mock calls. (Radek Holy)
+- Add debuginfo-install plugin. (RhBug:1045770) (Igor Gnatenko)
+- builddep: needs to be run under root. (RhBug:1065851) (Ales Kozumplik)
+
+* Thu Feb 6 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.3-1
+- tests: import mock through support so its simpler for the test cases. (Ales Kozumplik)
+- packaging: fix typos in the spec. (Ales Kozumplik)
+- [completion_cache] Cache installed packages, update the cache less frequently (Elad Alfassa)
+- Add bash completion to dnf (Elad Alfassa)
+- packaging: missing buildrequire (Ales Kozumplik)
+
+* Mon Jan 13 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.2-1
+- First release.
+
+* Wed Jan 8 2014 Cristian Ciupitu <cristian.ciupitu@yahoo.com> - 0.0.1-4
+- Spec updates.
+
+* Tue Jan 7 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.1-3
+- Spec updates.
+
+* Mon Jan 6 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.1-2
+- Spec updates.
+
+* Fri Dec 20 2013 Aleš Kozumplík <ales@redhat.com> - 0.0.1-1
+- The initial package version.
diff --git a/doc/conf.py b/doc/conf.py
index f2741a4..f1976ae 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -56,7 +56,7 @@ copyright = u'2014, Red Hat, Licensed under GPLv2+'
# The short X.Y version.
def version_readout():
- fn = os.path.join(_dirname, '../package/dnf-plugins-core.spec')
+ fn = os.path.join(_dirname, '../dnf-plugins-core.spec')
with open(fn) as f:
lines = f.readlines()
for line in lines:
@@ -242,6 +242,8 @@ AUTHORS=[u'See AUTHORS in your Core DNF Plugins distribution']
man_pages = [
('builddep', 'dnf.plugin.builddep', u'DNF builddep Plugin',
AUTHORS, 8),
+ ('config_manager', 'dnf.plugin.config_manager',
+ u'DNF config-manager Plugin', AUTHORS, 8),
('copr', 'dnf.plugin.copr', u'DNF copr Plugin',
AUTHORS, 8),
('debuginfo-install', 'dnf.plugin.debuginfo-install',
diff --git a/doc/config_manager.rst b/doc/config_manager.rst
new file mode 100644
index 0000000..cdfbf2d
--- /dev/null
+++ b/doc/config_manager.rst
@@ -0,0 +1,79 @@
+..
+ Copyright (C) 2015 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 config-manager Plugin
+==========================
+
+Manage main DNF configuration options, toggle which
+repositories are enabled or disabled, and add new repositories.
+
+--------
+Synopsis
+--------
+
+``dnf config-manager [options] <repo>...``
+
+---------
+Arguments
+---------
+
+``<repo>``
+ Display / modify specified repository. If not specified display / modify main DNF configuration.
+
+-------
+Options
+-------
+
+``--help-cmd``
+ Show this help.
+
+``--add-repo=URL``
+ Add (and enable) the repo from the specified file or url.
+
+``--dump``
+ Print dump of current configuration values to stdout.
+
+``--set-disabled``
+ Disable the specified repos (automatically saves).
+
+``--set-enabled``
+ Enable the specified repos (automatically saves).
+
+``--save``
+ Save the current options (useful with --setopt).
+
+--------
+Examples
+--------
+``dnf config-manager --add-repo http://example.com/some/additional.repo``
+ Download additional.repo and store it in repodir.
+
+``dnf config-manager --add-repo http://example.com/different/repo``
+ Create new repo file with http://example.com/different/repo as baseurl and enable it.
+
+``dnf config-manager``
+ Display main DNF configuration.
+
+``dnf config-manager repo``
+ Display configuration of repo.
+
+``dnf config-manager --set-enabled repo``
+ Enable repo and make the change permanent.
+
+``dnf config-manager --setopt proxy=http://proxy.example.com:3128/ repo1 repo2 --save``
+ Update proxy setting in repo1 and repo2 and make the change permanent.
diff --git a/doc/download.rst b/doc/download.rst
index d4653d8..9a24b42 100644
--- a/doc/download.rst
+++ b/doc/download.rst
@@ -42,7 +42,7 @@ Options
Show this help.
``--source``
- Download the source rpm.
+ Download the source rpm. Enables source repositories of all enabled binary repositories.
``--destdir``
Download directory, default is the current directory (the directory must exist).
diff --git a/doc/index.rst b/doc/index.rst
index e1ee869..3c5b459 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -26,6 +26,7 @@ This documents core plugins of DNF:
release_notes
builddep
+ config_manager
copr
debuginfo-install
download
diff --git a/doc/repoquery.rst b/doc/repoquery.rst
index 99a8eb7..e14f3ba 100644
--- a/doc/repoquery.rst
+++ b/doc/repoquery.rst
@@ -25,7 +25,7 @@ Query package information from Yum repositories.
Synopsis
--------
-``dnf repoquery [<select-options>] [<query-options>] [<pkg-name>]``
+``dnf repoquery [<select-options>] [<query-options>] [<pkg-spec>]``
``dnf repoquery --querytags``
-----------
@@ -38,11 +38,18 @@ Description
Select Options
--------------
-Together with ``<pkg-name>``, control what packages are displayed in the output. If ``<pkg-name>`` is given, the set of resulting packages is limited to the ones with a matching name (globbing supported), else all packages are considered.
+Together with ``<pkg-spec>``, control what packages are displayed in the output. If ``<pkg-spec>`` is given, the set of resulting packages matching the specification. All packages are considered if no ``<pkg-spec>`` is specified.
+
+``<pkg-spec>``
+ Package specification like: name[-[epoch:]version[-release]][.arch]. See
+ http://dnf.readthedocs.org/en/latest/command_ref.html#specifying-packages
``--arch <arch>``
Limit the resulting set only to packages of arch ``<arch>``.
+``-f <file>``, ``--file <file>``
+ Limit the resulting set only to package that owns ``<file>``.
+
``--repoid <id>``
Limit the resulting set only to packages from repo identified by ``<id>``.
@@ -71,6 +78,9 @@ The following are mutually exclusive, i.e. at most one can be specified. If no q
``-l, --list``
Show list of files in the package.
+``-s, --source``
+ Show package source RPM name.
+
``--obsoletes``
Display capabilities that the package obsoletes. Same as ``--qf "%{obsoletes}``.
@@ -96,6 +106,14 @@ Display requires of all ligttpd packages::
dnf repoquery --requires lighttpd
+Display source rpm of ligttpd package::
+
+ dnf repoquery --source lighttpd
+
+Display package name that owns the given file::
+
+ dnf repoquery --file /etc/lighttpd/lighttpd.conf
+
Display name, architecture and the containing repository of all lighttpd packages::
dnf repoquery --queryformat '%{name}.%{arch} : %{reponame}' lighttpd
diff --git a/package/archive b/package/archive
deleted file mode 100755
index 16f652e..0000000
--- a/package/archive
+++ /dev/null
@@ -1,11 +0,0 @@
-#! /bin/bash
-
-GITREV=${1:-$(git rev-parse --short HEAD)}
-# shorten to 7 characters
-GITREV=${GITREV:0:7}
-
-echo $GITREV
-
-TARGET_DIR=$HOME/rpmbuild/SOURCES
-mkdir -p $TARGET_DIR
-git archive ${GITREV} --prefix=dnf-plugins-core/ | xz > $TARGET_DIR/dnf-plugins-core-${GITREV}.tar.xz
diff --git a/package/build-test-rpm b/package/build-test-rpm
deleted file mode 100755
index 2241c8c..0000000
--- a/package/build-test-rpm
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-DIR=$(dirname "$0")
-GITREV=${1:-$(git rev-parse --short HEAD)}
-# shorten long SHA1 from user to 7 characters
-GITREV=${GITREV:0:7}
-
-$DIR/archive "$GITREV"
-rpmbuild -ba --define "gitrev $GITREV" $DIR/*.spec
diff --git a/package/dnf-plugins-core.spec b/package/dnf-plugins-core.spec
deleted file mode 100644
index ac288a7..0000000
--- a/package/dnf-plugins-core.spec
+++ /dev/null
@@ -1,268 +0,0 @@
-%{!?gitrev: %global gitrev c8940d0}
-%{?!dnf_version: %global dnf_version 0.6.3}
-
-Name: dnf-plugins-core
-Version: 0.1.5
-Release: 1%{?dist}
-Summary: Core Plugins for DNF
-Group: System Environment/Base
-License: GPLv2+
-URL: https://github.com/rpm-software-management/dnf-plugins-core
-
-# source archive is created by running package/archive from a git checkout
-Source0: dnf-plugins-core-%{gitrev}.tar.xz
-
-BuildArch: noarch
-BuildRequires: cmake
-BuildRequires: dnf = %{dnf_version}
-BuildRequires: gettext
-BuildRequires: pykickstart
-BuildRequires: python-nose
-BuildRequires: python-sphinx
-BuildRequires: python2-devel
-Requires: dnf = %{dnf_version}
-Requires: pykickstart
-Requires: python-requests
-
-%description
-Core Plugins for DNF. This package enhance DNF with builddep, copr,
-debuginfo-install, download, kickstart, needs-restarting, repoquery and
-reposync commands. Additionally provides generate_completion_cache, noroot and
-protected_packages passive plugins.
-
-%package -n python3-dnf-plugins-core
-Summary: Core Plugins for DNF
-Group: System Environment/Base
-BuildRequires: python3-devel
-BuildRequires: python3-dnf = %{dnf_version}
-BuildRequires: python3-nose
-BuildRequires: python3-sphinx
-Requires: python3-dnf = %{dnf_version}
-
-%description -n python3-dnf-plugins-core
-Core Plugins for DNF, Python 3 version. This package enhance DNF with builddep, copr,
-debuginfo-install, download, kickstart, needs-restarting, repoquery and
-reposync commands. Additionally provides generate_completion_cache, noroot and
-protected_packages passive plugins.
-
-%prep
-%setup -q -n dnf-plugins-core
-rm -rf py3
-mkdir ../py3
-cp -a . ../py3/
-mv ../py3 ./
-
-%build
-%cmake .
-make %{?_smp_mflags}
-make doc-man
-pushd py3
-%cmake -DPYTHON_DESIRED:str=3 .
-make %{?_smp_mflags}
-make doc-man
-popd
-
-%install
-make install DESTDIR=$RPM_BUILD_ROOT
-%find_lang %{name}
-pushd py3
-make install DESTDIR=$RPM_BUILD_ROOT
-popd
-
-%check
-PYTHONPATH=./plugins /usr/bin/nosetests-2.* -s tests/
-PYTHONPATH=./plugins /usr/bin/nosetests-3.* -s tests/
-
-%files -f %{name}.lang
-%doc AUTHORS COPYING README.rst
-%dir %{_sysconfdir}/dnf/protected.d
-%ghost %{_var}/cache/dnf/packages.db
-%{python_sitelib}/dnf-plugins/*
-%{python_sitelib}/dnfpluginscore/
-%{_mandir}/man8/dnf.plugin.*
-
-%files -n python3-dnf-plugins-core -f %{name}.lang
-%doc AUTHORS COPYING README.rst
-%dir %{_sysconfdir}/dnf/protected.d
-%ghost %{_var}/cache/dnf/packages.db
-%exclude %{python3_sitelib}/dnf-plugins/__pycache__/
-%{python3_sitelib}/dnf-plugins/*
-%{python3_sitelib}/dnf-plugins/__pycache__/*
-%{python3_sitelib}/dnfpluginscore/
-%{_mandir}/man8/dnf.plugin.*
-
-%changelog
-
-* Fri Dec 5 2014 Jan Silhan <jsilhan@redhat.com> - 0.1.4-1
-- revert of commit 80ae3f4 (Jan Silhan)
-- transifex update (Jan Silhan)
-- spec: binded to current dnf version (Jan Silhan)
-- generate_completion_cache: use sqlite instead of text files (Igor Gnatenko)
-- logging: renamed log file (Related:RhBug:1074715) (Jan Silhan)
-- Add reposync. (RhBug:1139738) (Ales Kozumplik)
-- download: fix traceback if rpm package has no defined sourcerpm (RhBug: 1144003) (Tim Lauridsen)
-- lint: ignore warnings of a test accessing protected attribute. (Ales Kozumplik)
-- repoquery lint: logger is not used. (Ales Kozumplik)
-- repoquery: support querying of weak deps. (Ales Kozumplik)
-- needs_restarting: fix typo (Miroslav Suchý)
-- copr: migrate copr plugin form urlgrabber to python-request (Miroslav Suchý)
-- Add needs-restarting command. (Ales Kozumplik)
-
-* Thu Sep 4 2014 Jan Silhan <jsilhan@redhat.com> - 0.1.3-1
-- repoquery: output times in UTC. (Ales Kozumplik)
-- repoquery: missing help messages. (Ales Kozumplik)
-- repoquery: add --info. (RhBug:1135984) (Ales Kozumplik)
-- add Jan to AUTHORS. (Ales Kozumplik)
-- spec: extended package description with plugin names and commands (Related:RhBug:1132335) (Jan Silhan)
-- copr: check for 'ok' in 'output' for json data (RhBug:1134378) (Igor Gnatenko)
-- README: changed references to new repo location (Jan Silhan)
-- transifex update (Jan Silhan)
-- copr: convert key to unicode before guessing lenght (Miroslav Suchý)
-- Add pnemade to AUTHORS (Ales Kozumplik)
-- debuginfo-install: Use logger as module level variable and not instance attribute since dnf-0.6.0 release (RhBug:1130559) (Parag Nemade)
-- copr: Use logger as module level variable and not instance attribute since dnf-0.6.0 release (RhBug:1130559) (Parag Nemade)
-- copr: implement help command (Igor Gnatenko)
-- debuginfo-install: fix indenting (Igor Gnatenko)
-- debuginfo-install: use srpm basename for debuginfo (Igor Gnatenko)
-
-* Mon Jul 28 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.2-1
-- BashCompletionCache: error strings are unicoded (RhBug:1118809) (Jan Silhan)
-- transifex update (Jan Silhan)
-- debuginfo-install: remove some pylint warnings (Igor Gnatenko)
-- debuginfo-install: fix installing when installed version not found in repos, optimize performance (RhBug: 1108321) (Ig
-- fix: copr plugin message for repo without builds (RhBug:1116389) (Adam Samalik)
-- logging: remove messages about initialization. (Ales Kozumplik)
-
-* Thu Jul 3 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.1-2
-- packaging: add protected_packages.py to the package. (Ales Kozumplik)
-
-* Thu Jul 3 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.1-1
-- protected_packages: prevent removal of the running kernel. (RhBug:1049310) (Ales Kozumplik)
-- packaging: create and own /etc/dnf/protected.d. (Ales Kozumplik)
-- doc: add documentation for protected_packages. (Ales Kozumplik)
-- doc: rename: generate-completion-cache -> generate_completion_cache. (Ales Kozumplik)
-- add protected_packages (RhBug:1111855) (Ales Kozumplik)
-- build: add python-requests to requires (RHBZ: 1104088) (Miroslav Suchý)
-- doc: typo: fix double 'plugin' in release notes. (Ales Kozumplik)
-
-* Wed Jun 4 2014 Aleš Kozumplík <ales@redhat.com> - 0.1.0-1
-- pylint: fix all pylint builddep problems. (Ales Kozumplik)
-- builddep: better error reporting on deps that actually don't exist. (Ales Kozumplik)
-- builddep: load available repos. (RhBug:1103906) (Ales Kozumplik)
-- tests: stop argparse from printing to stdout when tests run. (Ales Kozumplik)
-- packaging: all the manual pages with a glob. (Ales Kozumplik)
-- fix: packaging problem with query.py. (Ales Kozumplik)
-- doc: add reference documentation for repoquery. (Ales Kozumplik)
-- repoquery: support --provides, --requires etc. (Ales Kozumplik)
-- repoquery: make the CLI more compatible with Yum's repoquery. (Ales Kozumplik)
-- repoquery: some cleanups in the plugin and the tests. (Ales Kozumplik)
-- rename: query->repoquery. (RhBug:1045078) (Ales Kozumplik)
-- add pylint script for dnf-core-plugins. (Ales Kozumplik)
-- tests: repoquery: fix unit tests. (Ales Kozumplik)
-- add query tool (Tim Lauridsen)
-
-* Wed May 28 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.8-1
-- build: add sphinx to build requires. (Ales Kozumplik)
-- doc: packaging: add license block to each .rst. (Ales Kozumplik)
-- tests: stray print() in test_download.py. (Ales Kozumplik)
-- doc: put each synopsis on new line (Miroslav Suchý)
-- doc: cosmetic: project name in the documentation. (Ales Kozumplik)
-- doc: cleanups, form, style. (Ales Kozumplik)
-- doc: add documentation and man pages (Tim Lauridsen)
-- copr: remove repofile if failed to enable repo (Igor Gnatenko)
-- copr: honor -y and --assumeno (Miroslav Suchý)
-- py3: absolute imports and unicode literals everywhere. (Ales Kozumplik)
-- debuginfo-install: doesn't install latest pkgs (RhBug: 1096507) (Igor Gnatenko)
-- debuginfo-install: fix description (Igor Gnatenko)
-- debuginfo-install: fix logger debug messages (Igor Gnatenko)
-- build: install the download plugin (Tim Lauridsen)
-- download: update the download plugin with --source, --destdir & --resolve options (Tim Lauridsen)
-- Add a special ArgumentParser to parsing plugin cmd arguments and options (Tim Lauridsen)
-- tests: add __init__.py to make tests a module and use abs imports (Tim Lauridsen)
-- build: simplify plugins/CMakeLists.txt. (Ales Kozumplik)
-- dnf.cli.commands.err_mini_usage() changed name. (Ales Kozumplik)
-- kickstart: do not include kickstart errors into own messages. (Radek Holy)
-
-* Wed Apr 23 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.7-1
-- build: gettext is also needed as a buildreq (Tim Lauridsen)
-- copr: use usage & summary class attributes, to work with dnf 0.5.0 use shared lib dnfpluginscore for translation wrapp
-- build: add cmake as buildreq (Tim Lauridsen)
-- generate-completion-cache: fix shared lib name (Tim Lauridsen)
-- make .spec use gitrev in the source file add helper script for building source archive (Tim Lauridsen)
-- Added transifex config (Tim Lauridsen)
-- tests: use cli logger in kickstart test (Tim Lauridsen)
-- Added translation .pot file Added da translation files so we have something to build & install (Tim Lauridsen)
-- Added CMake files Added CMake build to .spec & and added translation files handling (Tim Lauridsen)
-- make plugins use shared lib added translation wrappers added missing usage & summary PEP8 fixes (Tim Lauridsen)
-- added shared dnfpluginscore lib (Tim Lauridsen)
-- copr: C:139, 0: Unnecessary parens after 'print' keyword (superfluous-parens) (Miroslav Suchý)
-- copr: W: 23, 0: Unused import gettext (unused-import) (Miroslav Suchý)
-- copr: C: 33, 0: No space allowed before : (Miroslav Suchý)
-- copr: some python3 migration (Miroslav Suchý)
-- copr: get rid of dnf i18n imports (Miroslav Suchý)
-- remove dnf.yum.i18n imports. (Ales Kozumplik)
-- copr: Fix the playground upgrade command. (Tadej Janež)
-- copr: implement search function (Igor Gnatenko)
-- better format output (Miroslav Suchý)
-- implement playground plugin (Miroslav Suchý)
-- move removing of repo into method (Miroslav Suchý)
-- check root only for actions which really need root (Miroslav Suchý)
-- move repo downloading into separate method (Miroslav Suchý)
-- define copr url as class attribute (Miroslav Suchý)
-- better wording of warning (Miroslav Suchý)
-- move question to function argument (Miroslav Suchý)
-- move guessing chroot into function (Miroslav Suchý)
-- copr: use common lib use Command.usage & summary cleanup imports & PEP8 fixes (Tim Lauridsen)
-- builddep: added usage & summary & fix some PEP8 issues (Tim Lauridsen)
-- kickstart: use new public Command.usage & Command.summary api (Tim Lauridsen)
-- fix resource leak in builddep.py. (Ales Kozumplik)
-- refactor: command plugins use demands mechanism. (Ales Kozumplik)
-- noroot: move to the new 'demands' mechanism to check the need of root. (Ales Kozumplik)
-- tests: fix locale independence. (Radek Holy)
-- [copr] correctly specify chroot when it should be guessed (Miroslav Suchý)
-
-* Mon Mar 17 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.6-1
-- clenaup: remove commented out code (Miroslav Suchý)
-- copr: list: print description (Igor Gnatenko)
-- builddep: rpm error messages sink. (Ales Kozumplik)
-- builddep: improve error handling on an command argument (RhBug:1074436) (Ales Kozumplik)
-- copr: handling case when no argument is passed on cli (Miroslav Suchý)
-- copr: delete excess argument (Igor Gnatenko)
-- add copr plugin (Miroslav Suchý)
-- debuginfo-install: check for root with dnf api (Igor Gnatenko)
-- packaging: fix bogus dates. (Ales Kozumplik)
-
-* Wed Feb 26 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.5-2
-- packaging: add debuginfo-install.py (Ales Kozumplik)
-
-* Wed Feb 26 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.5-1
-- packaging: add builddep.py to the RPM. (Ales Kozumplik)
-
-* Tue Feb 25 2014 Radek Holý <rholy@redhat.com> - 0.0.4-1
-- refactor: use Base.install instead of installPkgs in kickstart plugin. (Radek Holy)
-- refactor: move kickstart arguments parsing to standalone method. (Radek Holy)
-- tests: test effects instead of mock calls. (Radek Holy)
-- Add debuginfo-install plugin. (RhBug:1045770) (Igor Gnatenko)
-- builddep: needs to be run under root. (RhBug:1065851) (Ales Kozumplik)
-
-* Thu Feb 6 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.3-1
-- tests: import mock through support so its simpler for the test cases. (Ales Kozumplik)
-- packaging: fix typos in the spec. (Ales Kozumplik)
-- [completion_cache] Cache installed packages, update the cache less frequently (Elad Alfassa)
-- Add bash completion to dnf (Elad Alfassa)
-- packaging: missing buildrequire (Ales Kozumplik)
-
-* Mon Jan 13 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.2-1
-- First release.
-
-* Wed Jan 8 2014 Cristian Ciupitu <cristian.ciupitu@yahoo.com> - 0.0.1-4
-- Spec updates.
-
-* Tue Jan 7 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.1-3
-- Spec updates.
-
-* Mon Jan 6 2014 Aleš Kozumplík <ales@redhat.com> - 0.0.1-2
-- Spec updates.
-
-* Fri Dec 20 2013 Aleš Kozumplík <ales@redhat.com> - 0.0.1-1
-- The initial package version.
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index a21777b..1f40737 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -1,5 +1,6 @@
INSTALL (FILES builddep.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins)
INSTALL (FILES debuginfo-install.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins)
+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)
diff --git a/plugins/config_manager.py b/plugins/config_manager.py
new file mode 100644
index 0000000..812e34a
--- /dev/null
+++ b/plugins/config_manager.py
@@ -0,0 +1,255 @@
+#
+# Copyright (C) 2015 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 dnfpluginscore import _, logger
+
+import dnf
+import dnf.cli
+import dnf.pycomp
+import dnfpluginscore
+import dnfpluginscore.lib
+import os
+import re
+import shutil
+
+
+class ConfigManager(dnf.Plugin):
+
+ name = 'config-manager'
+
+ def __init__(self, base, cli):
+ super(ConfigManager, self).__init__(base, cli)
+ self.base = base
+ self.cli = cli
+ if self.cli is not None:
+ self.cli.register_command(ConfigManagerCommand)
+
+
+class ConfigManagerCommand(dnf.cli.Command):
+
+ aliases = ['config-manager']
+ summary = _('manage dnf configuration options and repositories')
+ usage = '[%s] [%s]' % (_('OPTIONS'), _('KEYWORDS'))
+
+ def __init__(self, cli):
+ super(ConfigManagerCommand, self).__init__(cli)
+ self.opts = None
+ self.parser = None
+
+ def configure(self, args):
+ # setup sack and populate it with enabled repos
+ demands = self.cli.demands
+ demands.available_repos = True
+
+ self.parser = dnfpluginscore.ArgumentParser(self.aliases[0])
+ self.parser.add_argument(
+ 'repo', nargs='*',
+ help=_('repo to modify'))
+ self.parser.add_argument(
+ '--save', default=False, action='store_true',
+ help=_('save the current options (useful with --setopt)'))
+ self.parser.add_argument(
+ '--set-enabled', default=False, action='store_true',
+ help=_('enable the specified repos (automatically saves)'))
+ self.parser.add_argument(
+ '--set-disabled', default=False, action='store_true',
+ help=_('disable the specified repos (automatically saves)'))
+ self.parser.add_argument(
+ '--add-repo', default=[], action='append', metavar='URL',
+ help=_('add (and enable) the repo from the specified file or url'))
+ self.parser.add_argument(
+ '--dump', default=False, action='store_true',
+ help=_('print current configuration values to stdout'))
+
+ self.opts = self.parser.parse_args(args)
+
+ if self.opts.help_cmd:
+ print(self.parser.format_help())
+ return
+
+ if (self.opts.save or self.opts.set_enabled or
+ self.opts.set_disabled or self.opts.add_repo):
+ demands.root_user = True
+
+
+ def run(self, _args):
+ """Execute the util action here."""
+
+ if self.opts.help_cmd:
+ return
+ if self.opts.set_enabled and self.opts.set_disabled:
+ logger.error(
+ _("Error: Trying to enable and disable repos at the same time."))
+ self.opts.set_enabled = self.opts.set_disabled = False
+ if self.opts.set_enabled and not self.opts.repo:
+ logger.error(_("Error: Trying to enable already enabled repos."))
+ self.opts.set_enabled = False
+
+ if self.opts.add_repo:
+ self.add_repo()
+ else:
+ self.modify_repo()
+
+ def modify_repo(self):
+ """ process --set-enabled, --set-disabled and --setopt options """
+
+ sbc = self.base.conf
+ modify = []
+ if hasattr(self.cli, 'main_setopts') and self.cli.main_setopts:
+ modify = self.cli.main_setopts.items
+ if not self.opts.repo or 'main' in self.opts.repo:
+ if self.opts.dump:
+ print(self.base.output.fmtSection('main'))
+ print(self.base.conf.dump())
+ if self.opts.save and modify:
+ # modify [main] in dnf.conf
+ dnfpluginscore.lib.write_raw_configfile(dnf.const.CONF_FILENAME,
+ 'main', sbc.substitutions,
+ sbc.cfg.options,
+ sbc.iteritems,
+ sbc.optionobj,
+ modify)
+
+ if self.opts.set_enabled or self.opts.set_disabled:
+ self.opts.save = True
+ modify.append('enabled')
+
+ if self.opts.repo:
+ matched = []
+ for name in self.opts.repo:
+ matched.extend(self.base.repos.get_matching(name))
+ else:
+ matched = self.base.repos.iter_enabled()
+
+ if not matched:
+ raise dnf.exceptions.Error(_("No matching repo to modify: %s.")
+ % ', '.join(self.opts.repo))
+ for repo in sorted(matched):
+ if self.opts.dump:
+ print(self.base.output.fmtSection('repo: ' + repo.id))
+ if self.opts.set_enabled and not repo.enabled:
+ repo.enable()
+ elif self.opts.set_disabled and repo.enabled:
+ repo.disable()
+ if self.opts.dump:
+ print(repo.dump())
+ repo_modify = modify[:]
+ if (hasattr(self.cli, 'repo_setopts')
+ and repo.id in self.cli.repo_setopts):
+ repo_modify.extend(self.cli.repo_setopts[repo.id].items)
+ if self.opts.save and modify:
+ dnfpluginscore.lib.write_raw_configfile(repo.repofile,
+ repo.id,
+ sbc.substitutions,
+ repo.cfg.options,
+ repo.iteritems,
+ repo.optionobj,
+ repo_modify)
+
+ def add_repo(self):
+ """ process --add-repo option """
+
+ # put repo file into first reposdir which exists or create it
+ myrepodir = None
+ for rdir in self.base.conf.reposdir:
+ if os.path.exists(rdir):
+ myrepodir = rdir
+ break
+
+ if not myrepodir:
+ myrepodir = self.base.conf.reposdir[0]
+ dnf.util.ensure_dir(myrepodir)
+
+ for url in self.opts.add_repo:
+ if dnf.pycomp.urlparse.urlparse(url).scheme == '':
+ url = 'file://' + os.path.abspath(url)
+ logger.info(_('Adding repo from: %s'), url)
+ if url.endswith('.repo'):
+ # .repo file - download, put into reposdir and enable it
+ destname = os.path.basename(url)
+ destname = os.path.join(myrepodir, destname)
+ try:
+ f = dnfpluginscore.lib.urlopen(self, None, url, 'w+')
+ shutil.copy2(f.name, destname)
+ f.close()
+ except IOError as e:
+ logger.error(e)
+ continue
+ else:
+ # just url to repo, create .repo file on our own
+ repoid = sanitize_url_to_fs(url)
+ reponame = 'created by dnf config-manager from %s' % url
+ destname = os.path.join(myrepodir, "%s.repo" % repoid)
+ content = "[%s]\nname=%s\nbaseurl=%s\nenabled=1\n" % \
+ (repoid, reponame, url)
+ if not save_to_file(destname, content):
+ continue
+
+
+def save_to_file(filename, content):
+ try:
+ with open(filename, 'w+') as fd:
+ dnf.pycomp.write_to_file(fd, content)
+ except (IOError, OSError) as e:
+ logger.error(_('Could not save repo to repofile %s: %s'),
+ filename, e)
+ return False
+ return True
+
+# Regular expressions to sanitise cache filenames
+RE_SCHEME = re.compile(r'^\w+:/*(\w+:|www\.)?')
+RE_SLASH = re.compile(r'[?/:&#|]+')
+RE_BEGIN = re.compile(r'^[,.]*')
+RE_FINAL = re.compile(r'[,.]*$')
+
+def sanitize_url_to_fs(url):
+ """Return a filename suitable for the filesystem
+
+ Strips dangerous and common characters to create a filename we
+ can use to store the cache in.
+ """
+
+ try:
+ if RE_SCHEME.match(url):
+ if dnf.pycomp.PY3:
+ url = url.encode('idna').decode('utf-8')
+ else:
+ if isinstance(url, str):
+ url = url.decode('utf-8').encode('idna')
+ else:
+ url = url.encode('idna')
+ if isinstance(url, unicode):
+ url = url.encode('utf-8')
+ except (UnicodeDecodeError, UnicodeEncodeError, UnicodeError, TypeError):
+ pass
+ url = RE_SCHEME.sub("", url)
+ url = RE_SLASH.sub("_", url)
+ url = RE_BEGIN.sub("", url)
+ url = RE_FINAL.sub("", url)
+
+ # limit length of url
+ if len(url) > 250:
+ parts = url[:185].split('_')
+ lastindex = 185-len(parts[-1])
+ csum = dnf.yum.misc.Checksums(['sha256'])
+ csum.update(url[lastindex:])
+ url = url[:lastindex] + '_' + csum.hexdigest()
+
+ return url
diff --git a/plugins/copr.py b/plugins/copr.py
index 3a91ce6..8295855 100644
--- a/plugins/copr.py
+++ b/plugins/copr.py
@@ -1,6 +1,6 @@
# supplies the 'copr' command.
#
-# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2014-2015 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
@@ -20,6 +20,7 @@
from __future__ import print_function
from dnfpluginscore import _, logger
from dnf.i18n import ucd
+import dnfpluginscore.lib
import dnf
import glob
@@ -30,9 +31,14 @@ import requests
import urllib
-yes = set([_('yes'), _('y')])
-no = set([_('no'), _('n'), ''])
+YES = set([_('yes'), _('y')])
+NO = set([_('no'), _('n'), ''])
+# compatibility with Py2 and Py3 - rename raw_input() to input() on Py2
+try:
+ input = raw_input
+except NameError:
+ pass
class Copr(dnf.Plugin):
"""DNF plugin supplying the 'copr' command."""
@@ -118,8 +124,7 @@ Do you want to continue? [y/N]: """)
#http://copr.fedoraproject.org/api/coprs/ignatenkobrain/
api_path = "/api/coprs/{}/".format(project_name)
- opener = urllib.FancyURLopener({})
- res = opener.open(self.copr_url + api_path)
+ res = dnfpluginscore.lib.urlopen(self, None, self.copr_url + api_path, 'w+')
try:
json_parse = json.loads(res.read())
except ValueError:
@@ -132,7 +137,7 @@ Do you want to continue? [y/N]: """)
i = 0
while i < len(json_parse["repos"]):
msg = "{0}/{1} : ".format(project_name,
- json_parse["repos"][i]["name"])
+ json_parse["repos"][i]["name"])
desc = json_parse["repos"][i]["description"]
if not desc:
desc = _("No description given")
@@ -143,18 +148,19 @@ Do you want to continue? [y/N]: """)
#http://copr.fedoraproject.org/api/coprs/search/tests/
api_path = "/api/coprs/search/{}/".format(project_name)
- opener = urllib.FancyURLopener({})
- res = opener.open(self.copr_url + api_path)
+ res = dnfpluginscore.lib.urlopen(self, None, self.copr_url + api_path, 'w+')
try:
json_parse = json.loads(res.read())
except ValueError:
- raise dnf.exceptions.Error(_("Can't parse search for '{}'.").format(project_name))
+ raise dnf.exceptions.Error(_("Can't parse search for '{}'."
+ ).format(project_name))
self._check_json_output(json_parse)
section_text = _("Matched: {}").format(project_name)
self._print_match_section(section_text)
i = 0
while i < len(json_parse["repos"]):
- msg = "{0}/{1} : ".format(json_parse["repos"][i]["username"], json_parse["repos"][i]["coprname"])
+ msg = "{0}/{1} : ".format(json_parse["repos"][i]["username"],
+ json_parse["repos"][i]["coprname"])
desc = json_parse["repos"][i]["description"]
if not desc:
desc = _("No description given.")
@@ -175,12 +181,12 @@ Do you want to continue? [y/N]: """)
elif self.base.conf.assumeno and not self.base.conf.assumeyes:
raise dnf.exceptions.Error(_('Safe and good answer. Exiting.'))
- answer = raw_input(question).lower()
+ answer = input(question).lower()
answer = _(answer)
- while not ((answer in yes) or (answer in no)):
- answer = raw_input(question).lower()
+ while not ((answer in YES) or (answer in NO)):
+ answer = input(question).lower()
answer = _(answer)
- if answer in yes:
+ if answer in YES:
return
else:
raise dnf.exceptions.Error(_('Safe and good answer. Exiting.'))
@@ -256,9 +262,9 @@ Do you want to continue? [y/N]: """)
return output
@classmethod
- def _check_json_output(cls, json):
- if json["output"] != "ok":
- raise dnf.exceptions.Error("{}".format(json["error"]))
+ def _check_json_output(cls, json_obj):
+ if json_obj["output"] != "ok":
+ raise dnf.exceptions.Error("{}".format(json_obj["error"]))
class Playground(dnf.Plugin):
@@ -294,7 +300,7 @@ Do you want to continue? [y/N]: """)
raise dnf.cli.CliError(_("Unknown response from server."))
for repo in output["repos"]:
project_name = "{0}/{1}".format(repo["username"],
- repo["coprname"])
+ repo["coprname"])
repo_filename = "/etc/yum.repos.d/_playground_{}.repo" \
.format(project_name.replace("/", "-"))
try:
@@ -304,7 +310,8 @@ Do you want to continue? [y/N]: """)
self.copr_url, project_name, chroot)
req = requests.get(api_url)
output2 = self._get_data(req)
- if output2 and ("output" in output2) and (output2["output"] == "ok"):
+ if (output2 and ("output" in output2)
+ and (output2["output"] == "ok")):
self._download_repo(project_name, repo_filename, chroot)
except dnf.exceptions.Error:
# likely 404 and that repo does not exist
diff --git a/plugins/debuginfo-install.py b/plugins/debuginfo-install.py
index 194b24c..4783ed2 100644
--- a/plugins/debuginfo-install.py
+++ b/plugins/debuginfo-install.py
@@ -23,6 +23,7 @@ from dnfpluginscore import _, logger
import dnf
import dnf.cli
+import dnf.subject
class DebuginfoInstall(dnf.Plugin):
@@ -44,8 +45,8 @@ class DebuginfoInstallCommand(dnf.cli.Command):
summary = _('install debuginfo packages')
usage = "[PACKAGE...]"
- done = []
- rejected = []
+ srcdone = []
+ reqdone = []
packages = None
packages_available = None
packages_installed = None
@@ -62,12 +63,11 @@ class DebuginfoInstallCommand(dnf.cli.Command):
self.packages = self.base.sack.query()
self.packages_available = self.packages.available()
self.packages_installed = self.packages.installed()
- for pkg in args:
- pkgs = self.packages_installed.filter(name=pkg)
- if not pkgs:
- pkgs = self.packages_available.filter(name=pkg)
- for pkg in pkgs:
- self._di_install(pkg, None)
+
+ for pkgspec in args:
+ for pkg in dnf.subject.Subject(pkgspec).get_best_query(
+ self.cli.base.sack):
+ self._di_install(pkg)
@staticmethod
def _pkgname_src(package):
@@ -84,86 +84,53 @@ class DebuginfoInstallCommand(dnf.cli.Command):
assert "-debuginfo" not in srcname
return "{}-debuginfo".format(srcname)
- def _is_available(self, package, match_evra):
+ def _dbg_available(self, package, match_evra):
dbgname = self._pkgname_dbg(package)
if match_evra:
- avail = self.packages_available.filter(
+ return self.packages_available.filter(
name="{}".format(dbgname),
epoch=int(package.epoch),
version=str(package.version),
release=str(package.release),
arch=str(package.arch))
else:
- avail = self.packages_available.filter(
+ return self.packages_available.filter(
name="{}".format(dbgname),
arch=str(package.arch))
- if len(avail) != 0:
- srcname = self._pkgname_src(package)
- if match_evra:
- return self.packages_available.filter(
- name="{}".format(srcname),
- epoch=int(package.epoch),
- version=str(package.version),
- release=str(package.release),
- arch=str(package.arch))
- else:
- return self.packages_available.filter(
- name="{}".format(srcname),
- arch=str(package.arch))
- else:
- return False
- def _di_install(self, package, require):
+ def _di_install(self, package):
srcname = self._pkgname_src(package)
dbgname = self._pkgname_dbg(package)
- if srcname in self.done \
- or require in self.done \
- or package in self.rejected:
- return
- if self._is_available(package, True):
- self.done.append(srcname)
- if require:
- self.done.append(require)
- di = "{0}-{1}:{2}-{3}.{4}".format(
- dbgname,
- package.epoch,
- package.version,
- package.release,
- package.arch)
- self.base.install(di)
- else:
- if self._is_available(package, False):
+ if not srcname in self.srcdone:
+ if self._dbg_available(package, True):
+ di = "{0}-{1}:{2}-{3}.{4}".format(
+ dbgname,
+ package.epoch,
+ package.version,
+ package.release,
+ package.arch)
+ self.base.install(di)
+ elif self._dbg_available(package, False):
di = "{0}.{1}".format(dbgname, package.arch)
self.base.install(di)
- self.done.append(srcname)
- if require:
- self.done.append(require)
- else:
- pass
+ self.srcdone.append(srcname)
+
+ if package.name in self.reqdone:
+ return
+ self.reqdone.append(package.name)
for req in package.requires:
if str(req).startswith("rpmlib("):
continue
- elif str(req) in self.done:
+ elif str(req) in self.reqdone:
continue
elif str(req).find(".so") != -1:
provides = self.packages_available.filter(provides=req)
for p in provides:
- if str(p.name) in self.done or p in self.rejected:
+ if p.name in self.reqdone:
continue
pkgs = self.packages_installed.filter(name=p.name)
- if len(pkgs) != 0:
- pkgs_avail = self._is_available(pkgs[0], True)
- if not pkgs_avail:
- for x in pkgs:
- logger.debug(
-_("Can't find debuginfo package for: {0}-{1}:{2}-{3}.{4}").format(
- x.name, x.epoch, x.version, x.release, x.arch))
- self.rejected.append(x)
- pkgs = []
- else:
- pkgs = pkgs_avail
- for pkg in pkgs:
- self._di_install(pkg, str(req))
+ for dep in pkgs:
+ self._di_install(dep)
def _enable_debug_repos(self):
repos = {}
diff --git a/plugins/dnfpluginscore/lib.py b/plugins/dnfpluginscore/lib.py
new file mode 100644
index 0000000..144d126
--- /dev/null
+++ b/plugins/dnfpluginscore/lib.py
@@ -0,0 +1,121 @@
+#
+# Copyright (C) 2015 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 dnf.pycomp import PY3
+
+import dnf
+import iniparse
+import librepo
+import tempfile
+
+
+def current_value(plugin, repo, option):
+ """
+ Returns current value of the option
+ (set in .repo or dnf.conf or on commandline).
+ """
+ if (repo is not None and
+ hasattr(repo, option) and getattr(repo, option) is not None):
+ return getattr(repo, option)
+ conf = plugin.base.conf
+ if (hasattr(conf, option) and getattr(conf, option) is not None):
+ return getattr(conf, option)
+ return None
+
+
+def urlopen(plugin, repo, url, mode='w+b', **kwargs):
+ """ modified dnf.util.urlopen() which respects proxy setting
+ even for non-repo downloads
+ """
+ conf = plugin.base.conf
+
+ def non_repo_handle():
+ handle = librepo.Handle()
+ handle.useragent = dnf.const.USER_AGENT
+ # see dnf.repo.Repo._handle_new_remote() how to pass
+ handle.maxspeed = conf.throttle if type(conf.throttle) is int \
+ else int(conf.bandwidth * conf.throttle)
+ handle.proxy = conf.proxy
+ handle.proxyuserpwd = dnf.repo._user_pass_str(conf.proxy_username,
+ conf.proxy_password)
+ handle.sslverifypeer = handle.sslverifyhost = conf.sslverify
+ return handle
+
+ if PY3 and 'b' not in mode:
+ kwargs.setdefault('encoding', 'utf-8')
+ fo = tempfile.NamedTemporaryFile(mode, **kwargs)
+ if repo:
+ handle = repo.get_handle()
+ else:
+ handle = non_repo_handle()
+ try:
+ librepo.download_url(url, fo.fileno(), handle)
+ except librepo.LibrepoException as e:
+ raise IOError(e.args[1])
+ fo.seek(0)
+ return fo
+
+
+def write_raw_configfile(filename, section_id, substitutions,
+ cfgoptions, items, optionobj,
+ modify=None):
+ """
+ Code adopted from yum-config-manager writeRawRepoFile().
+ filename - name of config file (.conf or .repo)
+ section_id - id of modified section (e.g. main, fedora, updates)
+ substitutions - instance of base.conf.substitutions
+ cfgoptions - options parsed from conf file (e.g. base.conf.cfg.options)
+ items - current global or repo settings (e.g. base.conf.iteritems)
+ optionobj - option parse object (e.g. base.conf.optionobj)
+ modify - list of modified options
+ """
+ ini = iniparse.INIConfig(open(filename))
+
+ osection_id = section_id
+ # b/c repoids can have $values in them we need to map both ways to figure
+ # out which one is which
+ if section_id not in ini:
+ for sect in ini:
+ if dnf.conf.parser.substitute(sect, substitutions) == section_id:
+ section_id = sect
+
+ # Updated the ConfigParser with the changed values
+ cfgopts = cfgoptions(osection_id)
+ for name, value in items():
+ if value is None: # Proxy
+ continue
+
+ if modify is not None and name not in modify:
+ continue
+
+ option = optionobj(name)
+ ovalue = option.tostring(value)
+ # If the value is the same, but just interpreted ... when we don't want
+ # to keep the interpreted values.
+ if (name in ini[section_id] and
+ ovalue == dnf.conf.parser.substitute(ini[section_id][name],
+ substitutions)):
+ ovalue = ini[section_id][name]
+
+ if name not in cfgopts and option.default == value:
+ continue
+
+ ini[section_id][name] = ovalue
+ fp = open(filename, "w")
+ fp.write(str(ini))
+ fp.close()
diff --git a/plugins/download.py b/plugins/download.py
index cbb6e4e..7e8bf41 100644
--- a/plugins/download.py
+++ b/plugins/download.py
@@ -1,6 +1,6 @@
# download.py, supplies the 'download' command.
#
-# Copyright (C) 2013-2014 Red Hat, Inc.
+# Copyright (C) 2013-2015 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
@@ -27,7 +27,6 @@ import dnf.exceptions
import dnf.i18n
import dnf.subject
import dnfpluginscore
-import functools
import hawkey
import itertools
import os
@@ -39,6 +38,7 @@ class Download(dnf.Plugin):
name = 'download'
def __init__(self, base, cli):
+ super(Download, self).__init__(base, cli)
self.base = base
self.cli = cli
if self.cli is not None:
@@ -51,6 +51,11 @@ class DownloadCommand(dnf.cli.Command):
summary = _('Download package to current directory')
usage = _('PACKAGE...')
+ def __init__(self, cli):
+ super(DownloadCommand, self).__init__(cli)
+ self.opts = None
+ self.parser = None
+
def configure(self, args):
# setup sack and populate it with enabled repos
demands = self.cli.demands
@@ -64,13 +69,15 @@ class DownloadCommand(dnf.cli.Command):
# You must only add options not used by dnf already
self.parser = dnfpluginscore.ArgumentParser(self.aliases[0])
self.parser.add_argument('packages', nargs='+',
- help=_('packages to download'))
+ help=_('packages to download'))
self.parser.add_argument("--source", action='store_true',
- help=_('download the src.rpm instead'))
- self.parser.add_argument('--destdir',
- help=_('download path, default is current dir'))
- self.parser.add_argument('--resolve', action='store_true',
- help=_('resolve and download needed dependencies'))
+ help=_('download the src.rpm instead'))
+ self.parser.add_argument(
+ '--destdir',
+ help=_('download path, default is current dir'))
+ self.parser.add_argument(
+ '--resolve', action='store_true',
+ help=_('resolve and download needed dependencies'))
# parse the options/args
# list available options/args on errors & exit
@@ -91,8 +98,7 @@ class DownloadCommand(dnf.cli.Command):
else:
dest = dnf.i18n.ucd(os.getcwd())
- move = functools.partial(self._move_package, dest)
- map(move, locations)
+ self._move_packages(dest, locations)
def _download_rpms(self, pkg_specs):
"""Download packages to dnf cache."""
@@ -137,7 +143,8 @@ class DownloadCommand(dnf.cli.Command):
logger.debug(_('Error in resolve'))
return []
- def _get_source_packages(self, pkgs):
+ @staticmethod
+ def _get_source_packages(pkgs):
"""Get list of source rpm names for a list of packages."""
source_pkgs = set()
for pkg in pkgs:
@@ -145,31 +152,27 @@ class DownloadCommand(dnf.cli.Command):
source_pkgs.add(pkg.sourcerpm)
logger.debug(' --> Package : %s Source : %s',
str(pkg), pkg.sourcerpm)
+ elif pkg.arch == 'src':
+ source_pkgs.add("%s-%s.src.rpm" % (pkg.name, pkg.evr))
else:
- logger.info(_("No source rpm definded for %s"), str(pkg))
+ logger.info(_("No source rpm defined for %s"), str(pkg))
return list(source_pkgs)
def _enable_source_repos(self):
"""Enable source repositories for enabled binary repositories.
- binary repositories will be disabled and the dnf sack will be reloaded
+ Don't disable the binary ones because they can contain SRPMs as well
+ (this applies to COPR and to user-managed repos).
+ The dnf sack will be reloaded.
"""
- repo_dict = {}
- # find the source repos for the enabled binary repos
+ # enable the source repos
for repo in self.base.repos.iter_enabled():
- source_repo = '%s-source' % repo.id
- if source_repo in self.base.repos:
- repo_dict[repo.id] = (repo, self.base.repos[source_repo])
- else:
- repo_dict[repo.id] = (repo, None)
- # disable the binary & enable the source ones
- for id_ in repo_dict:
- repo, src_repo = repo_dict[id_]
- repo.disable()
- if src_repo:
- logger.info(_('enabled %s repository') % src_repo.id)
- src_repo.enable()
- # reload the sack
+ source_repo_id = '%s-source' % repo.id
+ if source_repo_id in self.base.repos:
+ source_repo = self.base.repos[source_repo_id]
+ logger.info(_('enabled %s repository'), source_repo.id)
+ source_repo.enable()
+ # reload the sack
self.base.fill_sack()
def _get_query(self, pkg_spec):
@@ -191,8 +194,12 @@ class DownloadCommand(dnf.cli.Command):
release=nevra.release, arch=nevra.arch)
return q
- def _move_package(self, target, location):
+ @staticmethod
+ def _move_packages(target, locations):
"""Move the downloaded package to target."""
- shutil.copy(location, target)
- os.unlink(location)
+ if not os.path.exists(target):
+ os.makedirs(target)
+ for pkg in locations:
+ shutil.copy(pkg, target)
+ os.unlink(pkg)
return target
diff --git a/plugins/generate_completion_cache.py b/plugins/generate_completion_cache.py
index 7fbb47a..b9df242 100644
--- a/plugins/generate_completion_cache.py
+++ b/plugins/generate_completion_cache.py
@@ -2,6 +2,7 @@
# generate_completion_cache.py - generate cache for dnf bash completion
# Copyright © 2013 Elad Alfassa <elad@fedoraproject.org>
# Copyright (C) 2014 Igor Gnatenko <i.gnatenko.brain@gmail.com>
+# Copyright (C) 2015 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
@@ -28,6 +29,7 @@ class BashCompletionCache(dnf.Plugin):
name = 'generate_completion_cache'
def __init__(self, base, cli):
+ super(BashCompletionCache, self).__init__(base, cli)
self.base = base
self.cache_file = "/var/cache/dnf/packages.db"
@@ -60,7 +62,7 @@ class BashCompletionCache(dnf.Plugin):
cur.execute("delete from available")
avail_pkgs = self.base.sack.query().available()
avail_pkgs_insert = [["{}.{}".format(x.name, x.arch)]
- for x in avail_pkgs if x.arch != "src"]
+ for x in avail_pkgs if x.arch != "src"]
cur.executemany("insert or ignore into available values (?)",
avail_pkgs_insert)
conn.commit()
@@ -80,7 +82,7 @@ class BashCompletionCache(dnf.Plugin):
cur.execute("delete from installed")
inst_pkgs = self.base.sack.query().installed()
inst_pkgs_insert = [["{}.{}".format(x.name, x.arch)]
- for x in inst_pkgs if x.arch != "src"]
+ for x in inst_pkgs if x.arch != "src"]
cur.executemany("insert or ignore into installed values (?)",
inst_pkgs_insert)
conn.commit()
diff --git a/plugins/ghost.py b/plugins/ghost.py
index 1cff03c..ac60780 100644
--- a/plugins/ghost.py
+++ b/plugins/ghost.py
@@ -1,6 +1,6 @@
# ghost.py, it's a show about nothing.
#
-# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2013-2015 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
@@ -29,6 +29,7 @@ class Ghost(dnf.Plugin):
name = 'ghost'
def __init__(self, base, cli):
+ super(Ghost, self).__init__(base, cli)
self.base = base
self.cli = cli
if cli is None:
@@ -36,7 +37,8 @@ class Ghost(dnf.Plugin):
else:
self._out('loaded (with CLI)')
- def _out(self, msg):
+ @staticmethod
+ def _out(msg):
logger.debug('Ghost plugin: %s', msg)
def config(self):
diff --git a/plugins/noroot.py b/plugins/noroot.py
index 014b226..f82b6a3 100644
--- a/plugins/noroot.py
+++ b/plugins/noroot.py
@@ -1,6 +1,6 @@
# noroot.py
#
-# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2013-2015 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
@@ -19,7 +19,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
-from dnfpluginscore import logger, _
+from dnfpluginscore import _
import dnf
import dnf.exceptions
@@ -33,6 +33,7 @@ class Noroot(dnf.Plugin):
name = 'noroot'
def __init__(self, base, cli):
+ super(Noroot, self).__init__(base, cli)
self.base = base
self.cli = cli
diff --git a/plugins/protected_packages.py b/plugins/protected_packages.py
index b202011..a241eae 100644
--- a/plugins/protected_packages.py
+++ b/plugins/protected_packages.py
@@ -1,7 +1,7 @@
# protected_packages.py
# Prevent package removals that could leave the system broken.
#
-# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2014-2015 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
@@ -20,7 +20,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
-from dnfpluginscore import _, logger
+from dnfpluginscore import _
import dnf
import dnf.exceptions
diff --git a/plugins/repoquery.py b/plugins/repoquery.py
index c4ebccc..ddce24c 100644
--- a/plugins/repoquery.py
+++ b/plugins/repoquery.py
@@ -24,6 +24,7 @@ from dnfpluginscore import _
import dnf
import dnf.cli
import dnf.exceptions
+import dnf.subject
import dnfpluginscore
import functools
import hawkey
@@ -62,6 +63,8 @@ def build_format_fn(opts):
return info_format
elif opts.queryfilelist:
return filelist_format
+ elif opts.querysourcerpm:
+ return sourcerpm_format
else:
return rpm2py_format(opts.queryformat).format
@@ -72,6 +75,9 @@ def info_format(pkg):
def filelist_format(pkg):
return "\n".join(pkg.files)
+def sourcerpm_format(pkg):
+ return pkg.sourcerpm
+
def parse_arguments(args):
# Setup ArgumentParser to handle util
parser = dnfpluginscore.ArgumentParser(RepoQueryCommand.aliases[0])
@@ -81,6 +87,8 @@ def parse_arguments(args):
help=_('show only results from this REPO'))
parser.add_argument('--arch', metavar='ARCH',
help=_('show only results from this ARCH'))
+ parser.add_argument('-f', '--file', metavar='FILE',
+ help=_('show only results that owns FILE'))
parser.add_argument('--whatprovides', metavar='REQ',
help=_('show only results there provides REQ'))
parser.add_argument('--whatrequires', metavar='REQ',
@@ -96,6 +104,9 @@ def parse_arguments(args):
outform.add_argument('-l', "--list", dest='queryfilelist',
default=False, action='store_true',
help=_('show list of files in the package'))
+ outform.add_argument('-s', "--source", dest='querysourcerpm',
+ default=False, action='store_true',
+ help=_('show package source RPM name'))
outform.add_argument('--qf', "--queryformat", dest='queryformat',
default=QFORMAT_DEFAULT,
help=_('format for displaying found packages'))
@@ -193,17 +204,19 @@ class RepoQueryCommand(dnf.cli.Command):
print(QUERY_TAGS)
return
- q = self.base.sack.query().available()
if opts.key:
- if set(opts.key) & set('*[?'): # is pattern ?
- fdict = {'name__glob': opts.key}
- else: # substring
- fdict = {'name': opts.key}
- q = q.filter(hawkey.ICASE, **fdict)
+ q = dnf.subject.Subject(opts.key, ignore_case=True).get_best_query(
+ self.base.sack, with_provides=False)
+ else:
+ q = self.base.sack.query()
+ # do not show packages from @System repo
+ q = q.available()
if opts.repoid:
q = q.filter(reponame=opts.repoid)
if opts.arch:
q = q.filter(arch=opts.arch)
+ if opts.file:
+ q = q.filter(file=opts.file)
if opts.whatprovides:
q = self.by_provides(self.base.sack, [opts.whatprovides], q)
if opts.whatrequires:
diff --git a/rel-eng/README b/rel-eng/README
new file mode 100644
index 0000000..c103bdf
--- /dev/null
+++ b/rel-eng/README
@@ -0,0 +1,7 @@
+Release instructions:
+
+1. Tag: tito tag
+2. Test: tito build --rpm --offline
+3. Push: git push && git push $ORIGIN $TAG
+4. Release: tito release fedora-git
+
diff --git a/rel-eng/packages/.readme b/rel-eng/packages/.readme
new file mode 100644
index 0000000..8999c8d
--- /dev/null
+++ b/rel-eng/packages/.readme
@@ -0,0 +1,3 @@
+the rel-eng/packages directory contains metadata files
+named after their packages. Each file has the latest tagged
+version and the project's relative directory.
diff --git a/rel-eng/packages/dnf-plugins-core b/rel-eng/packages/dnf-plugins-core
new file mode 100644
index 0000000..d7b9e19
--- /dev/null
+++ b/rel-eng/packages/dnf-plugins-core
@@ -0,0 +1 @@
+0.1.5-2 ./
diff --git a/rel-eng/releasers.conf b/rel-eng/releasers.conf
new file mode 100644
index 0000000..ffeb709
--- /dev/null
+++ b/rel-eng/releasers.conf
@@ -0,0 +1,3 @@
+[fedora-git]
+releaser = tito.release.FedoraGitReleaser
+branches = f21
diff --git a/rel-eng/tito.props b/rel-eng/tito.props
new file mode 100644
index 0000000..1084386
--- /dev/null
+++ b/rel-eng/tito.props
@@ -0,0 +1,5 @@
+[buildconfig]
+builder = tito.distributionbuilder.DistributionBuilder
+tagger = tito.tagger.ReleaseTagger
+changelog_do_not_remove_cherrypick = 1
+changelog_format = %s (%a)
diff --git a/scripts/lint b/scripts/lint
index 8b4f630..5423164 100755
--- a/scripts/lint
+++ b/scripts/lint
@@ -21,8 +21,9 @@ disable "-d W0141" # used builtin 'map' function
disable "-d W0142" # used star magic
VAR_NAMES=--variable-rgx='[a-z_][a-z0-9_]*$'
+DUMMY_NAMES='--dummy-variables-rgx=_.*'
MISC=--max-line-length=82
-pylint --rcfile=/dev/null --reports=n $DISABLED "$VAR_NAMES" $MISC $* \
+pylint --rcfile=/dev/null --reports=n $DISABLED "$VAR_NAMES" "$DUMMY_NAMES" $MISC $* \
"$TEMPLATE" \
| egrep -v -f $FALSE_POSITIVES
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..5672629
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,8 @@
+To run tests from the source tree, run this
+(working directory = root of the source tree):
+
+export PYTHONPATH=./plugins
+nosetests tests/
+
+You can run tests under specific Python version using nosetests-2.7
+or nosetests-3.4.
diff --git a/tests/test_config_manager.py b/tests/test_config_manager.py
new file mode 100644
index 0000000..64c581d
--- /dev/null
+++ b/tests/test_config_manager.py
@@ -0,0 +1,121 @@
+# Copyright (C) 2015 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 tests.support import mock, RepoStub
+
+import config_manager
+import dnf
+import filecmp
+import iniparse
+import os
+import shutil
+import tempfile
+import unittest
+
+
+REPOLABEL = "testrepo"
+REPOCONTENT = """[testrepo]
+name=TestRepo
+baseurl=file:///tmp
+enabled=1
+"""
+
+class ConfigManagerBase(mock.MagicMock):
+ conf = dnf.conf.Conf()
+
+class ConfigManagerCommandTest(unittest.TestCase):
+
+ def setUp(self):
+ cli = dnf.cli.cli.Cli(ConfigManagerBase())
+ self.cmd = config_manager.ConfigManagerCommand(cli)
+ self.cmd.base.conf.reposdir = [tempfile.mkdtemp()]
+
+ self.addCleanup(shutil.rmtree, self.cmd.base.conf.reposdir[0])
+
+ def test_add_from_repofile(self):
+ tempfile_kwargs = {'mode': 'w', 'suffix': '.repo', 'delete': False}
+ if dnf.pycomp.PY3:
+ tempfile_kwargs['encoding'] = 'utf8'
+
+ repofile = tempfile.NamedTemporaryFile(**tempfile_kwargs)
+ dnf.pycomp.write_to_file(repofile, REPOCONTENT)
+ repofile.close()
+
+ args = ['--add-repo', repofile.name]
+ self.cmd.configure(args)
+ self.cmd.run(args)
+
+ installed_repofile = os.path.join(self.cmd.base.conf.reposdir[0],
+ os.path.basename(repofile.name))
+ with open(installed_repofile) as f:
+ added = f.read()
+
+ self.assertMultiLineEqual(REPOCONTENT, added)
+
+ def get_matching(x):
+ repo = dnf.repo.Repo(x, '/tmp')
+ repo.repofile = installed_repofile
+ repo.cfg = iniparse.compat.RawConfigParser()
+ repo.cfg.read(installed_repofile)
+ return [repo]
+ self.cmd.base.repos.get_matching = get_matching
+ self.cmd.base.output = dnf.cli.output.Output(self.cmd.base, self.cmd.base.conf)
+
+ self.subtest_disable(REPOLABEL, installed_repofile)
+ self.subtest_enable(REPOLABEL, installed_repofile)
+
+ os.unlink(repofile.name)
+
+ def test_add_from_repourl(self):
+ long_url = 'file:///tmp/%s' % ('/'.join([str(x) for x in range(1,100)]))
+ name = 'tmp_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21' \
+ + '_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39' \
+ + '_40_41_42_43_44_45_46_47_48_49_50_51_52_53_54_55_56_57' \
+ + '_58_59_60_61_62_63__b3085fd1c13941e151ce4afe9d8670774d' \
+ + 'c8e19395f2a785bc1d210eccc0869b'
+ repofile = name + '.repo'
+
+ repocontent = "[%s]\nname=created by dnf config-manager from %s\n" \
+ "baseurl=%s\nenabled=1\n" % (name, long_url, long_url)
+ args = ['--add-repo', long_url]
+ self.cmd.configure(args)
+ self.cmd.run(args)
+ with open(os.path.join(self.cmd.base.conf.reposdir[0], repofile)) as f:
+ added = f.read()
+
+ self.assertMultiLineEqual(repocontent, added)
+
+ def subtest_disable(self, label, fname):
+ args = ['--set-disabled', label]
+ self.cmd.configure(args)
+ self.cmd.run(args)
+
+ with open(fname) as f:
+ added = f.read()
+ disabled = REPOCONTENT.replace("enabled=1", "enabled=0")
+ self.assertMultiLineEqual(disabled, added)
+
+ def subtest_enable(self, label, fname):
+ args = ['--set-enabled', label]
+ self.cmd.configure(args)
+ self.cmd.run(args)
+
+ with open(fname) as f:
+ added = f.read()
+ self.assertMultiLineEqual(REPOCONTENT, added)
diff --git a/tests/test_download.py b/tests/test_download.py
index 4158171..7bee1b6 100644
--- a/tests/test_download.py
+++ b/tests/test_download.py
@@ -170,8 +170,8 @@ class DownloadlCommandTest(unittest.TestCase):
self.assertFalse(repos['foobar-source'].enabled)
self.cmd._enable_source_repos()
self.assertTrue(repos['foo-source'].enabled)
- self.assertFalse(repos['foo'].enabled)
- self.assertFalse(repos['bar'].enabled)
+ self.assertTrue(repos['foo'].enabled)
+ self.assertTrue(repos['bar'].enabled)
self.assertFalse(repos['foobar-source'].enabled)
def test_get_source_packages(self):
diff --git a/tests/test_repoquery.py b/tests/test_repoquery.py
index 771a583..bf32857 100644
--- a/tests/test_repoquery.py
+++ b/tests/test_repoquery.py
@@ -46,6 +46,8 @@ EXPECTED_FILELIST_FORMAT = """\
/var/foobar\
"""
+EXPECTED_SOURCERPM_FORMAT = """\
+foo-1.0.1-1.f20.src.rpm"""
class PkgStub(object):
def __init__(self):
@@ -81,6 +83,9 @@ class ArgParseTest(unittest.TestCase):
opts, _ = repoquery.parse_arguments(['--provides'])
self.assertEqual(opts.queryformat, '%{provides}')
+ def test_file(self):
+ opts, _ = repoquery.parse_arguments(['/var/foobar'])
+ self.assertIsNone(opts.file)
class InfoFormatTest(unittest.TestCase):
def test_info(self):
@@ -94,6 +99,11 @@ class FilelistFormatTest(unittest.TestCase):
self.assertEqual(repoquery.filelist_format(pkg),
EXPECTED_FILELIST_FORMAT)
+class SourceRPMFormatTest(unittest.TestCase):
+ def test_info(self):
+ pkg = repoquery.PackageWrapper(PkgStub())
+ self.assertEqual(repoquery.sourcerpm_format(pkg),
+ EXPECTED_SOURCERPM_FORMAT)
class OutputTest(unittest.TestCase):
def test_output(self):