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

Side by Side Diff: gsutil.py

Issue 742173002: GSUtil.py wrapper script (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Working tests Created 6 years, 1 month 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 unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Run a pinned gsutil."""
7
8
9 import argparse
10 import shutil
11 import zipfile
12 import hashlib
13 import base64
14 import os
15 import sys
16 import json
17 import urllib
18 import subprocess
19
20
21 GSUTIL_URL = 'https://storage.googleapis.com/pub/'
22 API_URL = 'https://www.googleapis.com/storage/v1/b/pub/o/'
23
24 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
25
26
27 class SubprocessError(Exception):
28 pass
29 class InvalidGsutilError(Exception):
30 pass
31
32
33 def call(args, verbose=True, **kwargs):
34 kwargs['stdout'] = subprocess.PIPE
35 kwargs['stderr'] = subprocess.STDOUT
36 proc = subprocess.Popen(args, **kwargs)
37 out = []
38 for line in proc.stdout:
39 out.append(line)
40 if verbose:
41 sys.stdout.write(line)
42 code = proc.wait()
43 if code:
44 raise SubprocessError('%s failed with %s' % (args, code))
45 return ''.join(out)
46
47
48 def download_gsutil(version, target_dir):
49 """Downloads gsutil into the target_dir."""
50 filename = 'gsutil_%s.zip' % version
51 target_filename = os.path.join(target_dir, filename)
52
53 # Check if the target exists already.
54 if os.path.exists(target_filename):
55 md5_calc = hashlib.md5()
56 with open(target_filename, 'rb') as f:
57 while True:
58 buf = f.read(4096)
59 if not buf:
60 break
61 md5_calc.update(buf)
62 local_md5 = md5_calc.hexdigest()
63
64 metadata_url = '%s%s' % (API_URL, filename)
65 metadata = json.load(urllib.urlopen(metadata_url))
66 remote_md5 = base64.b64decode(metadata['md5Hash'])
67
68 if local_md5 == remote_md5:
69 return target_filename
70 os.remove(target_filename)
71
72 # Do the download.
73 url = '%s%s' % (GSUTIL_URL, filename)
74 u = urllib.urlopen(url)
75 with open(target_filename, 'wb') as f:
76 while True:
77 buf = u.read(4096)
78 if not buf:
79 break
80 f.write(buf)
81 return target_filename
82
83
84 def check_gsutil(gsutil_bin):
85 """Run gsutil version and make sure it runs."""
86 try:
87 call([gsutil_bin, 'version'], verbose=False)
88 return True
89 except SubprocessError:
90 return False
91
92
93 def ensure_gsutil(version, target):
94 bin_dir = os.path.join(target, 'gsutil_%s' % version)
95 gsutil_bin = os.path.join(bin_dir, 'gsutil', 'gsutil')
96 if os.path.isfile(gsutil_bin) and check_gsutil(gsutil_bin):
97 # Everything is awesome! we're all done here.
98 return gsutil_bin
99
100 if os.path.isdir(bin_dir):
101 # Clean up if we're redownloading a corrupted gsutil.
102 shutil.rmtree(bin_dir)
103 cache_dir = os.path.join(target, '.cache_dir')
104 if not os.path.isdir(cache_dir):
105 os.makedirs(cache_dir)
106 target_zip_filename = download_gsutil(version, cache_dir)
107 with zipfile.ZipFile(target_zip_filename, 'r') as target_zip:
108 target_zip.extractall(bin_dir)
109 os.chmod(gsutil_bin, 0755) # python zipfile doesn't set exec bit.
110
111 # Final check that the gsutil bin is okay. This should never fail.
112 if not check_gsutil(gsutil_bin):
113 raise InvalidGsutilError()
114
115 return gsutil_bin
116
117
118 def run_gsutil(_force_version, fallback, _target, args):
119 # TODO(hinoka): Actually use this
120 # gsutil_bin = ensure_gsutil(force_version, target)
121 cmd = [sys.executable, fallback] + args
122 call(cmd)
123
124
125 def parse_args():
126 parser = argparse.ArgumentParser()
127 parser.add_argument('--force_version', default='4.6')
128 parser.add_argument('--fallback')
129 parser.add_argument('--target', default=os.path.join(THIS_DIR, 'gsutil_bin'))
130 parser.add_argument('args', nargs='*')
131
132 args = parser.parse_args()
133 return args.force_version, args.fallback, args.target, args.args
134
135
136 def main():
137 force_version, fallback, target, args = parse_args()
138 run_gsutil(force_version, fallback, target, args)
139
140 if __name__ == '__main__':
141 sys.exit(main())
OLDNEW
« no previous file with comments | « .gitignore ('k') | tests/gsutil_test.py » ('j') | tests/gsutil_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698