Skip to content

Commit

Permalink
api: add Base.package_install et al. and Base.add_remote_rpm(). (RhBu…
Browse files Browse the repository at this point in the history
…g:1079519)

Make the CLI use these building blocks.

Document the new API calls.
  • Loading branch information
Ales Kozumplik committed Mar 28, 2014
1 parent 5f3c335 commit 64bd3c2
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 100 deletions.
114 changes: 36 additions & 78 deletions dnf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
import signal
import time


class Base(object):
def __init__(self):
# :api
Expand Down Expand Up @@ -918,6 +917,15 @@ def download_packages(self, pkglist, progress=None, callback_total=None):
if callback_total is not None:
callback_total(remote_pkgs, remote_size, beg_download)

def add_remote_rpm(self, path):
# :api
self.sack.create_cmdline_repo()
if not os.path.exists(path) and '://' in path:
# download remote rpm to a tempfile
path = dnf.util.urlopen(path, suffix='.rpm', delete=False).name
self._tempfiles.append(path)
return self.sack.add_cmdline_package(path)

def sigCheckPkg(self, po):
"""Verify the GPG signature of the given package object.
Expand Down Expand Up @@ -1556,6 +1564,33 @@ def install_groupie(self, pkg_name, inst_set):
return 1
return 0

def package_downgrade(self, pkg):
# :api
if pkg.from_system:
msg = 'downgrade_package() for an installed package.'
raise NotImplementedError(msg)

installed = sorted(self.sack.query().installed().filter(name=pkg.name))
if len(installed) > 0 and installed[0] > pkg:
self._goal.install(pkg)
self._goal.erase(installed[0])
return 2
return 0

def package_install(self, pkg):
# :api
self._goal.install(pkg)
return 1

def package_upgrade(self, pkg):
# :api
if pkg.from_system:
msg = 'upgrade_package() for an installed package.'
raise NotImplementedError(msg)

self._goal.upgrade_to(pkg)
return 1

def upgrade(self, pkg_spec, reponame=None):
# :api
sltr = dnf.subject.Subject(pkg_spec).get_best_selector(self.sack)
Expand Down Expand Up @@ -1624,83 +1659,6 @@ def remove(self, pkg_spec, reponame=None):
self._goal.erase(pkg, clean_deps=clean_deps)
return len(installed)

def _local_common(self, path):
self.sack.create_cmdline_repo()
try:
if not os.path.exists(path) and '://' in path:
# download remote rpm to a tempfile
path = dnf.util.urlopen(path, suffix='.rpm', delete=False).name
self._tempfiles.append(path)
po = self.sack.add_cmdline_package(path)
except IOError:
self.logger.critical(_('Cannot open: %s. Skipping.'), path)
return None
return po

def downgrade_local(self, path):
"""Mark a package on the local filesystem (i.e. not from a
repository) to be downgraded.
:param pkg: a string specifying the path to an rpm file in the
local filesystem to be marked to be downgraded
:param po: a :class:`packages.YumLocalPackage`
:return: a list of the transaction members added to the
transaction set by this method
"""
po = self._local_common(path)
if not po:
return 0

installed = sorted(self.sack.query().installed().filter(name=po.name))
if len(installed) > 0 and installed[0] > po:
self._goal.install(po)
self._goal.erase(installed[0])
return 2
return 0

def install_local(self, path):
"""Mark a package on the local filesystem (i.e. not from a
repository) for installation.
:param pkg: a string specifying the path to an rpm file in the
local filesystem to be marked for installation
:param po: a :class:`packages.YumLocalPackage`
:param updateonly: if True, the given package will only be
marked for installation if it is an upgrade for a package
that is already installed. If False, this restriction is
not enforced
:return: a list of the transaction members added to the
transaction set by this method
"""
po = self._local_common(path)
if not po:
return 0
self._goal.install(po)
return 1

def update_local(self, path):
po = self._local_common(path)
if not po:
return 0
self._goal.upgrade_to(po)
return 1

def reinstall_local(self, path):
"""Mark a package on the local filesystem (i.e. not from a
repository) for reinstallation.
:param pkg: a string specifying the path to an rpm file in the
local filesystem to be marked for reinstallation
:param po: a :class:`packages.YumLocalPackage`
:return: a list of the transaction members added to the
transaction set by this method
"""
po = self._local_common(path)
if not po:
return 0
self._goal.install(po)
return 1

def reinstall(self, pkg_spec, old_reponame=None, new_reponame=None,
new_reponame_neq=None, remove_na=False):
self._add_reinstall_rpm_probfilters()
Expand Down
3 changes: 2 additions & 1 deletion dnf/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ def downgradePkgs(self, userlist):

for arg in userlist:
if arg.endswith('.rpm'):
self.downgrade_local(arg)
pkg = self.add_remote_rpm(arg)
self.package_downgrade(pkg)
continue # it was something on disk and it ended in rpm
# no matter what we don't go looking at repos

Expand Down
3 changes: 2 additions & 1 deletion dnf/cli/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,8 @@ def run(self, extcmds):
pkg_specs, filenames = self.parse_extcmds(extcmds)

# Reinstall files.
results = map(self.base.reinstall_local, filenames)
local_pkgs = map(self.base.add_remote_rpm, filenames)
results = map(self.base.package_install, local_pkgs)
done = functools.reduce(operator.or_, results, False)

# Reinstall packages.
Expand Down
3 changes: 2 additions & 1 deletion dnf/cli/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ def run(self, extcmds):
pkg_specs, grp_specs, filenames = self.parse_extcmds(extcmds)

# Install files.
results = map(self.base.install_local, filenames)
local_pkgs = map(self.base.add_remote_rpm, filenames)
results = map(self.base.package_install, local_pkgs)
done = functools.reduce(operator.or_, results, False)

# Install groups.
Expand Down
3 changes: 2 additions & 1 deletion dnf/cli/commands/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ def run(self, extcmds):
done = True
else:
# Update files.
results = map(self.base.update_local, filenames)
local_pkgs = map(self.base.add_remote_rpm, filenames)
results = map(self.base.package_upgrade, local_pkgs)
done = functools.reduce(operator.or_, results, False)

# Update packages.
Expand Down
18 changes: 17 additions & 1 deletion doc/api_base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@

Init an instance with a reasonable default configuration. The constructor takes no arguments.

.. method:: add_remote_rpm(path)

Add RPM file at `path` to the :attr:`sack` and return the respective :class:`dnf.package.Package` instance. Does the download to a temporary file if `path` is a remote URL. Raises :exc:`IOError` if there are problems obtaining or reading the file.

.. method:: close()

Close all external handles the object holds. This is called automatically via context manager mechanism if the instance is handled using the ``with`` statement.
Expand Down Expand Up @@ -94,7 +98,7 @@

.. _package_marking-label:

The :class:`.Base` class provides a number of methods to make packaging requests that can later be resolved and turned into a transaction. The `pkg_spec` argument they take must be a package specification recognized by :class:`dnf.subject.Subject`. If these methods fail to find suitable packages for the operation they raise a :exc:`~dnf.exceptions.MarkingError`. Note that successful completion of these methods does not necessarily imply that the desired transaction can be carried out (e.g. for dependency reasons).
The :class:`.Base` class provides a number of methods to make packaging requests that can later be resolved and turned into a transaction. The `pkg_spec` argument some of them take must be a package specification recognized by :class:`dnf.subject.Subject`. If these methods fail to find suitable packages for the operation they raise a :exc:`~dnf.exceptions.MarkingError`. Note that successful completion of these methods does not necessarily imply that the desired transaction can be carried out (e.g. for dependency reasons).

.. method:: downgrade(pkg_spec)

Expand All @@ -104,6 +108,18 @@

Mark packages matching `pkg_spec` for installation.

.. method:: package_downgrade(pkg)

If `pkg` is a :class:`dnf.package.Package` in an available repository, mark the matching installed package for downgrade to `pkg`.

.. method:: package_install(pkg)

Mark `pkg` (a :class:`dnf.package.Package` instance) for installation.

.. method:: package_upgrade(pkg)

If `pkg` is a :class:`dnf.package.Package` in an available repository, mark the matching installed package for upgrade to `pkg`.

.. method:: remove(pkg_spec)

Mark packages matching `pkg_spec` for removal.
Expand Down
6 changes: 6 additions & 0 deletions tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import dnf.const
import dnf.exceptions
import dnf.match_counter
import dnf.package
import dnf.subject
import dnf.transaction
import hawkey
Expand Down Expand Up @@ -120,6 +121,11 @@ class MockYumBaseTest(PycompTestCase):
def setUp(self):
self.yumbase = support.MockBase("main")

def test_add_remote_rpm(self):
pkg = self.yumbase.add_remote_rpm(support.TOUR_50_PKG_PATH)
self.assertIsInstance(pkg, dnf.package.Package)
self.assertEqual(pkg.name, 'tour')

def test_search_counted(self):
counter = dnf.match_counter.MatchCounter()
self.yumbase.search_counted(counter, 'summary', 'ation')
Expand Down
5 changes: 3 additions & 2 deletions tests/test_downgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@
import hawkey

class DowngradeTest(support.ResultTestCase):
def test_downgrade_local(self):
def test_package_downgrade(self):
yumbase = support.MockBase()
sack = yumbase.sack

cnt = yumbase.downgrade_local(support.TOUR_44_PKG_PATH)
pkg = yumbase.add_remote_rpm(support.TOUR_44_PKG_PATH)
cnt = yumbase.package_downgrade(pkg)
self.assertGreater(cnt, 0)
(installed, removed) = self.installed_removed(yumbase)
self.assertItemsEqual(map(str, installed), ("tour-4-4.noarch", ))
Expand Down
4 changes: 0 additions & 4 deletions tests/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ def test_install_nevra(self):
new_set = self.yumbase.sack.query().installed() + [lotus]
self.assertResult(self.yumbase, new_set)

def test_install_local(self):
cnt = self.yumbase.install_local(support.TOUR_50_PKG_PATH)
self.assertEqual(cnt, 1)

def test_install_reponame(self):
"""Test whether packages are filtered by the reponame."""
result = itertools.chain(
Expand Down
4 changes: 0 additions & 4 deletions tests/test_reinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ def test_reinstall(self):
new_set += list(available_query.nevra("pepper-20-0.x86_64"))
self.assertResult(self.base, new_set)

def test_reinstall_local(self):
cnt = self.base.reinstall_local(support.TOUR_50_PKG_PATH)
self.assertEqual(cnt, 1)

def test_reinstall_new_reponame_available(self):
"""Test whether it installs packages only from the repository."""
reinstalled_count = self.base.reinstall('librita', new_reponame='main')
Expand Down
14 changes: 7 additions & 7 deletions tests/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ def test_upgrade_all_reponame(self):
base.sack.query().installed().filter(name__neq='hole'),
base.sack.query().upgrades().filter(reponame='third_party')))

def test_update_local(self):
yumbase = support.MockBase()
sack = yumbase.sack
cnt = yumbase.update_local(support.TOUR_51_PKG_PATH)
def test_upgrade_to_package(self):
base = support.MockBase()
pkg = base.add_remote_rpm(support.TOUR_51_PKG_PATH)
cnt = base.package_upgrade(pkg)
self.assertEqual(cnt, 1)
new_pkg = sack.query().available().filter(name="tour")[0]
new_set = support.installed_but(yumbase.sack, "tour") + [new_pkg]
self.assertResult(yumbase, new_set)
new_pkg = base.sack.query().available().filter(name="tour")[0]
new_set = support.installed_but(base.sack, "tour") + [new_pkg]
self.assertResult(base, new_set)

def test_update_arches(self):
yumbase = support.MockBase("main", "updates")
Expand Down

0 comments on commit 64bd3c2

Please sign in to comment.