| #!/usr/bin/python |
| # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| # for details. All rights reserved. Use of this source code is governed by a |
| # BSD-style license that can be found in the LICENSE file. |
| |
| import optparse |
| import os |
| import os.path |
| import re |
| import requests |
| import shutil |
| import subprocess |
| import sys |
| import tempfile |
| |
| SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) |
| DART_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, '..', '..', '..')) |
| |
| # Dartium DEPS file from the DEPS file checked into the dart-lang/sdk integration |
| # branch. |
| DEPS_GIT = ('https://raw.githubusercontent.com/dart-lang/sdk/' |
| 'integration/tools/deps/dartium.deps/DEPS') |
| |
| # Whitelist of files to keep. |
| WHITELIST = [ |
| r'LICENSE(\S+)', |
| r'(\S+)\.idl', |
| r'(\S+)\.json', |
| r'(\S+)\.py', |
| r'(\S+)\.txt', |
| ] |
| |
| # WebKit / WebCore info. |
| CHROME_TRUNK = "https://src.chromium.org" |
| WEBKIT_URL_PATTERN = r'"dartium_webkit_branch": "(\S+)",' |
| WEBKIT_REV_PATTERN = r'"dartium_webkit_revision": "(\d+)",' |
| WEBCORE_SUBPATH = 'Source/core' |
| MODULES_SUBPATH = 'Source/modules' |
| BINDINGS_SUBPATH = 'Source/bindings' |
| |
| LOCAL_WEBKIT_IDL_PATH = os.path.join(DART_PATH, 'third_party', 'WebCore') |
| LOCAL_WEBKIT_README = """\ |
| This directory contains a copy of WebKit/WebCore IDL files. |
| See the attached LICENSE-* files in this directory. |
| |
| Please do not modify the files here. They are periodically copied |
| using the script: $DART_ROOT/sdk/lib/html/scripts/%(script)s |
| |
| The current version corresponds to: |
| URL: %(url)s |
| Current revision: %(revision)s |
| """ |
| |
| # Chrome info. |
| CHROME_URL_PATTERN = r'"dartium_chromium_branch": "(\S+)",' |
| CHROME_REV_PATTERN = r'"dartium_chromium_revision": "(\d+)",' |
| CHROME_IDL_SUBPATH = 'trunk/src/chrome/common/extensions/api' |
| CHROME_COMMENT_EATER_SUBPATH = 'trunk/src/tools/json_comment_eater' |
| CHROME_COMPILER_SUBPATH = 'trunk/src/tools/json_schema_compiler' |
| CHROME_IDL_PARSER_SUBPATH = 'trunk/src/ppapi/generators' |
| CHROME_PLY_SUBPATH = 'trunk/src/third_party/ply' |
| LOCAL_CHROME_IDL_PATH = os.path.join(DART_PATH, 'third_party', 'chrome', 'idl') |
| LOCAL_CHROME_COMMENT_EATER_PATH = os.path.join( |
| DART_PATH, 'third_party', 'chrome', 'tools', 'json_comment_eater') |
| LOCAL_CHROME_COMPILER_PATH = os.path.join(DART_PATH, 'third_party', 'chrome', |
| 'tools', 'json_schema_compiler') |
| LOCAL_CHROME_IDL_PARSER_PATH = os.path.join(DART_PATH, 'third_party', 'chrome', |
| 'ppapi', 'generators') |
| LOCAL_CHROME_PLY_PATH = os.path.join(DART_PATH, 'third_party', 'chrome', |
| 'third_party', 'ply') |
| LOCAL_CHROME_README = """\ |
| This directory contains a copy of Chromium IDL and generation scripts |
| used to generate Dart APIs for Chrome Apps. |
| |
| The original files are from: |
| URL: %(url)s |
| Current revision: %(revision)s |
| |
| Please see the corresponding LICENSE file at |
| %(url)s/trunk/src/LICENSE. |
| """ |
| DEPTH_FILES = 'files' |
| DEPTH_INFINITY = 'infinity' |
| |
| # Regular expressions corresponding to URL/revision patters in the |
| # DEPS file. |
| DEPS_PATTERNS = { |
| 'webkit': (CHROME_TRUNK, WEBKIT_URL_PATTERN, WEBKIT_REV_PATTERN), |
| # 'chrome': (CHROME_TRUNK, CHROME_URL_PATTERN, CHROME_REV_PATTERN), |
| } |
| |
| # List of components to update. |
| UPDATE_LIST = [ |
| # (component, remote subpath, local path, local readme file, depth) |
| |
| # WebKit IDL. |
| ('webkit', WEBCORE_SUBPATH, os.path.join(LOCAL_WEBKIT_IDL_PATH, 'core'), |
| LOCAL_WEBKIT_README, DEPTH_INFINITY), |
| ('webkit', MODULES_SUBPATH, os.path.join(LOCAL_WEBKIT_IDL_PATH, 'modules'), |
| LOCAL_WEBKIT_README, DEPTH_INFINITY), |
| ('webkit', BINDINGS_SUBPATH, os.path.join(LOCAL_WEBKIT_IDL_PATH, 'bindings'), |
| LOCAL_WEBKIT_README, DEPTH_INFINITY), |
| |
| # Chrome IDL. |
| ('chrome', CHROME_IDL_SUBPATH, LOCAL_CHROME_IDL_PATH, LOCAL_CHROME_README, |
| DEPTH_INFINITY), |
| # Chrome PPAPI generators. Contains idl_parser.py which is used by the |
| # Chrome IDL compiler. |
| ('chrome', CHROME_IDL_PARSER_SUBPATH, LOCAL_CHROME_IDL_PARSER_PATH, |
| LOCAL_CHROME_README, DEPTH_FILES), |
| # ply files. |
| ('chrome', CHROME_PLY_SUBPATH, LOCAL_CHROME_PLY_PATH, LOCAL_CHROME_README, |
| DEPTH_INFINITY), |
| # Path for json_comment_eater, which is needed by the Chrome IDL compiler. |
| ('chrome', CHROME_COMMENT_EATER_SUBPATH, LOCAL_CHROME_COMMENT_EATER_PATH, |
| LOCAL_CHROME_README, DEPTH_FILES), |
| # Chrome IDL compiler files. |
| ('chrome', CHROME_COMPILER_SUBPATH, LOCAL_CHROME_COMPILER_PATH, |
| LOCAL_CHROME_README, DEPTH_INFINITY), |
| ] |
| |
| |
| def RunCommand(cmd, valid_exits=[0]): |
| """Executes a shell command and return its stdout.""" |
| print ' '.join(cmd) |
| pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| output = pipe.communicate() |
| if pipe.returncode in valid_exits: |
| return output[0] |
| else: |
| print output[1] |
| print 'FAILED. RET_CODE=%d' % pipe.returncode |
| sys.exit(pipe.returncode) |
| |
| def GetDepsFromGit(): |
| req = requests.get(DEPS_GIT) |
| return req.text |
| |
| def GetSvnRevision(deps, component): |
| """Returns a tuple with the (dartium webkit repo, latest revision).""" |
| url_base, url_pattern, rev_pattern = DEPS_PATTERNS[component] |
| url = url_base + re.search(url_pattern, deps).group(1) |
| revision = re.search(rev_pattern, deps).group(1) |
| return (url, revision) |
| |
| |
| def RefreshFiles(url, revision, remote_path, local_path, depth): |
| """Refreshes refreshes files in the local_path to specific url / |
| revision / remote_path, exporting to depth""" |
| cwd = os.getcwd() |
| try: |
| if os.path.exists(local_path): |
| shutil.rmtree(local_path) |
| head, tail = os.path.split(local_path) |
| if not os.path.exists(head): |
| os.makedirs(head) |
| os.chdir(head) |
| RunCommand(['svn', 'export', '--depth', depth, '-r', revision, |
| url + '/' + remote_path, tail]) |
| finally: |
| os.chdir(cwd) |
| |
| |
| def PruneExtraFiles(local_path): |
| """Removes all files that do not match the whitelist.""" |
| pattern = re.compile(reduce(lambda x,y: '%s|%s' % (x,y), |
| map(lambda z: '(%s)' % z, WHITELIST))) |
| for (root, dirs, files) in os.walk(local_path, topdown=False): |
| for f in files: |
| if not pattern.match(f): |
| os.remove(os.path.join(root, f)) |
| for d in dirs: |
| dirpath = os.path.join(root, d) |
| if not os.listdir(dirpath): |
| shutil.rmtree(dirpath) |
| |
| |
| def GenerateReadme(local_path, template, url, revision): |
| readme = template % { |
| 'script': os.path.basename(__file__), |
| 'url': url, |
| 'revision': revision } |
| |
| readme_path = os.path.join(local_path, 'README') |
| out = open(readme_path, 'w') |
| out.write(readme) |
| out.close() |
| |
| ZIP_ARCHIVE = 'version-control-dirs.zip' |
| |
| def SaveVersionControlDir(local_path): |
| if os.path.exists(local_path): |
| RunCommand([ |
| 'sh', '-c', |
| 'find %s -name .svn -or -name .git | zip -r %s -@' % ( |
| os.path.relpath(local_path), ZIP_ARCHIVE) |
| ], [0, 12]) # It is ok if zip has nothing to do (exit code 12). |
| |
| def RestoreVersionControlDir(local_path): |
| archive_path = os.path.join(local_path, ZIP_ARCHIVE) |
| if os.path.exists(archive_path): |
| RunCommand(['unzip', ZIP_ARCHIVE, '-d', '.']) |
| RunCommand(['rm', ZIP_ARCHIVE]) |
| |
| def ParseOptions(): |
| parser = optparse.OptionParser() |
| parser.add_option('--webkit-revision', '-w', dest='webkit_revision', |
| help='WebKit IDL revision to install', default=None) |
| parser.add_option('--chrome-revision', '-c', dest='chrome_revision', |
| help='Chrome IDL revision to install', default=None) |
| args, _ = parser.parse_args() |
| update = {} |
| update['webkit'] = args.webkit_revision |
| return update |
| |
| |
| def main(): |
| update = ParseOptions() |
| deps = GetDepsFromGit() |
| for (component, remote_path, local_path, readme, depth) in UPDATE_LIST: |
| if component in update.keys(): |
| revision = update[component] |
| url, latest = GetSvnRevision(deps, component) |
| if revision is None: |
| revision = latest |
| SaveVersionControlDir(local_path); |
| RefreshFiles(url, revision, remote_path, local_path, depth) |
| PruneExtraFiles(local_path) |
| GenerateReadme(local_path, readme, url, revision) |
| RestoreVersionControlDir(local_path); |
| |
| if __name__ == '__main__': |
| main() |