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