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 |