blob: ebdd0258c748d884dcc2aafe308fb07301767cbc [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",
28 "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 Lewis75090cf2019-10-25 14:13:11 +010032 "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 Lewis75090cf2019-10-25 14:13:11 +010037 "rollup": "^1.23.1",
Yang Guo4fd355c2019-09-19 10:59:03 +020038 "typescript": "3.5.3"
39}
40
41
42def popen(arguments, cwd=None):
43 return subprocess.Popen(arguments, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
44
45
46def clean_node_modules():
47 # Clean the node_modules folder first. That way only the packages listed above
48 # (and their deps) are installed.
49 try:
50 shutil.rmtree(path.realpath(devtools_paths.node_modules_path()))
51 except OSError as err:
52 print('Error removing node_modules: %s, %s' % (err.filename, err.strerror))
53
54
55def strip_private_fields():
56 # npm adds private fields which need to be stripped.
57 pattern = path.join(devtools_paths.node_modules_path(), 'package.json')
58 packages = []
59 for root, dirnames, filenames in os.walk(devtools_paths.node_modules_path()):
60 for filename in filter(lambda f: f == 'package.json', filenames):
61 packages.append(path.join(root, filename))
62
63 for pkg in packages:
64 with open(pkg, 'r+') as pkg_file:
65 prop_removal_count = 0
66 try:
67 pkg_data = json.load(pkg_file)
68
69 # Remove anything that begins with an underscore, as these are
70 # the private fields in a package.json
71 for key in pkg_data.keys():
72 if key.find(u'_') == 0:
73 pkg_data.pop(key)
74 prop_removal_count = prop_removal_count + 1
75
76 pkg_file.truncate(0)
77 pkg_file.seek(0)
78 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
79 print("(%s): %s" % (prop_removal_count, pkg))
80 except:
81 print('Unable to fix: %s' % pkg)
82 return True
83
84 return False
85
86
Paul Lewis75090cf2019-10-25 14:13:11 +010087def remove_package_json_entries():
88 with open(devtools_paths.package_json_path(), 'r+') as pkg_file:
89 try:
90 pkg_data = json.load(pkg_file)
91
92 # Remove the dependencies and devDependencies from the root package.json
93 # so that they can't be used to overwrite the node_modules managed by this file.
94 for key in pkg_data.keys():
95 if key.find(u'dependencies') == 0 or key.find(u'devDependencies') == 0:
96 pkg_data.pop(key)
97
98 pkg_file.truncate(0)
99 pkg_file.seek(0)
100 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
101 except:
102 print('Unable to fix: %s' % pkg)
103 return True
104 return False
105
106
Yang Guo4fd355c2019-09-19 10:59:03 +0200107def install_deps():
108 clean_node_modules()
109
Paul Lewis75090cf2019-10-25 14:13:11 +0100110 exec_command = ['npm', 'install', '--save-dev']
Yang Guo4fd355c2019-09-19 10:59:03 +0200111 for pkg, version in DEPS.items():
Paul Lewis75090cf2019-10-25 14:13:11 +0100112 # For git URLs we append the url rather than package@version, since the package@version
113 # formulation doesn't work.
114 if version.find(u'git+') == 0:
115 exec_command.append('%s' % version)
116 else:
117 exec_command.append('%s@%s' % (pkg, version))
Yang Guo4fd355c2019-09-19 10:59:03 +0200118
119 errors_found = False
120 npm_proc_result = subprocess.check_call(exec_command, cwd=devtools_paths.root_path())
121 if npm_proc_result != 0:
122 errors_found = True
123
124 # If npm fails, bail here, otherwise attempt to strip private fields.
125 if errors_found:
126 return True
127
128 errors_found = strip_private_fields()
Paul Lewis75090cf2019-10-25 14:13:11 +0100129 if errors_found:
130 return True
131
132 errors_found = remove_package_json_entries()
Yang Guo4fd355c2019-09-19 10:59:03 +0200133 return errors_found
134
135
136npm_errors_found = install_deps()
137
138if npm_errors_found:
139 print('npm installation failed')
140else:
141 print('npm installation successful')