#!/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.

"""
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.
"""

import argparse
import os
import shutil
import subprocess
import sys
import stat

TARGET_SUBDIR = os.path.join("deps", "v8")

SUB_REPOSITORIES = [ ["base", "trace_event", "common"],
                     ["testing", "gtest"],
                     ["third_party", "jinja2"],
                     ["third_party", "markupsafe"] ]

DELETE_FROM_GITIGNORE = [ "/base",
                          "/testing/gtest",
                          "/third_party/jinja2",
                          "/third_party/markupsafe" ]

# 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"
  subprocess.check_call(["gclient", "sync", "--nohooks"], cwd=path)

def UninitGit(path):
  target = os.path.join(path, ".git")
  if os.path.isdir(target):
    print ">> Cleaning up %s" % path
    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)

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.
  """
  print ">> Committing patch"
  subprocess.check_call(
      ["git", "-c", "user.name=fake", "-c", "user.email=fake@chromium.org",
       "commit", "--allow-empty", "-m", "placeholder-commit"],
      cwd=options.v8_path,
  )

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 = [
    ["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
  ]
  try:
    for command in git_commands:
      subprocess.check_call(command, cwd=target)
  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)

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)

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")
  parser.add_argument("--gclient", action="store_true", help="Run gclient sync")
  parser.add_argument("--commit", action="store_true", help="Create commit")
  parser.add_argument("--with-patch", action="store_true",
                      help="Apply also staged files")
  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)
  # Commit patch on trybots to main V8 repository.
  if options.with_patch:
    CommitPatch(options)
  # Update main V8 repository.
  UpdateTarget([""], options)
  # Patch .gitignore before updating sub-repositories.
  UpdateGitIgnore(options)
  for repo in SUB_REPOSITORIES:
    UpdateTarget(repo, options)
  if options.commit:
    CreateCommit(options)

if __name__ == "__main__":
  Main(sys.argv[1:])
