From d35c19b6aaeb79df700bf063f4bf3d298c20bf7a Mon Sep 17 00:00:00 2001 From: Reinier Heeres Date: Tue, 18 Dec 2007 13:43:34 +0100 Subject: [PATCH] Allow activity up- and downgrades #4906, also fix #5382 --- lib/sugar/activity/registry.py | 10 ++++-- lib/sugar/bundle/activitybundle.py | 42 +++++++++++++++++++++-- lib/sugar/datastore/datastore.py | 6 ++++ services/shell/activityregistryservice.py | 1 + shell/view/frame/activitiestray.py | 2 +- 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/lib/sugar/activity/registry.py b/lib/sugar/activity/registry.py index c21d4a50..ac672d5e 100644 --- a/lib/sugar/activity/registry.py +++ b/lib/sugar/activity/registry.py @@ -29,15 +29,17 @@ def _activity_info_from_dict(info_dict): if not info_dict: return None return ActivityInfo(info_dict['name'], info_dict['icon'], - info_dict['bundle_id'], info_dict['path'], - info_dict['show_launcher'], info_dict['command']) + info_dict['bundle_id'], info_dict['version'], + info_dict['path'], info_dict['show_launcher'], + info_dict['command']) class ActivityInfo(object): - def __init__(self, name, icon, bundle_id, + def __init__(self, name, icon, bundle_id, version, path, show_launcher, command): self.name = name self.icon = icon self.bundle_id = bundle_id + self.version = version self.path = path self.command = command self.show_launcher = show_launcher @@ -146,6 +148,8 @@ class ActivityRegistry(gobject.GObject): self._mime_type_to_activities.clear() def remove_bundle(self, bundle_path): + self._service_name_to_activity_info.clear() + self._mime_type_to_activities.clear() return self._registry.RemoveBundle(bundle_path) def _activity_removed_cb(self, info_dict): diff --git a/lib/sugar/bundle/activitybundle.py b/lib/sugar/bundle/activitybundle.py index ce1510f0..ee72f809 100644 --- a/lib/sugar/bundle/activitybundle.py +++ b/lib/sugar/bundle/activitybundle.py @@ -22,10 +22,15 @@ import locale import os import tempfile -from sugar.bundle.bundle import Bundle, MalformedBundleException +from sugar.bundle.bundle import Bundle, MalformedBundleException, \ + AlreadyInstalledException, RegistrationException, \ + NotInstalledException + from sugar import activity from sugar import env +import logging + class ActivityBundle(Bundle): """A Sugar activity bundle @@ -204,8 +209,16 @@ class ActivityBundle(Bundle): else: return False + def need_upgrade(self): + act = activity.get_registry().get_activity(self._bundle_id) + if act is None or act.version != self._activity_version: + return True + else: + return False + def install(self): - if self.is_installed(): + act = activity.get_registry().get_activity(self._bundle_id) + if act is not None and act.path.startswith(env.get_user_activities_path()): raise AlreadyInstalledException install_dir = env.get_user_activities_path() @@ -250,12 +263,21 @@ class ActivityBundle(Bundle): if not activity.get_registry().add_bundle(install_path): raise RegistrationException - def uninstall(self): + def uninstall(self, force=False): if self._unpacked: install_path = self._path else: if not self.is_installed(): raise NotInstalledException + + act = activity.get_registry().get_activity(self._bundle_id) + if not force and act.version != self._activity_version: + logging.warning('Not uninstalling because different bundle present') + return + elif not act.path.startswith(env.get_user_activities_path()): + logging.warning('Not uninstalling system activity') + return + install_path = os.path.join(env.get_user_activities_path(), self._zip_root_dir) @@ -283,3 +305,17 @@ class ActivityBundle(Bundle): if not activity.get_registry().remove_bundle(install_path): raise RegistrationException + def upgrade(self): + act = activity.get_registry().get_activity(self._bundle_id) + if act is None: + logging.warning('Activity not installed') + elif act.path.startswith(env.get_user_activities_path()): + try: + self.uninstall(force=True) + except Exception, e: + logging.warning('Uninstall failed (%s), still trying to install newer bundle', e) + else: + logging.warning('Unable to uninstall system activity, installing upgraded version in user activities') + + self.install() + diff --git a/lib/sugar/datastore/datastore.py b/lib/sugar/datastore/datastore.py index 5238d18b..334c866a 100644 --- a/lib/sugar/datastore/datastore.py +++ b/lib/sugar/datastore/datastore.py @@ -160,10 +160,16 @@ class DSObject(object): if bundle_id is not None: raise ValueError('Object is a bundle, cannot be resumed as an activity.') + logging.debug('Creating activity bundle') bundle = ActivityBundle(self.file_path) if not bundle.is_installed(): + logging.debug('Installing activity bundle') bundle.install() + elif bundle.need_upgrade(): + logging.debug('Upgrading activity bundle') + bundle.upgrade() + logging.debug('activityfactory.creating bundle with id %r', bundle.get_bundle_id()) activityfactory.create(bundle.get_bundle_id()) else: if not self.get_activities() and bundle_id is None: diff --git a/services/shell/activityregistryservice.py b/services/shell/activityregistryservice.py index b4323ee2..9c2dda7f 100644 --- a/services/shell/activityregistryservice.py +++ b/services/shell/activityregistryservice.py @@ -113,6 +113,7 @@ class ActivityRegistry(dbus.service.Object): return {'name': bundle.get_name(), 'icon': bundle.get_icon(), 'bundle_id': bundle.get_bundle_id(), + 'version': bundle.get_activity_version(), 'path': bundle.get_path(), 'command': bundle.get_command(), 'show_launcher': bundle.get_show_launcher()} diff --git a/shell/view/frame/activitiestray.py b/shell/view/frame/activitiestray.py index 6f8e89e9..3dbf9552 100644 --- a/shell/view/frame/activitiestray.py +++ b/shell/view/frame/activitiestray.py @@ -129,7 +129,7 @@ class ActivitiesTray(hippo.CanvasBox): def _activity_removed_cb(self, activity_registry, activity_info): for item in self._tray.get_children(): - if item.get_bundle_id() == activity_info.service_name: + if item.get_bundle_id() == activity_info.bundle_id: self._tray.remove_item(item) return