Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: ensure_dependencies.py

Issue 29526588: Issue 5559 - include Node.js in ensure_dependencies.py (Closed)
Patch Set: Refactoring according to new integration notes Created Aug. 25, 2017, 9:50 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 # This Source Code Form is subject to the terms of the Mozilla Public 3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 6
7 import sys 7 import sys
8 import os 8 import os
9 import posixpath 9 import posixpath
10 import re 10 import re
11 import io 11 import io
12 import errno 12 import errno
13 import logging 13 import logging
14 import subprocess 14 import subprocess
15 import urlparse 15 import urlparse
16 import argparse 16 import argparse
17 import json
17 18
18 from collections import OrderedDict 19 from collections import OrderedDict
19 from ConfigParser import RawConfigParser 20 from ConfigParser import RawConfigParser
20 21
21 USAGE = ''' 22 USAGE = '''
22 A dependencies file should look like this: 23 A dependencies file should look like this:
23 24
24 # VCS-specific root URLs for the repositories 25 # VCS-specific root URLs for the repositories
25 _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/ 26 _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/
26 # File to update this script from (optional) 27 # File to update this script from (optional)
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 return os.path.join(path, *normpath.split(posixpath.sep)) 239 return os.path.join(path, *normpath.split(posixpath.sep))
239 240
240 241
241 def get_repo_type(repo): 242 def get_repo_type(repo):
242 for name, repotype in repo_types.iteritems(): 243 for name, repotype in repo_types.iteritems():
243 if repotype.istype(repo): 244 if repotype.istype(repo):
244 return name 245 return name
245 return 'hg' 246 return 'hg'
246 247
247 248
249 def resolve_npm_dependencies(target, vcs):
250 """Install Node.js production-only dependencies if necessary and desired.
251
252 When the target dependency has additional Node.js dependencies declared
253 run "npm install --only=production --loglevel=warn" to resolve the declared
254 dependencies.
255
256 Additionally, make sure that any VCS will ignore the installed files.
257
258 Requires Node.js to be installed locally.
259 """
260 try:
261 with open(os.path.join(target, 'package.json'), 'r') as fp:
262 package_data = json.load(fp)
263
264 # In case a package.json does not exist at all or if there are no
265 # production dependencies declared, we don't need to run npm and can
266 # bail out early
267 if not package_data.get('dependencies', False):
268 return
269 except IOError:
270 return
271
272 try:
273 cmd = ['npm', 'install', '--only=production', '--loglevel=warn']
274 subprocess.check_output(cmd, cwd=target)
275
276 # Make sure Node.js related files / folders are ignored by the VCS in
277 # use
278 repo_types[vcs].ignore(
279 os.path.join(target, 'node_modules'), target
280 )
281 except OSError as e:
282 import errno
283 if e.errno == errno.ENOENT:
284 logging.error('Failed to install Node.js dependencies for %s,'
285 ' please ensure Node.js is installed.', target)
286 else:
287 raise
288
289
248 def ensure_repo(parentrepo, parenttype, target, type, root, sourcename): 290 def ensure_repo(parentrepo, parenttype, target, type, root, sourcename):
249 if os.path.exists(target): 291 if os.path.exists(target):
250 return 292 return
251 293
252 if SKIP_DEPENDENCY_UPDATES: 294 if SKIP_DEPENDENCY_UPDATES:
253 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, ' 295 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, '
254 '%s not cloned', target) 296 '%s not cloned', target)
255 return 297 return
256 298
257 postprocess_url = repo_types[type].postprocess_url 299 postprocess_url = repo_types[type].postprocess_url
258 root = postprocess_url(root) 300 root = postprocess_url(root)
259 sourcename = postprocess_url(sourcename) 301 sourcename = postprocess_url(sourcename)
260 302
261 if os.path.exists(root): 303 if os.path.exists(root):
262 url = os.path.join(root, sourcename) 304 url = os.path.join(root, sourcename)
263 else: 305 else:
264 url = urlparse.urljoin(root, sourcename) 306 url = urlparse.urljoin(root, sourcename)
265 307
266 logging.info('Cloning repository %s into %s' % (url, target)) 308 logging.info('Cloning repository %s into %s' % (url, target))
267 repo_types[type].clone(url, target) 309 repo_types[type].clone(url, target)
268 repo_types[parenttype].ignore(target, parentrepo) 310 repo_types[parenttype].ignore(target, parentrepo)
311 resolve_npm_dependencies(target, type)
269 312
270 313
271 def update_repo(target, type, revision): 314 def update_repo(target, type, revision):
272 resolved_revision = repo_types[type].get_revision_id(target, revision) 315 resolved_revision = repo_types[type].get_revision_id(target, revision)
273 current_revision = repo_types[type].get_revision_id(target) 316 current_revision = repo_types[type].get_revision_id(target)
274 317
275 if resolved_revision != current_revision: 318 if resolved_revision != current_revision:
276 if SKIP_DEPENDENCY_UPDATES: 319 if SKIP_DEPENDENCY_UPDATES:
277 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, ' 320 logging.warning('SKIP_DEPENDENCY_UPDATES environment variable set, '
278 '%s not checked out to %s', target, revision) 321 '%s not checked out to %s', target, revision)
279 return 322 return
280 323
281 if not resolved_revision: 324 if not resolved_revision:
282 logging.info('Revision %s is unknown, downloading remote changes' % revision) 325 logging.info('Revision %s is unknown, downloading remote changes' % revision)
283 repo_types[type].pull(target) 326 repo_types[type].pull(target)
284 resolved_revision = repo_types[type].get_revision_id(target, revisio n) 327 resolved_revision = repo_types[type].get_revision_id(target, revisio n)
285 if not resolved_revision: 328 if not resolved_revision:
286 raise Exception('Failed to resolve revision %s' % revision) 329 raise Exception('Failed to resolve revision %s' % revision)
287 330
288 logging.info('Updating repository %s to revision %s' % (target, resolved _revision)) 331 logging.info('Updating repository %s to revision %s' % (target, resolved _revision))
289 repo_types[type].update(target, resolved_revision, revision) 332 repo_types[type].update(target, resolved_revision, revision)
333 resolve_npm_dependencies(target, type)
Wladimir Palant 2017/08/25 10:01:59 For Mercurial repositories, both cloning and updat
tlucas 2017/08/25 10:06:40 Done.
290 334
291 335
292 def resolve_deps(repodir, level=0, self_update=True, overrideroots=None, skipdep endencies=set()): 336 def resolve_deps(repodir, level=0, self_update=True, overrideroots=None, skipdep endencies=set()):
293 config = read_deps(repodir) 337 config = read_deps(repodir)
294 if config is None: 338 if config is None:
295 if level == 0: 339 if level == 0:
296 logging.warning('No dependencies file in directory %s, nothing to do ...\n%s' % (repodir, USAGE)) 340 logging.warning('No dependencies file in directory %s, nothing to do ...\n%s' % (repodir, USAGE))
297 return 341 return
298 if level >= 10: 342 if level >= 10:
299 logging.warning('Too much subrepository nesting, ignoring %s' % repo) 343 logging.warning('Too much subrepository nesting, ignoring %s' % repo)
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 args = parser.parse_args() 415 args = parser.parse_args()
372 416
373 if args.quiet: 417 if args.quiet:
374 logging.disable(logging.INFO) 418 logging.disable(logging.INFO)
375 419
376 repos = args.repos 420 repos = args.repos
377 if not len(repos): 421 if not len(repos):
378 repos = [os.path.dirname(__file__)] 422 repos = [os.path.dirname(__file__)]
379 for repo in repos: 423 for repo in repos:
380 resolve_deps(repo) 424 resolve_deps(repo)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld