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 |