| 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 if not isinstance(self.url, | 175 if not isinstance(self.url, |
| 176 (basestring, self.FromImpl, self.FileImpl, None.__class__)): | 176 (basestring, self.FromImpl, self.FileImpl, None.__class__)): |
| 177 raise gclient_utils.Error('dependency url must be either a string, None, ' | 177 raise gclient_utils.Error('dependency url must be either a string, None, ' |
| 178 'File() or From() instead of %s' % | 178 'File() or From() instead of %s' % |
| 179 self.url.__class__.__name__) | 179 self.url.__class__.__name__) |
| 180 if '/' in self.deps_file or '\\' in self.deps_file: | 180 if '/' in self.deps_file or '\\' in self.deps_file: |
| 181 raise gclient_utils.Error('deps_file name must not be a path, just a ' | 181 raise gclient_utils.Error('deps_file name must not be a path, just a ' |
| 182 'filename. %s' % self.deps_file) | 182 'filename. %s' % self.deps_file) |
| 183 | 183 |
| 184 def LateOverride(self, url): | 184 def LateOverride(self, url): |
| 185 """Resolves the parsed url from url. |
| 186 |
| 187 Manages From() keyword accordingly. Do not touch self.parsed_url nor |
| 188 self.url because it may called with other urls due to From().""" |
| 185 overriden_url = self.get_custom_deps(self.name, url) | 189 overriden_url = self.get_custom_deps(self.name, url) |
| 186 if overriden_url != url: | 190 if overriden_url != url: |
| 187 self.parsed_url = overriden_url | |
| 188 logging.debug('%s, %s was overriden to %s' % (self.name, url, | 191 logging.debug('%s, %s was overriden to %s' % (self.name, url, |
| 189 self.parsed_url)) | 192 overriden_url)) |
| 193 return overriden_url |
| 190 elif isinstance(url, self.FromImpl): | 194 elif isinstance(url, self.FromImpl): |
| 191 ref = [dep for dep in self.tree(True) if url.module_name == dep.name] | 195 ref = [dep for dep in self.tree(True) if url.module_name == dep.name] |
| 192 if not len(ref) == 1: | 196 if not len(ref) == 1: |
| 193 raise Exception('Failed to find one reference to %s. %s' % ( | 197 raise Exception('Failed to find one reference to %s. %s' % ( |
| 194 url.module_name, ref)) | 198 url.module_name, ref)) |
| 195 ref = ref[0] | 199 ref = ref[0] |
| 196 sub_target = url.sub_target_name or self.name | 200 sub_target = url.sub_target_name or self.name |
| 197 # Make sure the referenced dependency DEPS file is loaded and file the | 201 # Make sure the referenced dependency DEPS file is loaded and file the |
| 198 # inner referenced dependency. | 202 # inner referenced dependency. |
| 199 ref.ParseDepsFile(False) | 203 ref.ParseDepsFile(False) |
| 200 found_dep = None | 204 found_dep = None |
| 201 for d in ref.dependencies: | 205 for d in ref.dependencies: |
| 202 if d.name == sub_target: | 206 if d.name == sub_target: |
| 203 found_dep = d | 207 found_dep = d |
| 204 break | 208 break |
| 205 if not found_dep: | 209 if not found_dep: |
| 206 raise Exception('Couldn\'t find %s in %s, referenced by %s' % ( | 210 raise Exception('Couldn\'t find %s in %s, referenced by %s' % ( |
| 207 sub_target, ref.name, self.name)) | 211 sub_target, ref.name, self.name)) |
| 208 # Call LateOverride() again. | 212 # Call LateOverride() again. |
| 209 self.parsed_url = found_dep.LateOverride(found_dep.url) | 213 parsed_url = found_dep.LateOverride(found_dep.url) |
| 210 logging.debug('%s, %s to %s' % (self.name, url, self.parsed_url)) | 214 logging.debug('%s, %s to %s' % (self.name, url, parsed_url)) |
| 215 return parsed_url |
| 211 elif isinstance(url, basestring): | 216 elif isinstance(url, basestring): |
| 212 parsed_url = urlparse.urlparse(url) | 217 parsed_url = urlparse.urlparse(url) |
| 213 if not parsed_url[0]: | 218 if not parsed_url[0]: |
| 214 # A relative url. Fetch the real base. | 219 # A relative url. Fetch the real base. |
| 215 path = parsed_url[2] | 220 path = parsed_url[2] |
| 216 if not path.startswith('/'): | 221 if not path.startswith('/'): |
| 217 raise gclient_utils.Error( | 222 raise gclient_utils.Error( |
| 218 'relative DEPS entry \'%s\' must begin with a slash' % url) | 223 'relative DEPS entry \'%s\' must begin with a slash' % url) |
| 219 # Create a scm just to query the full url. | 224 # Create a scm just to query the full url. |
| 220 parent_url = self.parent.parsed_url | 225 parent_url = self.parent.parsed_url |
| 221 if isinstance(parent_url, self.FileImpl): | 226 if isinstance(parent_url, self.FileImpl): |
| 222 parent_url = parent_url.file_location | 227 parent_url = parent_url.file_location |
| 223 scm = gclient_scm.CreateSCM(parent_url, self.root_dir(), None) | 228 scm = gclient_scm.CreateSCM(parent_url, self.root_dir(), None) |
| 224 self.parsed_url = scm.FullUrlForRelativeUrl(url) | 229 parsed_url = scm.FullUrlForRelativeUrl(url) |
| 225 else: | 230 else: |
| 226 self.parsed_url = url | 231 parsed_url = url |
| 227 logging.debug('%s, %s -> %s' % (self.name, url, self.parsed_url)) | 232 logging.debug('%s, %s -> %s' % (self.name, url, parsed_url)) |
| 233 return parsed_url |
| 228 elif isinstance(url, self.FileImpl): | 234 elif isinstance(url, self.FileImpl): |
| 229 self.parsed_url = url | 235 parsed_url = url |
| 230 logging.debug('%s, %s -> %s (File)' % (self.name, url, self.parsed_url)) | 236 logging.debug('%s, %s -> %s (File)' % (self.name, url, parsed_url)) |
| 231 return self.parsed_url | 237 return parsed_url |
| 238 elif url is None: |
| 239 return None |
| 240 else: |
| 241 raise gclient_utils.Error('Unkown url type') |
| 232 | 242 |
| 233 def ParseDepsFile(self, direct_reference): | 243 def ParseDepsFile(self, direct_reference): |
| 234 """Parses the DEPS file for this dependency.""" | 244 """Parses the DEPS file for this dependency.""" |
| 235 if direct_reference: | 245 if direct_reference: |
| 236 # Maybe it was referenced earlier by a From() keyword but it's now | 246 # Maybe it was referenced earlier by a From() keyword but it's now |
| 237 # directly referenced. | 247 # directly referenced. |
| 238 self.direct_reference = direct_reference | 248 self.direct_reference = direct_reference |
| 239 if self.deps_parsed: | 249 if self.deps_parsed: |
| 240 return | 250 return |
| 241 self.deps_parsed = True | 251 self.deps_parsed = True |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 # dependency local path. | 302 # dependency local path. |
| 293 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url | 303 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url |
| 294 deps = rel_deps | 304 deps = rel_deps |
| 295 | 305 |
| 296 # Convert the deps into real Dependency. | 306 # Convert the deps into real Dependency. |
| 297 for name, url in deps.iteritems(): | 307 for name, url in deps.iteritems(): |
| 298 if name in [s.name for s in self.dependencies]: | 308 if name in [s.name for s in self.dependencies]: |
| 299 raise | 309 raise |
| 300 self.dependencies.append(Dependency(self, name, url, None, None, None, | 310 self.dependencies.append(Dependency(self, name, url, None, None, None, |
| 301 None)) | 311 None)) |
| 302 # Sort by name. | 312 # Sorting by name would in theory make the whole thing coherent, since |
| 313 # subdirectories will be sorted after the parent directory, but that doens't |
| 314 # work with From() that fetch from a dependency with a name being sorted |
| 315 # later. But if this would be removed right now, many projects wouldn't be |
| 316 # able to sync anymore. |
| 303 self.dependencies.sort(key=lambda x: x.name) | 317 self.dependencies.sort(key=lambda x: x.name) |
| 304 logging.info('Loaded: %s' % str(self)) | 318 logging.info('Loaded: %s' % str(self)) |
| 305 | 319 |
| 306 def RunCommandRecursively(self, options, revision_overrides, | 320 def RunCommandRecursively(self, options, revision_overrides, |
| 307 command, args, pm): | 321 command, args, pm): |
| 308 """Runs 'command' before parsing the DEPS in case it's a initial checkout | 322 """Runs 'command' before parsing the DEPS in case it's a initial checkout |
| 309 or a revert.""" | 323 or a revert.""" |
| 310 assert self._file_list == [] | 324 assert self._file_list == [] |
| 311 # When running runhooks, there's no need to consult the SCM. | 325 # When running runhooks, there's no need to consult the SCM. |
| 312 # All known hooks are expected to run unconditionally regardless of working | 326 # All known hooks are expected to run unconditionally regardless of working |
| 313 # copy state, so skip the SCM status check. | 327 # copy state, so skip the SCM status check. |
| 314 run_scm = command not in ('runhooks', None) | 328 run_scm = command not in ('runhooks', None) |
| 315 self.LateOverride(self.url) | 329 self.parsed_url = self.LateOverride(self.url) |
| 316 if run_scm and self.parsed_url: | 330 if run_scm and self.parsed_url: |
| 317 if isinstance(self.parsed_url, self.FileImpl): | 331 if isinstance(self.parsed_url, self.FileImpl): |
| 318 # Special support for single-file checkout. | 332 # Special support for single-file checkout. |
| 319 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): | 333 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): |
| 320 options.revision = self.parsed_url.GetRevision() | 334 options.revision = self.parsed_url.GetRevision() |
| 321 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), | 335 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), |
| 322 self.root_dir(), | 336 self.root_dir(), |
| 323 self.name) | 337 self.name) |
| 324 scm.RunCommand('updatesingle', options, | 338 scm.RunCommand('updatesingle', options, |
| 325 args + [self.parsed_url.GetFilename()], | 339 args + [self.parsed_url.GetFilename()], |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 return CMDhelp(parser, argv) | 1176 return CMDhelp(parser, argv) |
| 1163 except gclient_utils.Error, e: | 1177 except gclient_utils.Error, e: |
| 1164 print >> sys.stderr, 'Error: %s' % str(e) | 1178 print >> sys.stderr, 'Error: %s' % str(e) |
| 1165 return 1 | 1179 return 1 |
| 1166 | 1180 |
| 1167 | 1181 |
| 1168 if '__main__' == __name__: | 1182 if '__main__' == __name__: |
| 1169 sys.exit(Main(sys.argv[1:])) | 1183 sys.exit(Main(sys.argv[1:])) |
| 1170 | 1184 |
| 1171 # vim: ts=2:sw=2:tw=80:et: | 1185 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |