| # 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()) |