Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2012 The LUCI Authors. All rights reserved. | 2 # Copyright 2012 The LUCI Authors. All rights reserved. |
| 3 # Use of this source code is governed under the Apache License, Version 2.0 | 3 # Use of this source code is governed under the Apache License, Version 2.0 |
| 4 # that can be found in the LICENSE file. | 4 # that can be found in the LICENSE file. |
| 5 | 5 |
| 6 """Runs a command with optional isolated input/output. | 6 """Runs a command with optional isolated input/output. |
| 7 | 7 |
| 8 Despite name "run_isolated", can run a generic non-isolated command specified as | 8 Despite name "run_isolated", can run a generic non-isolated command specified as |
| 9 args. | 9 args. |
| 10 | 10 |
| 11 If input isolated hash is provided, fetches it, creates a tree of hard links, | 11 If input isolated hash is provided, fetches it, creates a tree of hard links, |
| 12 appends args to the command in the fetched isolated and runs it. | 12 appends args to the command in the fetched isolated and runs it. |
| 13 To improve performance, keeps a local cache. | 13 To improve performance, keeps a local cache. |
| 14 The local cache can safely be deleted. | 14 The local cache can safely be deleted. |
| 15 | 15 |
| 16 Any ${EXECUTABLE_SUFFIX} on the command line will be replaced with ".exe" string | 16 Any ${EXECUTABLE_SUFFIX} on the command line will be replaced with ".exe" string |
| 17 on Windows and "" on other platforms. | 17 on Windows and "" on other platforms. |
| 18 | 18 |
| 19 Any ${ISOLATED_OUTDIR} on the command line will be replaced by the location of a | 19 Any ${ISOLATED_OUTDIR} on the command line will be replaced by the location of a |
| 20 temporary directory upon execution of the command specified in the .isolated | 20 temporary directory upon execution of the command specified in the .isolated |
| 21 file. All content written to this directory will be uploaded upon termination | 21 file. All content written to this directory will be uploaded upon termination |
| 22 and the .isolated file describing this directory will be printed to stdout. | 22 and the .isolated file describing this directory will be printed to stdout. |
| 23 | 23 |
| 24 Any ${SWARMING_BOT_FILE} on the command line will be replaced by the value of | 24 Any ${SWARMING_BOT_FILE} on the command line will be replaced by the value of |
| 25 the --bot-file parameter. This file is used by a swarming bot to communicate | 25 the --bot-file parameter. This file is used by a swarming bot to communicate |
| 26 state of the host to tasks. It is written to by the swarming bot's | 26 state of the host to tasks. It is written to by the swarming bot's |
| 27 on_before_task() hook in the swarming server's custom bot_config.py. | 27 on_before_task() hook in the swarming server's custom bot_config.py. |
| 28 """ | 28 """ |
| 29 | 29 |
| 30 __version__ = '0.8.5' | 30 __version__ = '0.8.6' |
| 31 | 31 |
| 32 import argparse | |
| 32 import base64 | 33 import base64 |
| 33 import collections | 34 import collections |
| 35 import json | |
| 34 import logging | 36 import logging |
| 35 import optparse | 37 import optparse |
| 36 import os | 38 import os |
| 37 import sys | 39 import sys |
| 38 import tempfile | 40 import tempfile |
| 39 import time | 41 import time |
| 40 | 42 |
| 41 from third_party.depot_tools import fix_encoding | 43 from third_party.depot_tools import fix_encoding |
| 42 | 44 |
| 43 from utils import file_path | 45 from utils import file_path |
| (...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 debug_group.add_option( | 753 debug_group.add_option( |
| 752 '--root-dir', help='Use a directory instead of a random one') | 754 '--root-dir', help='Use a directory instead of a random one') |
| 753 parser.add_option_group(debug_group) | 755 parser.add_option_group(debug_group) |
| 754 | 756 |
| 755 auth.add_auth_options(parser) | 757 auth.add_auth_options(parser) |
| 756 | 758 |
| 757 parser.set_defaults(cache='cache', cipd_cache='cipd_cache') | 759 parser.set_defaults(cache='cache', cipd_cache='cipd_cache') |
| 758 return parser | 760 return parser |
| 759 | 761 |
| 760 | 762 |
| 761 def main(args): | 763 def parse_args(args): |
| 764 # Create a fake mini-parser just to get out the "-a" command. Note that | |
| 765 # it's not documented here; instead, it's documented in create_option_parser | |
|
M-A Ruel
2016/10/24 20:25:09
It's not?
aludwin
2016/10/24 21:03:53
Whoops, I forgot to actually document it in create
| |
| 766 # even though that parser will never actually get to parse it. This is | |
| 767 # because -f is exclusive with all other options and arguments. | |
| 768 file_argparse = argparse.ArgumentParser() | |
|
M-A Ruel
2016/10/24 20:25:09
file_argparse = argparse.ArgumentParser(add_help=F
aludwin
2016/10/24 21:03:53
Done.
| |
| 769 file_argparse.add_argument("-a", "--argsfile") | |
| 770 (file_args, nonfile_args) = file_argparse.parse_known_args(args) | |
| 771 if not file_args.argsfile == None: | |
| 772 if len(nonfile_args) > 0: | |
| 773 file_argparse.error('Can\'t specify --argsfile with' | |
| 774 'any other arguments (%s)' % nonfile_args) | |
| 775 try: | |
| 776 with open(file_args.argsfile, 'r') as f: | |
| 777 args = json.loads(f.read()) | |
| 778 except Exception as e: | |
|
M-A Ruel
2016/10/24 20:25:09
except (IOError, OSError, ValueError): as e:
pri
aludwin
2016/10/24 21:03:53
We don't need to sys.exit or return. After this li
| |
| 779 print "Couldn't read arguments: %s" % e | |
| 780 | |
| 781 # Even if we failed to read the args, just call the normal parser now since it | |
| 782 # will print the correct help message. | |
| 762 parser = create_option_parser() | 783 parser = create_option_parser() |
| 763 options, args = parser.parse_args(args) | 784 options, args = parser.parse_args(args) |
| 785 return (parser, options, args) | |
| 786 | |
| 787 | |
| 788 def main(args): | |
| 789 (parser, options, args) = parse_args(args) | |
| 764 | 790 |
| 765 isolated_cache = isolateserver.process_cache_options(options) | 791 isolated_cache = isolateserver.process_cache_options(options) |
| 766 if options.clean: | 792 if options.clean: |
| 767 if options.isolated: | 793 if options.isolated: |
| 768 parser.error('Can\'t use --isolated with --clean.') | 794 parser.error('Can\'t use --isolated with --clean.') |
| 769 if options.isolate_server: | 795 if options.isolate_server: |
| 770 parser.error('Can\'t use --isolate-server with --clean.') | 796 parser.error('Can\'t use --isolate-server with --clean.') |
| 771 if options.json: | 797 if options.json: |
| 772 parser.error('Can\'t use --json with --clean.') | 798 parser.error('Can\'t use --json with --clean.') |
| 773 isolated_cache.cleanup() | 799 isolated_cache.cleanup() |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 822 except cipd.Error as ex: | 848 except cipd.Error as ex: |
| 823 print >> sys.stderr, ex.message | 849 print >> sys.stderr, ex.message |
| 824 return 1 | 850 return 1 |
| 825 | 851 |
| 826 | 852 |
| 827 if __name__ == '__main__': | 853 if __name__ == '__main__': |
| 828 subprocess42.inhibit_os_error_reporting() | 854 subprocess42.inhibit_os_error_reporting() |
| 829 # Ensure that we are always running with the correct encoding. | 855 # Ensure that we are always running with the correct encoding. |
| 830 fix_encoding.fix_encoding() | 856 fix_encoding.fix_encoding() |
| 831 file_path.enable_symlink() | 857 file_path.enable_symlink() |
| 858 | |
| 832 sys.exit(main(sys.argv[1:])) | 859 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |