Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Unified Diff: gsutil.py

Issue 1346213003: gsutil: Parallel-safe, specify target, add clean. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/gsutil_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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())
« no previous file with comments | « no previous file | tests/gsutil_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698