The activity registry is now private to the shell.
Changed the activityfactory to take a bundle instead of a bundle_id so that it doesn't depend on the registry.
This commit is contained in:
parent
0f33a634c0
commit
5c6c7ab1d1
@ -6,5 +6,4 @@ sugar_PYTHON = \
|
|||||||
activityhandle.py \
|
activityhandle.py \
|
||||||
activityservice.py \
|
activityservice.py \
|
||||||
bundlebuilder.py \
|
bundlebuilder.py \
|
||||||
main.py \
|
main.py
|
||||||
registry.py
|
|
||||||
|
@ -53,6 +53,3 @@ class. This class allows for querying the ID of the root
|
|||||||
window, requesting sharing across the network, and basic
|
window, requesting sharing across the network, and basic
|
||||||
"what type of application are you" queries.
|
"what type of application are you" queries.
|
||||||
"""
|
"""
|
||||||
from sugar.activity.registry import ActivityRegistry
|
|
||||||
from sugar.activity.registry import get_registry
|
|
||||||
from sugar.activity.registry import ActivityInfo
|
|
||||||
|
@ -23,7 +23,6 @@ import gobject
|
|||||||
|
|
||||||
from sugar.presence import presenceservice
|
from sugar.presence import presenceservice
|
||||||
from sugar.activity.activityhandle import ActivityHandle
|
from sugar.activity.activityhandle import ActivityHandle
|
||||||
from sugar.activity import registry
|
|
||||||
from sugar import util
|
from sugar import util
|
||||||
from sugar import env
|
from sugar import env
|
||||||
|
|
||||||
@ -84,9 +83,9 @@ def create_activity_id():
|
|||||||
def get_environment(activity):
|
def get_environment(activity):
|
||||||
environ = os.environ.copy()
|
environ = os.environ.copy()
|
||||||
|
|
||||||
bin_path = os.path.join(activity.path, 'bin')
|
bin_path = os.path.join(activity.get_path(), 'bin')
|
||||||
|
|
||||||
activity_root = env.get_profile_path(activity.bundle_id)
|
activity_root = env.get_profile_path(activity.get_bundle_id())
|
||||||
if not os.path.exists(activity_root):
|
if not os.path.exists(activity_root):
|
||||||
os.mkdir(activity_root)
|
os.mkdir(activity_root)
|
||||||
|
|
||||||
@ -102,19 +101,19 @@ def get_environment(activity):
|
|||||||
if not os.path.exists(tmp_dir):
|
if not os.path.exists(tmp_dir):
|
||||||
os.mkdir(tmp_dir)
|
os.mkdir(tmp_dir)
|
||||||
|
|
||||||
environ['SUGAR_BUNDLE_PATH'] = activity.path
|
environ['SUGAR_BUNDLE_PATH'] = activity.get_path()
|
||||||
environ['SUGAR_BUNDLE_ID'] = activity.bundle_id
|
environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id()
|
||||||
environ['SUGAR_ACTIVITY_ROOT'] = activity_root
|
environ['SUGAR_ACTIVITY_ROOT'] = activity_root
|
||||||
environ['PATH'] = bin_path + ':' + environ['PATH']
|
environ['PATH'] = bin_path + ':' + environ['PATH']
|
||||||
#environ['RAINBOW_STRACE_LOG'] = '1'
|
#environ['RAINBOW_STRACE_LOG'] = '1'
|
||||||
|
|
||||||
if activity.path.startswith(env.get_user_activities_path()):
|
if activity.get_path().startswith(env.get_user_activities_path()):
|
||||||
environ['SUGAR_LOCALEDIR'] = os.path.join(activity.path, 'locale')
|
environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(), 'locale')
|
||||||
|
|
||||||
if activity.bundle_id in [ 'org.laptop.WebActivity',
|
if activity.get_bundle_id() in [ 'org.laptop.WebActivity',
|
||||||
'org.laptop.GmailActivity',
|
'org.laptop.GmailActivity',
|
||||||
'org.laptop.WikiBrowseActivity'
|
'org.laptop.WikiBrowseActivity'
|
||||||
]:
|
]:
|
||||||
environ['RAINBOW_CONSTANT_UID'] = 'yes'
|
environ['RAINBOW_CONSTANT_UID'] = 'yes'
|
||||||
|
|
||||||
return environ
|
return environ
|
||||||
@ -123,8 +122,8 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
|
|||||||
if not activity_id:
|
if not activity_id:
|
||||||
activity_id = create_activity_id()
|
activity_id = create_activity_id()
|
||||||
|
|
||||||
command = activity.command.split(' ')
|
command = activity.get_command().split(' ')
|
||||||
command.extend(['-b', activity.bundle_id])
|
command.extend(['-b', activity.get_bundle_id()])
|
||||||
command.extend(['-a', activity_id])
|
command.extend(['-a', activity_id])
|
||||||
|
|
||||||
if object_id is not None:
|
if object_id is not None:
|
||||||
@ -139,7 +138,7 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
|
|||||||
def open_log_file(activity):
|
def open_log_file(activity):
|
||||||
i = 1
|
i = 1
|
||||||
while True:
|
while True:
|
||||||
path = env.get_logs_path('%s-%s.log' % (activity.bundle_id, i))
|
path = env.get_logs_path('%s-%s.log' % (activity.get_bundle_id(), i))
|
||||||
try:
|
try:
|
||||||
fd = os.open(path, os.O_EXCL | os.O_CREAT \
|
fd = os.open(path, os.O_EXCL | os.O_CREAT \
|
||||||
| os.O_SYNC | os.O_WRONLY, 0644)
|
| os.O_SYNC | os.O_WRONLY, 0644)
|
||||||
@ -164,10 +163,10 @@ class ActivityCreationHandler(gobject.GObject):
|
|||||||
create call.
|
create call.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, service_name, handle):
|
def __init__(self, bundle, handle):
|
||||||
"""Initialise the handler
|
"""Initialise the handler
|
||||||
|
|
||||||
service_name -- the service name of the bundle factory
|
bundle -- the ActivityBundle to launch
|
||||||
activity_handle -- stores the values which are to
|
activity_handle -- stores the values which are to
|
||||||
be passed to the service to uniquely identify
|
be passed to the service to uniquely identify
|
||||||
the activity to be created and the sharing
|
the activity to be created and the sharing
|
||||||
@ -190,15 +189,16 @@ class ActivityCreationHandler(gobject.GObject):
|
|||||||
"""
|
"""
|
||||||
gobject.GObject.__init__(self)
|
gobject.GObject.__init__(self)
|
||||||
|
|
||||||
self._service_name = service_name
|
self._bundle = bundle
|
||||||
|
self._service_name = bundle.get_bundle_id()
|
||||||
self._handle = handle
|
self._handle = handle
|
||||||
|
|
||||||
self._use_rainbow = os.path.exists('/etc/olpc-security')
|
self._use_rainbow = os.path.exists('/etc/olpc-security')
|
||||||
if service_name in [ 'org.laptop.JournalActivity',
|
if self._service_name in [ 'org.laptop.JournalActivity',
|
||||||
'org.laptop.Terminal',
|
'org.laptop.Terminal',
|
||||||
'org.laptop.Log',
|
'org.laptop.Log',
|
||||||
'org.laptop.Analyze'
|
'org.laptop.Analyze'
|
||||||
]:
|
]:
|
||||||
self._use_rainbow = False
|
self._use_rainbow = False
|
||||||
|
|
||||||
bus = dbus.SessionBus()
|
bus = dbus.SessionBus()
|
||||||
@ -233,49 +233,46 @@ class ActivityCreationHandler(gobject.GObject):
|
|||||||
reply_handler=self._no_reply_handler,
|
reply_handler=self._no_reply_handler,
|
||||||
error_handler=self._notify_launch_error_handler)
|
error_handler=self._notify_launch_error_handler)
|
||||||
|
|
||||||
activity_registry = registry.get_registry()
|
environ = get_environment(self._bundle)
|
||||||
activity = activity_registry.get_activity(self._service_name)
|
(log_path, log_file) = open_log_file(self._bundle)
|
||||||
if activity:
|
command = get_command(self._bundle, self._handle.activity_id,
|
||||||
environ = get_environment(activity)
|
self._handle.object_id,
|
||||||
(log_path, log_file) = open_log_file(activity)
|
self._handle.uri)
|
||||||
command = get_command(activity, self._handle.activity_id,
|
|
||||||
self._handle.object_id,
|
|
||||||
self._handle.uri)
|
|
||||||
|
|
||||||
if not self._use_rainbow:
|
if not self._use_rainbow:
|
||||||
# use gobject spawn functionality, so that zombies are
|
# use gobject spawn functionality, so that zombies are
|
||||||
# automatically reaped by the gobject event loop.
|
# automatically reaped by the gobject event loop.
|
||||||
def child_setup():
|
def child_setup():
|
||||||
# clone logfile.fileno() onto stdout/stderr
|
# clone logfile.fileno() onto stdout/stderr
|
||||||
os.dup2(log_file.fileno(), 1)
|
os.dup2(log_file.fileno(), 1)
|
||||||
os.dup2(log_file.fileno(), 2)
|
os.dup2(log_file.fileno(), 2)
|
||||||
# close all other fds
|
# close all other fds
|
||||||
_close_fds()
|
_close_fds()
|
||||||
# we need to sanitize and str-ize the various bits which
|
# we need to sanitize and str-ize the various bits which
|
||||||
# dbus gives us.
|
# dbus gives us.
|
||||||
gobject.spawn_async([str(s) for s in command],
|
gobject.spawn_async([str(s) for s in command],
|
||||||
envp=['%s=%s' % (k, str(v))
|
envp=['%s=%s' % (k, str(v))
|
||||||
for k, v in environ.items()],
|
for k, v in environ.items()],
|
||||||
working_directory=str(activity.path),
|
working_directory=str(self._bundle.get_path()),
|
||||||
child_setup=child_setup,
|
child_setup=child_setup,
|
||||||
flags=(gobject.SPAWN_SEARCH_PATH |
|
flags=(gobject.SPAWN_SEARCH_PATH |
|
||||||
gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN))
|
gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN))
|
||||||
log_file.close()
|
log_file.close()
|
||||||
else:
|
else:
|
||||||
log_file.close()
|
log_file.close()
|
||||||
system_bus = dbus.SystemBus()
|
system_bus = dbus.SystemBus()
|
||||||
factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
|
factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
|
||||||
_RAINBOW_ACTIVITY_FACTORY_PATH)
|
_RAINBOW_ACTIVITY_FACTORY_PATH)
|
||||||
factory.CreateActivity(
|
factory.CreateActivity(
|
||||||
log_path,
|
log_path,
|
||||||
environ,
|
environ,
|
||||||
command,
|
command,
|
||||||
environ['SUGAR_BUNDLE_PATH'],
|
environ['SUGAR_BUNDLE_PATH'],
|
||||||
environ['SUGAR_BUNDLE_ID'],
|
environ['SUGAR_BUNDLE_ID'],
|
||||||
timeout=30,
|
timeout=30,
|
||||||
reply_handler=self._create_reply_handler,
|
reply_handler=self._create_reply_handler,
|
||||||
error_handler=self._create_error_handler,
|
error_handler=self._create_error_handler,
|
||||||
dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
|
dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
|
||||||
|
|
||||||
def _no_reply_handler(self, *args):
|
def _no_reply_handler(self, *args):
|
||||||
pass
|
pass
|
||||||
@ -315,18 +312,18 @@ class ActivityCreationHandler(gobject.GObject):
|
|||||||
logging.error("Datastore find failed %s" % err)
|
logging.error("Datastore find failed %s" % err)
|
||||||
self._create_activity()
|
self._create_activity()
|
||||||
|
|
||||||
def create(service_name, activity_handle=None):
|
def create(bundle, activity_handle=None):
|
||||||
"""Create a new activity from its name."""
|
"""Create a new activity from its name."""
|
||||||
if not activity_handle:
|
if not activity_handle:
|
||||||
activity_handle = ActivityHandle()
|
activity_handle = ActivityHandle()
|
||||||
return ActivityCreationHandler(service_name, activity_handle)
|
return ActivityCreationHandler(bundle, activity_handle)
|
||||||
|
|
||||||
def create_with_uri(service_name, uri):
|
def create_with_uri(bundle, uri):
|
||||||
"""Create a new activity and pass the uri as handle."""
|
"""Create a new activity and pass the uri as handle."""
|
||||||
activity_handle = ActivityHandle(uri=uri)
|
activity_handle = ActivityHandle(uri=uri)
|
||||||
return ActivityCreationHandler(service_name, activity_handle)
|
return ActivityCreationHandler(bundle, activity_handle)
|
||||||
|
|
||||||
def create_with_object_id(service_name, object_id):
|
def create_with_object_id(bundle, object_id):
|
||||||
"""Create a new activity and pass the object id as handle."""
|
"""Create a new activity and pass the object id as handle."""
|
||||||
activity_handle = ActivityHandle(object_id=object_id)
|
activity_handle = ActivityHandle(object_id=object_id)
|
||||||
return ActivityCreationHandler(service_name, activity_handle)
|
return ActivityCreationHandler(bundle, activity_handle)
|
||||||
|
@ -1,189 +0,0 @@
|
|||||||
# Copyright (C) 2006-2007 Red Hat, Inc.
|
|
||||||
# Copyright (C) 2007 One Laptop Per Child
|
|
||||||
#
|
|
||||||
# This library is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
|
||||||
# License as published by the Free Software Foundation; either
|
|
||||||
# version 2 of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This library 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
|
|
||||||
# Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
|
||||||
# License along with this library; if not, write to the
|
|
||||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
# Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import dbus
|
|
||||||
import gobject
|
|
||||||
|
|
||||||
_ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry'
|
|
||||||
_ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry'
|
|
||||||
_ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry'
|
|
||||||
|
|
||||||
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['version'],
|
|
||||||
info_dict['path'], info_dict['show_launcher'],
|
|
||||||
info_dict['command'], info_dict['favorite'],
|
|
||||||
info_dict['installation_time'],
|
|
||||||
info_dict['position_x'], info_dict['position_y'])
|
|
||||||
|
|
||||||
class ActivityInfo(object):
|
|
||||||
def __init__(self, name, icon, bundle_id, version, path, show_launcher,
|
|
||||||
command, favorite, installation_time, position_x, position_y):
|
|
||||||
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
|
|
||||||
self.favorite = favorite
|
|
||||||
self.installation_time = installation_time
|
|
||||||
self.position = (position_x, position_y)
|
|
||||||
|
|
||||||
class ActivityRegistry(gobject.GObject):
|
|
||||||
__gsignals__ = {
|
|
||||||
'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
||||||
([gobject.TYPE_PYOBJECT])),
|
|
||||||
'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
||||||
([gobject.TYPE_PYOBJECT])),
|
|
||||||
'activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
||||||
([gobject.TYPE_PYOBJECT]))
|
|
||||||
}
|
|
||||||
def __init__(self):
|
|
||||||
gobject.GObject.__init__(self)
|
|
||||||
|
|
||||||
bus = dbus.SessionBus()
|
|
||||||
|
|
||||||
# NOTE: We need to follow_name_owner_changes here
|
|
||||||
# because we can not connect to a signal unless
|
|
||||||
# we follow the changes or we start the service
|
|
||||||
# before we connect. Starting the service here
|
|
||||||
# causes a major bottleneck during startup
|
|
||||||
bus_object = bus.get_object(_ACTIVITY_REGISTRY_SERVICE_NAME,
|
|
||||||
_ACTIVITY_REGISTRY_PATH,
|
|
||||||
follow_name_owner_changes = True)
|
|
||||||
self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE)
|
|
||||||
self._registry.connect_to_signal('ActivityAdded',
|
|
||||||
self._activity_added_cb)
|
|
||||||
self._registry.connect_to_signal('ActivityRemoved',
|
|
||||||
self._activity_removed_cb)
|
|
||||||
self._registry.connect_to_signal('ActivityChanged',
|
|
||||||
self._activity_changed_cb)
|
|
||||||
|
|
||||||
# Two caches fo saving some travel across dbus.
|
|
||||||
self._service_name_to_activity_info = {}
|
|
||||||
self._mime_type_to_activities = {}
|
|
||||||
|
|
||||||
def _convert_info_list(self, info_list):
|
|
||||||
result = []
|
|
||||||
|
|
||||||
for info_dict in info_list:
|
|
||||||
result.append(_activity_info_from_dict(info_dict))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def get_activities(self):
|
|
||||||
info_list = self._registry.GetActivities()
|
|
||||||
return self._convert_info_list(info_list)
|
|
||||||
|
|
||||||
def _get_activities_cb(self, reply_handler, info_list):
|
|
||||||
result = []
|
|
||||||
for info_dict in info_list:
|
|
||||||
result.append(_activity_info_from_dict(info_dict))
|
|
||||||
|
|
||||||
reply_handler(result)
|
|
||||||
|
|
||||||
def _get_activities_error_cb(self, error_handler, e):
|
|
||||||
if error_handler:
|
|
||||||
error_handler(e)
|
|
||||||
else:
|
|
||||||
logging.error('Error getting activities async: %s' % str(e))
|
|
||||||
|
|
||||||
def get_activities_async(self, reply_handler=None, error_handler=None):
|
|
||||||
if not reply_handler:
|
|
||||||
logging.error('Function get_activities_async called' \
|
|
||||||
'without a reply handler. Can not run.')
|
|
||||||
return
|
|
||||||
|
|
||||||
self._registry.GetActivities(
|
|
||||||
reply_handler=lambda info_list: \
|
|
||||||
self._get_activities_cb(reply_handler, info_list),
|
|
||||||
error_handler=lambda e: \
|
|
||||||
self._get_activities_error_cb(error_handler, e))
|
|
||||||
|
|
||||||
def get_activity(self, service_name):
|
|
||||||
if self._service_name_to_activity_info.has_key(service_name):
|
|
||||||
return self._service_name_to_activity_info[service_name]
|
|
||||||
|
|
||||||
info_dict = self._registry.GetActivity(service_name)
|
|
||||||
activity_info = _activity_info_from_dict(info_dict)
|
|
||||||
|
|
||||||
self._service_name_to_activity_info[service_name] = activity_info
|
|
||||||
return activity_info
|
|
||||||
|
|
||||||
def find_activity(self, name):
|
|
||||||
info_list = self._registry.FindActivity(name)
|
|
||||||
return self._convert_info_list(info_list)
|
|
||||||
|
|
||||||
def get_activities_for_type(self, mime_type):
|
|
||||||
if self._mime_type_to_activities.has_key(mime_type):
|
|
||||||
return self._mime_type_to_activities[mime_type]
|
|
||||||
|
|
||||||
info_list = self._registry.GetActivitiesForType(mime_type)
|
|
||||||
activities = self._convert_info_list(info_list)
|
|
||||||
|
|
||||||
self._mime_type_to_activities[mime_type] = activities
|
|
||||||
return activities
|
|
||||||
|
|
||||||
def add_bundle(self, bundle_path):
|
|
||||||
result = self._registry.AddBundle(bundle_path)
|
|
||||||
# Need to invalidate here because get_activity could be called after
|
|
||||||
# add_bundle and before we receive activity-added, causing a race.
|
|
||||||
self._invalidate_cache()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _activity_added_cb(self, info_dict):
|
|
||||||
logging.debug('ActivityRegistry._activity_added_cb: invalidating cache')
|
|
||||||
self._invalidate_cache()
|
|
||||||
self.emit('activity-added', _activity_info_from_dict(info_dict))
|
|
||||||
|
|
||||||
def _invalidate_cache(self):
|
|
||||||
self._service_name_to_activity_info.clear()
|
|
||||||
self._mime_type_to_activities.clear()
|
|
||||||
|
|
||||||
def remove_bundle(self, bundle_path):
|
|
||||||
self._invalidate_cache()
|
|
||||||
return self._registry.RemoveBundle(bundle_path)
|
|
||||||
|
|
||||||
def _activity_removed_cb(self, info_dict):
|
|
||||||
logging.debug('ActivityRegistry._activity_removed_cb: flushing caches')
|
|
||||||
self._invalidate_cache()
|
|
||||||
self.emit('activity-removed', _activity_info_from_dict(info_dict))
|
|
||||||
|
|
||||||
def _activity_changed_cb(self, info_dict):
|
|
||||||
logging.debug('ActivityRegistry._activity_changed_cb: flushing caches')
|
|
||||||
self._invalidate_cache()
|
|
||||||
self.emit('activity-changed', _activity_info_from_dict(info_dict))
|
|
||||||
|
|
||||||
def set_activity_favorite(self, bundle_id, version, favorite):
|
|
||||||
self._registry.SetActivityFavorite(bundle_id, version, favorite)
|
|
||||||
|
|
||||||
def set_activity_position(self, bundle_id, version, x, y):
|
|
||||||
self._registry.SetActivityPosition(bundle_id, version, x, y)
|
|
||||||
|
|
||||||
_registry = None
|
|
||||||
|
|
||||||
def get_registry():
|
|
||||||
global _registry
|
|
||||||
if not _registry:
|
|
||||||
_registry = ActivityRegistry()
|
|
||||||
return _registry
|
|
@ -259,7 +259,6 @@ class ActivityBundle(Bundle):
|
|||||||
|
|
||||||
return command
|
return command
|
||||||
|
|
||||||
|
|
||||||
def get_mime_types(self):
|
def get_mime_types(self):
|
||||||
"""Get the MIME types supported by the activity"""
|
"""Get the MIME types supported by the activity"""
|
||||||
return self._mime_types
|
return self._mime_types
|
||||||
@ -268,22 +267,7 @@ class ActivityBundle(Bundle):
|
|||||||
"""Get whether there should be a visible launcher for the activity"""
|
"""Get whether there should be a visible launcher for the activity"""
|
||||||
return self._show_launcher
|
return self._show_launcher
|
||||||
|
|
||||||
def is_installed(self):
|
def install(self, install_dir, strict_manifest=False):
|
||||||
if activity.get_registry().get_activity(self._bundle_id):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def need_upgrade(self):
|
|
||||||
"""Returns True if installing this activity bundle is meaningful -
|
|
||||||
that is, if an identical version of this activity is not
|
|
||||||
already installed.
|
|
||||||
|
|
||||||
Until we have cryptographic hashes to check identity, returns
|
|
||||||
True always. See http://dev.laptop.org/ticket/7534."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def unpack(self, install_dir, strict_manifest=False):
|
|
||||||
self._unzip(install_dir)
|
self._unzip(install_dir)
|
||||||
|
|
||||||
install_path = os.path.join(install_dir, self._zip_root_dir)
|
install_path = os.path.join(install_dir, self._zip_root_dir)
|
||||||
@ -352,35 +336,7 @@ class ActivityBundle(Bundle):
|
|||||||
os.path.basename(info_file)))
|
os.path.basename(info_file)))
|
||||||
return install_path
|
return install_path
|
||||||
|
|
||||||
def install(self):
|
def uninstall(self, install_path, force=False):
|
||||||
activities_path = env.get_user_activities_path()
|
|
||||||
act = activity.get_registry().get_activity(self._bundle_id)
|
|
||||||
if act is not None and act.path.startswith(activities_path):
|
|
||||||
raise AlreadyInstalledException
|
|
||||||
|
|
||||||
install_dir = env.get_user_activities_path()
|
|
||||||
install_path = self.unpack(install_dir)
|
|
||||||
|
|
||||||
if not activity.get_registry().add_bundle(install_path):
|
|
||||||
raise RegistrationException
|
|
||||||
|
|
||||||
def uninstall(self, force=False):
|
|
||||||
if self._zip_file is None:
|
|
||||||
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, different bundle present')
|
|
||||||
return
|
|
||||||
elif not act.path.startswith(env.get_user_activities_path()):
|
|
||||||
logging.warning('Not uninstalling system activity')
|
|
||||||
return
|
|
||||||
|
|
||||||
install_path = act.path
|
|
||||||
|
|
||||||
xdg_data_home = os.getenv('XDG_DATA_HOME',
|
xdg_data_home = os.getenv('XDG_DATA_HOME',
|
||||||
os.path.expanduser('~/.local/share'))
|
os.path.expanduser('~/.local/share'))
|
||||||
|
|
||||||
@ -404,23 +360,3 @@ class ActivityBundle(Bundle):
|
|||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
self._uninstall(install_path)
|
self._uninstall(install_path)
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user