[Pkg-mozext-commits] [adblock-plus] 145/464: Added new build scripts, functionality of replace create_xpi.pl, make_devbuild.pl and make_babelzilla_build.pl is already implemented

David Prévot taffit at moszumanska.debian.org
Tue Jul 22 20:44:11 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository adblock-plus.

commit 40aa2969ec3f8ed9bab64f675cf06e9d658c521d
Author: Wladimir Palant <trev at adblockplus.org>
Date:   Fri May 13 16:27:22 2011 +0200

    Added new build scripts, functionality of replace create_xpi.pl, make_devbuild.pl and make_babelzilla_build.pl is already implemented
---
 __init__.py      |   0
 build.py         |  62 ++++++++++++
 install.rdf.tmpl |  92 +++++++++++++++++
 localeTools.py   |  65 ++++++++++++
 packager.py      | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 521 insertions(+)

diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/build.py b/build.py
new file mode 100644
index 0000000..5eb6a4a
--- /dev/null
+++ b/build.py
@@ -0,0 +1,62 @@
+# coding: utf-8
+
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.1 (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+
+import os, sys
+from getopt import getopt, GetoptError
+import buildtools.packager as packager
+
+def usage():
+  print '''Usage: %s [output_file]
+
+Options:
+  -h          --help              Print this message and exit
+  -l l1,l2,l3 --locales=l1,l2,l3  Only include the given locales (if omitted:
+                                  all locales not marked as incomplete)
+  -b num      --build=num         Use given build number (if omitted the build
+                                  number will be retrieved from Mercurial)
+  -k file     --key=file          File containing private key and certificates
+                                  required to sign the package
+  -r          --release           Create a release build
+              --babelzilla        Create a build for Babelzilla
+''' % os.path.basename(sys.argv[0])
+
+def processArgs(baseDir, args):
+  try:
+    opts, args = getopt(sys.argv[1:], 'hl:b:k:r', ['help', 'locales', 'build=', 'key=', 'release', 'babelzilla'])
+  except GetoptError, e:
+    print str(e)
+    usage()
+    sys.exit(2)
+
+  locales = None
+  buildNum = None
+  releaseBuild = False
+  keyFile = None
+  limitMetadata = False
+  for option, value in opts:
+    if option in ('-h', '--help'):
+      usage()
+      sys.exit()
+    elif option in ('-l', '--locales'):
+      locales = value.split(',')
+    elif option in ('-b', '--build'):
+      buildNum = int(value)
+    elif option in ('-k', '--key'):
+      keyFile = value
+    elif option in ('-r', '--release'):
+      releaseBuild = True
+    elif option == '--babelzilla':
+      locales = 'all'
+      limitMetadata = True
+
+  outFile = None
+  if len(args) >= 1:
+    outFile = args[0]
+
+  packager.createBuild(baseDir, outFile=outFile, locales=locales, buildNum=buildNum,
+                       releaseBuild=releaseBuild, keyFile=keyFile,
+                       limitMetadata=limitMetadata)
diff --git a/install.rdf.tmpl b/install.rdf.tmpl
new file mode 100644
index 0000000..63a6602
--- /dev/null
+++ b/install.rdf.tmpl
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>{{metadata.get('general', 'id')}}</em:id>
+    <em:version>{{version}}</em:version>
+    <em:name>{{localeMetadata[defaultLocale].name}}</em:name>
+    <em:description>{{localeMetadata[defaultLocale].description}}</em:description>
+    <em:creator>{{metadata.get('general', 'author')}}</em:creator>
+    <em:homepageURL>{{metadata.get('homepage', 'default')}}</em:homepageURL>
+    <em:type>2</em:type>
+
+    {%- if not releaseBuild or metadata.has_option('general', 'updateURL') %}
+    <em:updateURL>
+      {{- metadata.get('general', 'updateURL') if releaseBuild else 'https://adblockplus.org/devbuilds/%s/update.rdf' % metadata.get('general', 'basename') -}}
+      {{- '?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%' -}}
+    </em:updateURL>
+    {%- endif %}
+
+    {%- if metadata.has_option('general', 'icon') %}
+    <em:iconURL>{{metadata.get('general', 'icon')}}</em:iconURL>
+    {%- endif %}
+
+    {%- if metadata.has_option('general', 'about') %}
+    <em:aboutURL>{{metadata.get('general', 'about')}}</em:aboutURL>
+    {%- endif %}
+
+    {%- if metadata.has_option('general', 'options') %}
+    <em:optionsURL>{{metadata.get('general', 'options')}}</em:optionsURL>
+    {%- endif %}
+
+    {%- if metadata.has_section('contributors') %}
+    {%- for option in metadata.options('contributors')|sort %}
+    <em:contributor>{{metadata.get('contributors', option)}}</em:contributor>
+    {%- endfor %}
+    {%- endif %}
+
+    {%- for translator in localeMetadata|translators %}
+    <em:translator>{{translator}}</em:translator>
+    {%- endfor %}
+
+    {%- if not limitMetadata %}
+    {%- for localeCode in localeMetadata.keys()|sort %}
+    {%- set locale = localeMetadata[localeCode] %}
+    <em:localized>
+      <Description>
+        <em:locale>{{localeCode}}</em:locale>
+        <em:name>
+          {%- if 'name' in locale -%}
+            {{locale.name}}
+          {%- else -%}
+            {{localeMetadata[defaultLocale].name}}
+          {%- endif -%}
+        </em:name>
+        <em:description>
+          {%- if 'description' in locale -%}
+            {{locale.description}}
+          {%- else -%}
+            {{localeMetadata[defaultLocale].description}}
+          {%- endif -%}
+        </em:description>
+        <em:creator>{{metadata.get('general', 'author')}}</em:creator>
+        <em:homepageURL>
+          {%- if metadata.has_option('homepage', localeCode) -%}
+            {{- metadata.get('homepage', localeCode) -}}
+          {%- elif metadata.has_option('homepage', localeCode.split('-')[0]) -%}
+            {{- metadata.get('homepage', localeCode.split('-')[0]) -}}
+          {%- else -%}
+            {{- metadata.get('homepage', 'default') -}}
+          {%- endif -%}
+        </em:homepageURL>
+      </Description>
+    </em:localized>
+    {%- endfor %}
+    {%- endif %}
+
+    {%- for appName in metadata.options('compat')|sort %}
+    {%- if appName in KNOWN_APPS %}
+    <em:targetApplication>
+      <Description>
+        <!-- {{appName}} -->
+        <em:id>{{KNOWN_APPS[appName]}}</em:id>
+        <em:minVersion>{{metadata.get('compat', appName).split('/')[0]}}</em:minVersion>
+        <em:maxVersion>{{metadata.get('compat', appName).split('/')[1]}}</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+    {%- endif %}
+    {%- endfor %}
+  </Description>
+</RDF>
diff --git a/localeTools.py b/localeTools.py
new file mode 100644
index 0000000..ee0aaa7
--- /dev/null
+++ b/localeTools.py
@@ -0,0 +1,65 @@
+# coding: utf-8
+
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.1 (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+
+import re, sys, codecs, cgi
+from StringIO import StringIO
+from ConfigParser import SafeConfigParser
+from xml.parsers.expat import ParserCreate, XML_PARAM_ENTITY_PARSING_ALWAYS
+
+def parseDTDString(data, path):
+  result = {}
+  parser = ParserCreate()
+  parser.UseForeignDTD(True)
+
+  def ExternalEntityRefHandler(context, base, systemId, publicId):
+    subparser = parser.ExternalEntityParserCreate(context, 'utf-8')
+    subparser.Parse(data.encode('utf-8'), True)
+    return 1
+
+  def EntityDeclHandler(entityName, is_parameter_entity, value, base, systemId, publicId, notationName):
+    result[entityName] = value
+
+  parser.UseForeignDTD(True)
+  parser.SetParamEntityParsing(XML_PARAM_ENTITY_PARSING_ALWAYS)
+  parser.ExternalEntityRefHandler = ExternalEntityRefHandler
+  parser.EntityDeclHandler = EntityDeclHandler
+  parser.Parse('<!DOCTYPE root SYSTEM "foo"><root/>', True)
+  result['_origData'] = data
+  return result
+
+def parsePropertiesString(data, path):
+  result = {}
+  for line in data.splitlines():
+    if re.search(r'^\s*[#!]', line):
+      continue
+    elif '=' in line:
+      key, value = line.split('=', 1)
+      result[key] = value
+    elif re.search(r'\S', line):
+      print >>sys.stderr, 'Unrecognized data in file %s: %s' % (path, line)
+  result['_origData'] = data
+  return result
+
+def parseString(data, path):
+  if path.endswith('.dtd'):
+    return parseDTDString(data, path)
+  elif path.endswith('.properties'):
+    return parsePropertiesString(data, path)
+  else:
+    return None
+
+def readFile(path):
+  fileHandle = codecs.open(path, 'rb', encoding='utf-8')
+  data = fileHandle.read()
+  fileHandle.close()
+  return parseString(data, path)
+
+def generateStringEntry(key, value, path):
+  if path.endswith('.dtd'):
+    return '<!ENTITY %s "%s">\n' % (cgi.escape(key, True), cgi.escape(value, True))
+  else:
+    return '%s=%s\n' % (key, value)
diff --git a/packager.py b/packager.py
new file mode 100644
index 0000000..d557f80
--- /dev/null
+++ b/packager.py
@@ -0,0 +1,302 @@
+# coding: utf-8
+
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.1 (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+
+import os, re, subprocess, jinja2, buildtools, codecs, hashlib, base64
+from ConfigParser import SafeConfigParser
+from StringIO import StringIO
+from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED
+import buildtools.localeTools as localeTools
+
+KNOWN_APPS = {
+  'conkeror':   '{a79fe89b-6662-4ff4-8e88-09950ad4dfde}',
+  'emusic':     'dlm at emusic.com',
+  'fennec':     '{a23983c0-fd0e-11dc-95ff-0800200c9a66}',
+  'firefox':    '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}',
+  'midbrowser':   '{aa5ca914-c309-495d-91cf-3141bbb04115}',
+  'prism':    'prism at developer.mozilla.org',
+  'seamonkey':  '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}',
+  'songbird':   'songbird at songbirdnest.com',
+  'thunderbird':  '{3550f703-e582-4d05-9a08-453d09bdfdc6}',
+  'toolkit':    'toolkit at mozilla.org',
+}
+
+defaultLocale = 'en-US'
+
+def getDefaultFileName(baseDir, metadata, version):
+  return os.path.join(baseDir, '%s-%s.xpi' % (metadata.get('general', 'baseName'), version))
+
+def getMetadataPath(baseDir):
+  return os.path.join(baseDir, 'metadata')
+
+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 getXPIFiles(baseDir):
+  return [os.path.join(baseDir, file) for file in ('components', 'modules', 'defaults', 'bootstrap.js', 'chrome.manifest', 'icon.png', 'icon64.png')]
+
+def getIgnoredFiles(params):
+  result = ['tests', 'mochitest', '.incomplete', 'meta.properties']
+  if params['releaseBuild']:
+    result.append('TimeLine.jsm')
+  return result
+
+def isValidLocale(localesDir, dir, includeIncomplete=False):
+  if re.search(r'[^\w\-]', dir):
+    return False
+  if not os.path.isdir(os.path.join(localesDir, dir)):
+    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 getBuildNum(baseDir):
+  (result, dummy) = subprocess.Popen(['hg', 'id', '-n'], stdout=subprocess.PIPE).communicate()
+  return re.sub(r'\W', '', result)
+
+def readMetadata(baseDir):
+  metadata = SafeConfigParser()
+  file = codecs.open(getMetadataPath(baseDir), 'rb', encoding='utf-8')
+  metadata.readfp(file)
+  file.close()
+  return metadata
+
+def processFile(path, data, params):
+  if not re.search(r'\.(manifest|xul|jsm?|xml|xhtml|rdf|dtd|properties|css)$', path):
+    return data
+
+  data = re.sub(r'\r', '', data)
+  data = data.replace('{{BUILD}}', params['buildNum'])
+  data = data.replace('{{VERSION}}', params['version'])
+
+  whitespaceRegExp = re.compile(r'^(  )+', re.M)
+  data = re.sub(whitespaceRegExp, lambda match: '\t' * (len(match.group(0)) / 2), data)
+
+  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)
+
+  if params['releaseBuild'] and path.endswith('.jsm'):
+    # Remove timeline calls from release builds
+    timelineRegExp1 = re.compile(r'^.*\b[tT]imeLine\.(\w+)\(.*', re.M)
+    timelineRegExp2 = re.compile(r'^.*Cu\.import\([^()]*\bTimeLine\.jsm\"\).*', re.M)
+    data = re.sub(timelineRegExp1, '', data)
+    data = re.sub(timelineRegExp2, '', 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()
+    try:
+      result[locale] = localeTools.readFile(os.path.join(getLocalesDir(baseDir), locale, 'meta.properties'))
+    except:
+      result[locale] = {}
+  return result
+
+def getTranslators(localeMetadata):
+  translators = {}
+  for locale in localeMetadata.itervalues():
+    if 'translator' in locale:
+      for translator in locale['translator'].split(','):
+        translator = translator.strip()
+        if translator:
+          translators[translator] = True
+  result = translators.keys()
+  result.sort()
+  return result
+
+def createManifest(baseDir, params):
+  global KNOWN_APPS, defaultLocale
+  env = jinja2.Environment(loader=jinja2.FileSystemLoader(buildtools.__path__[0]), autoescape=True, extensions=['jinja2.ext.autoescape'])
+  env.filters['translators'] = getTranslators
+  template = env.get_template('install.rdf.tmpl')
+  templateData = dict(params)
+  templateData['localeMetadata'] = readLocaleMetadata(baseDir, params['locales'])
+  templateData['KNOWN_APPS'] = KNOWN_APPS
+  templateData['defaultLocale'] = defaultLocale
+  return template.render(templateData).encode('utf-8')
+
+def readFile(files, params, path, name):
+  ignoredFiles = getIgnoredFiles(params)
+  if os.path.isdir(path):
+    for file in os.listdir(path):
+      if file in ignoredFiles:
+        continue
+      readFile(files, params, os.path.join(path, file), '%s/%s' % (name, file))
+  else:
+    file = open(path, 'rb')
+    data = processFile(path, file.read(), params)
+    file.close()
+    files[name] = data
+
+def fixupLocales(baseDir, files, params):
+  global defaultLocale
+
+  # Read in default locale data, it might not be included in files
+  defaultLocaleDir = os.path.join(getLocalesDir(baseDir), defaultLocale)
+  reference = {}
+  ignoredFiles = getIgnoredFiles(params)
+  for file in os.listdir(defaultLocaleDir):
+    path = os.path.join(defaultLocaleDir, file)
+    if file in ignoredFiles or not os.path.isfile(path):
+      continue
+    data = localeTools.readFile(path)
+    if data:
+      reference[file] = data
+
+  for locale in params['locales']:
+    for file in reference.iterkeys():
+      path = '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 createChromeJar(baseDir, params):
+  files = {}
+  for name, path in getChromeSubdirs(baseDir, params['locales']).iteritems():
+    if os.path.isdir(path):
+      readFile(files, params, path, name)
+  if not params['limitMetadata']:
+    fixupLocales(baseDir, files, params)
+
+  data = StringIO()
+  jar = ZipFile(data, 'w', ZIP_STORED)
+  for name, value in files.iteritems():
+    jar.writestr(name, value)
+  jar.close()
+  return data.getvalue()
+
+def readXPIFiles(baseDir, params, files):
+  for path in getXPIFiles(baseDir):
+    if os.path.exists(path):
+      readFile(files, params, path, os.path.basename(path))
+
+def signFiles(files, keyFile):
+  import M2Crypto
+  manifest = []
+  signature = []
+
+  def getDigest(data):
+    md5 = hashlib.md5()
+    md5.update(data)
+    sha1 = hashlib.sha1()
+    sha1.update(data)
+    return 'Digest-Algorithms: MD5 SHA1\nMD5-Digest: %s\nSHA1-Digest: %s\n' % (base64.b64encode(md5.digest()), base64.b64encode(sha1.digest()))
+
+  def addSection(manifestData, signaturePrefix):
+    manifest.append(manifestData)
+    signatureData = ''
+    if signaturePrefix:
+      signatureData += signaturePrefix
+    signatureData += getDigest(manifestData)
+    signature.append(signatureData)
+
+  addSection('Manifest-Version: 1.0\n', 'Signature-Version: 1.0\n')
+  fileNames = files.keys()
+  fileNames.sort()
+  for fileName in fileNames:
+    addSection('Name: %s\n%s' % (fileName, getDigest(files[fileName])), 'Name: %s\n' % fileName)
+  files['META-INF/manifest.mf'] = '\n'.join(manifest)
+  files['META-INF/zigbert.sf'] = '\n'.join(signature)
+
+  keyHandle = open(keyFile, 'rb')
+  keyData = keyHandle.read()
+  keyHandle.close()
+  stack = M2Crypto.X509.X509_Stack()
+  first = True
+  for match in re.finditer(r'-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----', keyData, re.S):
+    if first:
+      # Skip first certificate
+      first = False
+    else:
+      stack.push(M2Crypto.X509.load_cert_string(match.group(0)))
+
+  mime = M2Crypto.SMIME.SMIME()
+  mime.load_key(keyFile)
+  mime.set_x509_stack(stack)
+  signature = mime.sign(M2Crypto.BIO.MemoryBuffer(files['META-INF/zigbert.sf'].encode('utf-8')), M2Crypto.SMIME.PKCS7_DETACHED | M2Crypto.SMIME.PKCS7_BINARY)
+
+  buffer = M2Crypto.BIO.MemoryBuffer()
+  signature.write_der(buffer)
+  files['META-INF/zigbert.rsa'] = buffer.read()
+
+def writeXPI(files, outFile):
+  zip = ZipFile(outFile, 'w', ZIP_DEFLATED)
+  names = files.keys()
+  names.sort(key=lambda x: '!' if x == 'META-INF/zigbert.rsa' else x)
+  for name in names:
+    zip.writestr(name, files[name])
+  zip.close()
+
+def createBuild(baseDir, outFile=None, locales=None, buildNum=None, releaseBuild=False, keyFile=None, limitMetadata=False):
+  if buildNum == None:
+    buildNum = getBuildNum(baseDir)
+  if locales == None:
+    locales = getLocales(baseDir)
+  elif locales == 'all':
+    locales = getLocales(baseDir, True)
+
+  metadata = readMetadata(baseDir)
+  version = metadata.get('general', 'version')
+  if not releaseBuild:
+    version += '.' + buildNum
+
+  if limitMetadata:
+    for option in metadata.options('compat'):
+      if not option in ('firefox', 'thunderbird', 'seamonkey'):
+        metadata.remove_option('compat', option)
+
+  if outFile == None:
+    outFile = getDefaultFileName(baseDir, metadata, version)
+
+  params = {
+    'locales': locales,
+    'releaseBuild': releaseBuild,
+    'buildNum': buildNum,
+    'version': version.encode('utf-8'),
+    'metadata': metadata,
+    'limitMetadata': limitMetadata,
+  }
+  files = {}
+  files['install.rdf'] = createManifest(baseDir, params)
+  files['chrome/%s.jar' % metadata.get('general', 'baseName')] = createChromeJar(baseDir, params)
+  readXPIFiles(baseDir, params, files)
+  if keyFile:
+    signFiles(files, keyFile)
+  writeXPI(files, outFile)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git



More information about the Pkg-mozext-commits mailing list