Index: gsutil.py |
diff --git a/gsutil.py b/gsutil.py |
index 53589a27bc48e97261d47f3d22a18b9ea1a4d88c..8a11c050651fe15dbc1ae9771357c5fc9573519f 100755 |
--- a/gsutil.py |
+++ b/gsutil.py |
@@ -14,6 +14,7 @@ import os |
import shutil |
import subprocess |
import sys |
+import time |
import urllib2 |
import zipfile |
@@ -26,7 +27,6 @@ DEFAULT_BIN_DIR = os.path.join(THIS_DIR, 'external_bin', 'gsutil') |
DEFAULT_FALLBACK_GSUTIL = os.path.join( |
THIS_DIR, 'third_party', 'gsutil', 'gsutil') |
- |
class InvalidGsutilError(Exception): |
pass |
@@ -73,22 +73,35 @@ def check_gsutil(gsutil_bin): |
[sys.executable, gsutil_bin, 'version'], |
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) == 0 |
-def ensure_gsutil(version, target): |
+def ensure_gsutil(version, target, clean): |
bin_dir = os.path.join(target, 'gsutil_%s' % version) |
gsutil_bin = os.path.join(bin_dir, 'gsutil', 'gsutil') |
- if os.path.isfile(gsutil_bin) and check_gsutil(gsutil_bin): |
+ if not clean and os.path.isfile(gsutil_bin) and check_gsutil(gsutil_bin): |
# Everything is awesome! we're all done here. |
return gsutil_bin |
- if os.path.isdir(bin_dir): |
- # Clean up if we're redownloading a corrupted gsutil. |
- shutil.rmtree(bin_dir) |
- cache_dir = os.path.join(target, '.cache_dir') |
+ # Clean up if we're redownloading a corrupted gsutil. |
+ suffix = '%d_%d' % (time.time(), os.getpid()) |
vapier
2015/09/17 19:31:00
this isn't parallel safe. you cannot rely on PID'
dnj
2015/09/17 19:51:47
Using "tempfile.mkdtemp" now.
|
+ try: |
+ cleanup_path = '%s.%s' % (bin_dir, suffix) |
+ shutil.move(bin_dir, cleanup_path) |
+ shutil.rmtree(cleanup_path) |
+ except IOError: |
+ # Directory was not present. |
+ pass |
+ |
+ cache_dir = os.path.join(target, '.cache_dir.%s' % (suffix,)) |
Ryan Tseng
2015/09/17 19:26:45
this would be more aptly called "tempdir" now?
ma
dnj
2015/09/17 19:51:46
Acknowledged.
|
if not os.path.isdir(cache_dir): |
os.makedirs(cache_dir) |
target_zip_filename = download_gsutil(version, cache_dir) |
with zipfile.ZipFile(target_zip_filename, 'r') as target_zip: |
- target_zip.extractall(bin_dir) |
+ target_zip.extractall(cache_dir) |
+ |
+ try: |
+ shutil.move(cache_dir, bin_dir) |
+ except IOError: |
+ # Something else did this in parallel. |
+ pass |
# Final check that the gsutil bin is okay. This should never fail. |
if not check_gsutil(gsutil_bin): |
@@ -97,9 +110,9 @@ def ensure_gsutil(version, target): |
return gsutil_bin |
-def run_gsutil(force_version, fallback, target, args): |
+def run_gsutil(force_version, fallback, target, args, clean=False): |
if force_version: |
- gsutil_bin = ensure_gsutil(force_version, target) |
+ gsutil_bin = ensure_gsutil(force_version, target, clean) |
else: |
gsutil_bin = fallback |
cmd = [sys.executable, gsutil_bin] + args |
@@ -107,10 +120,18 @@ def run_gsutil(force_version, fallback, target, args): |
def parse_args(): |
+ bin_dir = os.environ.get('DEPOT_TOOLS_GSUTIL_BIN_DIR') |
Ryan Tseng
2015/09/17 19:26:45
get(key, default)
dnj
2015/09/17 19:51:47
Done.
|
+ if not bin_dir: |
+ bin_dir = DEFAULT_BIN_DIR |
+ |
parser = argparse.ArgumentParser() |
parser.add_argument('--force-version', default='4.13') |
+ parser.add_argument('--clean', action='store_true', |
Ryan Tseng
2015/09/17 19:26:45
What do you see the use case for this being?
dnj
2015/09/17 19:51:47
Useful for testing massively in parallel.
|
+ help='Clear any existing gsutil package, forcing a new download.') |
parser.add_argument('--fallback', default=DEFAULT_FALLBACK_GSUTIL) |
- parser.add_argument('--target', default=DEFAULT_BIN_DIR) |
+ parser.add_argument('--target', default=bin_dir, |
+ help='The target directory to download/store a gsutil version in. ' |
+ '(default is %(default)s).') |
parser.add_argument('args', nargs=argparse.REMAINDER) |
args, extras = parser.parse_known_args() |
@@ -118,12 +139,13 @@ def parse_args(): |
args.args.pop(0) |
if extras: |
args.args = extras + args.args |
- return args.force_version, args.fallback, args.target, args.args |
+ return args |
def main(): |
- force_version, fallback, target, args = parse_args() |
- return run_gsutil(force_version, fallback, target, args) |
+ args = parse_args() |
+ return run_gsutil(args.force_version, args.fallback, args.target, args.args, |
+ clean=args.clean) |
if __name__ == '__main__': |
sys.exit(main()) |