2017-03-14 08:26:12 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# Copyright 2017 the V8 project authors. All rights reserved.
|
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
|
2017-04-25 13:39:03 +00:00
|
|
|
"""
|
|
|
|
Use this script to update V8 in a Node.js checkout.
|
|
|
|
|
|
|
|
Requirements:
|
|
|
|
- Node.js checkout in which V8 should be updated.
|
|
|
|
- V8 checkout at the commit to which Node.js should be updated.
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
$ update_node.py <path_to_v8> <path_to_node>
|
|
|
|
|
|
|
|
This will synchronize the content of <path_to_node>/deps/v8 with <path_to_v8>,
|
|
|
|
and a few V8 dependencies require in Node.js. It will also update .gitignore
|
|
|
|
appropriately.
|
|
|
|
|
|
|
|
Optional flags:
|
|
|
|
--gclient Run `gclient sync` on the V8 checkout before updating.
|
|
|
|
--commit Create commit with the updated V8 in the Node.js checkout.
|
|
|
|
--with-patch Also include currently staged files in the V8 checkout.
|
|
|
|
"""
|
|
|
|
|
2017-03-14 08:26:12 +00:00
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
import subprocess
|
|
|
|
import sys
|
2017-11-09 09:13:52 +00:00
|
|
|
import stat
|
2017-03-14 08:26:12 +00:00
|
|
|
|
|
|
|
TARGET_SUBDIR = os.path.join("deps", "v8")
|
|
|
|
|
2017-03-16 12:54:55 +00:00
|
|
|
SUB_REPOSITORIES = [ ["base", "trace_event", "common"],
|
|
|
|
["testing", "gtest"],
|
2017-03-14 08:26:12 +00:00
|
|
|
["third_party", "jinja2"],
|
|
|
|
["third_party", "markupsafe"] ]
|
|
|
|
|
|
|
|
DELETE_FROM_GITIGNORE = [ "/base",
|
2017-03-14 09:36:40 +00:00
|
|
|
"/testing/gtest",
|
|
|
|
"/third_party/jinja2",
|
|
|
|
"/third_party/markupsafe" ]
|
2017-03-14 08:26:12 +00:00
|
|
|
|
|
|
|
# Node.js requires only a single header file from gtest to build V8.
|
|
|
|
# Both jinja2 and markupsafe are required to generate part of the inspector.
|
|
|
|
ADD_TO_GITIGNORE = [ "/testing/gtest/*",
|
|
|
|
"!/testing/gtest/include",
|
|
|
|
"/testing/gtest/include/*",
|
|
|
|
"!/testing/gtest/include/gtest",
|
|
|
|
"/testing/gtest/include/gtest/*",
|
|
|
|
"!/testing/gtest/include/gtest/gtest_prod.h",
|
|
|
|
"!/third_party/jinja2",
|
|
|
|
"!/third_party/markupsafe" ]
|
|
|
|
|
|
|
|
def RunGclient(path):
|
|
|
|
assert os.path.isdir(path)
|
|
|
|
print ">> Running gclient sync"
|
2017-03-14 12:49:26 +00:00
|
|
|
subprocess.check_call(["gclient", "sync", "--nohooks"], cwd=path)
|
2017-03-14 08:26:12 +00:00
|
|
|
|
|
|
|
def UninitGit(path):
|
|
|
|
target = os.path.join(path, ".git")
|
|
|
|
if os.path.isdir(target):
|
|
|
|
print ">> Cleaning up %s" % path
|
2017-11-09 09:13:52 +00:00
|
|
|
def OnRmError(func, path, exec_info):
|
|
|
|
# This might happen on Windows
|
|
|
|
os.chmod(path, stat.S_IWRITE)
|
|
|
|
os.unlink(path)
|
|
|
|
shutil.rmtree(target, onerror=OnRmError)
|
2017-03-14 08:26:12 +00:00
|
|
|
|
2017-04-05 10:02:58 +00:00
|
|
|
def CommitPatch(options):
|
|
|
|
"""Makes a dummy commit for the changes in the index.
|
|
|
|
|
|
|
|
On trybots, bot_updated applies the patch to the index. We commit it to make
|
|
|
|
the fake git clone fetch it into node.js. We can leave the commit, as
|
|
|
|
bot_update will ensure a clean state on each run.
|
|
|
|
"""
|
2017-08-02 08:23:36 +00:00
|
|
|
print ">> Committing patch"
|
2017-04-05 10:02:58 +00:00
|
|
|
subprocess.check_call(
|
2017-05-17 07:19:18 +00:00
|
|
|
["git", "-c", "user.name=fake", "-c", "user.email=fake@chromium.org",
|
|
|
|
"commit", "--allow-empty", "-m", "placeholder-commit"],
|
2017-04-05 10:02:58 +00:00
|
|
|
cwd=options.v8_path,
|
2017-04-04 12:59:22 +00:00
|
|
|
)
|
|
|
|
|
2017-03-14 08:26:12 +00:00
|
|
|
def UpdateTarget(repository, options):
|
|
|
|
source = os.path.join(options.v8_path, *repository)
|
|
|
|
target = os.path.join(options.node_path, TARGET_SUBDIR, *repository)
|
|
|
|
print ">> Updating target directory %s" % target
|
|
|
|
print ">> from active branch at %s" % source
|
|
|
|
if not os.path.exists(target):
|
|
|
|
os.makedirs(target)
|
|
|
|
# Remove possible remnants of previous incomplete runs.
|
|
|
|
UninitGit(target)
|
|
|
|
|
|
|
|
git_commands = [
|
2017-03-14 12:49:26 +00:00
|
|
|
["git", "init"], # initialize target repo
|
|
|
|
["git", "remote", "add", "origin", source], # point to the source repo
|
|
|
|
["git", "fetch", "origin", "HEAD"], # sync to the current branch
|
|
|
|
["git", "reset", "--hard", "FETCH_HEAD"], # reset to the current branch
|
|
|
|
["git", "clean", "-fd"], # delete removed files
|
2017-03-14 08:26:12 +00:00
|
|
|
]
|
|
|
|
try:
|
|
|
|
for command in git_commands:
|
2017-03-14 12:49:26 +00:00
|
|
|
subprocess.check_call(command, cwd=target)
|
2017-03-14 08:26:12 +00:00
|
|
|
except:
|
|
|
|
raise
|
|
|
|
finally:
|
|
|
|
UninitGit(target)
|
|
|
|
|
|
|
|
def UpdateGitIgnore(options):
|
|
|
|
file_name = os.path.join(options.node_path, TARGET_SUBDIR, ".gitignore")
|
|
|
|
assert os.path.isfile(file_name)
|
|
|
|
print ">> Updating .gitignore with lines"
|
|
|
|
with open(file_name) as gitignore:
|
|
|
|
content = gitignore.readlines()
|
|
|
|
content = [x.strip() for x in content]
|
|
|
|
for x in DELETE_FROM_GITIGNORE:
|
|
|
|
if x in content:
|
|
|
|
print "- %s" % x
|
|
|
|
content.remove(x)
|
|
|
|
for x in ADD_TO_GITIGNORE:
|
|
|
|
if x not in content:
|
|
|
|
print "+ %s" % x
|
|
|
|
content.append(x)
|
|
|
|
content.sort(key=lambda x: x[1:] if x.startswith("!") else x)
|
|
|
|
with open(file_name, "w") as gitignore:
|
|
|
|
for x in content:
|
|
|
|
gitignore.write("%s\n" % x)
|
|
|
|
|
2017-03-14 12:49:26 +00:00
|
|
|
def CreateCommit(options):
|
|
|
|
print ">> Creating commit."
|
|
|
|
# Find git hash from source.
|
|
|
|
githash = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"],
|
|
|
|
cwd=options.v8_path).strip()
|
|
|
|
# Create commit at target.
|
|
|
|
git_commands = [
|
|
|
|
["git", "checkout", "-b", "update_v8_to_%s" % githash], # new branch
|
|
|
|
["git", "add", "."], # add files
|
|
|
|
["git", "commit", "-m", "Update V8 to %s" % githash] # new commit
|
|
|
|
]
|
|
|
|
for command in git_commands:
|
|
|
|
subprocess.check_call(command, cwd=options.node_path)
|
|
|
|
|
2017-03-14 08:26:12 +00:00
|
|
|
def ParseOptions(args):
|
|
|
|
parser = argparse.ArgumentParser(description="Update V8 in Node.js")
|
|
|
|
parser.add_argument("v8_path", help="Path to V8 checkout")
|
|
|
|
parser.add_argument("node_path", help="Path to Node.js checkout")
|
2017-03-14 12:49:26 +00:00
|
|
|
parser.add_argument("--gclient", action="store_true", help="Run gclient sync")
|
|
|
|
parser.add_argument("--commit", action="store_true", help="Create commit")
|
2017-04-04 12:59:22 +00:00
|
|
|
parser.add_argument("--with-patch", action="store_true",
|
|
|
|
help="Apply also staged files")
|
2017-03-14 08:26:12 +00:00
|
|
|
options = parser.parse_args(args)
|
|
|
|
assert os.path.isdir(options.v8_path)
|
|
|
|
options.v8_path = os.path.abspath(options.v8_path)
|
|
|
|
assert os.path.isdir(options.node_path)
|
|
|
|
options.node_path = os.path.abspath(options.node_path)
|
|
|
|
return options
|
|
|
|
|
|
|
|
def Main(args):
|
|
|
|
options = ParseOptions(args)
|
|
|
|
if options.gclient:
|
|
|
|
RunGclient(options.v8_path)
|
2017-04-05 10:02:58 +00:00
|
|
|
# Commit patch on trybots to main V8 repository.
|
|
|
|
if options.with_patch:
|
|
|
|
CommitPatch(options)
|
2017-03-14 08:26:12 +00:00
|
|
|
# Update main V8 repository.
|
|
|
|
UpdateTarget([""], options)
|
|
|
|
# Patch .gitignore before updating sub-repositories.
|
|
|
|
UpdateGitIgnore(options)
|
|
|
|
for repo in SUB_REPOSITORIES:
|
|
|
|
UpdateTarget(repo, options)
|
2017-03-14 12:49:26 +00:00
|
|
|
if options.commit:
|
|
|
|
CreateCommit(options)
|
2017-03-14 08:26:12 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
Main(sys.argv[1:])
|