Merge branch 'master' of git://dev.laptop.org/users/marco/sugar-toolkit

This commit is contained in:
Marco Pesenti Gritti 2008-05-27 21:07:12 +02:00
commit 56ad8d8231

View File

@ -15,218 +15,224 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA. # Boston, MA 02111-1307, USA.
import sys
import os import os
import zipfile import zipfile
import tarfile
import shutil import shutil
import subprocess import subprocess
import re import re
import gettext import gettext
from optparse import OptionParser
from sugar import env from sugar import env
from sugar.bundle.activitybundle import ActivityBundle from sugar.bundle.activitybundle import ActivityBundle
class _SvnFileList(list): def list_files(base_dir, ignore_dirs=None, ignore_files=None):
def __init__(self): result = []
f = os.popen('svn list -R')
for line in f.readlines(): for root, dirs, files in os.walk(base_dir):
filename = line.strip() for f in files:
if os.path.isfile(filename): if ignore_files and f not in ignore_files:
self.append(filename) rel_path = root[len(base_dir) + 1:]
result.append(os.path.join(rel_path, f))
if ignore_dirs and root == base_dir:
for ignore in ignore_dirs:
if ignore in dirs:
dirs.remove(ignore)
return result
class Config(object):
def __init__(self, bundle_name):
self.source_dir = os.getcwd()
bundle = ActivityBundle(self.source_dir)
version = bundle.get_activity_version()
self.bundle_name = bundle_name
self.xo_name = '%s-%d.xo' % (self.bundle_name, version)
self.tarball_name = '%s-%d.tar.bz2' % (self.bundle_name, version)
self.bundle_id = bundle.get_bundle_id()
self.bundle_root_dir = self.bundle_name + '.activity'
self.tarball_root_dir = '%s-%d' % (self.bundle_name, version)
info_path = os.path.join(self.source_dir, 'activity', 'activity.info')
f = open(info_path,'r')
info = f.read()
f.close() f.close()
match = re.search('^name\s*=\s*(.*)$', info, flags = re.MULTILINE)
self.activity_name = match.group(1)
class _GitFileList(list): class Builder(object):
def __init__(self): def __init__(self, config):
f = os.popen('git-ls-files') self.config = config
for line in f.readlines():
filename = line.strip()
if not filename.startswith('.'):
self.append(filename)
f.close()
class _DefaultFileList(list): def build(self):
def __init__(self): self.build_locale()
for name in os.listdir('activity'):
if name.endswith('.svg'):
self.append(os.path.join('activity', name))
self.append('activity/activity.info') def build_locale(self):
po_dir = os.path.join(self.config.source_dir, 'po')
if os.path.isfile(_get_source_path('NEWS')): for f in os.listdir(po_dir):
self.append('NEWS') if not f.endswith('.po'):
continue
class _ManifestFileList(_DefaultFileList): file_name = os.path.join(po_dir, f)
def __init__(self, manifest): lang = f[:-3]
_DefaultFileList.__init__(self)
self.append(manifest)
f = open(manifest,'r') localedir = os.path.join(self.config.source_dir, 'locale', lang)
for line in f.readlines(): mo_path = os.path.join(localedir, 'LC_MESSAGES')
stripped_line = line.strip() if not os.path.isdir(mo_path):
if stripped_line and not stripped_line in self: os.makedirs(mo_path)
self.append(stripped_line)
f.close()
class _AllFileList(list): mo_file = os.path.join(mo_path, "%s.mo" % self.config.bundle_id)
def __init__(self): args = ["msgfmt", "--output-file=%s" % mo_file, file_name]
for root, dirs, files in os.walk('.'): retcode = subprocess.call(args)
if not root.startswith('./locale'): if retcode:
for f in files: print 'ERROR - msgfmt failed with return code %i.' % retcode
if not f.endswith('.xo') and \
f != '.gitignore':
self.append(os.path.join(root, f))
def _extract_bundle(source_file, dest_dir): cat = gettext.GNUTranslations(open(mo_file, 'r'))
if not os.path.exists(dest_dir): translated_name = cat.gettext(self.config.activity_name)
os.mkdir(dest_dir) linfo_file = os.path.join(localedir, 'activity.linfo')
f = open(linfo_file, 'w')
f.write('[Activity]\nname = %s\n' % translated_name)
f.close()
zf = zipfile.ZipFile(source_file) class Packager(object):
def __init__(self, config):
self.config = config
self.dist_dir = os.path.join(self.config.source_dir, 'dist')
self.package_path = None
for name in zf.namelist(): if not os.path.exists(self.dist_dir):
path = os.path.join(dest_dir, name) os.mkdir(self.dist_dir)
if not os.path.exists(os.path.dirname(path)):
os.makedirs(os.path.dirname(path))
outfile = open(path, 'wb') class BuildPackager(Packager):
outfile.write(zf.read(name)) def __init__(self, config):
outfile.flush() Packager.__init__(self, config)
outfile.close() self.build_dir = self.config.source_dir
def _get_source_path(path=None): def get_files(self):
if path: return list_files(self.build_dir,
return os.path.join(os.getcwd(), path) ignore_dirs=[ 'po', 'dist', '.git' ],
else: ignore_files=[ '.gitignore' ])
return os.getcwd()
def _get_bundle_dir(): class XOPackager(BuildPackager):
bundle_name = os.path.basename(_get_source_path()) def __init__(self, config):
return bundle_name + '.activity' BuildPackager.__init__(self, config)
self.package_path = os.path.join(self.dist_dir, self.config.xo_name)
def _get_package_name(bundle_name): def package(self):
bundle = ActivityBundle(_get_source_path()) bundle_zip = zipfile.ZipFile(self.package_path, 'w',
zipname = '%s-%d.xo' % (bundle_name, bundle.get_activity_version()) zipfile.ZIP_DEFLATED)
return zipname
for f in self.get_files():
bundle_zip.write(os.path.join(self.build_dir, f),
os.path.join(self.config.bundle_root_dir, f))
def _delete_backups(arg, dirname, names): bundle_zip.close()
for name in names:
if name.endswith('~') or name.endswith('pyc'):
os.remove(os.path.join(dirname, name))
def _get_bundle_id(): class SourcePackager(Packager):
bundle = ActivityBundle(_get_source_path()) def __init__(self, config):
return bundle.get_bundle_id() Packager.__init__(self, config)
self.package_path = os.path.join(self.dist_dir,
self.config.tarball_name)
def cmd_help(): def get_files(self):
return list_files(self.config.source_dir,
ignore_dirs=[ 'locale', 'dist', '.git' ],
ignore_files=[ '.gitignore' ])
def package(self):
tar = tarfile.open(self.package_path, "w")
for f in self.get_files():
tar.add(os.path.join(self.config.source_dir, f),
os.path.join(self.config.tarball_root_dir, f))
tar.close()
def cmd_help(config, options, args):
print 'Usage: \n\ print 'Usage: \n\
setup.py build - build generated files \n\
setup.py dev - setup for development \n\ setup.py dev - setup for development \n\
setup.py dist - create a bundle package \n\ setup.py dist_xo - create a xo bundle package \n\
setup.py dist_source - create a tar source package \n\
setup.py install [dirname] - install the bundle \n\ setup.py install [dirname] - install the bundle \n\
setup.py uninstall [dirname] - uninstall the bundle \n\ setup.py uninstall [dirname] - uninstall the bundle \n\
setup.py genpot - generate the gettext pot file \n\ setup.py genpot - generate the gettext pot file \n\
setup.py genl10n - generate localization files \n\
setup.py clean - clean the directory \n\
setup.py release - do a new release of the bundle \n\ setup.py release - do a new release of the bundle \n\
setup.py help - print this message \n\ setup.py help - print this message \n\
' '
def cmd_dev(): def cmd_dev(config, options, args):
bundle_path = env.get_user_activities_path() bundle_path = env.get_user_activities_path()
if not os.path.isdir(bundle_path): if not os.path.isdir(bundle_path):
os.mkdir(bundle_path) os.mkdir(bundle_path)
bundle_path = os.path.join(bundle_path, _get_bundle_dir()) bundle_path = os.path.join(bundle_path, config.bundle_top_dir)
try: try:
os.symlink(_get_source_path(), bundle_path) os.symlink(config.source_dir, bundle_path)
except OSError: except OSError:
if os.path.islink(bundle_path): if os.path.islink(bundle_path):
print 'ERROR - The bundle has been already setup for development.' print 'ERROR - The bundle has been already setup for development.'
else: else:
print 'ERROR - A bundle with the same name is already installed.' print 'ERROR - A bundle with the same name is already installed.'
def _get_file_list(manifest): def cmd_dist_xo(config, options, args):
if os.path.isfile(manifest): builder = Builder(config)
return _ManifestFileList(manifest) builder.build()
elif os.path.isdir('.git'):
return _GitFileList()
elif os.path.isdir('.svn'):
return _SvnFileList()
else:
return _AllFileList()
def _get_po_list(manifest): packager = XOPackager(config)
file_list = {} packager.package()
po_regex = re.compile("po/(.*)\.po$") def cmd_dist_source(config, options, args):
for file_name in _get_file_list(manifest): packager = SourcePackager(config)
match = po_regex.match(file_name) packager.package()
if match:
file_list[match.group(1)] = file_name
return file_list def cmd_install(config, options, args):
path = args[0]
def _get_l10n_list(manifest): packager = XOPackager(config)
l10n_list = [] packager.package()
for lang in _get_po_list(manifest).keys(): root_path = os.path.join(args[0], config.bundle_root_dir)
filename = _get_bundle_id() + '.mo' if os.path.isdir(root_path):
l10n_list.append(os.path.join('locale', lang, 'LC_MESSAGES', filename)) shutil.rmtree(root_path)
l10n_list.append(os.path.join('locale', lang, 'activity.linfo'))
return l10n_list if not os.path.exists(path):
os.mkdir(path)
def _get_activity_name(): zf = zipfile.ZipFile(packager.package_path)
info_path = os.path.join(_get_source_path(), 'activity', 'activity.info')
f = open(info_path,'r')
info = f.read()
f.close()
match = re.search('^name\s*=\s*(.*)$', info, flags = re.MULTILINE)
return match.group(1)
def cmd_dist(bundle_name, manifest): for name in zf.namelist():
cmd_genl10n(bundle_name, manifest) full_path = os.path.join(path, name)
file_list = _get_file_list(manifest) if not os.path.exists(os.path.dirname(full_path)):
os.makedirs(os.path.dirname(full_path))
zipname = _get_package_name(bundle_name) outfile = open(full_path, 'wb')
bundle_zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) outfile.write(zf.read(name))
base_dir = bundle_name + '.activity' outfile.flush()
outfile.close()
for filename in file_list:
bundle_zip.write(filename, os.path.join(base_dir, filename))
for filename in _get_l10n_list(manifest): def cmd_genpot(config, options, args):
bundle_zip.write(filename, os.path.join(base_dir, filename)) po_path = os.path.join(config.source_dir, 'po')
bundle_zip.close()
def cmd_install(bundle_name, manifest, path):
cmd_dist(bundle_name, manifest)
cmd_uninstall(path)
_extract_bundle(_get_package_name(bundle_name), path)
def cmd_uninstall(path):
path = os.path.join(path, _get_bundle_dir())
if os.path.isdir(path):
shutil.rmtree(path)
def cmd_genpot(bundle_name, manifest):
po_path = os.path.join(_get_source_path(), 'po')
if not os.path.isdir(po_path): if not os.path.isdir(po_path):
os.mkdir(po_path) os.mkdir(po_path)
python_files = [] python_files = []
file_list = _get_file_list(manifest) for root_dummy, dirs_dummy, files in os.walk(config.source_dir):
for file_name in file_list: for file_name in files:
if file_name.endswith('.py'): if file_name.endswith('.py'):
python_files.append(file_name) python_files.append(file_name)
# First write out a stub .pot file containing just the translated # First write out a stub .pot file containing just the translated
# activity name, then have xgettext merge the rest of the # activity name, then have xgettext merge the rest of the
# translations into that. (We can't just append the activity name # translations into that. (We can't just append the activity name
# to the end of the .pot file afterwards, because that might # to the end of the .pot file afterwards, because that might
# create a duplicate msgid.) # create a duplicate msgid.)
pot_file = os.path.join('po', '%s.pot' % bundle_name) pot_file = os.path.join('po', '%s.pot' % config.bundle_name)
activity_name = _get_activity_name() escaped_name = re.sub('([\\\\"])', '\\\\\\1', config.activity_name)
escaped_name = re.sub('([\\\\"])', '\\\\\\1', activity_name)
f = open(pot_file, 'w') f = open(pot_file, 'w')
f.write('#: activity/activity.info:2\n') f.write('#: activity/activity.info:2\n')
f.write('msgid "%s"\n' % escaped_name) f.write('msgid "%s"\n' % escaped_name)
@ -241,34 +247,7 @@ def cmd_genpot(bundle_name, manifest):
if retcode: if retcode:
print 'ERROR - xgettext failed with return code %i.' % retcode print 'ERROR - xgettext failed with return code %i.' % retcode
def cmd_release(config, options, args):
def cmd_genl10n(bundle_name, manifest):
source_path = _get_source_path()
activity_name = _get_activity_name()
po_list = _get_po_list(manifest)
for lang in po_list.keys():
file_name = po_list[lang]
localedir = os.path.join(source_path, 'locale', lang)
mo_path = os.path.join(localedir, 'LC_MESSAGES')
if not os.path.isdir(mo_path):
os.makedirs(mo_path)
mo_file = os.path.join(mo_path, "%s.mo" % _get_bundle_id())
args = ["msgfmt", "--output-file=%s" % mo_file, file_name]
retcode = subprocess.call(args)
if retcode:
print 'ERROR - msgfmt failed with return code %i.' % retcode
cat = gettext.GNUTranslations(open(mo_file, 'r'))
translated_name = cat.gettext(activity_name)
linfo_file = os.path.join(localedir, 'activity.linfo')
f = open(linfo_file, 'w')
f.write('[Activity]\nname = %s\n' % translated_name)
f.close()
def cmd_release(bundle_name, manifest):
if not os.path.isdir('.git'): if not os.path.isdir('.git'):
print 'ERROR - this command works only for git repositories' print 'ERROR - this command works only for git repositories'
@ -278,7 +257,7 @@ def cmd_release(bundle_name, manifest):
print 'Bumping activity version...' print 'Bumping activity version...'
info_path = os.path.join(_get_source_path(), 'activity', 'activity.info') info_path = os.path.join(config.source_dir, 'activity', 'activity.info')
f = open(info_path,'r') f = open(info_path,'r')
info = f.read() info = f.read()
f.close() f.close()
@ -292,7 +271,7 @@ def cmd_release(bundle_name, manifest):
f.write(info) f.write(info)
f.close() f.close()
news_path = os.path.join(_get_source_path(), 'NEWS') news_path = os.path.join(config.source_dir, 'NEWS')
if os.environ.has_key('SUGAR_NEWS'): if os.environ.has_key('SUGAR_NEWS'):
print 'Update NEWS.sugar...' print 'Update NEWS.sugar...'
@ -305,7 +284,7 @@ def cmd_release(bundle_name, manifest):
else: else:
sugar_news = '' sugar_news = ''
sugar_news += '%s - %d\n\n' % (bundle_name, version) sugar_news += '%s - %d\n\n' % (config.bundle_name, version)
f = open(news_path,'r') f = open(news_path,'r')
for line in f.readlines(): for line in f.readlines():
@ -345,42 +324,25 @@ def cmd_release(bundle_name, manifest):
print 'ERROR - cannot push to git' print 'ERROR - cannot push to git'
print 'Creating the bundle...' print 'Creating the bundle...'
cmd_dist(bundle_name, manifest) packager = XOPackager(config)
packager.package()
print 'Done.' print 'Done.'
def cmd_clean(): def cmd_build(config, options, args):
os.path.walk('.', _delete_backups, None) builder = Builder(config)
builder.build()
def sanity_check(): def start(bundle_name):
if not os.path.isfile(_get_source_path('NEWS')): parser = OptionParser()
print 'WARNING: NEWS file is missing.' (options, args) = parser.parse_args()
def start(bundle_name, manifest='MANIFEST'): config = Config(bundle_name)
sanity_check()
try:
globals()['cmd_' + args[0]](config, options, args[1:])
except (KeyError, IndexError):
cmd_help(config, options, args)
if len(sys.argv) < 2:
cmd_help()
elif sys.argv[1] == 'build':
pass
elif sys.argv[1] == 'dev':
cmd_dev()
elif sys.argv[1] == 'dist':
cmd_dist(bundle_name, manifest)
elif sys.argv[1] == 'install' and len(sys.argv) == 3:
cmd_install(bundle_name, manifest, sys.argv[2])
elif sys.argv[1] == 'uninstall' and len(sys.argv) == 3:
cmd_uninstall(sys.argv[2])
elif sys.argv[1] == 'genpot':
cmd_genpot(bundle_name, manifest)
elif sys.argv[1] == 'genl10n':
cmd_genl10n(bundle_name, manifest)
elif sys.argv[1] == 'clean':
cmd_clean()
elif sys.argv[1] == 'release':
cmd_release(bundle_name, manifest)
else:
cmd_help()
if __name__ == '__main__': if __name__ == '__main__':
start() start()