blob: 339923ef597756e1cc03b6f2edba3b94d3bfd01d [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import optparse
import os
import re
import shutil
import sys
import tempfile
import urllib
import zipfile
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def get_gae_sdk_version(gae_path):
"""Returns the installed GAE SDK version or None."""
version_path = os.path.join(gae_path, 'VERSION')
if os.path.isfile(version_path):
values = dict(
map(lambda x: x.strip(), l.split(':'))
for l in open(version_path) if ':' in l)
if 'release' in values:
return values['release'].strip('"')
def get_latest_gae_sdk_url(name):
"""Returns the url to get the latest GAE SDK and its version."""
url = ''
logging.debug('%s', url)
content = urllib.urlopen(url).read()
regexp = (
+ re.escape(name) + r'[0-9\.]+?\.zip)')
m =, content)
url =
# Calculate the version from the url.
new_version = + r'(.+?).zip', url).group(1)
# Upgrade to https
return url.replace('http://', 'https://'), new_version
def extract_zip(z, root_path):
"""Extracts files in a zipfile but keep the executable bits."""
count = 0
for f in z.infolist():
perm = (f.external_attr >> 16L) & 0777
filepath = os.path.join(root_path, f.filename)
logging.debug('Extracting %s' % f.filename)
if f.filename.endswith('/'):
os.mkdir(filepath, perm)
z.extract(f, root_path)
os.chmod(filepath, perm)
count += 1
print('Extracted %d files' % count)
def install_latest_gae_sdk(root_path, fetch_go, dry_run):
if fetch_go:
if sys.platform == 'darwin':
name = 'go_appengine_sdk_darwin_amd64-'
# Add other platforms as needed.
name = 'go_appengine_sdk_linux_amd64-'
name = 'google_appengine_'
# The zip file already contains 'google_appengine' in its path so it's a bit
# awkward to unzip otherwise. Hard code the path in for now.
gae_path = os.path.join(root_path, 'google_appengine')
print('Looking up path %s' % gae_path)
version = get_gae_sdk_version(gae_path)
if version:
print('Found installed version %s' % version)
print('Didn\'t find an SDK')
url, new_version = get_latest_gae_sdk_url(name)
print('New version is %s' % new_version)
if version == new_version:
return 0
if os.path.isdir(gae_path):
print('Removing previous version')
if not dry_run:
print('Fetching %s' % url)
if not dry_run:
with tempfile.NamedTemporaryFile() as f:
# Assuming we're extracting there. In fact, we have no idea.
print('Extracting into %s' % gae_path)
z = zipfile.ZipFile(, 'r')
extract_zip(z, root_path)
return 0
def main():
parser = optparse.OptionParser()
parser.add_option('-v', '--verbose', action='store_true')
'-g', '--go', action='store_true', help='Defaults to python SDK')
'-d', '--dest', default=os.path.dirname(BASE_DIR), help='Output')
parser.add_option('--dry-run', action='store_true', help='Do not download')
options, args = parser.parse_args()
if args:
parser.error('Unsupported args: %s' % ' '.join(args))
logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR)
return install_latest_gae_sdk(
os.path.abspath(options.dest), options.go, options.dry_run)
if __name__ == '__main__':