diff options
author | Lucian Branescu Mihaila <lucian.branescu@gmail.com> | 2009-07-06 23:07:38 (GMT) |
---|---|---|
committer | Lucian Branescu Mihaila <lucian.branescu@gmail.com> | 2009-07-06 23:07:38 (GMT) |
commit | 94b652b3b082f23267a77526bab69a10a14128c8 (patch) | |
tree | dd5b89c17e8a4dd301d3b99281639d3de002170d /ssb.py | |
parent | ba9a2ad7a188d571d3f0aa8172c71db9a2b7741a (diff) |
Initial commit
Diffstat (limited to 'ssb.py')
-rw-r--r-- | ssb.py | 169 |
1 files changed, 169 insertions, 0 deletions
@@ -0,0 +1,169 @@ +# Copyright (C) 2009, Lucian Branescu Mihaila +# +# 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 St, Fifth Floor, Boston, MA 02110-1301 USA + +import shutil +import os +import tempfile +import zipfile +import ConfigParser +import logging +import functools + +from sugar.activity import activity +from sugar.activity import bundlebuilder +from sugar.bundle.activitybundle import ActivityBundle +from sugar.datastore import datastore +from sugar import profile + +DOMAIN_PREFIX = 'org.sugarlabs.ssb' + +def get_is_ssb(activity): + '''determine if the activity is an SSB''' + return activity.get_bundle_id().startswith(DOMAIN_PREFIX) + +# freeze some arguments, equivalent to def list_files(path): ... +list_files = functools.partial(bundlebuilder.list_files, + ignore_dirs=bundlebuilder.IGNORE_DIRS, + ignore_files=bundlebuilder.IGNORE_FILES.append('.DS_STORE')) + +def remove_paths(paths, root=None): + '''remove all paths in the list, fail silently''' + if root is not None: + paths = [os.path.join(root, i) for i in paths] + + for path in paths: + try: + if os.path.isdir(path): + shutil.rmtree(path) + else: + os.remove(path) + except OSError: + logging.warning('failed to remove: ' + path) + +def copy_profile(): + '''get the data from the bundle and into the profile''' + ssb_data_path = os.path.join(activity.get_bundle_path(), 'data/ssb_data') + data_path = os.path.join(activity.get_activity_root(), 'data') + + if os.path.isdir(ssb_data_path): + # we can't use shutil.copytree for the entire dir + for i in os.listdir(ssb_data_path): + src = os.path.join(ssb_data_path, i) + dst = os.path.join(data_path, i) + if not os.path.exists(dst): + if os.path.isdir(src): + shutil.copytree(src, dst) + else: # is there a better way? + shutil.copy(src, dst) + +class SSBCreator(object): + def __init__(self, title, uri): + self.title = title + self.name = title.replace(' ', '') + self.uri = uri + self.bundle_id = '%s.%sActivity' % (DOMAIN_PREFIX, self.name) + + self.bundle_path = activity.get_bundle_path() + self.data_path = os.path.join(activity.get_activity_root(), 'data') + self.temp_path = tempfile.mkdtemp() # make sure there's no collisions + self.ssb_path = os.path.join(self.temp_path, self.name + '.activity') + + def __del__(self): + '''clean up after ourselves, fail silently''' + shutil.rmtree(self.temp_path, ignore_errors=True) + + def change_info(self): + '''change the .info file accordingly''' + path = os.path.join(self.ssb_path, 'activity/activity.info') + + config = ConfigParser.RawConfigParser() + config.read(path) + + if config.get('Activity', 'name') == 'Browse': + version = 1 + else: + version = int(config.get('Activity', 'activity_version')) + 1 + + config.set('Activity', 'activity_version', version) + config.set('Activity', 'name', self.title) + config.set('Activity', 'bundle_id', self.bundle_id) + config.set('Activity', 'icon', 'activity-ssb') + + # write the changes + f = open(path, 'w') + config.write(f) + f.close() + + def create(self): + '''actual creation''' + # copy the bundle + shutil.copytree(self.bundle_path, self.ssb_path) + + self.change_info() + + # add the ssb icon + shutil.copy(os.path.join(self.ssb_path, 'icons/activity-ssb.svg'), + os.path.join(self.ssb_path, 'activity')) + + # set homepage + f = open(os.path.join(self.ssb_path, 'data/homepage'), 'w') + f.write(self.uri) + f.close() + + # copy profile + ssb_data_path = os.path.join(self.ssb_path, 'data/ssb_data') + shutil.copytree(self.data_path, ssb_data_path) + + # delete undesirable things from the profile + remove_paths(['Cache', 'cookies.sqlite'], + root=os.path.join(ssb_data_path, 'gecko')) + + # create MANIFEST + files = list_files(self.ssb_path) + f = open(os.path.join(self.ssb_path, 'MANIFEST'), 'w') + for i in files: + f.write(i+'\n') + f.close() + + # create .xo bundle + # include the manifest + files.append('MANIFEST') + + self.xo_path = os.path.join(self.temp_path, self.name.lower() + '.xo') + + # zip everything + xo = zipfile.ZipFile(self.xo_path, 'w', zipfile.ZIP_DEFLATED) + for i in files: + xo.write(os.path.join(self.ssb_path, i), + os.path.join(self.name + '.activity', i)) + xo.close() + + def install(self): + '''install the generated .xo bundle''' + bundle = ActivityBundle(self.xo_path) + bundle.install() + + def show_in_journal(self): + '''send the generated .xo bundle to the journal''' + jobject = datastore.create() + jobject.metadata['title'] = self.title + jobject.metadata['mime_type'] = 'application/vnd.olpc-sugar' + jobject.metadata['icon-color'] = profile.get_color().to_string() + jobject.file_path = self.xo_path + + datastore.write(jobject) + + activity.show_object_in_journal(jobject.object_id)
\ No newline at end of file |