OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """A wrapper script to manage a set of client modules in different SCM. | 6 """A wrapper script to manage a set of client modules in different SCM. |
7 | 7 |
8 This script is intended to be used to help basic management of client | 8 This script is intended to be used to help basic management of client |
9 program sources residing in one or more Subversion modules and Git | 9 program sources residing in one or more Subversion modules and Git |
10 repositories, along with other modules it depends on, also in Subversion or Git, | 10 repositories, along with other modules it depends on, also in Subversion or Git, |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 scope = {} | 421 scope = {} |
422 filename = os.path.join(self._root_dir, self._options.entries_filename) | 422 filename = os.path.join(self._root_dir, self._options.entries_filename) |
423 if not os.path.exists(filename): | 423 if not os.path.exists(filename): |
424 return [] | 424 return [] |
425 exec(gclient_utils.FileRead(filename), scope) | 425 exec(gclient_utils.FileRead(filename), scope) |
426 return scope["entries"] | 426 return scope["entries"] |
427 | 427 |
428 class FromImpl: | 428 class FromImpl: |
429 """Used to implement the From syntax.""" | 429 """Used to implement the From syntax.""" |
430 | 430 |
431 def __init__(self, module_name): | 431 def __init__(self, module_name, sub_target_name=None): |
| 432 """module_name is the dep module we want to include from. It can also be |
| 433 the name of a subdirectory to include from. |
| 434 |
| 435 sub_target_name is an optional parameter if the module name in the other |
| 436 DEPS file is different. E.g., you might want to map src/net to net.""" |
432 self.module_name = module_name | 437 self.module_name = module_name |
| 438 self.sub_target_name = sub_target_name |
433 | 439 |
434 def __str__(self): | 440 def __str__(self): |
435 return 'From("%s")' % self.module_name | 441 return 'From(%s, %s)' % (repr(self.module_name), |
| 442 repr(self.sub_target_name)) |
| 443 |
| 444 def GetUrl(self, target_name, sub_deps_base_url, root_dir, sub_deps): |
| 445 """Resolve the URL for this From entry.""" |
| 446 sub_deps_target_name = target_name |
| 447 if self.sub_target_name: |
| 448 sub_deps_target_name = self.sub_target_name |
| 449 url = sub_deps[sub_deps_target_name] |
| 450 if url.startswith('/'): |
| 451 # If it's a relative URL, we need to resolve the URL relative to the |
| 452 # sub deps base URL. |
| 453 if not isinstance(sub_deps_base_url, basestring): |
| 454 sub_deps_base_url = sub_deps_base_url.GetPath() |
| 455 scm = gclient_scm.CreateSCM(sub_deps_base_url, root_dir, |
| 456 None) |
| 457 url = scm.FullUrlForRelativeUrl(url) |
| 458 return url |
436 | 459 |
437 class FileImpl: | 460 class FileImpl: |
438 """Used to implement the File('') syntax which lets you sync a single file | 461 """Used to implement the File('') syntax which lets you sync a single file |
439 from an SVN repo.""" | 462 from an SVN repo.""" |
440 | 463 |
441 def __init__(self, file_location): | 464 def __init__(self, file_location): |
442 self.file_location = file_location | 465 self.file_location = file_location |
443 | 466 |
444 def __str__(self): | 467 def __str__(self): |
445 return 'File("%s")' % self.file_location | 468 return 'File("%s")' % self.file_location |
(...skipping 18 matching lines...) Expand all Loading... |
464 | 487 |
465 def Lookup(self, var_name): | 488 def Lookup(self, var_name): |
466 """Implements the Var syntax.""" | 489 """Implements the Var syntax.""" |
467 if var_name in self._custom_vars: | 490 if var_name in self._custom_vars: |
468 return self._custom_vars[var_name] | 491 return self._custom_vars[var_name] |
469 elif var_name in self._local_scope.get("vars", {}): | 492 elif var_name in self._local_scope.get("vars", {}): |
470 return self._local_scope["vars"][var_name] | 493 return self._local_scope["vars"][var_name] |
471 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 494 raise gclient_utils.Error("Var is not defined: %s" % var_name) |
472 | 495 |
473 def _ParseSolutionDeps(self, solution_name, solution_deps_content, | 496 def _ParseSolutionDeps(self, solution_name, solution_deps_content, |
474 custom_vars): | 497 custom_vars, parse_hooks): |
475 """Parses the DEPS file for the specified solution. | 498 """Parses the DEPS file for the specified solution. |
476 | 499 |
477 Args: | 500 Args: |
478 solution_name: The name of the solution to query. | 501 solution_name: The name of the solution to query. |
479 solution_deps_content: Content of the DEPS file for the solution | 502 solution_deps_content: Content of the DEPS file for the solution |
480 custom_vars: A dict of vars to override any vars defined in the DEPS file. | 503 custom_vars: A dict of vars to override any vars defined in the DEPS file. |
481 | 504 |
482 Returns: | 505 Returns: |
483 A dict mapping module names (as relative paths) to URLs or an empty | 506 A dict mapping module names (as relative paths) to URLs or an empty |
484 dict if the solution does not have a DEPS file. | 507 dict if the solution does not have a DEPS file. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 os_deps = local_scope["deps_os"].get(deps_os_key, {}) | 547 os_deps = local_scope["deps_os"].get(deps_os_key, {}) |
525 if len(deps_to_include) > 1: | 548 if len(deps_to_include) > 1: |
526 # Ignore any overrides when including deps for more than one | 549 # Ignore any overrides when including deps for more than one |
527 # platform, so we collect the broadest set of dependencies available. | 550 # platform, so we collect the broadest set of dependencies available. |
528 # We may end up with the wrong revision of something for our | 551 # We may end up with the wrong revision of something for our |
529 # platform, but this is the best we can do. | 552 # platform, but this is the best we can do. |
530 deps.update([x for x in os_deps.items() if not x[0] in deps]) | 553 deps.update([x for x in os_deps.items() if not x[0] in deps]) |
531 else: | 554 else: |
532 deps.update(os_deps) | 555 deps.update(os_deps) |
533 | 556 |
534 if 'hooks' in local_scope: | 557 if 'hooks' in local_scope and parse_hooks: |
535 self._deps_hooks.extend(local_scope['hooks']) | 558 self._deps_hooks.extend(local_scope['hooks']) |
536 | 559 |
537 # If use_relative_paths is set in the DEPS file, regenerate | 560 # If use_relative_paths is set in the DEPS file, regenerate |
538 # the dictionary using paths relative to the directory containing | 561 # the dictionary using paths relative to the directory containing |
539 # the DEPS file. | 562 # the DEPS file. |
540 if local_scope.get('use_relative_paths'): | 563 if local_scope.get('use_relative_paths'): |
541 rel_deps = {} | 564 rel_deps = {} |
542 for d, url in deps.items(): | 565 for d, url in deps.items(): |
543 # normpath is required to allow DEPS to use .. in their | 566 # normpath is required to allow DEPS to use .. in their |
544 # dependency local path. | 567 # dependency local path. |
(...skipping 18 matching lines...) Expand all Loading... |
563 | 586 |
564 Raises: | 587 Raises: |
565 Error: If a dependency conflicts with another dependency or of a solution. | 588 Error: If a dependency conflicts with another dependency or of a solution. |
566 """ | 589 """ |
567 deps = {} | 590 deps = {} |
568 for solution in self.GetVar("solutions"): | 591 for solution in self.GetVar("solutions"): |
569 custom_vars = solution.get("custom_vars", {}) | 592 custom_vars = solution.get("custom_vars", {}) |
570 solution_deps = self._ParseSolutionDeps( | 593 solution_deps = self._ParseSolutionDeps( |
571 solution["name"], | 594 solution["name"], |
572 solution_deps_content[solution["name"]], | 595 solution_deps_content[solution["name"]], |
573 custom_vars) | 596 custom_vars, |
| 597 True) |
574 | 598 |
575 # If a line is in custom_deps, but not in the solution, we want to append | 599 # If a line is in custom_deps, but not in the solution, we want to append |
576 # this line to the solution. | 600 # this line to the solution. |
577 if "custom_deps" in solution: | 601 if "custom_deps" in solution: |
578 for d in solution["custom_deps"]: | 602 for d in solution["custom_deps"]: |
579 if d not in solution_deps: | 603 if d not in solution_deps: |
580 solution_deps[d] = solution["custom_deps"][d] | 604 solution_deps[d] = solution["custom_deps"][d] |
581 | 605 |
582 for d in solution_deps: | 606 for d in solution_deps: |
583 if "custom_deps" in solution and d in solution["custom_deps"]: | 607 if "custom_deps" in solution and d in solution["custom_deps"]: |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 if command == 'update' and not self._options.verbose: | 796 if command == 'update' and not self._options.verbose: |
773 pm.end() | 797 pm.end() |
774 | 798 |
775 # Second pass for inherited deps (via the From keyword) | 799 # Second pass for inherited deps (via the From keyword) |
776 for d in deps_to_process: | 800 for d in deps_to_process: |
777 if isinstance(deps[d], self.FromImpl): | 801 if isinstance(deps[d], self.FromImpl): |
778 filename = os.path.join(self._root_dir, | 802 filename = os.path.join(self._root_dir, |
779 deps[d].module_name, | 803 deps[d].module_name, |
780 self._options.deps_file) | 804 self._options.deps_file) |
781 content = gclient_utils.FileRead(filename) | 805 content = gclient_utils.FileRead(filename) |
782 sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {}) | 806 sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {}, |
783 url = sub_deps[d] | 807 False) |
| 808 # Getting the URL from the sub_deps file can involve having to resolve |
| 809 # a File() or having to resolve a relative URL. To resolve relative |
| 810 # URLs, we need to pass in the orignal sub deps URL. |
| 811 sub_deps_base_url = deps[deps[d].module_name] |
| 812 url = deps[d].GetUrl(d, sub_deps_base_url, self._root_dir, sub_deps) |
784 entries[d] = url | 813 entries[d] = url |
785 if run_scm: | 814 if run_scm: |
786 self._options.revision = revision_overrides.get(d) | 815 self._options.revision = revision_overrides.get(d) |
787 scm = gclient_scm.CreateSCM(url, self._root_dir, d) | 816 scm = gclient_scm.CreateSCM(url, self._root_dir, d) |
788 scm.RunCommand(command, self._options, args, file_list) | 817 scm.RunCommand(command, self._options, args, file_list) |
789 self._options.revision = None | 818 self._options.revision = None |
790 | 819 |
791 # Convert all absolute paths to relative. | 820 # Convert all absolute paths to relative. |
792 for i in range(len(file_list)): | 821 for i in range(len(file_list)): |
793 # TODO(phajdan.jr): We should know exactly when the paths are absolute. | 822 # TODO(phajdan.jr): We should know exactly when the paths are absolute. |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 | 1321 |
1293 if "__main__" == __name__: | 1322 if "__main__" == __name__: |
1294 try: | 1323 try: |
1295 result = Main(sys.argv) | 1324 result = Main(sys.argv) |
1296 except gclient_utils.Error, e: | 1325 except gclient_utils.Error, e: |
1297 print >> sys.stderr, "Error: %s" % str(e) | 1326 print >> sys.stderr, "Error: %s" % str(e) |
1298 result = 1 | 1327 result = 1 |
1299 sys.exit(result) | 1328 sys.exit(result) |
1300 | 1329 |
1301 # vim: ts=2:sw=2:tw=80:et: | 1330 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |