Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: packagerChrome.py

Issue 9257092: More build tools improvements (Closed)
Patch Set: Added some more changes required to build Firefox and Chrome extensions from the same repository (s… Created Jan. 25, 2013, 1:47 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « packager.py ('k') | packagerGecko.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # coding: utf-8 1 # coding: utf-8
2 2
3 # This file is part of the Adblock Plus build tools, 3 # This file is part of the Adblock Plus build tools,
4 # Copyright (C) 2006-2012 Eyeo GmbH 4 # Copyright (C) 2006-2012 Eyeo GmbH
5 # 5 #
6 # Adblock Plus is free software: you can redistribute it and/or modify 6 # Adblock Plus is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License version 3 as 7 # it under the terms of the GNU General Public License version 3 as
8 # published by the Free Software Foundation. 8 # published by the Free Software Foundation.
9 # 9 #
10 # Adblock Plus is distributed in the hope that it will be useful, 10 # Adblock Plus is distributed in the hope that it will be useful,
(...skipping 26 matching lines...) Expand all
37 37
38 if params['devenv']: 38 if params['devenv']:
39 result.add('qunit') 39 result.add('qunit')
40 40
41 baseDir = params['baseDir'] 41 baseDir = params['baseDir']
42 for file in os.listdir(baseDir): 42 for file in os.listdir(baseDir):
43 if file.endswith('.js') or file.endswith('.html') or file.endswith('.xml'): 43 if file.endswith('.js') or file.endswith('.html') or file.endswith('.xml'):
44 result.add(file) 44 result.add(file)
45 return result 45 return result
46 46
47 def processFile(path, data, params):
48 # We don't change anything yet, this function currently only exists here so
49 # that it can be overridden if necessary.
50 return data
51
47 def createManifest(params): 52 def createManifest(params):
48 template = getTemplate('manifest.json.tmpl') 53 template = getTemplate('manifest.json.tmpl')
49 templateData = dict(params) 54 templateData = dict(params)
50 55
51 baseDir = templateData['baseDir'] 56 baseDir = templateData['baseDir']
52 metadata = templateData['metadata'] 57 metadata = templateData['metadata']
53 58
54 if metadata.has_option('general', 'pageAction'): 59 if metadata.has_option('general', 'pageAction') and metadata.get('general', 'p ageAction') != '':
55 icon, popup = re.split(r'\s+', metadata.get('general', 'pageAction'), 1) 60 icon, popup = re.split(r'\s+', metadata.get('general', 'pageAction'), 1)
56 templateData['pageAction'] = {'icon': icon, 'popup': popup} 61 templateData['pageAction'] = {'icon': icon, 'popup': popup}
57 62
58 if metadata.has_option('general', 'icons'): 63 if metadata.has_option('general', 'icons'):
59 icons = {} 64 icons = {}
60 iconsDir = baseDir 65 iconsDir = baseDir
61 for dir in metadata.get('general', 'icons').split('/')[0:-1]: 66 for dir in metadata.get('general', 'icons').split('/')[0:-1]:
62 iconsDir = os.path.join(iconsDir, dir) 67 iconsDir = os.path.join(iconsDir, dir)
63 68
64 prefix, suffix = metadata.get('general', 'icons').split('/')[-1].split('?', 1) 69 prefix, suffix = metadata.get('general', 'icons').split('/')[-1].split('?', 1)
65 for file in os.listdir(iconsDir): 70 for file in os.listdir(iconsDir):
66 path = os.path.join(iconsDir, file) 71 path = os.path.join(iconsDir, file)
67 if os.path.isfile(path) and file.startswith(prefix) and file.endswith(suff ix): 72 if os.path.isfile(path) and file.startswith(prefix) and file.endswith(suff ix):
68 size = file[len(prefix):-len(suffix)] 73 size = file[len(prefix):-len(suffix)]
69 if not re.search(r'\D', size): 74 if not re.search(r'\D', size):
70 icons[size] = os.path.relpath(path, baseDir).replace('\\', '/') 75 icons[size] = os.path.relpath(path, baseDir).replace('\\', '/')
71 76
72 templateData['icons'] = icons 77 templateData['icons'] = icons
73 78
74 if metadata.has_option('general', 'permissions'): 79 if metadata.has_option('general', 'permissions'):
75 templateData['permissions'] = re.split(r'\s+', metadata.get('general', 'perm issions')) 80 templateData['permissions'] = re.split(r'\s+', metadata.get('general', 'perm issions'))
76 if params['experimentalAPI']: 81 if params['experimentalAPI']:
77 templateData['permissions'].append('experimental') 82 templateData['permissions'].append('experimental')
78 83
79 if metadata.has_option('general', 'backgroundScripts'): 84 if metadata.has_option('general', 'backgroundScripts'):
80 templateData['backgroundScripts'] = re.split(r'\s+', metadata.get('general', 'backgroundScripts')) 85 templateData['backgroundScripts'] = re.split(r'\s+', metadata.get('general', 'backgroundScripts'))
81 if params['devenv']: 86 if params['devenv']:
82 templateData['backgroundScripts'].append('devenvPoller__.js') 87 templateData['backgroundScripts'].append('devenvPoller__.js')
83 88
84 if metadata.has_option('general', 'webAccessible'): 89 if metadata.has_option('general', 'webAccessible') and metadata.get('general', 'webAccessible') != '':
85 templateData['webAccessible'] = re.split(r'\s+', metadata.get('general', 'we bAccessible')) 90 templateData['webAccessible'] = re.split(r'\s+', metadata.get('general', 'we bAccessible'))
86 91
87 if metadata.has_section('contentScripts'): 92 if metadata.has_section('contentScripts'):
88 contentScripts = [] 93 contentScripts = []
89 for run_at, scripts in metadata.items('contentScripts'): 94 for run_at, scripts in metadata.items('contentScripts'):
95 if scripts == '':
96 continue
90 contentScripts.append({ 97 contentScripts.append({
91 'matches': ['http://*/*', 'https://*/*'], 98 'matches': ['http://*/*', 'https://*/*'],
92 'js': re.split(r'\s+', scripts), 99 'js': re.split(r'\s+', scripts),
93 'run_at': run_at, 100 'run_at': run_at,
94 'all_frames': True, 101 'all_frames': True,
95 }) 102 })
96 templateData['contentScripts'] = contentScripts 103 templateData['contentScripts'] = contentScripts
97 104
98 manifest = template.render(templateData) 105 manifest = template.render(templateData)
99 106
100 # Normalize JSON structure 107 # Normalize JSON structure
101 licenseComment = re.compile(r'/\*.*?\*/', re.S) 108 licenseComment = re.compile(r'/\*.*?\*/', re.S)
102 data = json.loads(re.sub(licenseComment, '', manifest, 1)) 109 data = json.loads(re.sub(licenseComment, '', manifest, 1))
103 if '_dummy' in data: 110 if '_dummy' in data:
104 del data['_dummy'] 111 del data['_dummy']
105 manifest = json.dumps(data, sort_keys=True, indent=2) 112 manifest = json.dumps(data, sort_keys=True, indent=2)
106 113
107 return manifest.encode('utf-8') 114 return manifest.encode('utf-8')
108 115
109 def createPoller(params): 116 def createPoller(params):
110 template = getTemplate('chromeDevenvPoller__.js.tmpl') 117 template = getTemplate('chromeDevenvPoller__.js.tmpl')
111 return template.render(params).encode('utf-8'); 118 return template.render(params).encode('utf-8');
112 119
113 def convertJS(params, files): 120 def convertJS(params, files):
114 from jshydra.abp_rewrite import doRewrite 121 from jshydra.abp_rewrite import doRewrite
115 baseDir = params['baseDir']
116 122
117 for file, sources in params['metadata'].items('convert_js'): 123 for item in params['metadata'].items('convert_js'):
124 file, sources = item
125 baseDir = os.path.dirname(item.source)
126
118 # Make sure the file is inside an included directory 127 # Make sure the file is inside an included directory
119 if '/' in file and not files.isIncluded(file): 128 if '/' in file and not files.isIncluded(file):
120 continue 129 continue
121 130
122 sourceFiles = re.split(r'\s+', sources) 131 sourceFiles = re.split(r'\s+', sources)
123 args = [] 132 args = []
124 try: 133 try:
125 argsStart = sourceFiles.index('--arg') 134 argsStart = sourceFiles.index('--arg')
126 args = sourceFiles[argsStart + 1:] 135 args = sourceFiles[argsStart + 1:]
127 sourceFiles = sourceFiles[0:argsStart] 136 sourceFiles = sourceFiles[0:argsStart]
128 except ValueError: 137 except ValueError:
129 pass 138 pass
130 139
131 sourceFiles = map(lambda f: os.path.abspath(os.path.join(baseDir, f)), sourc eFiles) 140 sourceFiles = map(lambda f: os.path.abspath(os.path.join(baseDir, f)), sourc eFiles)
132 files[file] = doRewrite(sourceFiles, args) 141 files[file] = doRewrite(sourceFiles, args)
133 142
143 def importGeckoLocales(params, files):
144 import localeTools
145
146 localeCodeMapping = {
147 'ar': 'ar',
148 'bg': 'bg',
149 'ca': 'ca',
150 'cs': 'cs',
151 'da': 'da',
152 'de': 'de',
153 'el': 'el',
154 'en-US': 'en_US',
155 'en-GB': 'en_GB',
156 'es-ES': 'es',
157 'es-AR': 'es_419',
158 'et': 'et',
159 'fi': 'fi',
160 # '': 'fil', ???
161 'fr': 'fr',
162 'he': 'he',
163 'hi-IN': 'hi',
164 'hr': 'hr',
165 'hu': 'hu',
166 'id': 'id',
167 'it': 'it',
168 'ja': 'ja',
169 'ko': 'ko',
170 'lt': 'lt',
171 'lv': 'lv',
172 'nl': 'nl',
173 # 'nb-NO': 'no', ???
174 'pl': 'pl',
175 'pt-BR': 'pt_BR',
176 'pt-PT': 'pt_PT',
177 'ro': 'ro',
178 'ru': 'ru',
179 'sk': 'sk',
180 'sl': 'sl',
181 'sr': 'sr',
182 'sv-SE': 'sv',
183 'th': 'th',
184 'tr': 'tr',
185 'uk': 'uk',
186 'vi': 'vi',
187 'zh-CN': 'zh_CN',
188 'zh-TW': 'zh_TW',
189 }
190
191 for source, target in localeCodeMapping.iteritems():
192 targetFile = '_locales/%s/messages.json' % target
193
194 for item in params['metadata'].items('import_locales'):
195 fileName, keys = item
196 parts = map(lambda n: source if n == '*' else n, fileName.split('/'))
197 sourceFile = os.path.join(os.path.dirname(item.source), *parts)
198 incompleteMarker = os.path.join(os.path.dirname(sourceFile), '.incomplete' )
199 if not os.path.exists(sourceFile) or os.path.exists(incompleteMarker):
200 continue
201
202 data = {}
203 if targetFile in files:
204 data = json.loads(files[targetFile].decode('utf-8'))
205
206 try:
207 sourceData = localeTools.readFile(sourceFile)
208
209 # Resolve wildcard imports
210 if keys == '*' or keys == '=*':
211 importList = sourceData.keys()
212 importList = filter(lambda k: not k.startswith('_'), importList)
213 if keys == '=*':
214 importList = map(lambda k: '=' + k, importList)
215 keys = ' '.join(importList)
216
217 for stringID in re.split(r'\s+', keys):
218 noMangling = False
219 if stringID.startswith('='):
220 stringID = stringID[1:]
221 noMangling = True
222
223 if stringID in sourceData:
224 if noMangling:
225 key = re.sub(r'\W', '_', stringID)
226 else:
227 key = re.sub(r'\..*', '', parts[-1]) + '_' + re.sub(r'\W', '_', st ringID)
228 if key in data:
229 print 'Warning: locale string %s defined multiple times' % key
230 data[key] = {'message': sourceData[stringID]}
231 except Exception, e:
232 print 'Warning: error importing locale data from %s: %s' % (sourceFile, e)
233
234 files[targetFile] = json.dumps(data, ensure_ascii=False, sort_keys=True,
235 indent=2, separators=(',', ': ')).encode('utf-8') + '\n'
236
134 def signBinary(zipdata, keyFile): 237 def signBinary(zipdata, keyFile):
135 import M2Crypto 238 import M2Crypto
136 if not os.path.exists(keyFile): 239 if not os.path.exists(keyFile):
137 M2Crypto.RSA.gen_key(1024, 65537, callback=lambda x: None).save_key(keyFile, cipher=None) 240 M2Crypto.RSA.gen_key(1024, 65537, callback=lambda x: None).save_key(keyFile, cipher=None)
138 key = M2Crypto.EVP.load_key(keyFile) 241 key = M2Crypto.EVP.load_key(keyFile)
139 key.sign_init() 242 key.sign_init()
140 key.sign_update(zipdata) 243 key.sign_update(zipdata)
141 return key.final() 244 return key.final()
142 245
143 def getPublicKey(keyFile): 246 def getPublicKey(keyFile):
(...skipping 20 matching lines...) Expand all
164 267
165 params = { 268 params = {
166 'baseDir': baseDir, 269 'baseDir': baseDir,
167 'releaseBuild': releaseBuild, 270 'releaseBuild': releaseBuild,
168 'version': version, 271 'version': version,
169 'experimentalAPI': experimentalAPI, 272 'experimentalAPI': experimentalAPI,
170 'devenv': devenv, 273 'devenv': devenv,
171 'metadata': metadata, 274 'metadata': metadata,
172 } 275 }
173 276
174 files = Files(getPackageFiles(params), getIgnoredFiles(params)) 277 files = Files(getPackageFiles(params), getIgnoredFiles(params),
278 process=lambda path, data: processFile(path, data, params))
175 files['manifest.json'] = createManifest(params) 279 files['manifest.json'] = createManifest(params)
176 if metadata.has_section('mapping'): 280 if metadata.has_section('mapping'):
177 files.readMappedFiles(baseDir, metadata.items('mapping')) 281 files.readMappedFiles(metadata.items('mapping'))
178 files.read(baseDir) 282 files.read(baseDir)
179 283
180 if metadata.has_section('convert_js'): 284 if metadata.has_section('convert_js'):
181 convertJS(params, files) 285 convertJS(params, files)
182 286
287 if metadata.has_section('import_locales'):
288 importGeckoLocales(params, files)
289
183 if devenv: 290 if devenv:
184 files['devenvPoller__.js'] = createPoller(params) 291 files['devenvPoller__.js'] = createPoller(params)
185 292
186 zipdata = files.zipToString() 293 zipdata = files.zipToString()
187 signature = None 294 signature = None
188 pubkey = None 295 pubkey = None
189 if keyFile != None: 296 if keyFile != None:
190 signature = signBinary(zipdata, keyFile) 297 signature = signBinary(zipdata, keyFile)
191 pubkey = getPublicKey(keyFile) 298 pubkey = getPublicKey(keyFile)
192 writePackage(outFile, pubkey, signature, zipdata) 299 writePackage(outFile, pubkey, signature, zipdata)
(...skipping 23 matching lines...) Expand all
216 def shutdown_server(server): 323 def shutdown_server(server):
217 time.sleep(10) 324 time.sleep(10)
218 server.shutdown() 325 server.shutdown()
219 thread.start_new_thread(shutdown_server, (server,)) 326 thread.start_new_thread(shutdown_server, (server,))
220 server.serve_forever() 327 server.serve_forever()
221 328
222 if connections[0] == 0: 329 if connections[0] == 0:
223 print 'Warning: No incoming connections, extension probably not active in th e browser yet' 330 print 'Warning: No incoming connections, extension probably not active in th e browser yet'
224 else: 331 else:
225 print 'Handled %i connection(s)' % connections[0] 332 print 'Handled %i connection(s)' % connections[0]
OLDNEW
« no previous file with comments | « packager.py ('k') | packagerGecko.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld