OLD | NEW |
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 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 raise Exception('Dependency path %s cannot be absolute' % subpath) | 239 raise Exception('Dependency path %s cannot be absolute' % subpath) |
240 if normpath == posixpath.pardir or normpath.startswith(posixpath.pardir + po
sixpath.sep): | 240 if normpath == posixpath.pardir or normpath.startswith(posixpath.pardir + po
sixpath.sep): |
241 raise Exception('Dependency path %s has to be inside the repository' % s
ubpath) | 241 raise Exception('Dependency path %s has to be inside the repository' % s
ubpath) |
242 return os.path.join(path, *normpath.split(posixpath.sep)) | 242 return os.path.join(path, *normpath.split(posixpath.sep)) |
243 | 243 |
244 | 244 |
245 def get_repo_type(repo): | 245 def get_repo_type(repo): |
246 for name, repotype in repo_types.iteritems(): | 246 for name, repotype in repo_types.iteritems(): |
247 if repotype.istype(repo): | 247 if repotype.istype(repo): |
248 return name | 248 return name |
249 return 'hg' | 249 return None |
250 | 250 |
251 | 251 |
252 def resolve_npm_dependencies(target, vcs): | 252 def resolve_npm_dependencies(target, vcs): |
253 """Install Node.js production-only dependencies if necessary and desired. | 253 """Install Node.js production-only dependencies if necessary and desired. |
254 | 254 |
255 When the target dependency has additional Node.js dependencies declared | 255 When the target dependency has additional Node.js dependencies declared |
256 run "npm install --only=production --loglevel=warn" to resolve the declared | 256 run "npm install --only=production --loglevel=warn" to resolve the declared |
257 dependencies. | 257 dependencies. |
258 | 258 |
259 Additionally, make sure that any VCS will ignore the installed files. | 259 Additionally, make sure that any VCS will ignore the installed files. |
(...skipping 24 matching lines...) Expand all Loading... |
284 # Node.js only provides a npm.cmd, which is executable but won't | 284 # Node.js only provides a npm.cmd, which is executable but won't |
285 # be recognized as such by CreateProcess(). | 285 # be recognized as such by CreateProcess(). |
286 npm_exec = 'npm.cmd' | 286 npm_exec = 'npm.cmd' |
287 else: | 287 else: |
288 npm_exec = 'npm' | 288 npm_exec = 'npm' |
289 | 289 |
290 cmd = [npm_exec, 'install', '--only=production', '--loglevel=warn', | 290 cmd = [npm_exec, 'install', '--only=production', '--loglevel=warn', |
291 '--no-package-lock', '--no-optional'] | 291 '--no-package-lock', '--no-optional'] |
292 subprocess.check_output(cmd, cwd=target) | 292 subprocess.check_output(cmd, cwd=target) |
293 | 293 |
294 repo_types[vcs].ignore(os.path.join(target, NPM_LOCKFILE), target) | 294 if vcs: |
295 repo_types[vcs].ignore(os.path.join(target, 'node_modules'), target) | 295 repo_types[vcs].ignore(os.path.join(target, NPM_LOCKFILE), target) |
| 296 repo_types[vcs].ignore(os.path.join(target, 'node_modules'), target) |
296 | 297 |
297 os.remove(lockfile_path) | 298 os.remove(lockfile_path) |
298 except OSError as e: | 299 except OSError as e: |
299 import errno | 300 import errno |
300 if e.errno == errno.ENOENT: | 301 if e.errno == errno.ENOENT: |
301 logging.error('Failed to install Node.js dependencies for %s,' | 302 logging.error('Failed to install Node.js dependencies for %s,' |
302 ' please ensure Node.js is installed.', target) | 303 ' please ensure Node.js is installed.', target) |
303 else: | 304 else: |
304 raise | 305 raise |
305 | 306 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 resolved_revision = repo_types[type].get_revision_id(target, revisio
n) | 345 resolved_revision = repo_types[type].get_revision_id(target, revisio
n) |
345 if not resolved_revision: | 346 if not resolved_revision: |
346 raise Exception('Failed to resolve revision %s' % revision) | 347 raise Exception('Failed to resolve revision %s' % revision) |
347 | 348 |
348 logging.info('Updating repository %s to revision %s' % (target, resolved
_revision)) | 349 logging.info('Updating repository %s to revision %s' % (target, resolved
_revision)) |
349 repo_types[type].update(target, resolved_revision, revision) | 350 repo_types[type].update(target, resolved_revision, revision) |
350 return True | 351 return True |
351 return False | 352 return False |
352 | 353 |
353 | 354 |
354 def resolve_deps(repodir, level=0, self_update=True, overrideroots=None, skipdep
endencies=set()): | 355 def resolve_deps(repodir, repotype, level=0, self_update=True, |
| 356 overrideroots=None, skipdependencies=set()): |
355 config = read_deps(repodir) | 357 config = read_deps(repodir) |
356 if config is None: | 358 if config is None: |
357 if level == 0: | 359 if level == 0: |
358 logging.warning('No dependencies file in directory %s, nothing to do
...\n%s' % (repodir, USAGE)) | 360 logging.warning('No dependencies file in directory %s, nothing to do
...\n%s' % (repodir, USAGE)) |
359 return | 361 return |
360 if level >= 10: | 362 if level >= 10: |
361 logging.warning('Too much subrepository nesting, ignoring %s' % repo) | 363 logging.warning('Too much subrepository nesting, ignoring %s' % repo) |
362 return | 364 return |
363 | 365 |
364 if overrideroots is not None: | 366 if overrideroots is not None: |
365 config['_root'] = overrideroots | 367 config['_root'] = overrideroots |
366 | 368 |
367 for dir, sources in sorted(config.iteritems()): | 369 for dir, sources in sorted(config.iteritems()): |
368 if (dir.startswith('_') or | 370 if (dir.startswith('_') or |
369 skipdependencies.intersection([s[0] for s in sources if s[0]])): | 371 skipdependencies.intersection([s[0] for s in sources if s[0]])): |
370 continue | 372 continue |
371 | 373 |
372 target = safe_join(repodir, dir) | 374 target = safe_join(repodir, dir) |
373 parenttype = get_repo_type(repodir) | 375 parenttype = repotype or 'hg' |
374 _root = config.get('_root', {}) | 376 _root = config.get('_root', {}) |
375 | 377 |
376 for key in sources.keys() + _root.keys(): | 378 for key in sources.keys() + _root.keys(): |
377 if key == parenttype or key is None and vcs != '*': | 379 if key == parenttype or key is None and vcs != '*': |
378 vcs = key | 380 vcs = key |
379 source, rev = merge_seqs(sources.get('*'), sources.get(vcs)) | 381 source, rev = merge_seqs(sources.get('*'), sources.get(vcs)) |
380 | 382 |
381 if not (vcs and source and rev): | 383 if not (vcs and source and rev): |
382 logging.warning('No valid source / revision found to create %s' % ta
rget) | 384 logging.warning('No valid source / revision found to create %s' % ta
rget) |
383 continue | 385 continue |
384 | 386 |
385 repo_cloned = ensure_repo(repodir, parenttype, target, vcs, | 387 repo_cloned = ensure_repo(repodir, parenttype, target, vcs, |
386 _root.get(vcs, ''), source) | 388 _root.get(vcs, ''), source) |
387 repo_updated = update_repo(target, vcs, rev) | 389 if repo_types[vcs].istype(target): |
| 390 repo_updated = update_repo(target, vcs, rev) |
| 391 npm_outdated = repo_cloned or repo_updated |
| 392 else: |
| 393 vcs = None |
| 394 npm_outdated = not os.path.exists( |
| 395 os.path.join(target, 'node_modules'), |
| 396 ) |
| 397 |
388 recent_npm_failed = os.path.exists(os.path.join(target, NPM_LOCKFILE)) | 398 recent_npm_failed = os.path.exists(os.path.join(target, NPM_LOCKFILE)) |
389 if repo_cloned or repo_updated or recent_npm_failed: | 399 if npm_outdated or recent_npm_failed: |
390 resolve_npm_dependencies(target, vcs) | 400 resolve_npm_dependencies(target, vcs) |
391 resolve_deps(target, level + 1, self_update=False, | 401 |
| 402 resolve_deps(target, vcs, level + 1, self_update=False, |
392 overrideroots=overrideroots, skipdependencies=skipdependenc
ies) | 403 overrideroots=overrideroots, skipdependencies=skipdependenc
ies) |
393 | 404 |
394 if self_update and '_self' in config and '*' in config['_self']: | 405 if self_update and '_self' in config and '*' in config['_self']: |
395 source = safe_join(repodir, config['_self']['*']) | 406 source = safe_join(repodir, config['_self']['*']) |
396 try: | 407 try: |
397 with io.open(source, 'rb') as handle: | 408 with io.open(source, 'rb') as handle: |
398 sourcedata = handle.read() | 409 sourcedata = handle.read() |
399 except IOError as e: | 410 except IOError as e: |
400 if e.errno != errno.ENOENT: | 411 if e.errno != errno.ENOENT: |
401 raise | 412 raise |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 parser.add_argument('-q', '--quiet', action='store_true', help='Suppress inf
ormational output') | 448 parser.add_argument('-q', '--quiet', action='store_true', help='Suppress inf
ormational output') |
438 args = parser.parse_args() | 449 args = parser.parse_args() |
439 | 450 |
440 if args.quiet: | 451 if args.quiet: |
441 logging.disable(logging.INFO) | 452 logging.disable(logging.INFO) |
442 | 453 |
443 repos = args.repos | 454 repos = args.repos |
444 if not len(repos): | 455 if not len(repos): |
445 repos = [os.path.dirname(__file__)] | 456 repos = [os.path.dirname(__file__)] |
446 for repo in repos: | 457 for repo in repos: |
447 resolve_deps(repo) | 458 resolve_deps(repo, get_repo_type(repo)) |
OLD | NEW |