• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright 2019 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6from __future__ import print_function
7import argparse
8import sys
9import os
10import subprocess
11import glob
12import shutil
13
14
15FILES_TO_SYNC = [
16    'README.md',
17    'check_protocol_compatibility.py',
18    'code_generator.py',
19    'concatenate_protocols.py',
20    'convert_protocol_to_json.py',
21    'encoding/encoding.h',
22    'encoding/encoding.cc',
23    'encoding/encoding_test.cc',
24    'inspector_protocol.gni',
25    'inspector_protocol.gypi',
26    'lib/*',
27    'pdl.py',
28    'templates/*',
29]
30
31
32def RunCmd(cmd):
33  p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
34  (stdoutdata, stderrdata) = p.communicate()
35  if p.returncode != 0:
36    raise Exception('%s: exit status %d', str(cmd), p.returncode)
37  return stdoutdata
38
39
40def CheckRepoIsClean(path, suffix):
41  os.chdir(path)  # As a side effect this also checks for existence of the dir.
42  # If path isn't a git repo, this will throw and exception.
43  # And if it is a git repo and 'git status' has anything interesting to say,
44  # then it's not clean (uncommitted files etc.)
45  if len(RunCmd(['git', 'status', '--porcelain'])) != 0:
46    raise Exception('%s is not a clean git repo (run git status)' % path)
47  if not path.endswith(suffix):
48    raise Exception('%s does not end with /%s' % (path, suffix))
49
50
51def CheckRepoIsNotAtMasterBranch(path):
52  os.chdir(path)
53  stdout = RunCmd(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip()
54  if stdout == 'master':
55    raise Exception('%s is at master branch - refusing to copy there.' % path)
56
57
58def CheckRepoIsV8Checkout(path):
59  os.chdir(path)
60  if (RunCmd(['git', 'config', '--get', 'remote.origin.url']).strip() !=
61      'https://chromium.googlesource.com/v8/v8.git'):
62    raise Exception('%s is not a proper V8 checkout.' % path)
63
64
65def CheckRepoIsInspectorProtocolCheckout(path):
66  os.chdir(path)
67  if (RunCmd(['git', 'config', '--get', 'remote.origin.url']).strip() !=
68      'https://chromium.googlesource.com/deps/inspector_protocol.git'):
69    raise Exception('%s is not a proper inspector_protocol checkout.' % path)
70
71
72def FindFilesToSyncIn(path):
73  files = []
74  for f in FILES_TO_SYNC:
75    files += glob.glob(os.path.join(path, f))
76  files = [os.path.relpath(f, path) for f in files]
77  return files
78
79
80def FilesAreEqual(path1, path2):
81  # We check for permissions (useful for executable scripts) and contents.
82  return (os.stat(path1).st_mode == os.stat(path2).st_mode and
83          open(path1).read() == open(path2).read())
84
85
86def GetHeadRevision(path):
87  os.chdir(path)
88  return RunCmd(['git', 'rev-parse', 'HEAD'])
89
90
91def main(argv):
92  parser = argparse.ArgumentParser(description=(
93      "Rolls the inspector_protocol project (upstream) into V8's "
94      "third_party (downstream)."))
95  parser.add_argument("--ip_src_upstream",
96                      help="The inspector_protocol (upstream) tree.",
97                      default="~/ip/src")
98  parser.add_argument("--v8_src_downstream",
99                      help="The V8 src tree.",
100                      default="~/v8/v8")
101  parser.add_argument('--force', dest='force', action='store_true',
102                      help=("Whether to carry out the modifications "
103                            "in the destination tree."))
104  parser.set_defaults(force=False)
105
106  args = parser.parse_args(argv)
107  upstream = os.path.normpath(os.path.expanduser(args.ip_src_upstream))
108  downstream = os.path.normpath(os.path.expanduser(
109      args.v8_src_downstream))
110  CheckRepoIsClean(upstream, '/src')
111  CheckRepoIsClean(downstream, '/v8')
112  CheckRepoIsInspectorProtocolCheckout(upstream)
113  CheckRepoIsV8Checkout(downstream)
114  # Check that the destination Git repo isn't at the master branch - it's
115  # generally a bad idea to check into the master branch, so we catch this
116  # common pilot error here early.
117  CheckRepoIsNotAtMasterBranch(downstream)
118  src_dir = upstream
119  dest_dir = os.path.join(downstream, 'third_party/inspector_protocol')
120  print('Rolling %s into %s ...' % (src_dir, dest_dir))
121  src_files = set(FindFilesToSyncIn(src_dir))
122  dest_files = set(FindFilesToSyncIn(dest_dir))
123  to_add = [f for f in src_files if f not in dest_files]
124  to_delete = [f for f in dest_files if f not in src_files]
125  to_copy = [f for f in src_files
126             if (f in dest_files and not FilesAreEqual(
127                 os.path.join(src_dir, f), os.path.join(dest_dir, f)))]
128  print('To add: %s' % to_add)
129  print('To delete: %s' % to_delete)
130  print('To copy: %s' % to_copy)
131  if not to_add and not to_delete and not to_copy:
132    print('Nothing to do. You\'re good.')
133    sys.exit(0)
134  if not args.force:
135    print('Rerun with --force if you wish the modifications to be done.')
136    sys.exit(1)
137  print('You said --force ... as you wish, modifying the destination.')
138  for f in to_add + to_copy:
139    contents = open(os.path.join(src_dir, f)).read()
140    contents = contents.replace(
141        'INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_',
142        'V8_INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_')
143    contents = contents.replace(
144        'namespace inspector_protocol_encoding',
145        'namespace v8_inspector_protocol_encoding')
146    open(os.path.join(dest_dir, f), 'w').write(contents)
147    shutil.copymode(os.path.join(src_dir, f), os.path.join(dest_dir, f))
148  for f in to_delete:
149    os.unlink(os.path.join(dest_dir, f))
150  head_revision = GetHeadRevision(upstream)
151  lines = open(os.path.join(dest_dir, 'README.v8')).readlines()
152  f = open(os.path.join(dest_dir, 'README.v8'), 'w')
153  for line in lines:
154    if line.startswith('Revision: '):
155      f.write('Revision: %s' % head_revision)
156    else:
157      f.write(line)
158  f.close()
159
160
161if __name__ == '__main__':
162  sys.exit(main(sys.argv[1:]))
163