OLD | NEW |
1 # This Source Code Form is subject to the terms of the Mozilla Public | 1 # This Source Code Form is subject to the terms of the Mozilla Public |
2 # License, v. 2.0. If a copy of the MPL was not distributed with this | 2 # License, v. 2.0. If a copy of the MPL was not distributed with this |
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. | 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
4 | 4 |
5 import os | 5 import os |
6 import sys | 6 import sys |
7 import re | 7 import re |
8 import subprocess | 8 import subprocess |
9 import shutil | 9 import shutil |
10 from getopt import getopt, GetoptError | 10 from getopt import getopt, GetoptError |
11 from StringIO import StringIO | 11 from StringIO import StringIO |
12 from zipfile import ZipFile | 12 from zipfile import ZipFile |
13 | 13 |
14 knownTypes = ('gecko-webext', 'chrome', 'generic', 'edge') | 14 knownTypes = {'gecko-webext', 'chrome', 'generic', 'edge'} |
15 | 15 |
16 | 16 |
17 class Command(object): | 17 class Command(object): |
18 name = property(lambda self: self._name) | 18 name = property(lambda self: self._name) |
19 shortDescription = property( | 19 shortDescription = property( |
20 lambda self: self._shortDescription, | 20 lambda self: self._shortDescription, |
21 lambda self, value: self.__dict__.update({'_shortDescription': value}) | 21 lambda self, value: self.__dict__.update({'_shortDescription': value}) |
22 ) | 22 ) |
23 description = property( | 23 description = property( |
24 lambda self: self._description, | 24 lambda self: self._description, |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 327 |
328 # JSDoc struggles wih huge objects: https://github.com/jsdoc3/jsdoc/issues/9
76 | 328 # JSDoc struggles wih huge objects: https://github.com/jsdoc3/jsdoc/issues/9
76 |
329 if type == 'chrome': | 329 if type == 'chrome': |
330 sources = [os.path.join(source_dir, filename) for filename in os.listdir
(source_dir) if filename != 'publicSuffixList.js'] | 330 sources = [os.path.join(source_dir, filename) for filename in os.listdir
(source_dir) if filename != 'publicSuffixList.js'] |
331 | 331 |
332 buildtools_path = os.path.dirname(__file__) | 332 buildtools_path = os.path.dirname(__file__) |
333 config = os.path.join(buildtools_path, 'jsdoc.conf') | 333 config = os.path.join(buildtools_path, 'jsdoc.conf') |
334 | 334 |
335 command = ['npm', 'run-script', 'jsdoc', '--', '--destination', targetDir, | 335 command = ['npm', 'run-script', 'jsdoc', '--', '--destination', targetDir, |
336 '--configure', config] + sources | 336 '--configure', config] + sources |
337 if any(opt in ('-q', '--quiet') for opt, _ in opts): | 337 if any(opt in {'-q', '--quiet'} for opt, _ in opts): |
338 process = subprocess.Popen(command, stdout=subprocess.PIPE, | 338 process = subprocess.Popen(command, stdout=subprocess.PIPE, |
339 stderr=subprocess.PIPE, cwd=buildtools_path) | 339 stderr=subprocess.PIPE, cwd=buildtools_path) |
340 stderr = process.communicate()[1] | 340 stderr = process.communicate()[1] |
341 retcode = process.poll() | 341 retcode = process.poll() |
342 if retcode: | 342 if retcode: |
343 sys.stderr.write(stderr) | 343 sys.stderr.write(stderr) |
344 raise subprocess.CalledProcessError(command, retcode) | 344 raise subprocess.CalledProcessError(command, retcode) |
345 else: | 345 else: |
346 subprocess.check_call(command, cwd=buildtools_path) | 346 subprocess.check_call(command, cwd=buildtools_path) |
347 | 347 |
348 | 348 |
349 def runReleaseAutomation(baseDir, scriptName, opts, args, type): | 349 def runReleaseAutomation(baseDir, scriptName, opts, args, type): |
350 keyFile = None | 350 keyFile = None |
351 downloadsRepo = os.path.join(baseDir, '..', 'downloads') | 351 downloadsRepo = os.path.join(baseDir, '..', 'downloads') |
352 for option, value in opts: | 352 for option, value in opts: |
353 if option in ('-k', '--key'): | 353 if option in {'-k', '--key'}: |
354 keyFile = value | 354 keyFile = value |
355 elif option in ('-d', '--downloads'): | 355 elif option in {'-d', '--downloads'}: |
356 downloadsRepo = value | 356 downloadsRepo = value |
357 | 357 |
358 if len(args) == 0: | 358 if len(args) == 0: |
359 print 'No version number specified for the release' | 359 print 'No version number specified for the release' |
360 usage(scriptName, type, 'release') | 360 usage(scriptName, type, 'release') |
361 return | 361 return |
362 version = args[0] | 362 version = args[0] |
363 if re.search(r'[^\d\.]', version): | 363 if re.search(r'[^\d\.]', version): |
364 print 'Wrong version number format' | 364 print 'Wrong version number format' |
365 usage(scriptName, type, 'release') | 365 usage(scriptName, type, 'release') |
(...skipping 14 matching lines...) Expand all Loading... |
380 | 380 |
381 | 381 |
382 with addCommand(lambda baseDir, scriptName, opts, args, type: usage(scriptName,
type), ('help', '-h', '--help')) as command: | 382 with addCommand(lambda baseDir, scriptName, opts, args, type: usage(scriptName,
type), ('help', '-h', '--help')) as command: |
383 command.shortDescription = 'Show this message' | 383 command.shortDescription = 'Show this message' |
384 | 384 |
385 with addCommand(runBuild, 'build') as command: | 385 with addCommand(runBuild, 'build') as command: |
386 command.shortDescription = 'Create a build' | 386 command.shortDescription = 'Create a build' |
387 command.description = 'Creates an extension build with given file name. If o
utput_file is missing a default name will be chosen.' | 387 command.description = 'Creates an extension build with given file name. If o
utput_file is missing a default name will be chosen.' |
388 command.params = '[options] [output_file]' | 388 command.params = '[options] [output_file]' |
389 command.addOption('Use given build number (if omitted the build number will
be retrieved from Mercurial)', short='b', long='build', value='num') | 389 command.addOption('Use given build number (if omitted the build number will
be retrieved from Mercurial)', short='b', long='build', value='num') |
390 command.addOption('File containing private key and certificates required to
sign the package', short='k', long='key', value='file', types=('chrome',)) | 390 command.addOption('File containing private key and certificates required to
sign the package', short='k', long='key', value='file', types={'chrome'}) |
391 command.addOption('Create a release build', short='r', long='release') | 391 command.addOption('Create a release build', short='r', long='release') |
392 command.supportedTypes = ('gecko-webext', 'chrome', 'edge') | 392 command.supportedTypes = {'gecko-webext', 'chrome', 'edge'} |
393 | 393 |
394 with addCommand(createDevEnv, 'devenv') as command: | 394 with addCommand(createDevEnv, 'devenv') as command: |
395 command.shortDescription = 'Set up a development environment' | 395 command.shortDescription = 'Set up a development environment' |
396 command.description = 'Will set up or update the devenv folder as an unpacke
d extension folder for development.' | 396 command.description = 'Will set up or update the devenv folder as an unpacke
d extension folder for development.' |
397 command.supportedTypes = ('gecko-webext', 'chrome') | 397 command.supportedTypes = {'gecko-webext', 'chrome'} |
398 | 398 |
399 with addCommand(setupTranslations, 'setuptrans') as command: | 399 with addCommand(setupTranslations, 'setuptrans') as command: |
400 command.shortDescription = 'Sets up translation languages' | 400 command.shortDescription = 'Sets up translation languages' |
401 command.description = 'Sets up translation languages for the project on crow
din.net.' | 401 command.description = 'Sets up translation languages for the project on crow
din.net.' |
402 command.params = '[options] project-key' | 402 command.params = '[options] project-key' |
403 | 403 |
404 with addCommand(updateTranslationMaster, 'translate') as command: | 404 with addCommand(updateTranslationMaster, 'translate') as command: |
405 command.shortDescription = 'Updates translation master files' | 405 command.shortDescription = 'Updates translation master files' |
406 command.description = 'Updates the translation master files in the project o
n crowdin.net.' | 406 command.description = 'Updates the translation master files in the project o
n crowdin.net.' |
407 command.params = '[options] project-key' | 407 command.params = '[options] project-key' |
408 | 408 |
409 with addCommand(uploadTranslations, 'uploadtrans') as command: | 409 with addCommand(uploadTranslations, 'uploadtrans') as command: |
410 command.shortDescription = 'Uploads existing translations' | 410 command.shortDescription = 'Uploads existing translations' |
411 command.description = 'Uploads already existing translations to the project
on crowdin.net.' | 411 command.description = 'Uploads already existing translations to the project
on crowdin.net.' |
412 command.params = '[options] project-key' | 412 command.params = '[options] project-key' |
413 | 413 |
414 with addCommand(getTranslations, 'gettranslations') as command: | 414 with addCommand(getTranslations, 'gettranslations') as command: |
415 command.shortDescription = 'Downloads translation updates' | 415 command.shortDescription = 'Downloads translation updates' |
416 command.description = 'Downloads updated translations from crowdin.net.' | 416 command.description = 'Downloads updated translations from crowdin.net.' |
417 command.params = '[options] project-key' | 417 command.params = '[options] project-key' |
418 | 418 |
419 with addCommand(generateDocs, 'docs') as command: | 419 with addCommand(generateDocs, 'docs') as command: |
420 command.shortDescription = 'Generate documentation (requires node.js)' | 420 command.shortDescription = 'Generate documentation (requires node.js)' |
421 command.description = ('Generate documentation files and write them into ' | 421 command.description = ('Generate documentation files and write them into ' |
422 'the specified directory.') | 422 'the specified directory.') |
423 command.addOption('Suppress JsDoc output', short='q', long='quiet') | 423 command.addOption('Suppress JsDoc output', short='q', long='quiet') |
424 command.params = '[options] <directory>' | 424 command.params = '[options] <directory>' |
425 command.supportedTypes = ('chrome',) | 425 command.supportedTypes = {'chrome'} |
426 | 426 |
427 with addCommand(runReleaseAutomation, 'release') as command: | 427 with addCommand(runReleaseAutomation, 'release') as command: |
428 command.shortDescription = 'Run release automation' | 428 command.shortDescription = 'Run release automation' |
429 command.description = 'Note: If you are not the project owner then you '
"probably don't want to run this!\n\n" 'Runs release automation: crea
tes downloads for the new version, tags ' 'source code repository as well
as downloads and buildtools repository.' | 429 command.description = 'Note: If you are not the project owner then you '
"probably don't want to run this!\n\n" 'Runs release automation: crea
tes downloads for the new version, tags ' 'source code repository as well
as downloads and buildtools repository.' |
430 command.addOption('File containing private key and certificates required to
sign the release.', short='k', long='key', value='file', types=('chrome', 'edge'
)) | 430 command.addOption('File containing private key and certificates required to
sign the release.', short='k', long='key', value='file', types={'chrome', 'edge'
}) |
431 command.addOption('Directory containing downloads repository (if omitted ../
downloads is assumed)', short='d', long='downloads', value='dir') | 431 command.addOption('Directory containing downloads repository (if omitted ../
downloads is assumed)', short='d', long='downloads', value='dir') |
432 command.params = '[options] <version>' | 432 command.params = '[options] <version>' |
433 command.supportedTypes = ('chrome', 'edge') | 433 command.supportedTypes = {'chrome', 'edge'} |
434 | 434 |
435 with addCommand(updatePSL, 'updatepsl') as command: | 435 with addCommand(updatePSL, 'updatepsl') as command: |
436 command.shortDescription = 'Updates Public Suffix List' | 436 command.shortDescription = 'Updates Public Suffix List' |
437 command.description = 'Downloads Public Suffix List (see http://publicsuffix
.org/) and generates lib/publicSuffixList.js from it.' | 437 command.description = 'Downloads Public Suffix List (see http://publicsuffix
.org/) and generates lib/publicSuffixList.js from it.' |
438 command.supportedTypes = ('chrome',) | 438 command.supportedTypes = {'chrome'} |
439 | 439 |
440 | 440 |
441 def getType(baseDir, scriptName, args): | 441 def getType(baseDir, scriptName, args): |
442 # Look for an explicit type parameter (has to be the first parameter) | 442 # Look for an explicit type parameter (has to be the first parameter) |
443 if len(args) >= 2 and args[0] == '-t': | 443 if len(args) >= 2 and args[0] == '-t': |
444 type = args[1] | 444 type = args[1] |
445 del args[1] | 445 del args[1] |
446 del args[0] | 446 del args[0] |
447 if type not in knownTypes: | 447 if type not in knownTypes: |
448 print ''' | 448 print ''' |
(...skipping 12 matching lines...) Expand all Loading... |
461 return types[0] | 461 return types[0] |
462 elif len(types) > 1: | 462 elif len(types) > 1: |
463 print ''' | 463 print ''' |
464 Ambiguous repository type, please specify -t parameter explicitly, e.g. | 464 Ambiguous repository type, please specify -t parameter explicitly, e.g. |
465 %s -t %s build | 465 %s -t %s build |
466 ''' % (scriptName, types[0]) | 466 ''' % (scriptName, types[0]) |
467 return None | 467 return None |
468 else: | 468 else: |
469 print ''' | 469 print ''' |
470 No metadata file found in this repository, a metadata file like | 470 No metadata file found in this repository, a metadata file like |
471 metadata.%s is required. | 471 metadata.* is required. |
472 ''' % knownTypes[0] | 472 ''' |
473 return None | 473 return None |
474 | 474 |
475 | 475 |
476 def processArgs(baseDir, args): | 476 def processArgs(baseDir, args): |
477 global commands | 477 global commands |
478 | 478 |
479 scriptName = os.path.basename(args[0]) | 479 scriptName = os.path.basename(args[0]) |
480 args = args[1:] | 480 args = args[1:] |
481 type = getType(baseDir, scriptName, args) | 481 type = getType(baseDir, scriptName, args) |
482 if type == None: | 482 if type == None: |
(...skipping 10 matching lines...) Expand all Loading... |
493 command = args[0] | 493 command = args[0] |
494 if command in commands: | 494 if command in commands: |
495 if commands[command].isSupported(type): | 495 if commands[command].isSupported(type): |
496 try: | 496 try: |
497 opts, args = commands[command].parseArgs(type, args[1:]) | 497 opts, args = commands[command].parseArgs(type, args[1:]) |
498 except GetoptError as e: | 498 except GetoptError as e: |
499 print str(e) | 499 print str(e) |
500 usage(scriptName, type, command) | 500 usage(scriptName, type, command) |
501 sys.exit(2) | 501 sys.exit(2) |
502 for option, value in opts: | 502 for option, value in opts: |
503 if option in ('-h', '--help'): | 503 if option in {'-h', '--help'}: |
504 usage(scriptName, type, command) | 504 usage(scriptName, type, command) |
505 sys.exit() | 505 sys.exit() |
506 commands[command](baseDir, scriptName, opts, args, type) | 506 commands[command](baseDir, scriptName, opts, args, type) |
507 else: | 507 else: |
508 print 'Command %s is not supported for this application type' % comm
and | 508 print 'Command %s is not supported for this application type' % comm
and |
509 usage(scriptName, type) | 509 usage(scriptName, type) |
510 else: | 510 else: |
511 print 'Command %s is unrecognized' % command | 511 print 'Command %s is unrecognized' % command |
512 usage(scriptName, type) | 512 usage(scriptName, type) |
OLD | NEW |