Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 '''A simple tool to update the Native Client SDK to the latest version''' | 6 '''A simple tool to update the Native Client SDK to the latest version''' |
| 7 | 7 |
| 8 import cStringIO | 8 import cStringIO |
| 9 import cygtar | 9 import cygtar |
| 10 import json | 10 import json |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 REVISION = '{REVISION}' | 28 REVISION = '{REVISION}' |
| 29 | 29 |
| 30 GLOBAL_HELP = '''Usage: naclsdk [options] command [command_options] | 30 GLOBAL_HELP = '''Usage: naclsdk [options] command [command_options] |
| 31 | 31 |
| 32 naclsdk is a simple utility that updates the Native Client (NaCl) | 32 naclsdk is a simple utility that updates the Native Client (NaCl) |
| 33 Software Developer's Kit (SDK). Each component is kept as a 'bundle' that | 33 Software Developer's Kit (SDK). Each component is kept as a 'bundle' that |
| 34 this utility can download as as subdirectory into the SDK. | 34 this utility can download as as subdirectory into the SDK. |
| 35 | 35 |
| 36 Commands: | 36 Commands: |
| 37 help [command] - Get either general or command-specific help | 37 help [command] - Get either general or command-specific help |
| 38 info - Displas information about a bundle | |
|
noelallen1
2012/08/15 21:33:35
Displays
binji
2012/08/15 23:12:44
Done.
| |
| 38 list - Lists the available bundles | 39 list - Lists the available bundles |
| 39 update/install - Updates/installs bundles in the SDK | 40 update/install - Updates/installs bundles in the SDK |
| 40 sources - Manage external package sources | 41 sources - Manage external package sources |
| 41 | 42 |
| 42 Example Usage: | 43 Example Usage: |
| 44 naclsdk info pepper_canary | |
| 43 naclsdk list | 45 naclsdk list |
| 44 naclsdk update --force pepper_17 | 46 naclsdk update --force pepper_17 |
| 45 naclsdk install recommended | 47 naclsdk install recommended |
| 46 naclsdk help update | 48 naclsdk help update |
| 47 naclsdk sources --list''' | 49 naclsdk sources --list''' |
| 48 | 50 |
| 49 CONFIG_FILENAME='naclsdk_config.json' | 51 CONFIG_FILENAME='naclsdk_config.json' |
| 50 MANIFEST_FILENAME='naclsdk_manifest2.json' | 52 MANIFEST_FILENAME='naclsdk_manifest2.json' |
| 51 SDK_TOOLS='sdk_tools' # the name for this tools directory | 53 SDK_TOOLS='sdk_tools' # the name for this tools directory |
| 52 USER_DATA_DIR='sdk_cache' | 54 USER_DATA_DIR='sdk_cache' |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 # json.dumps sometimes returns trailing whitespace and does not put | 355 # json.dumps sometimes returns trailing whitespace and does not put |
| 354 # a newline at the end. This code fixes these problems. | 356 # a newline at the end. This code fixes these problems. |
| 355 pretty_lines = pretty_string.split('\n') | 357 pretty_lines = pretty_string.split('\n') |
| 356 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n' | 358 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n' |
| 357 | 359 |
| 358 | 360 |
| 359 #------------------------------------------------------------------------------ | 361 #------------------------------------------------------------------------------ |
| 360 # Commands | 362 # Commands |
| 361 | 363 |
| 362 | 364 |
| 365 def Info(options, argv, config): | |
| 366 '''Usage: %prof info [options] bundle_names... | |
| 367 | |
| 368 Displays information about a SDK bundle.''' | |
| 369 | |
| 370 DebugPrint("Running List command with: %s, %s" %(options, argv)) | |
| 371 | |
| 372 parser = optparse.OptionParser(usage=Info.__doc__) | |
| 373 (info_options, args) = parser.parse_args(argv) | |
| 374 | |
| 375 if not args: | |
| 376 parser.print_help() | |
| 377 return | |
| 378 | |
| 379 manifest = LoadManifestFromURLs([options.manifest_url] + config.GetSources()) | |
| 380 valid_bundles = [bundle.name for bundle in manifest.GetBundles()] | |
| 381 valid_args = set(args) & set(valid_bundles) | |
| 382 invalid_args = set(args) - valid_args | |
| 383 if invalid_args: | |
| 384 InfoPrint('Unknown bundle(s): %s\n' % (', '.join(invalid_args))) | |
| 385 | |
| 386 for bundle_name in args: | |
| 387 if bundle_name not in valid_args: | |
| 388 continue | |
| 389 | |
| 390 bundle = manifest.GetBundle(bundle_name) | |
| 391 | |
| 392 InfoPrint('%s' % bundle.name) | |
| 393 for key, value in bundle.iteritems(): | |
| 394 if key == manifest_util.ARCHIVES_KEY: | |
| 395 archive = bundle.GetHostOSArchive() | |
| 396 InfoPrint(' Archive:') | |
| 397 for archive_key, archive_value in archive.iteritems(): | |
| 398 InfoPrint(' %s: %s' % (archive_key, archive_value)) | |
| 399 elif key not in (manifest_util.ARCHIVES_KEY, manifest_util.NAME_KEY): | |
| 400 InfoPrint(' %s: %s' % (key, value)) | |
| 401 InfoPrint('') | |
| 402 | |
| 403 | |
| 363 def List(options, argv, config): | 404 def List(options, argv, config): |
| 364 '''Usage: %prog [options] list | 405 '''Usage: %prog list [options] |
| 365 | 406 |
| 366 Lists the available SDK bundles that are available for download.''' | 407 Lists the available SDK bundles that are available for download.''' |
| 367 def PrintBundles(bundles): | 408 |
| 368 for bundle in bundles: | 409 def PrintBundle(local_bundle, bundle, needs_update, display_revisions): |
| 369 InfoPrint(' %s' % bundle.name) | 410 installed = local_bundle is not None |
| 370 for key, value in bundle.iteritems(): | 411 # If bundle is None, there is no longer a remote bundle with this name. |
| 371 if key not in (manifest_util.ARCHIVES_KEY, manifest_util.NAME_KEY): | 412 if bundle is None: |
| 372 InfoPrint(' %s: %s' % (key, value)) | 413 bundle = local_bundle |
| 414 | |
| 415 if display_revisions: | |
| 416 if needs_update: | |
| 417 revision = ' (r%s -> r%s)' % (local_bundle.revision, bundle.revision) | |
| 418 else: | |
| 419 revision = ' (r%s)' % (bundle.revision,) | |
| 420 else: | |
| 421 revision = '' | |
| 422 | |
| 423 InfoPrint(' %s%s %s (%s)%s' % ( | |
| 424 'I' if installed else ' ', | |
| 425 '*' if needs_update else ' ', | |
| 426 bundle.name, | |
| 427 bundle.stability, | |
| 428 revision)) | |
| 429 | |
| 373 | 430 |
| 374 DebugPrint("Running List command with: %s, %s" %(options, argv)) | 431 DebugPrint("Running List command with: %s, %s" %(options, argv)) |
| 375 | 432 |
| 376 parser = optparse.OptionParser(usage=List.__doc__) | 433 parser = optparse.OptionParser(usage=List.__doc__) |
| 434 parser.add_option( | |
| 435 '-r', '--revision', dest='revision', | |
| 436 default=False, action='store_true', | |
| 437 help='display revision numbers') | |
| 377 (list_options, args) = parser.parse_args(argv) | 438 (list_options, args) = parser.parse_args(argv) |
| 439 | |
| 378 manifest = LoadManifestFromURLs([options.manifest_url] + config.GetSources()) | 440 manifest = LoadManifestFromURLs([options.manifest_url] + config.GetSources()) |
| 379 InfoPrint('Available bundles:') | |
| 380 PrintBundles(manifest.GetBundles()) | |
| 381 # Print the local information. | |
| 382 manifest_path = os.path.join(options.user_data_dir, options.manifest_filename) | 441 manifest_path = os.path.join(options.user_data_dir, options.manifest_filename) |
| 383 local_manifest = LoadFromFile(manifest_path, manifest_util.SDKManifest()) | 442 local_manifest = LoadFromFile(manifest_path, manifest_util.SDKManifest()) |
| 384 InfoPrint('\nCurrently installed bundles:') | 443 |
| 385 PrintBundles(local_manifest.GetBundles()) | 444 any_bundles_need_update = False |
| 445 InfoPrint('Bundles:') | |
| 446 InfoPrint(' I: installed\n *: update available\n') | |
| 447 for bundle in manifest.GetBundles(): | |
| 448 local_bundle = local_manifest.GetBundle(bundle.name) | |
| 449 installed = local_bundle is not None | |
| 450 needs_update = local_bundle and local_manifest.BundleNeedsUpdate(bundle) | |
| 451 if needs_update: | |
| 452 any_bundles_need_update = True | |
| 453 | |
| 454 PrintBundle(local_bundle, bundle, needs_update, list_options.revision) | |
| 455 | |
| 456 if not any_bundles_need_update: | |
| 457 InfoPrint('\nAll installed bundles are up-to-date.') | |
| 458 | |
| 459 local_only_bundles = set([b.name for b in local_manifest.GetBundles()]) | |
| 460 local_only_bundles -= set([b.name for b in manifest.GetBundles()]) | |
| 461 if local_only_bundles: | |
| 462 InfoPrint('\nBundles installed locally that are not available remotely:') | |
| 463 for bundle_name in local_only_bundles: | |
| 464 local_bundle = local_manifest.GetBundle(bundle_name) | |
| 465 PrintBundle(local_bundle, None, False, list_options.revision) | |
| 386 | 466 |
| 387 | 467 |
| 388 def Update(options, argv, config): | 468 def Update(options, argv, config): |
| 389 '''Usage: %prog [options] update [target] | 469 '''Usage: %prog update [options] [target] |
|
noelallen1
2012/08/15 21:33:35
[global_options] update [options]
binji
2012/08/15 23:12:44
Done.
| |
| 390 | 470 |
| 391 Updates the Native Client SDK to a specified version. By default, this | 471 Updates the Native Client SDK to a specified version. By default, this |
| 392 command updates all the recommended components. The update process works | 472 command updates all the recommended components. The update process works |
| 393 like this: | 473 like this: |
| 394 1. Fetch the manifest from the mirror. | 474 1. Fetch the manifest from the mirror. |
| 395 2. Load manifest from USER_DATA_DIR - if there is no local manifest file, | 475 2. Load manifest from USER_DATA_DIR - if there is no local manifest file, |
| 396 make an empty manifest object. | 476 make an empty manifest object. |
| 397 3. Update each the bundle: | 477 3. Update each the bundle: |
| 398 for bundle in bundles: | 478 for bundle in bundles: |
| 399 # Compare bundle versions & revisions. | 479 # Compare bundle versions & revisions. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 'Run update with the --force option to overwrite the ' | 571 'Run update with the --force option to overwrite the ' |
| 492 'existing directory.\nWarning: This will overwrite any ' | 572 'existing directory.\nWarning: This will overwrite any ' |
| 493 'modifications you have made within this directory.' | 573 'modifications you have made within this directory.' |
| 494 % bundle.name) | 574 % bundle.name) |
| 495 else: | 575 else: |
| 496 UpdateBundle() | 576 UpdateBundle() |
| 497 else: | 577 else: |
| 498 InfoPrint('%s is already up-to-date.' % bundle.name) | 578 InfoPrint('%s is already up-to-date.' % bundle.name) |
| 499 | 579 |
| 500 def Sources(options, argv, config): | 580 def Sources(options, argv, config): |
| 501 '''Usage: %prog [options] sources [--list,--add URL,--remove URL] | 581 '''Usage: %prog sources [options] [--list,--add URL,--remove URL] |
| 502 | 582 |
| 503 Manage additional package sources. URL should point to a valid package | 583 Manage additional package sources. URL should point to a valid package |
| 504 manifest file for download. | 584 manifest file for download. |
| 505 ''' | 585 ''' |
| 506 DebugPrint("Running Sources command with: %s, %s" % (options, argv)) | 586 DebugPrint("Running Sources command with: %s, %s" % (options, argv)) |
| 507 | 587 |
| 508 parser = optparse.OptionParser(usage=Sources.__doc__) | 588 parser = optparse.OptionParser(usage=Sources.__doc__) |
| 509 parser.add_option( | 589 parser.add_option( |
| 510 '-a', '--add', dest='url_to_add', | 590 '-a', '--add', dest='url_to_add', |
| 511 default=None, | 591 default=None, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 538 if write_config: | 618 if write_config: |
| 539 WriteToFile(os.path.join(options.user_data_dir, options.config_filename), | 619 WriteToFile(os.path.join(options.user_data_dir, options.config_filename), |
| 540 config) | 620 config) |
| 541 | 621 |
| 542 #------------------------------------------------------------------------------ | 622 #------------------------------------------------------------------------------ |
| 543 # Command-line interface | 623 # Command-line interface |
| 544 | 624 |
| 545 | 625 |
| 546 def main(argv): | 626 def main(argv): |
| 547 '''Main entry for the sdk_update utility''' | 627 '''Main entry for the sdk_update utility''' |
| 548 parser = optparse.OptionParser(usage=GLOBAL_HELP) | 628 parser = optparse.OptionParser(usage=GLOBAL_HELP, add_help_option=False) |
| 549 DEFAULT_SDK_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | 629 DEFAULT_SDK_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 550 | 630 |
| 631 # Manually add help options so we can ignore it when auto-updating. | |
| 632 parser.add_option( | |
| 633 '-h', '--help', dest='help', action='store_true', | |
| 634 help='show this help message and exit') | |
| 551 parser.add_option( | 635 parser.add_option( |
| 552 '-U', '--manifest-url', dest='manifest_url', | 636 '-U', '--manifest-url', dest='manifest_url', |
| 553 default='https://commondatastorage.googleapis.com/nativeclient-mirror/' | 637 default='https://commondatastorage.googleapis.com/nativeclient-mirror/' |
| 554 'nacl/nacl_sdk/%s' % MANIFEST_FILENAME, | 638 'nacl/nacl_sdk/%s' % MANIFEST_FILENAME, |
| 555 help='override the default URL for the NaCl manifest file') | 639 help='override the default URL for the NaCl manifest file') |
| 556 parser.add_option( | 640 parser.add_option( |
| 557 '-d', '--debug', dest='debug', | 641 '-d', '--debug', dest='debug', |
| 558 default=False, action='store_true', | 642 default=False, action='store_true', |
| 559 help='enable displaying debug information to stderr') | 643 help='enable displaying debug information to stderr') |
| 560 parser.add_option( | 644 parser.add_option( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 583 parser.add_option( | 667 parser.add_option( |
| 584 '-c', '--config', dest='config_filename', | 668 '-c', '--config', dest='config_filename', |
| 585 default=CONFIG_FILENAME, | 669 default=CONFIG_FILENAME, |
| 586 help="name of the local config file relative to user-data-dir") | 670 help="name of the local config file relative to user-data-dir") |
| 587 parser.add_option( | 671 parser.add_option( |
| 588 '--update-sdk-tools', dest='update_sdk_tools', | 672 '--update-sdk-tools', dest='update_sdk_tools', |
| 589 default=False, action='store_true') | 673 default=False, action='store_true') |
| 590 | 674 |
| 591 | 675 |
| 592 COMMANDS = { | 676 COMMANDS = { |
| 677 'info': Info, | |
| 593 'list': List, | 678 'list': List, |
| 594 'update': Update, | 679 'update': Update, |
| 595 'install': Update, | 680 'install': Update, |
| 596 'sources': Sources, | 681 'sources': Sources, |
| 597 } | 682 } |
| 598 | 683 |
| 599 # Separate global options from command-specific options | 684 # Separate global options from command-specific options |
| 600 global_argv = argv | 685 global_argv = argv |
| 601 command_argv = [] | 686 command_argv = [] |
| 602 for index, arg in enumerate(argv): | 687 for index, arg in enumerate(argv): |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 626 | 711 |
| 627 if options.show_version: | 712 if options.show_version: |
| 628 print "Native Client SDK Updater, version r%s" % (REVISION,) | 713 print "Native Client SDK Updater, version r%s" % (REVISION,) |
| 629 exit(0) | 714 exit(0) |
| 630 | 715 |
| 631 | 716 |
| 632 if not args: | 717 if not args: |
| 633 print "Need to supply a command" | 718 print "Need to supply a command" |
| 634 PrintHelpAndExit() | 719 PrintHelpAndExit() |
| 635 | 720 |
| 721 if options.help: | |
| 722 PrintHelpAndExit() | |
| 723 | |
| 636 def DefaultHandler(unused_options=None, unused_args=None, unused_config=None): | 724 def DefaultHandler(unused_options=None, unused_args=None, unused_config=None): |
| 637 print "Unknown Command: %s" % args[0] | 725 print "Unknown Command: %s" % args[0] |
| 638 PrintHelpAndExit() | 726 PrintHelpAndExit() |
| 639 | 727 |
| 640 def InvokeCommand(args): | 728 def InvokeCommand(args): |
| 641 command = COMMANDS.get(args[0], DefaultHandler) | 729 command = COMMANDS.get(args[0], DefaultHandler) |
| 642 # Load the config file before running commands | 730 # Load the config file before running commands |
| 643 config = LoadFromFile(os.path.join(options.user_data_dir, | 731 config = LoadFromFile(os.path.join(options.user_data_dir, |
| 644 options.config_filename), | 732 options.config_filename), |
| 645 SDKConfig()) | 733 SDKConfig()) |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 658 | 746 |
| 659 return 0 # Success | 747 return 0 # Success |
| 660 | 748 |
| 661 | 749 |
| 662 if __name__ == '__main__': | 750 if __name__ == '__main__': |
| 663 try: | 751 try: |
| 664 sys.exit(main(sys.argv[1:])) | 752 sys.exit(main(sys.argv[1:])) |
| 665 except Error as error: | 753 except Error as error: |
| 666 print "Error: %s" % error | 754 print "Error: %s" % error |
| 667 sys.exit(1) | 755 sys.exit(1) |
| OLD | NEW |