| 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 |