| 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 argparse | 5 import argparse |
| 6 import logging | 6 import logging |
| 7 import os | 7 import os |
| 8 import re | 8 import re |
| 9 import shutil | 9 import shutil |
| 10 import subprocess | 10 import subprocess |
| 11 import sys | 11 import sys |
| 12 from functools import partial | 12 from functools import partial |
| 13 from StringIO import StringIO | 13 from StringIO import StringIO |
| 14 from zipfile import ZipFile | 14 from zipfile import ZipFile |
| 15 from buildtools.localeTools import read_locale_config |
| 15 | 16 |
| 16 KNOWN_PLATFORMS = {'chrome', 'gecko', 'edge', 'generic'} | 17 KNOWN_PLATFORMS = {'chrome', 'gecko', 'edge', 'generic'} |
| 17 | 18 |
| 18 MAIN_PARSER = argparse.ArgumentParser( | 19 MAIN_PARSER = argparse.ArgumentParser( |
| 19 description=__doc__, | 20 description=__doc__, |
| 20 formatter_class=argparse.RawDescriptionHelpFormatter) | 21 formatter_class=argparse.RawDescriptionHelpFormatter) |
| 21 | 22 |
| 22 SUB_PARSERS = MAIN_PARSER.add_subparsers(title='Commands', dest='action', | 23 SUB_PARSERS = MAIN_PARSER.add_subparsers(title='Commands', dest='action', |
| 23 metavar='[command]') | 24 metavar='[command]') |
| 24 | 25 |
| 25 ALL_COMMANDS = [] | 26 ALL_COMMANDS = [] |
| 26 | 27 |
| 27 | 28 |
| 28 def make_argument(*args, **kwargs): | 29 def make_argument(*args, **kwargs): |
| 29 def _make_argument(*args, **kwargs): | 30 def _make_argument(*args, **kwargs): |
| 30 parser = kwargs.pop('parser') | 31 parser = kwargs.pop('parser') |
| 31 parser.add_argument(*args, **kwargs) | 32 parser.add_argument(*args, **kwargs) |
| 32 | 33 |
| 33 return partial(_make_argument, *args, **kwargs) | 34 return partial(_make_argument, *args, **kwargs) |
| 34 | 35 |
| 35 | 36 |
| 36 def argparse_command(valid_platforms=None, arguments=()): | 37 def argparse_command(valid_platforms=None, multi_platform=False, arguments=()): |
| 37 def wrapper(func): | 38 def wrapper(func): |
| 38 def func_wrapper(*args, **kwargs): | 39 def func_wrapper(*args, **kwargs): |
| 39 return func(*args, **kwargs) | 40 return func(*args, **kwargs) |
| 40 | 41 |
| 41 short_desc, long_desc = func.__doc__.split(os.linesep + os.linesep, 1) | 42 short_desc, long_desc = func.__doc__.split(os.linesep + os.linesep, 1) |
| 42 | 43 |
| 43 ALL_COMMANDS.append({ | 44 ALL_COMMANDS.append({ |
| 44 'name': func.__name__, | 45 'name': func.__name__, |
| 45 'description': long_desc, | 46 'description': long_desc, |
| 46 'help_text': short_desc, | 47 'help_text': short_desc, |
| 47 'valid_platforms': valid_platforms or KNOWN_PLATFORMS, | 48 'valid_platforms': valid_platforms or KNOWN_PLATFORMS, |
| 49 'multi_platform': multi_platform, |
| 48 'function': func, | 50 'function': func, |
| 49 'arguments': arguments, | 51 'arguments': arguments, |
| 50 }) | 52 }) |
| 51 return func_wrapper | 53 return func_wrapper |
| 52 | |
| 53 return wrapper | 54 return wrapper |
| 54 | 55 |
| 55 | 56 |
| 56 def make_subcommand(name, description, help_text, function, arguments): | 57 def make_subcommand(name, description, help_text, function, arguments): |
| 57 new_parser = SUB_PARSERS.add_parser( | 58 new_parser = SUB_PARSERS.add_parser( |
| 58 name, description=description, help=help_text, | 59 name, description=description, help=help_text, |
| 59 formatter_class=argparse.RawDescriptionHelpFormatter, | 60 formatter_class=argparse.RawDescriptionHelpFormatter, |
| 60 ) | 61 ) |
| 61 | 62 |
| 62 for argument in arguments: | 63 for argument in arguments: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 86 types.add(p) | 87 types.add(p) |
| 87 | 88 |
| 88 if len(types) == 0: | 89 if len(types) == 0: |
| 89 logging.error('No metadata file found in this repository. Expecting ' | 90 logging.error('No metadata file found in this repository. Expecting ' |
| 90 'one or more of {} to be present.'.format( | 91 'one or more of {} to be present.'.format( |
| 91 ', '.join('metadata.' + p for p in KNOWN_PLATFORMS))) | 92 ', '.join('metadata.' + p for p in KNOWN_PLATFORMS))) |
| 92 build_available_subcommands._result = False | 93 build_available_subcommands._result = False |
| 93 return False | 94 return False |
| 94 | 95 |
| 95 for command_params in ALL_COMMANDS: | 96 for command_params in ALL_COMMANDS: |
| 97 multi_platform = command_params.pop('multi_platform') |
| 96 platforms = types.intersection(command_params.pop('valid_platforms')) | 98 platforms = types.intersection(command_params.pop('valid_platforms')) |
| 97 if len(platforms) > 1: | 99 if len(platforms) > 1: |
| 100 if multi_platform: |
| 101 help_text = ('Multiple types may be specifed (each preceded ' |
| 102 'by -t/--type)') |
| 103 action = 'append' |
| 104 else: |
| 105 help_text = None |
| 106 action = 'store' |
| 107 |
| 98 command_params['arguments'] += ( | 108 command_params['arguments'] += ( |
| 99 make_argument('-t', '--type', dest='platform', required=True, | 109 make_argument('-t', '--type', dest='platform', required=True, |
| 100 choices=platforms), | 110 choices=platforms, action=action, |
| 111 help=help_text), |
| 101 ) | 112 ) |
| 102 make_subcommand(**command_params) | 113 make_subcommand(**command_params) |
| 103 elif len(platforms) == 1: | 114 elif len(platforms) == 1: |
| 104 sub_parser = make_subcommand(**command_params) | 115 sub_parser = make_subcommand(**command_params) |
| 105 sub_parser.set_defaults(platform=platforms.pop()) | 116 sub_parser.set_defaults(platform=platforms.pop()) |
| 106 | 117 |
| 107 build_available_subcommands._result = True | 118 build_available_subcommands._result = True |
| 108 return True | 119 return True |
| 109 | 120 |
| 110 | 121 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 from buildtools.packager import getDevEnvPath | 183 from buildtools.packager import getDevEnvPath |
| 173 devenv_dir = getDevEnvPath(base_dir, platform) | 184 devenv_dir = getDevEnvPath(base_dir, platform) |
| 174 | 185 |
| 175 shutil.rmtree(devenv_dir, ignore_errors=True) | 186 shutil.rmtree(devenv_dir, ignore_errors=True) |
| 176 | 187 |
| 177 file.seek(0) | 188 file.seek(0) |
| 178 with ZipFile(file, 'r') as zip_file: | 189 with ZipFile(file, 'r') as zip_file: |
| 179 zip_file.extractall(devenv_dir) | 190 zip_file.extractall(devenv_dir) |
| 180 | 191 |
| 181 | 192 |
| 182 def read_locale_config(base_dir, platform, metadata): | |
| 183 if platform != 'generic': | |
| 184 import buildtools.packagerChrome as packager | |
| 185 locale_dir = os.path.join(base_dir, '_locales') | |
| 186 locale_config = { | |
| 187 'default_locale': packager.defaultLocale, | |
| 188 } | |
| 189 else: | |
| 190 locale_dir = os.path.join( | |
| 191 base_dir, *metadata.get('locales', 'base_path').split('/') | |
| 192 ) | |
| 193 locale_config = { | |
| 194 'default_locale': metadata.get('locales', 'default_locale') | |
| 195 } | |
| 196 | |
| 197 locale_config['base_path'] = locale_dir | |
| 198 | |
| 199 locales = [(locale.replace('_', '-'), os.path.join(locale_dir, locale)) | |
| 200 for locale in os.listdir(locale_dir)] | |
| 201 locale_config['locales'] = dict(locales) | |
| 202 | |
| 203 return locale_config | |
| 204 | |
| 205 | |
| 206 project_key_argument = make_argument( | 193 project_key_argument = make_argument( |
| 207 'project_key', help='The crowdin project key.' | 194 'project_key', help='The crowdin project key.' |
| 208 ) | 195 ) |
| 209 | 196 |
| 210 | 197 |
| 211 @argparse_command( | 198 @argparse_command( |
| 212 arguments=(project_key_argument, ) | 199 arguments=(project_key_argument, ) |
| 213 ) | 200 ) |
| 214 def setuptrans(base_dir, project_key, platform, **kwargs): | 201 def setuptrans(base_dir, project_key, platform, **kwargs): |
| 215 """ | 202 """ |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 | 319 |
| 333 | 320 |
| 334 def valid_version_format(value): | 321 def valid_version_format(value): |
| 335 if re.search(r'[^\d\.]', value): | 322 if re.search(r'[^\d\.]', value): |
| 336 raise argparse.ArgumentTypeError('Wrong version number format') | 323 raise argparse.ArgumentTypeError('Wrong version number format') |
| 337 | 324 |
| 338 return value | 325 return value |
| 339 | 326 |
| 340 | 327 |
| 341 @argparse_command( | 328 @argparse_command( |
| 342 valid_platforms={'chrome', 'edge'}, | 329 valid_platforms={'chrome', 'gecko', 'edge'}, multi_platform=True, |
| 343 arguments=( | 330 arguments=( |
| 344 make_argument( | 331 make_argument( |
| 345 '-k', '--key', dest='key_file', | 332 '-k', '--key', dest='key_file', |
| 346 help=('File containing private key and certificates required to ' | 333 help=('File containing private key and certificates required to ' |
| 347 'sign the release.')), | 334 'sign the release.')), |
| 348 make_argument( | 335 make_argument( |
| 349 '-d', '--downloads-repository', dest='downloads_repository', | 336 '-d', '--downloads-repository', dest='downloads_repository', |
| 350 help=('Directory containing downloads repository (if omitted ' | 337 help=('Directory containing downloads repository (if omitted ' |
| 351 '../downloads is assumed)')), | 338 '../downloads is assumed)')), |
| 352 make_argument( | 339 make_argument( |
| 353 'version', help='Version number of the release', | 340 'version', help='Version number of the release', |
| 354 type=valid_version_format) | 341 type=valid_version_format) |
| 355 ) | 342 ) |
| 356 ) | 343 ) |
| 357 def release(base_dir, downloads_repository, key_file, platform, version, | 344 def release(base_dir, downloads_repository, key_file, platform, version, |
| 358 **kwargs): | 345 **kwargs): |
| 359 """ | 346 """ |
| 360 Run release automation. | 347 Run release automation. |
| 361 | 348 |
| 362 Note: If you are not the project owner then you probably don't want to run | 349 Note: If you are not the project owner then you probably don't want to run |
| 363 this! | 350 this! |
| 364 | 351 |
| 365 Run release automation: create downloads for the new version, tag source | 352 Run release automation: create downloads for the new version, tag source |
| 366 code repository as well as downloads and buildtools repository. | 353 code repository as well as downloads and buildtools repository. |
| 367 """ | 354 """ |
| 368 if downloads_repository is None: | 355 if downloads_repository is None: |
| 369 downloads_repository = os.path.join(base_dir, os.pardir, 'downloads') | 356 downloads_repository = os.path.join(base_dir, os.pardir, 'downloads') |
| 370 | 357 |
| 371 if platform == 'chrome' and key_file is None: | 358 if 'chrome' in platform and key_file is None: |
| 372 logging.error('You must specify a key file for this release') | 359 logging.error('You must specify a key file for this release') |
| 373 return | 360 return |
| 374 | 361 |
| 375 import buildtools.releaseAutomation as releaseAutomation | 362 import buildtools.releaseAutomation as releaseAutomation |
| 376 releaseAutomation.run(base_dir, platform, version, key_file, | 363 releaseAutomation.run(base_dir, platform, version, key_file, |
| 377 downloads_repository) | 364 downloads_repository) |
| 378 | 365 |
| 379 | 366 |
| 380 @argparse_command(valid_platforms={'chrome'}) | 367 @argparse_command(valid_platforms={'chrome'}) |
| 381 def updatepsl(base_dir, **kwargs): | 368 def updatepsl(base_dir, **kwargs): |
| (...skipping 10 matching lines...) Expand all Loading... |
| 392 if build_available_subcommands(base_dir): | 379 if build_available_subcommands(base_dir): |
| 393 MAIN_PARSER.set_defaults(base_dir=base_dir) | 380 MAIN_PARSER.set_defaults(base_dir=base_dir) |
| 394 | 381 |
| 395 # If no args are provided, this module is run directly from the command | 382 # If no args are provided, this module is run directly from the command |
| 396 # line. argparse will take care of consuming sys.argv. | 383 # line. argparse will take care of consuming sys.argv. |
| 397 arguments = MAIN_PARSER.parse_args(args if len(args) > 0 else None) | 384 arguments = MAIN_PARSER.parse_args(args if len(args) > 0 else None) |
| 398 | 385 |
| 399 function = arguments.function | 386 function = arguments.function |
| 400 del arguments.function | 387 del arguments.function |
| 401 function(**vars(arguments)) | 388 function(**vars(arguments)) |
| OLD | NEW |