diff --git a/bin/yunohost-api b/bin/yunohost-api index 470f61c6..3e8e7e31 100755 --- a/bin/yunohost-api +++ b/bin/yunohost-api @@ -196,12 +196,12 @@ if __name__ == '__main__': # Run the server from moulinette import api, MoulinetteError - from yunohost import get_versions + from yunohost.utils.packages import ynh_packages_version ret = api(_retrieve_namespaces(), host=opts.host, port=opts.port, routes={ ('GET', '/installed'): is_installed, - ('GET', '/version'): get_versions, + ('GET', '/version'): ynh_packages_version, }, use_cache=opts.use_cache, use_websocket=opts.use_websocket ) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 4e09d68d..721d3334 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -57,7 +57,7 @@ _global: help: Display YunoHost packages versions action: callback callback: - method: yunohost.get_versions + method: yunohost.utils.packages.ynh_packages_version return: true ############################# diff --git a/locales/en.json b/locales/en.json index e6bef7ab..6852e9c6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -202,6 +202,10 @@ "user_info_failed" : "Unable to retrieve user information", "user_home_creation_failed" : "Unable to create user home folder", + "package_unexpected_error" : "An unexpected error occured with the package '{pkgname}'", + "package_unknown" : "Unknown package '{pkgname}'", + "package_not_installed" : "Package '{pkgname}' is not installed", + "admin_password" : "Administration password", "ask_firstname" : "First name", "ask_lastname" : "Last name", diff --git a/src/yunohost/__init__.py b/src/yunohost/__init__.py index 5bfacdca..e69de29b 100644 --- a/src/yunohost/__init__.py +++ b/src/yunohost/__init__.py @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -""" YunoHost scripts for the moulinette """ - -""" License - - Copyright (C) 2015 YUNOHOST.ORG - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program; if not, see http://www.gnu.org/licenses - -""" - -## Packages versions - -def get_version(package): - """Get the version of package""" - from moulinette.utils import process - return process.check_output( - "dpkg-query -W -f='${{Version}}' {0}".format(package) - ).strip() - -def get_versions(*args, **kwargs): - """Get the version of each YunoHost package""" - from collections import OrderedDict - return OrderedDict([ - ('moulinette', get_version('moulinette')), - ('yunohost', get_version('yunohost')), - ('yunohost-admin', get_version('yunohost-admin')), - ('ssowat', get_version('ssowat')), - ]) - -def has_min_version(min_version, package='yunohost', strict=False): - """Check if a package has minimum version""" - from distutils.version import LooseVersion, StrictVersion - cmp_cls = StrictVersion if strict else LooseVersion - version = cmp_cls(get_version(package)) - if version >= cmp_cls(min_version): - return True - return False diff --git a/src/yunohost/app.py b/src/yunohost/app.py index a9cfeb66..4ee7883a 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -39,8 +39,8 @@ import subprocess from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger -from . import has_min_version -from .service import service_log +from yunohost.service import service_log +from yunohost.utils.packages import has_min_version logger = getActionLogger('yunohost.app') diff --git a/src/yunohost/utils/__init__.py b/src/yunohost/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/yunohost/utils/packages.py b/src/yunohost/utils/packages.py new file mode 100644 index 00000000..c4f4fe76 --- /dev/null +++ b/src/yunohost/utils/packages.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- + +""" License + + Copyright (C) 2015 YUNOHOST.ORG + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses + +""" +from collections import OrderedDict + +import apt +from apt_pkg import version_compare + + +# Exceptions ----------------------------------------------------------------- + +class PackageException(Exception): + """Base exception related to a package + + Represent an exception related to the package named `pkgname`. If no + `message` is provided, it will first try to use the translation key + `message_key` if defined by the derived class. Otherwise, a standard + message will be used. + + """ + message_key = 'package_unexpected_error' + + def __init__(self, pkgname, message=None): + super(PackageException, self).__init__( + message or m18n.n(self.message_key, pkgname=pkgname)) + self.pkgname = pkgname + + +class UnknownPackage(PackageException): + message_key = 'package_unknown' + + +class UninstalledPackage(PackageException): + message_key = 'package_not_installed' + + +# Packages and cache helpers ------------------------------------------------- + +def get_installed_version(*pkgnames, **kwargs): + """Get the installed version of package(s) + + Retrieve one or more packages named `pkgnames` and return their installed + version as a dict or as a string if only one is requested. If `strict` is + `True`, an exception will be raised if a package is unknown or not + installed. + + """ + cache = apt.Cache() + strict = kwargs.get('strict', False) + versions = OrderedDict() + for pkgname in pkgnames: + try: + pkg = cache[pkgname] + except KeyError: + if strict: + raise UnknownPackage(pkgname) + logger.warning(m18n.n('package_unknown', pkgname=pkgname)) + try: + version = pkg.installed.version + except AttributeError: + if strict: + raise UninstalledPackage(pkgname) + version = None + versions[pkgname] = version + if len(pkgnames) == 1: + return versions[pkgnames[0]] + return versions + +def has_min_version(min_version, package='yunohost'): + """Check if a package has a minimum installed version""" + version = get_installed_version(package) + if version_compare(version, min_version) > 0: + return True + return False + + +# YunoHost related methods --------------------------------------------------- + +def ynh_packages_version(*args, **kwargs): + """Return the version of each YunoHost package""" + return get_installed_version( + 'yunohost', 'yunohost-admin', 'moulinette', 'ssowat', + )