| Index: packagerGecko.py |
| diff --git a/packagerGecko.py b/packagerGecko.py |
| deleted file mode 100644 |
| index 0b038d2c05de350381bb4bf132cf598b14f1e094..0000000000000000000000000000000000000000 |
| --- a/packagerGecko.py |
| +++ /dev/null |
| @@ -1,340 +0,0 @@ |
| -# This Source Code Form is subject to the terms of the Mozilla Public |
| -# License, v. 2.0. If a copy of the MPL was not distributed with this |
| -# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| - |
| -import os |
| -import sys |
| -import re |
| -import hashlib |
| -import base64 |
| -import urllib |
| -import json |
| -import io |
| -from ConfigParser import SafeConfigParser |
| -from StringIO import StringIO |
| -import xml.dom.minidom as minidom |
| -import buildtools.localeTools as localeTools |
| - |
| -import packager |
| -from packager import readMetadata, getMetadataPath, getDefaultFileName, getBuildVersion, getTemplate, Files |
| - |
| -KNOWN_APPS = { |
| - 'conkeror': '{a79fe89b-6662-4ff4-8e88-09950ad4dfde}', |
| - 'emusic': 'dlm@emusic.com', |
| - 'fennec': '{a23983c0-fd0e-11dc-95ff-0800200c9a66}', |
| - 'fennec2': '{aa3c5121-dab2-40e2-81ca-7ea25febc110}', |
| - 'firefox': '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}', |
| - 'midbrowser': '{aa5ca914-c309-495d-91cf-3141bbb04115}', |
| - 'prism': 'prism@developer.mozilla.org', |
| - 'seamonkey': '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}', |
| - 'songbird': 'songbird@songbirdnest.com', |
| - 'thunderbird': '{3550f703-e582-4d05-9a08-453d09bdfdc6}', |
| - 'toolkit': 'toolkit@mozilla.org', |
| - 'adblockbrowser': '{55aba3ac-94d3-41a8-9e25-5c21fe874539}', |
| -} |
| - |
| -defaultLocale = 'en-US' |
| - |
| - |
| -def getChromeDir(baseDir): |
| - return os.path.join(baseDir, 'chrome') |
| - |
| - |
| -def getLocalesDir(baseDir): |
| - return os.path.join(getChromeDir(baseDir), 'locale') |
| - |
| - |
| -def getChromeSubdirs(baseDir, locales): |
| - result = {} |
| - chromeDir = getChromeDir(baseDir) |
| - for subdir in ('content', 'skin'): |
| - result[subdir] = os.path.join(chromeDir, subdir) |
| - for locale in locales: |
| - result['locale/%s' % locale] = os.path.join(chromeDir, 'locale', locale) |
| - return result |
| - |
| - |
| -def getPackageFiles(params): |
| - result = { |
| - 'chrome', 'components', 'modules', 'lib', 'resources', 'webextension', |
| - 'chrome.manifest', 'icon.png', 'icon64.png' |
| - } |
| - |
| - baseDir = params['baseDir'] |
| - for file in os.listdir(baseDir): |
| - if file.endswith('.js') or file.endswith('.xml'): |
| - result.add(file) |
| - return result |
| - |
| - |
| -def getIgnoredFiles(params): |
| - return {'.incomplete', 'meta.properties'} |
| - |
| - |
| -def archive_path(path, baseDir): |
| - return '/'.join(os.path.split(os.path.relpath(path, baseDir))) |
| - |
| - |
| -def isValidLocale(localesDir, dir, includeIncomplete=False): |
| - if re.search(r'[^\w\-]', dir): |
| - return False |
| - curLocaleDir = os.path.join(localesDir, dir) |
| - if not os.path.isdir(curLocaleDir): |
| - return False |
| - if len(os.listdir(curLocaleDir)) == 0: |
| - return False |
| - if not includeIncomplete and os.path.exists(os.path.join(localesDir, dir, '.incomplete')): |
| - return False |
| - return True |
| - |
| - |
| -def getLocales(baseDir, includeIncomplete=False): |
| - global defaultLocale |
| - localesDir = getLocalesDir(baseDir) |
| - locales = filter(lambda dir: isValidLocale(localesDir, dir, includeIncomplete), os.listdir(localesDir)) |
| - locales.sort(key=lambda x: '!' if x == defaultLocale else x) |
| - return locales |
| - |
| - |
| -def processFile(path, data, params): |
| - if path.endswith('.manifest') and data.find('{{LOCALE}}') >= 0: |
| - localesRegExp = re.compile(r'^(.*?){{LOCALE}}(.*?){{LOCALE}}(.*)$', re.M) |
| - replacement = '\n'.join(map(lambda locale: r'\1%s\2%s\3' % (locale, locale), params['locales'])) |
| - data = re.sub(localesRegExp, replacement, data) |
| - |
| - return data |
| - |
| - |
| -def readLocaleMetadata(baseDir, locales): |
| - result = {} |
| - |
| - # Make sure we always have fallback data even if the default locale isn't part |
| - # of the build |
| - locales = list(locales) |
| - if not defaultLocale in locales: |
| - locales.append(defaultLocale) |
| - |
| - for locale in locales: |
| - data = SafeConfigParser() |
| - data.optionxform = str |
| - try: |
| - result[locale] = localeTools.readFile(os.path.join(getLocalesDir(baseDir), locale, 'meta.properties')) |
| - except: |
| - result[locale] = {} |
| - return result |
| - |
| - |
| -def getContributors(metadata): |
| - main = [] |
| - additional = set() |
| - if metadata.has_section('contributors'): |
| - options = metadata.options('contributors') |
| - options.sort() |
| - for option in options: |
| - value = metadata.get('contributors', option) |
| - if re.search(r'\D', option): |
| - match = re.search(r'^\s*(\S+)\s+//([^/\s]+)/@(\S+)\s*$', value) |
| - if not match: |
| - print >>sys.stderr, 'Warning: unrecognized contributor location "%s"\n' % value |
| - continue |
| - baseDir = os.path.dirname(metadata.option_source('contributors', option)) |
| - parts = match.group(1).split('/') |
| - dom = minidom.parse(os.path.join(baseDir, *parts)) |
| - tags = dom.getElementsByTagName(match.group(2)) |
| - for tag in tags: |
| - if tag.hasAttribute(match.group(3)): |
| - for name in re.split(r'\s*,\s*', tag.getAttribute(match.group(3))): |
| - additional.add(name) |
| - else: |
| - main.append(value) |
| - return main + sorted(additional, key=unicode.lower) |
| - |
| - |
| -def initTranslators(localeMetadata): |
| - for locale in localeMetadata.itervalues(): |
| - if 'translator' in locale: |
| - locale['translators'] = sorted(map(lambda t: t.strip(), locale['translator'].split(',')), key=unicode.lower) |
| - else: |
| - locale['translators'] = [] |
| - |
| - |
| -def createManifest(params): |
| - global KNOWN_APPS, defaultLocale |
| - template = getTemplate('install.rdf.tmpl', autoEscape=True) |
| - templateData = dict(params) |
| - templateData['localeMetadata'] = readLocaleMetadata(params['baseDir'], params['locales']) |
| - initTranslators(templateData['localeMetadata']) |
| - templateData['KNOWN_APPS'] = KNOWN_APPS |
| - templateData['defaultLocale'] = defaultLocale |
| - return template.render(templateData).encode('utf-8') |
| - |
| - |
| -def importLocales(params, files): |
| - SECTION = 'import_locales' |
| - if not params['metadata'].has_section(SECTION): |
| - return |
| - |
| - import localeTools |
| - |
| - for locale in params['locales']: |
| - for item in params['metadata'].items(SECTION): |
| - path, keys = item |
| - parts = [locale if p == '*' else p for p in path.split('/')] |
| - source = os.path.join(os.path.dirname(item.source), *parts) |
| - if not os.path.exists(source): |
| - continue |
| - |
| - with io.open(source, 'r', encoding='utf-8') as handle: |
| - data = json.load(handle) |
| - |
| - target_name = os.path.splitext(os.path.basename(source))[0] + '.properties' |
| - target = archive_path(os.path.join(getLocalesDir(params['baseDir']), locale, target_name), params['baseDir']) |
| - |
| - files[target] = '' |
| - for key, value in sorted(data.items()): |
| - message = value['message'] |
| - files[target] += localeTools.generateStringEntry(key, message, target).encode('utf-8') |
| - |
| - |
| -def fixupLocales(params, files): |
| - global defaultLocale |
| - |
| - # Read in default locale data, it might not be included in package files |
| - defaultLocaleDir = os.path.join(getLocalesDir(params['baseDir']), defaultLocale) |
| - reference_files = Files(getPackageFiles(params), getIgnoredFiles(params)) |
| - reference_files.read(defaultLocaleDir, archive_path(defaultLocaleDir, params['baseDir'])) |
| - reference_params = dict(params) |
| - reference_params['locales'] = [defaultLocale] |
| - importLocales(reference_params, reference_files) |
| - |
| - reference = {} |
| - for path, data in reference_files.iteritems(): |
| - filename = path.split('/')[-1] |
| - data = localeTools.parseString(data.decode('utf-8'), filename) |
| - if data: |
| - reference[filename] = data |
| - |
| - for locale in params['locales']: |
| - for file in reference.iterkeys(): |
| - path = 'chrome/locale/%s/%s' % (locale, file) |
| - if path in files: |
| - data = localeTools.parseString(files[path].decode('utf-8'), path) |
| - for key, value in reference[file].iteritems(): |
| - if not key in data: |
| - files[path] += localeTools.generateStringEntry(key, value, path).encode('utf-8') |
| - else: |
| - files[path] = reference[file]['_origData'].encode('utf-8') |
| - |
| - |
| -def processJSONFiles(params, files): |
| - prefix = 'lib/' |
| - for name, content in files.iteritems(): |
| - if name.startswith(prefix) and name.endswith('.json'): |
| - params['jsonRequires'][name[len(prefix):]] = json.loads(content) |
| - for name in params['jsonRequires'].iterkeys(): |
| - del files[prefix + name] |
| - |
| - |
| -def addMissingFiles(params, files): |
| - templateData = { |
| - 'hasChrome': False, |
| - 'hasChromeRequires': False, |
| - 'hasShutdownHandlers': False, |
| - 'chromeWindows': [], |
| - 'requires': set(), |
| - 'jsonRequires': params['jsonRequires'], |
| - 'metadata': params['metadata'], |
| - 'hasWebExtension': params['hasWebExtension'], |
| - 'multicompartment': params['multicompartment'], |
| - 'applications': dict((v, k) for k, v in KNOWN_APPS.iteritems()), |
| - } |
| - |
| - def checkScript(name): |
| - content = files[name] |
| - for match in re.finditer(r'(?:^|\s)require\(\s*"([\w\-]+)"\s*\)', content): |
| - templateData['requires'].add(match.group(1)) |
| - if name.startswith('chrome/content/'): |
| - templateData['hasChromeRequires'] = True |
| - if not '/' in name or name.startswith('lib/'): |
| - if re.search(r'(?:^|\s)onShutdown\.', content): |
| - templateData['hasShutdownHandlers'] = True |
| - |
| - for name, content in files.iteritems(): |
| - if name == 'chrome.manifest': |
| - templateData['hasChrome'] = True |
| - elif name.endswith('.js'): |
| - checkScript(name) |
| - elif name.endswith('.xul'): |
| - match = re.search(r'<(?:window|dialog)\s[^>]*\bwindowtype="([^">]+)"', content) |
| - if match: |
| - templateData['chromeWindows'].append(match.group(1)) |
| - |
| - while True: |
| - missing = [] |
| - for module in templateData['requires']: |
| - moduleFile = 'lib/' + module + '.js' |
| - if not moduleFile in files: |
| - import buildtools |
| - path = os.path.join(buildtools.__path__[0], moduleFile) |
| - if os.path.exists(path): |
| - missing.append((path, moduleFile)) |
| - if not len(missing): |
| - break |
| - for path, moduleFile in missing: |
| - files.read(path, moduleFile) |
| - checkScript(moduleFile) |
| - |
| - template = getTemplate('bootstrap.js.tmpl') |
| - files['bootstrap.js'] = template.render(templateData).encode('utf-8') |
| - |
| - |
| -def createBuild(baseDir, type='gecko', outFile=None, locales=None, buildNum=None, releaseBuild=False, multicompartment=False): |
| - if locales == None: |
| - locales = getLocales(baseDir) |
| - elif locales == 'all': |
| - locales = getLocales(baseDir, True) |
| - |
| - metadata = readMetadata(baseDir, type) |
| - version = getBuildVersion(baseDir, metadata, releaseBuild, buildNum) |
| - |
| - if outFile == None: |
| - outFile = getDefaultFileName(metadata, version, 'xpi') |
| - |
| - contributors = getContributors(metadata) |
| - |
| - params = { |
| - 'baseDir': baseDir, |
| - 'locales': locales, |
| - 'releaseBuild': releaseBuild, |
| - 'version': version.encode('utf-8'), |
| - 'metadata': metadata, |
| - 'contributors': contributors, |
| - 'multicompartment': multicompartment, |
| - 'hasWebExtension': os.path.isdir(os.path.join(baseDir, 'webextension')), |
| - 'jsonRequires': {}, |
| - } |
| - |
| - mapped = metadata.items('mapping') if metadata.has_section('mapping') else [] |
| - skip = [opt for opt, _ in mapped] + ['chrome'] |
| - files = Files(getPackageFiles(params), getIgnoredFiles(params), |
| - process=lambda path, data: processFile(path, data, params)) |
| - files['install.rdf'] = createManifest(params) |
| - files.readMappedFiles(mapped) |
| - files.read(baseDir, skip=skip) |
| - for name, path in getChromeSubdirs(baseDir, params['locales']).iteritems(): |
| - if os.path.isdir(path): |
| - files.read(path, 'chrome/%s' % name, skip=skip) |
| - importLocales(params, files) |
| - fixupLocales(params, files) |
| - processJSONFiles(params, files) |
| - if not 'bootstrap.js' in files: |
| - addMissingFiles(params, files) |
| - if metadata.has_section('preprocess'): |
| - files.preprocess([f for f, _ in metadata.items('preprocess')]) |
| - files.zip(outFile, sortKey=lambda x: '!' if x == 'META-INF/zigbert.rsa' else x) |
| - |
| - |
| -def autoInstall(baseDir, type, host, port, multicompartment=False): |
| - fileBuffer = StringIO() |
| - createBuild(baseDir, type=type, outFile=fileBuffer, multicompartment=multicompartment) |
| - urllib.urlopen('http://%s:%s/' % (host, port), data=fileBuffer.getvalue()) |