def install(self, bundle, uid=None, force_downgrade=False): activities_path = env.get_user_activities_path() for installed_bundle in self._bundles: if bundle.get_bundle_id() == installed_bundle.get_bundle_id() and \ NormalizedVersion(bundle.get_activity_version()) <= \ NormalizedVersion(installed_bundle.get_activity_version()): if not force_downgrade: raise AlreadyInstalledException else: self.uninstall(installed_bundle, force=True) elif bundle.get_bundle_id() == installed_bundle.get_bundle_id(): self.uninstall(installed_bundle, force=True) install_dir = env.get_user_activities_path() if isinstance(bundle, JournalEntryBundle): install_path = bundle.install(uid) elif isinstance(bundle, ContentBundle): install_path = bundle.install() else: install_path = bundle.install(install_dir) # TODO treat ContentBundle in special way # needs rethinking while fixing ContentBundle support if isinstance(bundle, ContentBundle) or \ isinstance(bundle, JournalEntryBundle): pass elif not self.add_bundle(install_path): raise RegistrationException
def generate_bundle(nick, new_basename): """Generate a new .xo bundle for the activity and copy it into the Journal. """ new_activity_name = _customize_activity_info( nick, new_basename) user_activities_path = get_user_activities_path() if os.path.exists(os.path.join(user_activities_path, new_basename, 'dist')): for path in glob.glob(os.path.join(user_activities_path, new_basename, 'dist', '*')): os.remove(path) config = bundlebuilder.Config(source_dir=os.path.join( user_activities_path, new_basename), dist_name='%s-1.xo' % (new_activity_name)) bundlebuilder.cmd_dist_xo(config, None) dsobject = datastore.create() dsobject.metadata['title'] = '%s-1.xo' % (new_activity_name) dsobject.metadata['mime_type'] = 'application/vnd.olpc-sugar' dsobject.set_file_path(os.path.join( user_activities_path, new_basename, 'dist', '%s-1.xo' % (new_activity_name))) datastore.write(dsobject) dsobject.destroy()
def finddir(): paths = ["/usr/share/sugar/activities", env.get_user_activities_path()] paths.append(os.path.join(os.path.expanduser("~"), "Activities")) sound_candidate_dirs = None for path in paths: if not os.path.exists(path): continue for f in os.listdir(path): if f in [ "TamTamMini.activity", "TamTamJam.activity", "TamTamEdit.activity", "TamTamSynthLab.activity", "MusicKeyboard.activity", ]: bundle_dir = os.path.join(path, f) tamtam_subdir = str(os.path.join(bundle_dir, "common", "Resources", "Sounds")) sound_candidate_dirs = [os.path.expandvars("$SUGAR_PATH/activities") + tamtam_subdir, tamtam_subdir] if sound_candidate_dirs is not None: for directory in sound_candidate_dirs: if os.path.isdir(directory): return directory raise SoundLibraryNotFoundError()
def finddir(): paths = ['/usr/share/sugar/activities', env.get_user_activities_path()] sound_candidate_dirs = None for path in paths: if not os.path.exists(path): continue for f in os.listdir(path): if f in ['TamTamMini.activity', 'TamTamJam.activity', 'TamTamEdit.activity', 'TamTamSynthLab.activity', 'MusicKeyboard.activity']: bundle_dir = os.path.join(path, f) tamtam_subdir = str( os.path.join(bundle_dir, 'common', 'Resources', 'Sounds')) sound_candidate_dirs = [ os.path.expandvars('$SUGAR_PATH/activities') + \ tamtam_subdir, tamtam_subdir ] if sound_candidate_dirs is not None: for directory in sound_candidate_dirs: if os.path.isdir(directory): return directory raise SoundLibraryNotFoundError()
def finddir(): paths = ['/usr/share/sugar/activities', env.get_user_activities_path()] paths.append(os.path.join(os.path.expanduser('~'), 'Activities')) sound_candidate_dirs = None for path in paths: if not os.path.exists(path): continue for f in os.listdir(path): if f in [ 'TamTamMini.activity', 'TamTamJam.activity', 'TamTamEdit.activity', 'TamTamSynthLab.activity', 'MusicKeyboard.activity' ]: bundle_dir = os.path.join(path, f) tamtam_subdir = str( os.path.join(bundle_dir, 'common', 'Resources', 'Sounds')) sound_candidate_dirs = [ os.path.expandvars('$SUGAR_PATH/activities') + tamtam_subdir, tamtam_subdir ] if sound_candidate_dirs is not None: for directory in sound_candidate_dirs: if os.path.isdir(directory): return directory raise SoundLibraryNotFoundError()
def generate_bundle(nick, new_basename): """Generate a new .xo bundle for the activity and copy it into the Journal. """ new_activity_name = _customize_activity_info(nick, new_basename) user_activities_path = get_user_activities_path() if os.path.exists(os.path.join(user_activities_path, new_basename, 'dist')): for path in glob.glob( os.path.join(user_activities_path, new_basename, 'dist', '*')): os.remove(path) source_dir = os.path.join(user_activities_path, new_basename) config = bundlebuilder.Config(source_dir=source_dir, dist_dir=os.path.join(source_dir, 'dist'), dist_name='%s-1' % (new_activity_name)) bundlebuilder.cmd_dist_xo(config, None) dsobject = datastore.create() dsobject.metadata['title'] = '%s-1.xo' % (new_activity_name) dsobject.metadata['mime_type'] = 'application/vnd.olpc-sugar' dsobject.set_file_path( os.path.join(user_activities_path, new_basename, 'dist', '%s-1.xo' % (new_activity_name))) datastore.write(dsobject) dsobject.destroy()
def get_environment(activity): environ = os.environ.copy() bin_path = os.path.join(activity.get_path(), 'bin') activity_root = env.get_profile_path(activity.get_bundle_id()) if not os.path.exists(activity_root): os.mkdir(activity_root) data_dir = os.path.join(activity_root, 'instance') if not os.path.exists(data_dir): os.mkdir(data_dir) data_dir = os.path.join(activity_root, 'data') if not os.path.exists(data_dir): os.mkdir(data_dir) tmp_dir = os.path.join(activity_root, 'tmp') if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) environ['SUGAR_BUNDLE_PATH'] = activity.get_path() environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id() environ['SUGAR_ACTIVITY_ROOT'] = activity_root environ['PATH'] = bin_path + ':' + environ['PATH'] if activity.get_path().startswith(env.get_user_activities_path()): environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(), 'locale') return environ
def get_environment(activity): environ = os.environ.copy() bin_path = os.path.join(activity.get_path(), 'bin') activity_root = env.get_profile_path(activity.get_bundle_id()) _mkdir(activity_root) instance_dir = os.path.join(activity_root, 'instance') _mkdir(instance_dir) data_dir = os.path.join(activity_root, 'data') _mkdir(data_dir) tmp_dir = os.path.join(activity_root, 'tmp') _mkdir(tmp_dir) environ['SUGAR_BUNDLE_PATH'] = activity.get_path() environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id() environ['SUGAR_ACTIVITY_ROOT'] = activity_root environ['PATH'] = bin_path + ':' + environ['PATH'] if activity.get_path().startswith(env.get_user_activities_path()): environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(), 'locale') return environ
def _get_temp_file_path(self, uri): # TODO: Should we use the HTTP headers for the file name? scheme_, netloc_, path, params_, query_, fragment_ = \ urlparse(uri) path = os.path.basename(path) if not os.path.exists(env.get_user_activities_path()): os.makedirs(env.get_user_activities_path()) base_name, extension_ = os.path.splitext(path) fd, file_path = tempfile.mkstemp(dir=env.get_user_activities_path(), prefix=base_name, suffix='.xo') os.close(fd) os.unlink(file_path) return file_path
def __init__(self): logging.debug('STARTUP: Loading the bundle registry') GObject.GObject.__init__(self) self._mime_defaults = self._load_mime_defaults() # Queue of bundles to be installed/upgraded self._install_queue = _InstallQueue(self) # Bundle installation happens in a separate thread, which needs # access to _bundles. Protect all _bundles access with a lock. self._lock = Lock() self._bundles = [] # hold a reference to the monitors so they don't get disposed self._gio_monitors = [] dirs = [env.get_user_activities_path(), env.get_user_library_path()] for data_dir in GLib.get_system_data_dirs(): dirs.append(os.path.join(data_dir, "sugar", "activities")) for activity_dir in dirs: self._scan_directory(activity_dir) directory = Gio.File.new_for_path(activity_dir) monitor = directory.monitor_directory( flags=Gio.FileMonitorFlags.NONE, cancellable=None) monitor.connect('changed', self.__file_monitor_changed_cb) self._gio_monitors.append(monitor) self._last_defaults_mtime = [] self._favorite_bundles = [] for i in range(desktop.get_number_of_views()): self._favorite_bundles.append({}) self._last_defaults_mtime.append(-1) client = GConf.Client.get_default() self._protected_activities = [] # FIXME, gconf_client_get_list not introspectable #681433 protected_activities = client.get( '/desktop/sugar/protected_activities') for gval in protected_activities.get_list(): activity_id = gval.get_string() self._protected_activities.append(activity_id) if self._protected_activities is None: self._protected_activities = [] try: self._load_favorites() except Exception: logging.exception('Error while loading favorite_activities.') self._merge_default_favorites() self._desktop_model = desktop.get_model() self._desktop_model.connect('desktop-view-icons-changed', self.__desktop_view_icons_changed_cb)
def _get_help_activity_path(): path = os.path.join(env.get_user_activities_path(), 'Help.activity') if os.path.exists(path): return path # if was installed by a distro package path = '/usr/share/sugar/activities/Help.activity' if os.path.exists(path): return path return None
def install(self): install_dir = env.get_user_activities_path() self._unzip(install_dir) install_path = os.path.join(install_dir, self._zip_root_dir) self.install_mime_type(install_path) return install_path
def _get_help_activity_path(): path = os.path.join(env.get_user_activities_path(), "Help.activity") if os.path.exists(path): return path # if was installed by a distro package path = "/usr/share/sugar/activities/Help.activity" if os.path.exists(path): return path return None
def __copy_to_home_cb(self, menu_item): """Make a local copy of the activity bundle in user_activities_path""" user_activities_path = get_user_activities_path() nick = customizebundle.generate_unique_id() new_basename = "%s_copy_of_%s" % (nick, os.path.basename(self._document_path)) if not os.path.exists(os.path.join(user_activities_path, new_basename)): shutil.copytree(self._document_path, os.path.join(user_activities_path, new_basename), symlinks=True) customizebundle.generate_bundle(nick, new_basename) else: _logger.debug("%s already exists", new_basename)
def _customize_activity_info(nick, new_basename): """Modify bundle_id in new activity.info file: (1) change the bundle_id to bundle_id_[NICKNAME]; (2) change the activity_icon [NICKNAME]-activity-icon.svg; (3) set activity_version to 1; (4) modify the activity icon by applying a customize overlay. """ new_activity_name = '' user_activities_path = get_user_activities_path() info_old = open( os.path.join(user_activities_path, new_basename, 'activity', 'activity.info'), 'r') info_new = open( os.path.join(user_activities_path, new_basename, 'activity', 'new_activity.info'), 'w') for line in info_old: if line.find('=') < 0: info_new.write(line) continue name, value = [token.strip() for token in line.split('=', 1)] if name == 'bundle_id': new_value = '%s_%s' % (value, nick) elif name == 'activity_version': new_value = '1' elif name == 'icon': new_value = value icon_name = value elif name == 'name': new_value = '%s_copy_of_%s' % (nick, value) new_activity_name = new_value else: info_new.write(line) continue info_new.write('%s = %s\n' % (name, new_value)) info_old.close() info_new.close() os.rename( os.path.join(user_activities_path, new_basename, 'activity', 'new_activity.info'), os.path.join(user_activities_path, new_basename, 'activity', 'activity.info')) _create_custom_icon(new_basename, icon_name) return new_activity_name
def __init__(self): logging.debug('STARTUP: Loading the bundle registry') GObject.GObject.__init__(self) self._mime_defaults = self._load_mime_defaults() # Queue of bundles to be installed/upgraded self._install_queue = _InstallQueue(self) # Bundle installation happens in a separate thread, which needs # access to _bundles. Protect all _bundles access with a lock. self._lock = Lock() self._bundles = [] # hold a reference to the monitors so they don't get disposed self._gio_monitors = [] dirs = [env.get_user_activities_path(), env.get_user_library_path()] for data_dir in GLib.get_system_data_dirs(): dirs.append(os.path.join(data_dir, "sugar", "activities")) for activity_dir in dirs: self._scan_directory(activity_dir) directory = Gio.File.new_for_path(activity_dir) monitor = directory.monitor_directory( flags=Gio.FileMonitorFlags.NONE, cancellable=None) monitor.connect('changed', self.__file_monitor_changed_cb) self._gio_monitors.append(monitor) self._favorite_bundles = [] for i in range(desktop.get_number_of_views()): self._favorite_bundles.append({}) settings = Gio.Settings('org.sugarlabs') self._protected_activities = settings.get_strv('protected-activities') try: self._load_favorites() except Exception: logging.exception('Error while loading favorite_activities.') self._hidden_activities = [] self._load_hidden_activities() self._convert_old_favorites() self._scan_new_favorites() self._desktop_model = desktop.get_model() self._desktop_model.connect('desktop-view-icons-changed', self.__desktop_view_icons_changed_cb)
def cmd_dev(config, options): """Setup for development""" bundle_path = env.get_user_activities_path() if not os.path.isdir(bundle_path): os.mkdir(bundle_path) bundle_path = os.path.join(bundle_path, config.bundle_root_dir) try: os.symlink(config.source_dir, bundle_path) except OSError: if os.path.islink(bundle_path): print('ERROR - The bundle has been already setup for development.') else: print('ERROR - A bundle with the same name is already installed.')
def __copy_to_home_cb(self, menu_item): """Make a local copy of the activity bundle in user_activities_path""" user_activities_path = get_user_activities_path() nick = customizebundle.generate_unique_id() new_basename = '%s_copy_of_%s' % ( nick, os.path.basename(self._document_path)) if not os.path.exists(os.path.join(user_activities_path, new_basename)): shutil.copytree(self._document_path, os.path.join(user_activities_path, new_basename), symlinks=True) customizebundle.generate_bundle(nick, new_basename) else: _logger.debug('%s already exists', new_basename)
def _customize_activity_info(nick, new_basename): """Modify bundle_id in new activity.info file: (1) change the bundle_id to bundle_id_[NICKNAME]; (2) change the activity_icon [NICKNAME]-activity-icon.svg; (3) set activity_version to 1; (4) modify the activity icon by applying a customize overlay. """ new_activity_name = '' user_activities_path = get_user_activities_path() info_old = open(os.path.join(user_activities_path, new_basename, 'activity', 'activity.info'), 'r') info_new = open(os.path.join(user_activities_path, new_basename, 'activity', 'new_activity.info'), 'w') for line in info_old: if line.find('=') < 0: info_new.write(line) continue name, value = [token.strip() for token in line.split('=', 1)] if name == 'bundle_id': new_value = '%s_%s' % (value, nick) elif name == 'activity_version': new_value = '1' elif name == 'icon': new_value = value icon_name = value elif name == 'name': new_value = '%s_copy_of_%s' % (nick, value) new_activity_name = new_value else: info_new.write(line) continue info_new.write('%s = %s\n' % (name, new_value)) info_old.close() info_new.close() os.rename(os.path.join(user_activities_path, new_basename, 'activity', 'new_activity.info'), os.path.join(user_activities_path, new_basename, 'activity', 'activity.info')) _create_custom_icon(new_basename, icon_name) return new_activity_name
def _create_custom_icon(new_basename, icon_name): """Modify activity icon by overlaying a badge: (1) Extract the payload from the badge icon; (2) Add a transform to resize it and position it; (3) Insert it into the activity icon. """ user_activities_path = get_user_activities_path() badge_path = None for path in Gtk.IconTheme.get_default().get_search_path(): if os.path.exists( os.path.join(path, 'sugar', 'scalable', BADGE_SUBPATH)): badge_path = path break if badge_path is None: _logger.debug('%s not found', BADGE_SUBPATH) return badge_fd = open( os.path.join(badge_path, 'sugar', 'scalable', BADGE_SUBPATH), 'r') badge_payload = _extract_svg_payload(badge_fd) badge_fd.close() badge_svg = BADGE_TRANSFORM + badge_payload + '\n</g>' icon_path = os.path.join(user_activities_path, new_basename, 'activity', icon_name + '.svg') icon_fd = open(icon_path, 'r') icon_payload = _extract_svg_payload(icon_fd) icon_fd.close() icon_svg = ICON_TRANSFORM + icon_payload + '\n</g>' tmp_path = os.path.join(user_activities_path, new_basename, 'activity', 'tmp.svg') tmp_icon_fd = open(tmp_path, 'w') tmp_icon_fd.write(XML_HEADER) tmp_icon_fd.write(SVG_START) tmp_icon_fd.write(icon_svg) tmp_icon_fd.write(badge_svg) tmp_icon_fd.write(SVG_END) tmp_icon_fd.close() os.remove(icon_path) os.rename(tmp_path, icon_path)
def _create_custom_icon(new_basename, icon_name): """Modify activity icon by overlaying a badge: (1) Extract the payload from the badge icon; (2) Add a transform to resize it and position it; (3) Insert it into the activity icon. """ user_activities_path = get_user_activities_path() badge_path = None for path in Gtk.IconTheme.get_default().get_search_path(): if os.path.exists(os.path.join(path, 'sugar', 'scalable', BADGE_SUBPATH)): badge_path = path break if badge_path is None: _logger.debug('%s not found', BADGE_SUBPATH) return badge_fd = open(os.path.join(badge_path, 'sugar', 'scalable', BADGE_SUBPATH), 'r') badge_payload = _extract_svg_payload(badge_fd) badge_fd.close() badge_svg = BADGE_TRANSFORM + badge_payload + '\n</g>' icon_path = os.path.join(user_activities_path, new_basename, 'activity', icon_name + '.svg') icon_fd = open(icon_path, 'r') icon_payload = _extract_svg_payload(icon_fd) icon_fd.close() icon_svg = ICON_TRANSFORM + icon_payload + '\n</g>' tmp_path = os.path.join(user_activities_path, new_basename, 'activity', 'tmp.svg') tmp_icon_fd = open(tmp_path, 'w') tmp_icon_fd.write(XML_HEADER) tmp_icon_fd.write(SVG_START) tmp_icon_fd.write(icon_svg) tmp_icon_fd.write(badge_svg) tmp_icon_fd.write(SVG_END) tmp_icon_fd.close() os.remove(icon_path) os.rename(tmp_path, icon_path)
def __init__(self): logging.debug('STARTUP: Loading the bundle registry') GObject.GObject.__init__(self) self._mime_defaults = self._load_mime_defaults() self._bundles = [] # hold a reference to the monitors so they don't get disposed self._gio_monitors = [] dirs = [env.get_user_activities_path()] for data_dir in GLib.get_system_data_dirs(): dirs.append(os.path.join(data_dir, "sugar", "activities")) for activity_dir in dirs: self._scan_directory(activity_dir) directory = Gio.File.new_for_path(activity_dir) monitor = directory.monitor_directory( \ flags=Gio.FileMonitorFlags.NONE, cancellable=None) monitor.connect('changed', self.__file_monitor_changed_cb) self._gio_monitors.append(monitor) self._last_defaults_mtime = -1 self._favorite_bundles = {} client = GConf.Client.get_default() self._protected_activities = [] # FIXME, gconf_client_get_list not introspectable #681433 protected_activities = client.get( '/desktop/sugar/protected_activities') for gval in protected_activities.get_list(): activity_id = gval.get_string() self._protected_activities.append(activity_id) if self._protected_activities is None: self._protected_activities = [] try: self._load_favorites() except Exception: logging.exception('Error while loading favorite_activities.') self._merge_default_favorites()
def __init__(self): logging.debug('STARTUP: Loading the bundle registry') GObject.GObject.__init__(self) self._mime_defaults = self._load_mime_defaults() self._bundles = [] # hold a reference to the monitors so they don't get disposed self._gio_monitors = [] dirs = [env.get_user_activities_path()] for data_dir in GLib.get_system_data_dirs(): dirs.append(os.path.join(data_dir, "sugar", "activities")) for activity_dir in dirs: self._scan_directory(activity_dir) directory = Gio.File.new_for_path(activity_dir) monitor = directory.monitor_directory( flags=Gio.FileMonitorFlags.NONE, cancellable=None) monitor.connect('changed', self.__file_monitor_changed_cb) self._gio_monitors.append(monitor) self._last_defaults_mtime = -1 self._favorite_bundles = {} client = GConf.Client.get_default() self._protected_activities = [] # FIXME, gconf_client_get_list not introspectable #681433 protected_activities = client.get( '/desktop/sugar/protected_activities') for gval in protected_activities.get_list(): activity_id = gval.get_string() self._protected_activities.append(activity_id) if self._protected_activities is None: self._protected_activities = [] try: self._load_favorites() except Exception: logging.exception('Error while loading favorite_activities.') self._merge_default_favorites()
def __copy_to_home_cb(self, menu_item, copy_alert=None): """Make a local copy of the activity bundle in user_activities_path""" user_activities_path = get_user_activities_path() nick = customizebundle.generate_unique_id() new_basename = '%s_copy_of_%s' % ( nick, os.path.basename(self._document_path)) if not os.path.exists(os.path.join(user_activities_path, new_basename)): self.__set_busy_cursor(True) def async_copy_activity_tree(): try: shutil.copytree(self._document_path, os.path.join( user_activities_path, new_basename), symlinks=True) customizebundle.generate_bundle(nick, new_basename) if copy_alert: self.get_toplevel().remove_alert(copy_alert) alert = NotifyAlert(10) alert.props.title = _('Duplicated') alert.props.msg = _('The activity has been duplicated') alert.connect('response', self.__alert_response_cb) self.get_toplevel().add_alert(alert) finally: self.__set_busy_cursor(False) GLib.idle_add(async_copy_activity_tree) else: if copy_alert: self.get_toplevel().remove_alert(copy_alert) self.__set_busy_cursor(False) alert = NotifyAlert(10) alert.props.title = _('Duplicated activity already exists') alert.props.msg = _('Delete your copy before trying to duplicate' ' the activity again') alert.connect('response', self.__alert_response_cb) self.get_toplevel().add_alert(alert)
def is_user_activity(self): return self.get_path().startswith(env.get_user_activities_path())