blob: 2afd560a09752cce5d3379996cc263a86dd216f5 [file] [log] [blame]
Yang Guo4fd355c2019-09-19 10:59:03 +02001# Copyright 2019 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""
5Helper to manage DEPS.
6"""
7
8import os
9import os.path as path
Yang Guo4fd355c2019-09-19 10:59:03 +020010import json
Yang Guo91178352019-10-31 08:50:19 +010011import shutil
12import subprocess
13import sys
14
15scripts_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16sys.path.append(scripts_path)
17
18import devtools_paths
Yang Guo4fd355c2019-09-19 10:59:03 +020019
20# List all DEPS here.
21DEPS = {
22 "@types/chai": "4.2.0",
23 "@types/mocha": "5.2.7",
24 "chai": "4.2.0",
Paul Lewis75090cf2019-10-25 14:13:11 +010025 "escodegen": "1.12.0",
Yang Guo4fd355c2019-09-19 10:59:03 +020026 "eslint": "6.0.1",
Paul Lewis75090cf2019-10-25 14:13:11 +010027 "esprima": "git+https://git@github.com/ChromeDevTools/esprima.git#4d0f0e18bd8d3731e5f931bf573af3394cbf7cbe",
Paul Lewis66e12062019-12-02 12:04:54 +000028 "handlebars": "4.3.1",
Yang Guo4fd355c2019-09-19 10:59:03 +020029 "karma": "4.2.0",
30 "karma-chai": "0.1.0",
31 "karma-chrome-launcher": "3.1.0",
Paul Lewisd9039092019-11-27 17:06:23 +000032 "karma-coverage-istanbul-instrumenter": "1.0.1",
33 "karma-coverage-istanbul-reporter": "2.1.0",
Yang Guo4fd355c2019-09-19 10:59:03 +020034 "karma-mocha": "1.3.0",
35 "karma-typescript": "4.1.1",
36 "mocha": "6.2.0",
Paul Lewisd9039092019-11-27 17:06:23 +000037 "puppeteer": "2.0.0",
Paul Lewis66e12062019-12-02 12:04:54 +000038 "rollup": "1.23.1",
39 "typescript": "3.5.3",
40 "yargs": "15.0.2"
Yang Guo4fd355c2019-09-19 10:59:03 +020041}
42
Paul Lewis66e12062019-12-02 12:04:54 +000043def exec_command(cmd):
Yang Guo4fd355c2019-09-19 10:59:03 +020044 try:
Paul Lewis66e12062019-12-02 12:04:54 +000045 cmd_proc_result = subprocess.check_call(cmd, cwd=devtools_paths.root_path())
46 except CalledProcessError as error:
47 print(error.output)
48 return True
49
50 return False
Yang Guo4fd355c2019-09-19 10:59:03 +020051
52
53def strip_private_fields():
54 # npm adds private fields which need to be stripped.
55 pattern = path.join(devtools_paths.node_modules_path(), 'package.json')
56 packages = []
57 for root, dirnames, filenames in os.walk(devtools_paths.node_modules_path()):
58 for filename in filter(lambda f: f == 'package.json', filenames):
59 packages.append(path.join(root, filename))
60
61 for pkg in packages:
62 with open(pkg, 'r+') as pkg_file:
63 prop_removal_count = 0
64 try:
65 pkg_data = json.load(pkg_file)
66
67 # Remove anything that begins with an underscore, as these are
68 # the private fields in a package.json
69 for key in pkg_data.keys():
70 if key.find(u'_') == 0:
71 pkg_data.pop(key)
72 prop_removal_count = prop_removal_count + 1
73
74 pkg_file.truncate(0)
75 pkg_file.seek(0)
76 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
77 print("(%s): %s" % (prop_removal_count, pkg))
78 except:
79 print('Unable to fix: %s' % pkg)
80 return True
81
82 return False
83
84
Paul Lewis66e12062019-12-02 12:04:54 +000085def install_missing_deps():
86 with open(devtools_paths.package_lock_json_path(), 'r+') as pkg_lock_file:
87 try:
88 pkg_lock_data = json.load(pkg_lock_file)
89 existing_deps = pkg_lock_data[u'dependencies']
90 new_deps = []
91
92 # Find any new DEPS and add them in.
93 for dep, version in DEPS.items():
94 if not (existing_deps[dep] and existing_deps[dep]['version'] == version):
95 new_deps.append("%s@%s" % (dep, version))
96
97 # Now install.
98 if len(new_deps) > 0:
99 cmd = ['npm', 'install', '--save-dev']
100 cmd.extend(new_deps)
101 return exec_command(cmd)
102
103 except Exception as exception:
104 print('Unable to fix: %s' % exception)
105 return True
106
107 return False
108
109
Paul Lewisd9039092019-11-27 17:06:23 +0000110def append_package_json_entries():
111 with open(devtools_paths.package_json_path(), 'r+') as pkg_file:
112 try:
113 pkg_data = json.load(pkg_file)
114
115 # Replace the dev deps.
116 pkg_data[u'devDependencies'] = DEPS
117
118 pkg_file.truncate(0)
119 pkg_file.seek(0)
120 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
121
122 except:
123 print('Unable to fix: %s' % sys.exc_info()[0])
124 return True
125 return False
126
127
Paul Lewis75090cf2019-10-25 14:13:11 +0100128def remove_package_json_entries():
129 with open(devtools_paths.package_json_path(), 'r+') as pkg_file:
130 try:
131 pkg_data = json.load(pkg_file)
132
133 # Remove the dependencies and devDependencies from the root package.json
134 # so that they can't be used to overwrite the node_modules managed by this file.
135 for key in pkg_data.keys():
136 if key.find(u'dependencies') == 0 or key.find(u'devDependencies') == 0:
137 pkg_data.pop(key)
138
139 pkg_file.truncate(0)
140 pkg_file.seek(0)
141 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
142 except:
143 print('Unable to fix: %s' % pkg)
144 return True
145 return False
146
147
Yang Guo4fd355c2019-09-19 10:59:03 +0200148def install_deps():
Paul Lewis66e12062019-12-02 12:04:54 +0000149 for (name, version) in DEPS.items():
150 if (version.find(u'^') == 0):
151 print('Versions must be locked to a specific version; remove ^ from the start of the version.')
152 return True
Yang Guo4fd355c2019-09-19 10:59:03 +0200153
Paul Lewis66e12062019-12-02 12:04:54 +0000154 if append_package_json_entries():
155 return True
156
157 if install_missing_deps():
Paul Lewisd9039092019-11-27 17:06:23 +0000158 return True
159
160 # Run the CI version of npm, which prevents updates to the versions of modules.
Paul Lewis66e12062019-12-02 12:04:54 +0000161 if exec_command(['npm', 'ci']):
Yang Guo4fd355c2019-09-19 10:59:03 +0200162 return True
163
Paul Lewis66e12062019-12-02 12:04:54 +0000164 if strip_private_fields():
Paul Lewis75090cf2019-10-25 14:13:11 +0100165 return True
166
Paul Lewis66e12062019-12-02 12:04:54 +0000167 return remove_package_json_entries()
Yang Guo4fd355c2019-09-19 10:59:03 +0200168
169
170npm_errors_found = install_deps()
171
172if npm_errors_found:
173 print('npm installation failed')
174else:
175 print('npm installation successful')