|  | # Upgrading Dart's SDK for HTML (blink IDLs). | 
|  | # | 
|  | # Typically this is done using the Dart WebCore branch (as it has to be | 
|  | # staged to get most things working). | 
|  | # | 
|  | # Enlist in third_party/WebCore: | 
|  | #      > cd src/dart/third_party | 
|  | #      > rm -rf WebCore    (NOTE: Normally detached head using gclient sync) | 
|  | #      > git clone https://github.com/dart-lang/webcore.git WebCore | 
|  | # | 
|  | # To update all *.idl, *.py, LICENSE files, and IDLExtendedAttributes.txt: | 
|  | #      > cd sdk | 
|  | #      > python tools/dom/scripts/idlsync.py | 
|  | # | 
|  | # Display blink files to delete, copy, update, and collisions to review: | 
|  | #      > python tools/dom/scripts/idlsync.py --check | 
|  | # | 
|  | # Bring over all blink files to dart/third_party/WebCore (*.py, *.idl, and | 
|  | # IDLExtendedAttributes.txt): | 
|  | #      > python tools/dom/scripts/idlsync.py | 
|  | # | 
|  | # Update the DEPS file SHA for "WebCore_rev" with the committed changes of files | 
|  | # in WebCore e.g.,   "WebCore_rev": "@NNNNNNNNNNNNNNNNNNNNNNNNN" | 
|  | # | 
|  | # Generate the sdk/*.dart files from the new IDLs and PYTHON IDL parsing code | 
|  | # copied to in dart/third_party/WebCore from src/third_party/WebKit (blink). | 
|  | # | 
|  | #      > cd src/dart/tools/dom/script | 
|  | #      > ./go.sh | 
|  | # | 
|  | # Finally, commit the files in dart/third_party/WebCore. | 
|  |  | 
|  | import errno | 
|  | import optparse | 
|  | import os.path | 
|  | import re | 
|  | import requests | 
|  | import subprocess | 
|  | import sys | 
|  | import time | 
|  |  | 
|  | from shutil import copyfile | 
|  |  | 
|  | # Dart DEPS file checked into the dart-lang/sdk master. | 
|  | DEPS_GIT = "https://raw.githubusercontent.com/dart-lang/sdk/master/DEPS" | 
|  | CHROME_TRUNK = "https://chromium.googlesource.com" | 
|  | WEBKIT_SHA_PATTERN = r'"WebCore_rev": "(\S+)",' | 
|  |  | 
|  | # Chromium remote (GIT repository) | 
|  | GIT_REMOTES_CHROMIUM = 'https://chromium.googlesource.com/chromium/src.git' | 
|  |  | 
|  | # location of this file | 
|  | SOURCE_FILE_DIR = 'tools/dom/scripts' | 
|  |  | 
|  | WEBKIT_SOURCE = 'src/third_party/WebKit/Source' | 
|  | WEBCORE_SOURCE = 'third_party/WebCore' | 
|  |  | 
|  | WEBKIT_BLINK_SOURCE = 'src/third_party/blink' | 
|  | WEBCORE_BLINK_SOURCE = 'third_party/WebCore/blink' | 
|  |  | 
|  | # Never automatically git add bindings/IDLExtendedAttributes.txt this file has | 
|  | # been modified by Dart but is usually changed by WebKit blink too. | 
|  | IDL_EXTENDED_ATTRIBUTES_FILE = 'IDLExtendedAttributes.txt' | 
|  |  | 
|  | # Don't automatically update, delete or add anything in this directory: | 
|  | #      bindings/dart/scripts | 
|  | # The scripts in the above directory is the source for our Dart generators that | 
|  | # is driven from the blink IDL parser AST | 
|  | DART_SDK_GENERATOR_SCRIPTS = 'bindings/dart/scripts' | 
|  |  | 
|  | # The __init__.py files allow Python to treat directories as packages. Used to | 
|  | # allow Dart's Python scripts to interact with Chrome's IDL parsing scripts. | 
|  | PYTHON_INITS = '__init__.py' | 
|  |  | 
|  | # sub directories containing IDLs (core and modules) from the base directory | 
|  | # src/third_party/WebKit/Source | 
|  | SUBDIRS = [ | 
|  | 'bindings', | 
|  | 'core', | 
|  | 'modules', | 
|  | ] | 
|  | IDL_EXT = '.idl' | 
|  | PY_EXT = '.py' | 
|  | LICENSE_FILE_PREFIX = 'LICENSE'  # e.g., LICENSE-APPLE, etc. | 
|  |  | 
|  | # Look in any file in WebCore we copy from WebKit if this comment is in the file | 
|  | # then flag this as a special .py or .idl file that needs to be looked at. | 
|  | DART_CHANGES = ' FIXMEDART: ' | 
|  |  | 
|  | # application options passed in. | 
|  | options = None | 
|  |  | 
|  | warning_messages = [] | 
|  |  | 
|  |  | 
|  | # Is --dry_run passed in. | 
|  | def isDryRun(): | 
|  | global options | 
|  | return options['dry_run'] is not None | 
|  |  | 
|  |  | 
|  | # Is --verbose passed in. | 
|  | def isVerbose(): | 
|  | global options | 
|  | return options['verbose'] is not None | 
|  |  | 
|  |  | 
|  | # If --WebKit= is specified then compute the directory of the Chromium | 
|  | # source. | 
|  | def chromiumDirectory(): | 
|  | global options | 
|  | if options['chromium_dir'] is not None: | 
|  | return os.path.expanduser(options['chromium_dir']) | 
|  | return os.cwd() | 
|  |  | 
|  |  | 
|  | def RunCommand(cmd, valid_exits=[0]): | 
|  | """Executes a shell command and return its stdout.""" | 
|  | if isVerbose(): | 
|  | 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) | 
|  |  | 
|  |  | 
|  | # returns True if // FIXMEDART: is in the file. | 
|  | def anyDartFixMe(filepath): | 
|  | if os.path.exists(filepath): | 
|  | data = open(filepath, 'r').read() | 
|  | return data.find(DART_CHANGES) != -1 | 
|  | else: | 
|  | return False | 
|  |  | 
|  |  | 
|  | # Give a base_dir compute the trailing directory after base_dir | 
|  | # returns the subpath from base_dir for the path passed in. | 
|  | def subpath(path, base_dir): | 
|  | dir_portion = '' | 
|  | head = path | 
|  | while True: | 
|  | head, tail = os.path.split(head) | 
|  | dir_portion = os.path.join(tail, dir_portion) | 
|  | if head == base_dir or tail == '': | 
|  | break | 
|  | return dir_portion | 
|  |  | 
|  |  | 
|  | # Copy any file in source_dir (WebKit) to destination_dir (dart/third_party/WebCore) | 
|  | # source_dir is the src/third_party/WebKit/Source location (blink) | 
|  | # destination_dir is the src/dart/third_party/WebCore location | 
|  | # returns idls_copied, py_copied, other_copied | 
|  | def copy_files(source_dir, src_prefix, destination_dir): | 
|  | original_cwd = os.getcwd() | 
|  | try: | 
|  | os.makedirs(destination_dir) | 
|  | except OSError as e: | 
|  | if e.errno != errno.EEXIST: | 
|  | raise | 
|  | os.chdir(destination_dir) | 
|  |  | 
|  | idls = 0  # *.idl files copied | 
|  | pys = 0  # *.py files copied | 
|  | others = 0  # all other files copied | 
|  |  | 
|  | for (root, _, files) in os.walk(source_dir, topdown=False): | 
|  | dir_portion = subpath(root, source_dir) | 
|  | for f in files: | 
|  | # Never automatically add any Dart generator scripts (these are the original | 
|  | # sources in WebCore) from WebKit to WebCore. | 
|  | if dir_portion != DART_SDK_GENERATOR_SCRIPTS: | 
|  | if (f.endswith(IDL_EXT) or f == IDL_EXTENDED_ATTRIBUTES_FILE or | 
|  | f.endswith(PY_EXT) or | 
|  | f.startswith(LICENSE_FILE_PREFIX)): | 
|  | if f.endswith(IDL_EXT): | 
|  | idls += 1 | 
|  | elif f.endswith(PY_EXT): | 
|  | pys += 1 | 
|  | else: | 
|  | others += 1 | 
|  | src_file = os.path.join(root, f) | 
|  |  | 
|  | # Compute the destination path using sdk/third_party/WebCore | 
|  | subdir_root = src_file[src_file.rfind(src_prefix) + | 
|  | len(src_prefix):] | 
|  | if subdir_root.startswith(os.path.sep): | 
|  | subdir_root = subdir_root[1:] | 
|  | dst_file = os.path.join(destination_dir, subdir_root) | 
|  |  | 
|  | # Need to make src/third_party/WebKit/Source/* to sdk/third_party/WebCore/* | 
|  |  | 
|  | destination = os.path.dirname(dst_file) | 
|  | if not os.path.exists(destination): | 
|  | os.makedirs(destination) | 
|  |  | 
|  | has_Dart_fix_me = anyDartFixMe(dst_file) | 
|  |  | 
|  | if not isDryRun(): | 
|  | copyfile(src_file, dst_file) | 
|  | if isVerbose(): | 
|  | #print('...copying %s' % os.path.split(dst_file)[1]) | 
|  | print('...copying %s' % dst_file) | 
|  | if f == IDL_EXTENDED_ATTRIBUTES_FILE: | 
|  | warning_messages.append(dst_file) | 
|  | else: | 
|  | if has_Dart_fix_me: | 
|  | warning_messages.append(dst_file) | 
|  | if not (isDryRun() or has_Dart_fix_me): | 
|  | # git add the file | 
|  | RunCommand(['git', 'add', dst_file]) | 
|  |  | 
|  | os.chdir(original_cwd) | 
|  |  | 
|  | return [idls, pys, others] | 
|  |  | 
|  |  | 
|  | # Remove any file in webcore_dir that no longer exist in the webkit_dir | 
|  | # webcore_dir src/dart/third_party/WebCore location | 
|  | # webkit_dir src/third_party/WebKit/Source location (blink) | 
|  | # only check if the subdir off from webcore_dir | 
|  | # return list of files deleted | 
|  | def remove_obsolete_webcore_files(webcore_dir, webkit_dir, subdir): | 
|  | files_to_delete = [] | 
|  |  | 
|  | original_cwd = os.getcwd() | 
|  |  | 
|  | if os.path.exists(webcore_dir): | 
|  | os.chdir(webcore_dir) | 
|  |  | 
|  | for (root, _, files) in os.walk( | 
|  | os.path.join(webcore_dir, subdir), topdown=False): | 
|  | dir_portion = subpath(root, webcore_dir) | 
|  | for f in files: | 
|  | # Never automatically deleted any Dart generator scripts (these are the | 
|  | # original sources in WebCore). | 
|  | if dir_portion != DART_SDK_GENERATOR_SCRIPTS: | 
|  | check_file = os.path.join(dir_portion, f) | 
|  | check_file_full_path = os.path.join(webkit_dir, check_file) | 
|  | if not os.path.exists(check_file_full_path) and \ | 
|  | not(check_file_full_path.endswith(PYTHON_INITS)): | 
|  | if not isDryRun(): | 
|  | # Remove the file using git | 
|  | RunCommand(['git', 'rm', check_file]) | 
|  | files_to_delete.append(check_file) | 
|  |  | 
|  | os.chdir(original_cwd) | 
|  |  | 
|  | return files_to_delete | 
|  |  | 
|  |  | 
|  | def ParseOptions(): | 
|  | parser = optparse.OptionParser() | 
|  | parser.add_option( | 
|  | '--chromium', | 
|  | '-c', | 
|  | dest='chromium_dir', | 
|  | action='store', | 
|  | type='string', | 
|  | help='WebKit Chrome directory (e.g., --chromium=~/chrome63', | 
|  | default=None) | 
|  | parser.add_option( | 
|  | '--verbose', | 
|  | '-v', | 
|  | dest='verbose', | 
|  | action='store_true', | 
|  | help='Dump all information', | 
|  | default=None) | 
|  | parser.add_option( | 
|  | '--dry_run', | 
|  | '-d', | 
|  | dest='dry_run', | 
|  | action='store_true', | 
|  | help='Display results without adding, updating or deleting any files', | 
|  | default=None) | 
|  | args, _ = parser.parse_args() | 
|  |  | 
|  | argOptions = {} | 
|  | argOptions['chromium_dir'] = args.chromium_dir | 
|  | argOptions['verbose'] = args.verbose | 
|  | argOptions['dry_run'] = args.dry_run | 
|  | return argOptions | 
|  |  | 
|  |  | 
|  | # Fetch the DEPS file in src/dart/tools/deps/dartium.deps/DEPS from the GIT repro. | 
|  | def GetDepsFromGit(): | 
|  | req = requests.get(DEPS_GIT) | 
|  | return req.text | 
|  |  | 
|  |  | 
|  | def ValidateGitRemotes(): | 
|  | #origin  https://chromium.googlesource.com/dart/dartium/src.git (fetch) | 
|  | remotes_list = RunCommand(['git', 'remote', '--verbose']).split() | 
|  | if (len(remotes_list) > 2 and remotes_list[0] == 'origin' and | 
|  | remotes_list[1] == GIT_REMOTES_CHROMIUM): | 
|  | return True | 
|  |  | 
|  | print 'ERROR: Unable to find dart/dartium/src repository %s' % GIT_REMOTES_CHROMIUM | 
|  | return False | 
|  |  | 
|  |  | 
|  | def getChromiumSHA(): | 
|  | cwd = os.getcwd() | 
|  | chromiumDir = chromiumDirectory() | 
|  |  | 
|  | webkit_dir = os.path.join(chromiumDir, WEBKIT_SOURCE) | 
|  | os.chdir(webkit_dir) | 
|  |  | 
|  | if ValidateGitRemotes(): | 
|  | chromium_sha = RunCommand(['git', 'log', '--format=format:%H', '-1']) | 
|  | else: | 
|  | chromium_sha = -1 | 
|  |  | 
|  | os.chdir(cwd) | 
|  | return chromium_sha | 
|  |  | 
|  |  | 
|  | def getCurrentDartSHA(): | 
|  | cwd = os.getcwd() | 
|  |  | 
|  | if cwd.endswith('dart'): | 
|  | # In src/dart | 
|  | src_dir, _ = os.path.split(cwd) | 
|  | elif cwd.endswith('sdk'): | 
|  | src_dir = cwd | 
|  | else: | 
|  | src_dir = os.path.join(cwd, 'sdk') | 
|  | os.chdir(src_dir) | 
|  |  | 
|  | if ValidateGitRemotes(): | 
|  | dart_sha = RunCommand(['git', 'log', '--format=format:%H', '-1']) | 
|  | else: | 
|  | dart_sha = -1 | 
|  |  | 
|  | os.chdir(cwd) | 
|  | return dart_sha | 
|  |  | 
|  |  | 
|  | # Returns the SHA of the Dartium/Chromiun in the DEPS file. | 
|  | def GetDEPSWebCoreGitRevision(deps, component): | 
|  | """Returns a tuple with the (dartium chromium repo, latest revision).""" | 
|  | foundIt = re.search(WEBKIT_SHA_PATTERN, deps) | 
|  | #url_base, url_pattern = DEPS_PATTERNS[component] | 
|  | #url = url_base + re.search(url_pattern, deps).group(1) | 
|  | # Get the SHA for the Chromium/WebKit changes for Dartium. | 
|  | #revision = url[len(url_base):] | 
|  | revision = foundIt.group(1)[1:] | 
|  | print '%s' % revision | 
|  | return revision | 
|  |  | 
|  |  | 
|  | def copy_subdir(src, src_prefix, dest, subdir): | 
|  | idls_deleted = remove_obsolete_webcore_files(dest, src, subdir) | 
|  | print "%s files removed in WebCore %s" % (idls_deleted.__len__(), subdir) | 
|  | if isVerbose(): | 
|  | for delete_file in idls_deleted: | 
|  | print "    %s" % delete_file | 
|  |  | 
|  | idls_copied, py_copied, other_copied = copy_files( | 
|  | os.path.join(src, subdir), src_prefix, dest) | 
|  | if idls_copied > 0: | 
|  | print "Copied %s IDLs to %s" % (idls_copied, subdir) | 
|  | if py_copied > 0: | 
|  | print "Copied %s PYs to %s" % (py_copied, subdir) | 
|  | if other_copied > 0: | 
|  | print "Copied %s other to %s\n" % (other_copied, subdir) | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | global options | 
|  | options = ParseOptions() | 
|  |  | 
|  | current_dir = os.path.dirname(os.path.abspath(__file__)) | 
|  | if not current_dir.endswith(SOURCE_FILE_DIR): | 
|  | print 'ERROR: idlsync.py not run in proper directory (%s)\n', current_dir | 
|  |  | 
|  | base_directory = current_dir[:current_dir.rfind(SOURCE_FILE_DIR)] | 
|  |  | 
|  | # Validate DEPS WebCore_rev SHA DOES NOT match the SHA of chromium master. | 
|  | deps = GetDepsFromGit() | 
|  | webcore_revision = GetDEPSWebCoreGitRevision(deps, 'webkit') | 
|  | chromium_sha = getChromiumSHA() | 
|  | if webcore_revision == chromium_sha: | 
|  | print "ERROR: Nothing to update in WebCore, WebCore_rev SHA in DEPS " \ | 
|  | "matches Chromium GIT master SHA in %s" % options['webkit_dir'] | 
|  | return | 
|  |  | 
|  | start_time = time.time() | 
|  |  | 
|  | # Copy scripts from third_party/blink/tools to third_party/WebCore/blink/tools | 
|  | # | 
|  | # This also implies that the files: | 
|  | #     WebCore/bindings/scripts/code_generator_web_agent_api.py | 
|  | #     WebCore/bindings/scripts/utilities.py | 
|  | # | 
|  | # Need to have sys.path.append at beginning of the above files changed from: | 
|  | # | 
|  | #    sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..', | 
|  | #                                 'third_party', 'blink', 'tools')) | 
|  | # to | 
|  | # | 
|  | #    sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', | 
|  | #                                 'blink', 'tools')) | 
|  | # | 
|  | webkit_blink_dir = os.path.join(chromiumDirectory(), WEBKIT_BLINK_SOURCE) | 
|  | webcore_blink_dir = os.path.join(base_directory, WEBCORE_BLINK_SOURCE) | 
|  | copy_subdir(webkit_blink_dir, WEBKIT_BLINK_SOURCE, webcore_blink_dir, "") | 
|  |  | 
|  | chromium_webkit_dir = os.path.join(chromiumDirectory(), WEBKIT_SOURCE) | 
|  | dart_webcore_dir = os.path.join(base_directory, WEBCORE_SOURCE) | 
|  | for subdir in SUBDIRS: | 
|  | copy_subdir(chromium_webkit_dir, WEBKIT_SOURCE, dart_webcore_dir, | 
|  | subdir) | 
|  |  | 
|  | end_time = time.time() | 
|  |  | 
|  | print 'WARNING: File(s) contain FIXMEDART and are NOT "git add " please review:' | 
|  | for warning in warning_messages: | 
|  | print '    %s' % warning | 
|  |  | 
|  | print '\nDone idlsync completed in %s seconds' % round( | 
|  | end_time - start_time, 2) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(main()) |