diff --git a/download_from_google_storage.py b/download_from_google_storage.py index b39879049..bbb9e64f3 100755 --- a/download_from_google_storage.py +++ b/download_from_google_storage.py @@ -11,6 +11,7 @@ import optparse import os import Queue import re +import stat import sys import threading import time @@ -185,6 +186,20 @@ def _downloader_worker_thread(thread_num, q, force, base_url, out_q.put('%d> %s' % (thread_num, err)) ret_codes.put((code, err)) + # Mark executable if necessary. We key off of the custom header + # "x-goog-meta-executable". + # + # TODO(hinoka): It is supposedly faster to use "gsutil stat" but that + # doesn't appear to be supported by the gsutil currently in our tree. When + # we update, this code should use that instead of "gsutil ls -L". + if not sys.platform.startswith('win'): + code, out, _ = gsutil.check_call('ls', '-L', file_url) + if code != 0: + out_q.put('%d> %s' % (thread_num, err)) + ret_codes.put((code, err)) + elif re.search('x-goog-meta-executable:', out): + st = os.stat(output_filename) + os.chmod(output_filename, st.st_mode | stat.S_IEXEC) def printer_worker(output_queue): while True: @@ -282,9 +297,21 @@ def main(args): help='Alias for "gsutil config". Run this if you want ' 'to initialize your saved Google Storage ' 'credentials.') + parser.add_option('-p', '--platform', + help='A regular expression that is compared against ' + 'Python\'s sys.platform. If this option is specified, ' + 'the download will happen only if there is a match.') (options, args) = parser.parse_args() - # First, make sure we can find a working instance of gsutil. + + # Make sure we should run at all based on platform matching. + if options.platform: + if not re.match(options.platform, sys.platform): + print('The current platform doesn\'t match "%s", skipping.' % + options.platform) + return 0 + + # Make sure we can find a working instance of gsutil. if os.path.exists(GSUTIL_DEFAULT_PATH): gsutil = Gsutil(GSUTIL_DEFAULT_PATH, boto_path=options.boto) else: diff --git a/upload_to_google_storage.py b/upload_to_google_storage.py index f10a8d83f..e6cd2eeb5 100755 --- a/upload_to_google_storage.py +++ b/upload_to_google_storage.py @@ -10,6 +10,7 @@ import optparse import os import Queue import re +import stat import sys import threading import time @@ -103,6 +104,18 @@ def _upload_worker( (filename, file_url, err))) continue + # Mark executable files with the header "x-goog-meta-executable: 1" which + # the download script will check for to preserve the executable bit. + if not sys.platform.startswith('win'): + if os.stat(filename).st_mode & stat.S_IEXEC: + code, _, err = gsutil.check_call('setmeta', '-h', + 'x-goog-meta-executable:1', file_url) + if code: + ret_codes.put( + (code, + 'Encountered error on setting metadata on %s\n%s' % + (file_url, err))) + def get_targets(args, parser, use_null_terminator): if not args: