| 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 """Meta checkout manager supporting both Subversion and GIT. | 6 """Meta checkout manager supporting both Subversion and GIT. |
| 7 | 7 |
| 8 Files | 8 Files |
| 9 .gclient : Current client configuration, written by 'config' command. | 9 .gclient : Current client configuration, written by 'config' command. |
| 10 Format is a Python script defining 'solutions', a list whose | 10 Format is a Python script defining 'solutions', a list whose |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 self.parsed_url = None | 146 self.parsed_url = None |
| 147 # These 2 are only set in .gclient and not in DEPS files. | 147 # These 2 are only set in .gclient and not in DEPS files. |
| 148 self.safesync_url = safesync_url | 148 self.safesync_url = safesync_url |
| 149 self.custom_vars = custom_vars or {} | 149 self.custom_vars = custom_vars or {} |
| 150 self.custom_deps = custom_deps or {} | 150 self.custom_deps = custom_deps or {} |
| 151 self.deps_hooks = [] | 151 self.deps_hooks = [] |
| 152 self.dependencies = [] | 152 self.dependencies = [] |
| 153 self.deps_file = deps_file or self.DEPS_FILE | 153 self.deps_file = deps_file or self.DEPS_FILE |
| 154 # A cache of the files affected by the current operation, necessary for | 154 # A cache of the files affected by the current operation, necessary for |
| 155 # hooks. | 155 # hooks. |
| 156 self.file_list = [] | 156 self._file_list = [] |
| 157 # If it is not set to True, the dependency wasn't processed for its child | 157 # If it is not set to True, the dependency wasn't processed for its child |
| 158 # dependency, i.e. its DEPS wasn't read. | 158 # dependency, i.e. its DEPS wasn't read. |
| 159 self.deps_parsed = False | 159 self.deps_parsed = False |
| 160 # A direct reference is dependency that is referenced by a deps, deps_os or | 160 # A direct reference is dependency that is referenced by a deps, deps_os or |
| 161 # solution. A indirect one is one that was loaded with From() or that | 161 # solution. A indirect one is one that was loaded with From() or that |
| 162 # exceeded recursion limit. | 162 # exceeded recursion limit. |
| 163 self.direct_reference = False | 163 self.direct_reference = False |
| 164 | 164 |
| 165 # Sanity checks | 165 # Sanity checks |
| 166 if not self.name and self.parent: | 166 if not self.name and self.parent: |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 raise | 297 raise |
| 298 self.dependencies.append(Dependency(self, name, url)) | 298 self.dependencies.append(Dependency(self, name, url)) |
| 299 # Sort by name. | 299 # Sort by name. |
| 300 self.dependencies.sort(key=lambda x: x.name) | 300 self.dependencies.sort(key=lambda x: x.name) |
| 301 logging.info('Loaded: %s' % str(self)) | 301 logging.info('Loaded: %s' % str(self)) |
| 302 | 302 |
| 303 def RunCommandRecursively(self, options, revision_overrides, | 303 def RunCommandRecursively(self, options, revision_overrides, |
| 304 command, args, pm): | 304 command, args, pm): |
| 305 """Runs 'command' before parsing the DEPS in case it's a initial checkout | 305 """Runs 'command' before parsing the DEPS in case it's a initial checkout |
| 306 or a revert.""" | 306 or a revert.""" |
| 307 assert self.file_list == [] | 307 assert self._file_list == [] |
| 308 # When running runhooks, there's no need to consult the SCM. | 308 # When running runhooks, there's no need to consult the SCM. |
| 309 # All known hooks are expected to run unconditionally regardless of working | 309 # All known hooks are expected to run unconditionally regardless of working |
| 310 # copy state, so skip the SCM status check. | 310 # copy state, so skip the SCM status check. |
| 311 run_scm = command not in ('runhooks', None) | 311 run_scm = command not in ('runhooks', None) |
| 312 self.LateOverride(self.url) | 312 self.LateOverride(self.url) |
| 313 if run_scm and self.parsed_url: | 313 if run_scm and self.parsed_url: |
| 314 if isinstance(self.parsed_url, self.FileImpl): | 314 if isinstance(self.parsed_url, self.FileImpl): |
| 315 # Special support for single-file checkout. | 315 # Special support for single-file checkout. |
| 316 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): | 316 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): |
| 317 options.revision = self.parsed_url.GetRevision() | 317 options.revision = self.parsed_url.GetRevision() |
| 318 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), | 318 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), |
| 319 self.root_dir(), | 319 self.root_dir(), |
| 320 self.name) | 320 self.name) |
| 321 scm.RunCommand('updatesingle', options, | 321 scm.RunCommand('updatesingle', options, |
| 322 args + [self.parsed_url.GetFilename()], | 322 args + [self.parsed_url.GetFilename()], |
| 323 self.file_list) | 323 self._file_list) |
| 324 else: | 324 else: |
| 325 options.revision = revision_overrides.get(self.name) | 325 options.revision = revision_overrides.get(self.name) |
| 326 scm = gclient_scm.CreateSCM(self.parsed_url, self.root_dir(), self.name) | 326 scm = gclient_scm.CreateSCM(self.parsed_url, self.root_dir(), self.name) |
| 327 scm.RunCommand(command, options, args, self.file_list) | 327 scm.RunCommand(command, options, args, self._file_list) |
| 328 self.file_list = [os.path.join(self.name, f.strip()) | 328 self._file_list = [os.path.join(self.name, f.strip()) |
| 329 for f in self.file_list] | 329 for f in self._file_list] |
| 330 options.revision = None | 330 options.revision = None |
| 331 if pm: | 331 if pm: |
| 332 # The + 1 comes from the fact that .gclient is considered a step in | 332 # The + 1 comes from the fact that .gclient is considered a step in |
| 333 # itself, .i.e. this code is called one time for the .gclient. This is not | 333 # itself, .i.e. this code is called one time for the .gclient. This is not |
| 334 # conceptually correct but it simplifies code. | 334 # conceptually correct but it simplifies code. |
| 335 pm._total = len(self.tree(False)) + 1 | 335 pm._total = len(self.tree(False)) + 1 |
| 336 pm.update() | 336 pm.update() |
| 337 if self.recursion_limit(): | 337 if self.recursion_limit(): |
| 338 # Then we can parse the DEPS file. | 338 # Then we can parse the DEPS file. |
| 339 self.ParseDepsFile(True) | 339 self.ParseDepsFile(True) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 358 # that. | 358 # that. |
| 359 if (options.force or | 359 if (options.force or |
| 360 isinstance(self.parsed_url, self.FileImpl) or | 360 isinstance(self.parsed_url, self.FileImpl) or |
| 361 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or | 361 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or |
| 362 os.path.isdir(os.path.join(self.root_dir(), self.name, '.git'))): | 362 os.path.isdir(os.path.join(self.root_dir(), self.name, '.git'))): |
| 363 for hook_dict in self.deps_hooks: | 363 for hook_dict in self.deps_hooks: |
| 364 self._RunHookAction(hook_dict, []) | 364 self._RunHookAction(hook_dict, []) |
| 365 else: | 365 else: |
| 366 # TODO(phajdan.jr): We should know exactly when the paths are absolute. | 366 # TODO(phajdan.jr): We should know exactly when the paths are absolute. |
| 367 # Convert all absolute paths to relative. | 367 # Convert all absolute paths to relative. |
| 368 for i in range(len(self.file_list)): | 368 file_list = self.file_list() |
| 369 for i in range(len(file_list)): |
| 369 # It depends on the command being executed (like runhooks vs sync). | 370 # It depends on the command being executed (like runhooks vs sync). |
| 370 if not os.path.isabs(self.file_list[i]): | 371 if not os.path.isabs(file_list[i]): |
| 371 continue | 372 continue |
| 372 | 373 |
| 373 prefix = os.path.commonprefix([self.root_dir().lower(), | 374 prefix = os.path.commonprefix([self.root_dir().lower(), |
| 374 self.file_list[i].lower()]) | 375 file_list[i].lower()]) |
| 375 self.file_list[i] = self.file_list[i][len(prefix):] | 376 file_list[i] = file_list[i][len(prefix):] |
| 376 | 377 |
| 377 # Strip any leading path separators. | 378 # Strip any leading path separators. |
| 378 while (self.file_list[i].startswith('\\') or | 379 while (file_list[i].startswith('\\') or |
| 379 self.file_list[i].startswith('/')): | 380 file_list[i].startswith('/')): |
| 380 self.file_list[i] = self.file_list[i][1:] | 381 file_list[i] = file_list[i][1:] |
| 381 | 382 |
| 382 # Run hooks on the basis of whether the files from the gclient operation | 383 # Run hooks on the basis of whether the files from the gclient operation |
| 383 # match each hook's pattern. | 384 # match each hook's pattern. |
| 384 for hook_dict in self.deps_hooks: | 385 for hook_dict in self.deps_hooks: |
| 385 pattern = re.compile(hook_dict['pattern']) | 386 pattern = re.compile(hook_dict['pattern']) |
| 386 matching_file_list = [f for f in self.file_list if pattern.search(f)] | 387 matching_file_list = [f for f in file_list if pattern.search(f)] |
| 387 if matching_file_list: | 388 if matching_file_list: |
| 388 self._RunHookAction(hook_dict, matching_file_list) | 389 self._RunHookAction(hook_dict, matching_file_list) |
| 389 if self.recursion_limit(): | 390 if self.recursion_limit(): |
| 390 for s in self.dependencies: | 391 for s in self.dependencies: |
| 391 s.RunHooksRecursively(options) | 392 s.RunHooksRecursively(options) |
| 392 | 393 |
| 393 def _RunHookAction(self, hook_dict, matching_file_list): | 394 def _RunHookAction(self, hook_dict, matching_file_list): |
| 394 """Runs the action from a single hook.""" | 395 """Runs the action from a single hook.""" |
| 395 logging.info(hook_dict) | 396 logging.info(hook_dict) |
| 396 logging.info(matching_file_list) | 397 logging.info(matching_file_list) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 result.extend(d.subtree(force_all)) | 433 result.extend(d.subtree(force_all)) |
| 433 return result | 434 return result |
| 434 | 435 |
| 435 def get_custom_deps(self, name, url): | 436 def get_custom_deps(self, name, url): |
| 436 """Returns a custom deps if applicable.""" | 437 """Returns a custom deps if applicable.""" |
| 437 if self.parent: | 438 if self.parent: |
| 438 url = self.parent.get_custom_deps(name, url) | 439 url = self.parent.get_custom_deps(name, url) |
| 439 # None is a valid return value to disable a dependency. | 440 # None is a valid return value to disable a dependency. |
| 440 return self.custom_deps.get(name, url) | 441 return self.custom_deps.get(name, url) |
| 441 | 442 |
| 443 def file_list(self): |
| 444 result = self._file_list[:] |
| 445 for d in self.dependencies: |
| 446 result.extend(d.file_list()) |
| 447 return result |
| 448 |
| 442 def __str__(self): | 449 def __str__(self): |
| 443 out = [] | 450 out = [] |
| 444 for i in ('name', 'url', 'safesync_url', 'custom_deps', 'custom_vars', | 451 for i in ('name', 'url', 'safesync_url', 'custom_deps', 'custom_vars', |
| 445 'deps_hooks', 'file_list'): | 452 'deps_hooks', '_file_list'): |
| 446 # 'deps_file' | 453 # 'deps_file' |
| 447 if self.__dict__[i]: | 454 if self.__dict__[i]: |
| 448 out.append('%s: %s' % (i, self.__dict__[i])) | 455 out.append('%s: %s' % (i, self.__dict__[i])) |
| 449 | 456 |
| 450 for d in self.dependencies: | 457 for d in self.dependencies: |
| 451 out.extend([' ' + x for x in str(d).splitlines()]) | 458 out.extend([' ' + x for x in str(d).splitlines()]) |
| 452 out.append('') | 459 out.append('') |
| 453 return '\n'.join(out) | 460 return '\n'.join(out) |
| 454 | 461 |
| 455 def __repr__(self): | 462 def __repr__(self): |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 return CMDhelp(parser, argv) | 1158 return CMDhelp(parser, argv) |
| 1152 except gclient_utils.Error, e: | 1159 except gclient_utils.Error, e: |
| 1153 print >> sys.stderr, 'Error: %s' % str(e) | 1160 print >> sys.stderr, 'Error: %s' % str(e) |
| 1154 return 1 | 1161 return 1 |
| 1155 | 1162 |
| 1156 | 1163 |
| 1157 if '__main__' == __name__: | 1164 if '__main__' == __name__: |
| 1158 sys.exit(Main(sys.argv[1:])) | 1165 sys.exit(Main(sys.argv[1:])) |
| 1159 | 1166 |
| 1160 # vim: ts=2:sw=2:tw=80:et: | 1167 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |