Am Mittwoch, den 03.07.2013, 14:11 +0100 schrieb Colin Watson: > > AFAIK the required API of the AppStore would be quite small and the > > package downloading and update calculation is done in the GUI component, > > right? So we could end up with a very small set of methods e.g. > > InstallFile() RemovePackages(), GetPackages(FILTER_INSTALLED)? > > I believe so, at least as a first pass. These would roughly map to > "click install", "click remove", and (forthcoming) "click list".
The native Aptdaemon D-Bus interface doesn't support querying the package cache. It was designed for a sophisticated client application that accesses the cache directly and only makes use of the daemon for the higher privileged manipulations of the cache. So if you want to have a click list method I would suggest using the PackageKit interface. Independently of the question if the interface is provided by aptdaemon or packagekit. I just wrote a small click backend for PackageKit as a proof of concept. You can find the patch attached to this mail. > There are some complexities relating to per-user installation of > packages, which is a requirement: that is, all packages will be unpacked > as a privileged user, but it's possible to unpack multiple parallel > versions of a package and each user will be able to register their own > "current version" links. Do you have any thoughts on whether this kind > of dual operation (unpack as privileged user, link as ordinary user) > should be done as two D-Bus methods or one? > I was indeed looking at aptdaemon for this. As an alternative to > replacing the whole worker, do you think it might make sense to modify > apt.debfile.DebPackage.install to understand click packages (a rather > small change, at least if it only handles the privileged side of > things)? Since they use the .deb container format, that seems like a > convenient class to reuse. Part of the point of using the same > container format was to reduce the amount of work we needed to do at > this kind of layer, for code that's fundamentally not that interesting. Replacing the "whole" worker isn't very intrusive. That is already done by the PackageKit compat mode :) Why would you need the debfile.DebPackage class at all? Since you don't have got any dependency information you could call the click command directly, right? The DebPackage is used to calculate the dependencies that need to be installed from the archive. The DebPackage class would only be interesting if the click-package command uses a status fd as dpkg/apt do. So after the 1.1 release of aptdaemon. I could refactor the workers a little bit to remove the dependency of python-apt. > > Furthermore it limits the click package implementation to Python or > > requires a Python library to access the click packages system. > > Not really. It would make sense to invoke /usr/bin/click as a > subprocess, which the relevant parts of aptdaemon can already do without > much difficulty, and as mentioned above we can reuse existing Python > libraries for things like handling some metadata. But it depends how > much sophistication you think aptdaemon would need. How much sophistication does the design team need? E.g. progress and status reporting? How to handle errors of the click command? > > On the other hand there is the PackageKit daemon and its D-Bus API. The > > PackageKit daemon allows to write backends in different languages: the > > current Python based click package system could use a spawned backend. > > If it is still the plan, click packages could be re-written in C/C++ > > later without having to do any changes on the communication between the > > daemon and the client. > > I'm not sure I understand how this isn't already the case with > aptdaemon. Can you elaborate? If you re-write a PackageKit backend the daemon-client-communication will be the same. You don't have to re-implement the whole communication in another language - only the backend. > > The support for the latest PackageKit 0.8 system D-Bus interface landed > > in aptdaemon's trunk today. I plan to release and upload a 1.1 version > > of aptdaemon soon. This will unblock the transition to packagekit 0.8.9 > > for saucy. > > That would be great, and let me know if I can help with that. I'm > really agnostic as to whether we use aptdaemon or PackageKit as the > backend; I think it definitely makes sense to use one of them rather > than inventing some new service, but I wanted to avoid getting caught up > in the PackageKit transition [...] I fixed some bugs recently and the 1.1 of aptdaemon with the PK 0.8 API gets into shape. > > PackageKit provides two D-Bus interfaces to manage software. The system > > D-Bus interface should be used by the native client libraries. For > > applications that cannot access the client libraries or don't want to > > provide a separate graphical user interface that handles errors or shows > > the progress there is also a small session D-Bus interface which is > > implemented by gnome-packagekit and apper. > > Do we need to use a session interface for the kinds of per-user work I > described? You could mis/re-use the InstallPackages transaction type to set the link to the version of the package that the user wants to use. Cheers, Sebastian
>From 20fe23b2cd459b51647b13d43bdd3d0a3a9ee2ba Mon Sep 17 00:00:00 2001 From: Sebastian Heinlein <[email protected]> Date: Sat, 6 Jul 2013 22:18:58 +0200 Subject: [PATCH] click: Add a very basic click package backend --- backends/Makefile.am | 4 + backends/click/Makefile.am | 21 ++++ backends/click/clickBackend.py | 67 +++++++++++ backends/click/pk-backend-click.c | 221 +++++++++++++++++++++++++++++++++++++ configure.ac | 12 +- 5 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 backends/click/Makefile.am create mode 100755 backends/click/clickBackend.py create mode 100644 backends/click/pk-backend-click.c diff --git a/backends/Makefile.am b/backends/Makefile.am index 68579c9..b5a3f8a 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -16,6 +16,10 @@ if BACKEND_TYPE_BOX SUBDIRS += box endif +if BACKEND_TYPE_CLICK +SUBDIRS += click +endif + if BACKEND_TYPE_CONARY SUBDIRS += conary endif diff --git a/backends/click/Makefile.am b/backends/click/Makefile.am new file mode 100644 index 0000000..df5b2a0 --- /dev/null +++ b/backends/click/Makefile.am @@ -0,0 +1,21 @@ +helperdir = $(datadir)/PackageKit/helpers/click +dist_helper_DATA = \ + clickBackend.py \ + $(NULL) + +plugindir = $(PK_PLUGIN_DIR) +plugin_LTLIBRARIES = libpk_backend_click.la +libpk_backend_click_la_SOURCES = pk-backend-click.c +libpk_backend_click_la_LIBADD = $(PK_PLUGIN_LIBS) +libpk_backend_click_la_LDFLAGS = -module -avoid-version +libpk_backend_click_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(WARNINGFLAGS_C) + +install-data-hook: + chmod a+rx $(DESTDIR)$(helperdir)/*.py + +clean-local: + rm -f *.pyc + rm -f *~ + + +-include $(top_srcdir)/git.mk diff --git a/backends/click/clickBackend.py b/backends/click/clickBackend.py new file mode 100755 index 0000000..4a0593b --- /dev/null +++ b/backends/click/clickBackend.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Provides an apt backend to PackageKit + +Copyright (C) 2013 Sebastian Heinlein <[email protected]> + +Licensed under the GNU General Public License Version 2 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +""" + +__author__ = "Sebastian Heinlein <[email protected]>" + + +import sys + +from clickpackage.install import ClickInstaller +from packagekit import backend, enums + + +CLICK_ROOT = "/opt/click.ubuntu.com" + + +class ClickPackageKitBackend(backend.PackageKitBaseBackend): + + """This class provides a PackageKit backend for the click + packages introduced in the Ubuntu Phone. + """ + + def install_files(self, transaction_flags, install_files): + """Install downloaded package files.""" + self.percentage(None) + self.status(enums.STATUS_INSTALL) + self.allow_cancel(False) + + installer = ClickInstaller(root=CLICK_ROOT, + force_missing_framework=False) + + for file_path in install_files: + try: + pkg_name, pkg_version = installer.audit(file_path) + except Exception as error: + self.error(enums.ERROR_INVALID_PACKAGE_FILE, str(error)) + break + self.package("%s;%s;;" % (pkg_name, pkg_version), + enums.INFO_INSTALLING, + "") + try: + installer.install(file_path) + except Exception as error: + self.error(enums.ERROR_INTERNAL_ERROR, str(error)) + break + self.package("%s;%s;;" % (pkg_name, pkg_version), + enums.INFO_INSTALLED, + "") + +def main(): + backend = ClickPackageKitBackend("") + backend.dispatcher(sys.argv[1:]) + +if __name__ == "__main__": + main() + +# vim: es=4 et sts=4 diff --git a/backends/click/pk-backend-click.c b/backends/click/pk-backend-click.c new file mode 100644 index 0000000..63aa080 --- /dev/null +++ b/backends/click/pk-backend-click.c @@ -0,0 +1,221 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2007-2010 Richard Hughes <[email protected]> + * Copyright (C) 2013 Sebastian Heinlein <[email protected]> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 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. + */ + +#include <config.h> +#include <pk-backend.h> +#include <pk-backend-spawn.h> +#include <string.h> + +typedef struct { + PkBackendSpawn *spawn; +} PkBackendClickPrivate; + +static PkBackendClickPrivate *priv; + +/** + * pk_backend_get_description: + */ +const gchar * +pk_backend_get_description (PkBackend *backend) +{ + return "Click"; +} + +/** + * pk_backend_get_author: + */ +const gchar * +pk_backend_get_author (PkBackend *backend) +{ + return "Sebastian Heinlein <[email protected]>"; +} + +/** + * pk_backend_stderr_cb: + */ +static gboolean +pk_backend_stderr_cb (PkBackendJob *job, const gchar *output) +{ + if (strstr (output, "DeprecationWarning") != NULL) + return FALSE; + return TRUE; +} + +/** + * pk_backend_stdout_cb: + */ +static gboolean +pk_backend_stdout_cb (PkBackendJob *job, const gchar *output) +{ + return TRUE; +} + + +/** + * pk_backend_initialize: + * This should only be run once per backend load, i.e. not every transaction + */ +void +pk_backend_initialize (PkBackend *backend) +{ + /* create private area */ + priv = g_new0 (PkBackendClickPrivate, 1); + + g_debug ("backend: initialize"); + priv->spawn = pk_backend_spawn_new (); + pk_backend_spawn_set_filter_stderr (priv->spawn, pk_backend_stderr_cb); + pk_backend_spawn_set_filter_stdout (priv->spawn, pk_backend_stdout_cb); + pk_backend_spawn_set_name (priv->spawn, "click"); + pk_backend_spawn_set_allow_sigkill (priv->spawn, FALSE); +} + +/** + * pk_backend_destroy: + * This should only be run once per backend load, i.e. not every transaction + */ +void +pk_backend_destroy (PkBackend *backend) +{ + g_debug ("backend: destroy"); + g_object_unref (priv->spawn); + g_free (priv); +} + +/** + * pk_backend_start_job: + */ +void +pk_backend_start_job (PkBackend *backend, PkBackendJob *job) +{ + if (pk_backend_spawn_is_busy (priv->spawn)) { + pk_backend_job_error_code (job, + PK_ERROR_ENUM_LOCK_REQUIRED, + "spawned backend requires lock"); + pk_backend_job_finished (job); + return; + } +} + +/** + * pk_backend_get_filters: + */ +PkBitfield +pk_backend_get_filters (PkBackend *backend) +{ + return pk_bitfield_from_enums ( + PK_FILTER_ENUM_INSTALLED, + -1); +} + +/** + * pk_backend_get_roles: + */ +PkBitfield +pk_backend_get_roles (PkBackend *backend) +{ + return pk_bitfield_from_enums ( + PK_ROLE_ENUM_GET_PACKAGES, + PK_ROLE_ENUM_INSTALL_FILES, + PK_ROLE_ENUM_REMOVE_PACKAGES, + -1); +} + +/** + * pk_backend_get_mime_types: + */ +gchar ** +pk_backend_get_mime_types (PkBackend *backend) +{ + const gchar *mime_types[] = { + "application/x-deb", + NULL }; + return g_strdupv ((gchar **) mime_types); +} + +/** + * * pk_backend_get_groups: + * */ +PkBitfield +pk_backend_get_groups (PkBackend *backend) +{ + return pk_bitfield_from_enums ( + PK_GROUP_ENUM_UNKNOWN, + -1); +} + +/** + * pk_backend_get_packages: + */ +void +pk_backend_get_packages (PkBackend *backend, PkBackendJob *job, PkBitfield filters) +{ + gchar *filters_text; + filters_text = pk_filter_bitfield_to_string (filters); + pk_backend_spawn_helper (priv->spawn, job, "clickBackend.py", "get-packages", filters_text, NULL); + g_free (filters_text); +} + +/** + * pk_backend_install_files: + */ +void +pk_backend_install_files (PkBackend *backend, PkBackendJob *job, PkBitfield transaction_flags, gchar **full_paths) +{ + gchar *package_ids_temp; + gchar *transaction_flags_temp; + package_ids_temp = g_strjoinv (PK_BACKEND_SPAWN_FILENAME_DELIM, full_paths); + transaction_flags_temp = pk_transaction_flag_bitfield_to_string (transaction_flags); + pk_backend_spawn_helper (priv->spawn, job, + "clickBackend.py", + "install-files", + transaction_flags_temp, + package_ids_temp, + NULL); + g_free (package_ids_temp); + g_free (transaction_flags_temp); +} + +/** + * pk_backend_remove_packages: + */ +void +pk_backend_remove_packages (PkBackend *backend, PkBackendJob *job, + PkBitfield transaction_flags, + gchar **package_ids, + gboolean allow_deps, + gboolean autoremove) +{ + gchar *package_ids_temp; + gchar *transaction_flags_temp; + package_ids_temp = pk_package_ids_to_string (package_ids); + transaction_flags_temp = pk_transaction_flag_bitfield_to_string (transaction_flags); + pk_backend_spawn_helper (priv->spawn, job, + "clickBackend.py", + "remove-packages", + transaction_flags_temp, + package_ids_temp, + pk_backend_bool_to_string (allow_deps), + pk_backend_bool_to_string (autoremove), + NULL); + g_free (package_ids_temp); + g_free (transaction_flags_temp); +} diff --git a/configure.ac b/configure.ac index b26bd05..12c34da 100644 --- a/configure.ac +++ b/configure.ac @@ -490,6 +490,7 @@ AC_ARG_ENABLE(alpm, AS_HELP_STRING([--enable-alpm],[use the ALPM backend]),enabl AC_ARG_ENABLE(apt, AS_HELP_STRING([--enable-apt],[use the APT backend]),enable_apt=$enableval,enable_apt=no) AC_ARG_ENABLE(aptcc, AS_HELP_STRING([--enable-aptcc],[use the APTcc backend]),enable_aptcc=$enableval,enable_aptcc=no) AC_ARG_ENABLE(box, AS_HELP_STRING([--enable-box],[use the BOX backend]),enable_box=$enableval,enable_box=no) +AC_ARG_ENABLE(click, AS_HELP_STRING([--enable-click],[use the Click backend]),enable_click=$enableval,enable_click=no) AC_ARG_ENABLE(conary, AS_HELP_STRING([--enable-conary],[use the CONARY backend]),enable_conary=$enableval,enable_conary=no) AC_ARG_ENABLE(dummy, AS_HELP_STRING([--enable-dummy],[use the dummy backend]),enable_dummy=$enableval,enable_dummy=yes) AC_ARG_ENABLE(entropy, AS_HELP_STRING([--enable-entropy],[use the entropy backend]),enable_entropy=$enableval,enable_entropy=no) @@ -511,6 +512,7 @@ AM_CONDITIONAL(BACKEND_TYPE_ALPM, [test x$enable_alpm = xyes]) AM_CONDITIONAL(BACKEND_TYPE_APT, [test x$enable_apt = xyes]) AM_CONDITIONAL(BACKEND_TYPE_APTCC, [test x$enable_aptcc = xyes]) AM_CONDITIONAL(BACKEND_TYPE_BOX, [test x$enable_box = xyes]) +AM_CONDITIONAL(BACKEND_TYPE_CLICK, [test x$enable_click = xyes]) AM_CONDITIONAL(BACKEND_TYPE_CONARY, [test x$enable_conary = xyes]) AM_CONDITIONAL(BACKEND_TYPE_DUMMY, [test x$enable_dummy = xyes]) AM_CONDITIONAL(BACKEND_TYPE_ENTROPY, [test x$enable_entropy = xyes]) @@ -580,7 +582,7 @@ dnl --------------------------------------------------------------------------- AC_ARG_WITH([default_backend], AS_HELP_STRING([--with-default-backend=<option>], [Default backend to use - auto,alpm,apt,aptcc,box,conary,dummy,entropy,hawkey,opkg,pisi,portage,ports,slapt,smart,urpmi,yum,zif,zypp (dummy)])) + auto,alpm,apt,aptcc,box,click,conary,dummy,entropy,hawkey,opkg,pisi,portage,ports,slapt,smart,urpmi,yum,zif,zypp (dummy)])) # default to a sane option for the installed tool if test x$with_default_backend = x; then if test -f /usr/bin/yum ; then @@ -589,6 +591,8 @@ if test x$with_default_backend = x; then with_default_backend=zif elif test -f /usr/lib/libalpm.so; then with_default_backend=alpm + elif test -f /usr/bin/click-package ; then + with_default_backend=click elif test -f /usr/bin/apt-get ; then with_default_backend=aptcc elif test -f /usr/bin/conary ; then @@ -757,6 +761,10 @@ if test x$enable_slapt = xyes; then AC_SUBST(SLAPT_LIBS) fi +if test x$enable_apt = xyes; then + PY_CHECK_MOD([clickpackage],,,AC_MSG_ERROR([Click backend needs python3-clickpackage.install])) +fi + AC_SUBST(PK_CONF_DIR, "\$(sysconfdir)/PackageKit") AC_SUBST(PK_YUM_PLUGIN_DIR, "\$(prefix)/lib/yum-plugins") AC_SUBST(PK_DB_DIR, "\$(localstatedir)/lib/PackageKit") @@ -792,6 +800,7 @@ backends/alpm/Makefile backends/apt/Makefile backends/aptcc/Makefile backends/box/Makefile +backends/click/Makefile backends/conary/Makefile backends/dummy/Makefile backends/entropy/Makefile @@ -872,6 +881,7 @@ echo " APTcc backend: ${enable_aptcc} BOX backend: ${enable_box} CONARY backend: ${enable_conary} + Click backend: ${enable_click} dummy backend: ${enable_dummy} Entropy backend: ${enable_entropy} Hawkey backend: ${enable_hawkey} -- 1.7.10.4
-- Mailing list: https://launchpad.net/~ubuntu-appstore-developers Post to : [email protected] Unsubscribe : https://launchpad.net/~ubuntu-appstore-developers More help : https://help.launchpad.net/ListHelp

