Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 """Meta checkout manager supporting both Subversion and GIT.""" | 6 """Meta checkout manager supporting both Subversion and GIT.""" |
| 7 # Files | 7 # Files |
| 8 # .gclient : Current client configuration, written by 'config' command. | 8 # .gclient : Current client configuration, written by 'config' command. |
| 9 # Format is a Python script defining 'solutions', a list whose | 9 # Format is a Python script defining 'solutions', a list whose |
| 10 # entries each are maps binding the strings "name" and "url" | 10 # entries each are maps binding the strings "name" and "url" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 import fix_encoding | 97 import fix_encoding |
| 98 import gclient_scm | 98 import gclient_scm |
| 99 import gclient_utils | 99 import gclient_utils |
| 100 from third_party.repo.progress import Progress | 100 from third_party.repo.progress import Progress |
| 101 import subcommand | 101 import subcommand |
| 102 import subprocess2 | 102 import subprocess2 |
| 103 from third_party import colorama | 103 from third_party import colorama |
| 104 | 104 |
| 105 | 105 |
| 106 class GClientKeywords(object): | 106 class GClientKeywords(object): |
| 107 class FromImpl(object): | 107 class FromImpl(gclient_utils.BaseRecord): |
| 108 """Used to implement the From() syntax.""" | 108 """Used to implement the From() syntax.""" |
| 109 | 109 |
| 110 def __init__(self, module_name, sub_target_name=None): | 110 def __init__(self, module_name, sub_target_name=None): |
| 111 """module_name is the dep module we want to include from. It can also be | 111 """module_name is the dep module we want to include from. It can also be |
| 112 the name of a subdirectory to include from. | 112 the name of a subdirectory to include from. |
| 113 | 113 |
| 114 sub_target_name is an optional parameter if the module name in the other | 114 sub_target_name is an optional parameter if the module name in the other |
| 115 DEPS file is different. E.g., you might want to map src/net to net.""" | 115 DEPS file is different. E.g., you might want to map src/net to net.""" |
| 116 self.module_name = module_name | 116 self.module_name = module_name |
| 117 self.sub_target_name = sub_target_name | 117 self.sub_target_name = sub_target_name |
| 118 | 118 |
| 119 def __str__(self): | 119 def __str__(self): |
| 120 return 'From(%s, %s)' % (repr(self.module_name), | 120 return 'From(%s, %s)' % (repr(self.module_name), |
| 121 repr(self.sub_target_name)) | 121 repr(self.sub_target_name)) |
| 122 | 122 |
| 123 class FileImpl(object): | 123 class FileImpl(gclient_utils.BaseRecord): |
| 124 """Used to implement the File('') syntax which lets you sync a single file | 124 """Used to implement the File('') syntax which lets you sync a single file |
| 125 from a SVN repo.""" | 125 from a SVN repo.""" |
| 126 | 126 |
| 127 def __init__(self, file_location): | 127 def __init__(self, file_location): |
| 128 self.file_location = file_location | 128 self.file_location = file_location |
| 129 | 129 |
| 130 def __str__(self): | 130 def __str__(self): |
| 131 return 'File("%s")' % self.file_location | 131 return 'File("%s")' % self.file_location |
| 132 | 132 |
| 133 def GetPath(self): | 133 def GetPath(self): |
| 134 return os.path.split(self.file_location)[0] | 134 return os.path.split(self.file_location)[0] |
| 135 | 135 |
| 136 def GetFilename(self): | 136 def GetFilename(self): |
| 137 rev_tokens = self.file_location.split('@') | 137 rev_tokens = self.file_location.split('@') |
| 138 return os.path.split(rev_tokens[0])[1] | 138 return os.path.split(rev_tokens[0])[1] |
| 139 | 139 |
| 140 def GetRevision(self): | 140 def GetRevision(self): |
| 141 rev_tokens = self.file_location.split('@') | 141 rev_tokens = self.file_location.split('@') |
| 142 if len(rev_tokens) > 1: | 142 if len(rev_tokens) > 1: |
| 143 return rev_tokens[1] | 143 return rev_tokens[1] |
| 144 return None | 144 return None |
| 145 | 145 |
| 146 class VarImpl(object): | 146 class VarImpl(gclient_utils.BaseRecord): |
| 147 def __init__(self, custom_vars, local_scope): | 147 def __init__(self, custom_vars, local_scope): |
| 148 self._custom_vars = custom_vars | 148 self._custom_vars = custom_vars |
| 149 self._local_scope = local_scope | 149 self._local_scope = local_scope |
| 150 | 150 |
| 151 def Lookup(self, var_name): | 151 def Lookup(self, var_name): |
| 152 """Implements the Var syntax.""" | 152 """Implements the Var syntax.""" |
| 153 if var_name in self._custom_vars: | 153 if var_name in self._custom_vars: |
| 154 return self._custom_vars[var_name] | 154 return self._custom_vars[var_name] |
| 155 elif var_name in self._local_scope.get("vars", {}): | 155 elif var_name in self._local_scope.get("vars", {}): |
| 156 return self._local_scope["vars"][var_name] | 156 return self._local_scope["vars"][var_name] |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 return url | 465 return url |
| 466 | 466 |
| 467 raise gclient_utils.Error('Unknown url type') | 467 raise gclient_utils.Error('Unknown url type') |
| 468 | 468 |
| 469 @staticmethod | 469 @staticmethod |
| 470 def MergeWithOsDeps(deps, deps_os, target_os_list): | 470 def MergeWithOsDeps(deps, deps_os, target_os_list): |
| 471 """Returns a new "deps" structure that is the deps sent in updated | 471 """Returns a new "deps" structure that is the deps sent in updated |
| 472 with information from deps_os (the deps_os section of the DEPS | 472 with information from deps_os (the deps_os section of the DEPS |
| 473 file) that matches the list of target os.""" | 473 file) that matches the list of target os.""" |
| 474 os_overrides = {} | 474 os_overrides = {} |
| 475 for the_target_os in target_os_list: | 475 # Sort target_os_list to ensure consistent conflict resolution. |
| 476 for the_target_os in sorted(target_os_list): | |
| 476 the_target_os_deps = deps_os.get(the_target_os, {}) | 477 the_target_os_deps = deps_os.get(the_target_os, {}) |
| 477 for os_dep_key, os_dep_value in the_target_os_deps.iteritems(): | 478 for os_dep_key, os_dep_value in the_target_os_deps.iteritems(): |
| 478 overrides = os_overrides.setdefault(os_dep_key, []) | 479 overrides = os_overrides.setdefault(os_dep_key, []) |
| 479 overrides.append((the_target_os, os_dep_value)) | 480 overrides.append((the_target_os, os_dep_value)) |
| 480 | 481 |
| 481 # If any os didn't specify a value (we have fewer value entries | |
| 482 # than in the os list), then it wants to use the default value. | |
| 483 for os_dep_key, os_dep_value in os_overrides.iteritems(): | |
| 484 if len(os_dep_value) != len(target_os_list): | |
| 485 # Record the default value too so that we don't accidently | |
| 486 # set it to None or miss a conflicting DEPS. | |
| 487 if os_dep_key in deps: | |
| 488 os_dep_value.append(('default', deps[os_dep_key])) | |
| 489 | |
| 490 target_os_deps = {} | 482 target_os_deps = {} |
| 491 for os_dep_key, os_dep_value in os_overrides.iteritems(): | 483 for os_dep_key, os_dep_values in os_overrides.iteritems(): |
| 492 # os_dep_value is a list of (os, value) pairs. | 484 # If any os didn't specify a value (we have fewer value entries |
| 493 possible_values = set(x[1] for x in os_dep_value if x[1] is not None) | 485 # than in the os list), then it wants to use the default value. |
| 494 if not possible_values: | 486 # We preferentially use default os val during conflicts. |
| 495 target_os_deps[os_dep_key] = None | 487 if len(os_dep_values) < len(target_os_list): |
| 496 else: | 488 os_dep_values.append(('default', deps.get(os_dep_key))) |
| 497 if len(possible_values) > 1: | 489 if len(set(val for _, val in os_dep_values if val is not None)) > 1: |
| 498 # It would be possible to abort here but it would be | 490 # It would be possible to abort here but it would be |
| 499 # unfortunate if we end up preventing any kind of checkout. | 491 # unfortunate if we end up preventing any kind of checkout. |
| 500 logging.error('Conflicting dependencies for %s: %s. (target_os=%s)', | 492 logging.error('Conflicting dependencies for %s: %s. (target_os=%s)', |
| 501 os_dep_key, os_dep_value, target_os_list) | 493 os_dep_key, os_dep_values, target_os_list) |
| 502 # Sorting to get the same result every time in case of conflicts. | 494 # Find the last non-None val, if it exists. |
| 503 target_os_deps[os_dep_key] = sorted(possible_values)[0] | 495 for _, val in reversed(os_dep_values): |
| 504 | 496 if val is not None: |
| 505 new_deps = deps.copy() | 497 break |
| 506 new_deps.update(target_os_deps) | 498 target_os_deps[os_dep_key] = val |
| 507 return new_deps | 499 return dict(deps, **target_os_deps) |
|
Daniel Bratell
2013/12/17 08:38:19
My pylint (not the one bundled) is noisily unhappy
| |
| 508 | 500 |
| 509 def ParseDepsFile(self): | 501 def ParseDepsFile(self): |
| 510 """Parses the DEPS file for this dependency.""" | 502 """Parses the DEPS file for this dependency.""" |
| 511 assert not self.deps_parsed | 503 assert not self.deps_parsed |
| 512 assert not self.dependencies | 504 assert not self.dependencies |
| 513 # One thing is unintuitive, vars = {} must happen before Var() use. | 505 # One thing is unintuitive, vars = {} must happen before Var() use. |
| 514 local_scope = {} | 506 local_scope = {} |
| 515 var = self.VarImpl(self.custom_vars, local_scope) | 507 var = self.VarImpl(self.custom_vars, local_scope) |
| 516 global_scope = { | 508 global_scope = { |
| 517 'File': self.FileImpl, | 509 'File': self.FileImpl, |
| (...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1916 raise | 1908 raise |
| 1917 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1909 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
| 1918 print >> sys.stderr, 'Error: %s' % str(e) | 1910 print >> sys.stderr, 'Error: %s' % str(e) |
| 1919 return 1 | 1911 return 1 |
| 1920 | 1912 |
| 1921 | 1913 |
| 1922 if '__main__' == __name__: | 1914 if '__main__' == __name__: |
| 1923 sys.exit(Main(sys.argv[1:])) | 1915 sys.exit(Main(sys.argv[1:])) |
| 1924 | 1916 |
| 1925 # vim: ts=2:sw=2:tw=80:et: | 1917 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |