| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 | 307 |
| 308 if not self.name and self.parent: | 308 if not self.name and self.parent: |
| 309 raise gclient_utils.Error('Dependency without name') | 309 raise gclient_utils.Error('Dependency without name') |
| 310 | 310 |
| 311 def LateOverride(self, url): | 311 def LateOverride(self, url): |
| 312 """Resolves the parsed url from url. | 312 """Resolves the parsed url from url. |
| 313 | 313 |
| 314 Manages From() keyword accordingly. Do not touch self.parsed_url nor | 314 Manages From() keyword accordingly. Do not touch self.parsed_url nor |
| 315 self.url because it may called with other urls due to From().""" | 315 self.url because it may called with other urls due to From().""" |
| 316 assert self.parsed_url == None or not self.should_process, self.parsed_url | 316 assert self.parsed_url == None or not self.should_process, self.parsed_url |
| 317 overriden_url = self.get_custom_deps(self.name, url) | 317 parsed_url = self.get_custom_deps(self.name, url) |
| 318 if overriden_url != url: | 318 if parsed_url != url: |
| 319 logging.info('%s, %s was overriden to %s' % (self.name, url, | 319 logging.info('LateOverride(%s, %s) -> %s' % (self.name, url, parsed_url)) |
| 320 overriden_url)) | 320 return parsed_url |
| 321 return overriden_url | 321 |
| 322 elif isinstance(url, self.FromImpl): | 322 if isinstance(url, self.FromImpl): |
| 323 ref = [ | 323 ref = [ |
| 324 dep for dep in self.root.subtree(True) if url.module_name == dep.name | 324 dep for dep in self.root.subtree(True) if url.module_name == dep.name |
| 325 ] | 325 ] |
| 326 if not ref: | 326 if not ref: |
| 327 raise gclient_utils.Error('Failed to find one reference to %s. %s' % ( | 327 raise gclient_utils.Error('Failed to find one reference to %s. %s' % ( |
| 328 url.module_name, ref)) | 328 url.module_name, ref)) |
| 329 # It may happen that len(ref) > 1 but it's no big deal. | 329 # It may happen that len(ref) > 1 but it's no big deal. |
| 330 ref = ref[0] | 330 ref = ref[0] |
| 331 sub_target = url.sub_target_name or self.name | 331 sub_target = url.sub_target_name or self.name |
| 332 # Make sure the referenced dependency DEPS file is loaded and file the | 332 # Make sure the referenced dependency DEPS file is loaded and file the |
| 333 # inner referenced dependency. | 333 # inner referenced dependency. |
| 334 ref.ParseDepsFile() | 334 ref.ParseDepsFile() |
| 335 found_dep = None | 335 found_dep = None |
| 336 for d in ref.dependencies: | 336 for d in ref.dependencies: |
| 337 if d.name == sub_target: | 337 if d.name == sub_target: |
| 338 found_dep = d | 338 found_dep = d |
| 339 break | 339 break |
| 340 if not found_dep: | 340 if not found_dep: |
| 341 raise gclient_utils.Error( | 341 raise gclient_utils.Error( |
| 342 'Couldn\'t find %s in %s, referenced by %s (parent: %s)\n%s' % ( | 342 'Couldn\'t find %s in %s, referenced by %s (parent: %s)\n%s' % ( |
| 343 sub_target, ref.name, self.name, self.parent.name, | 343 sub_target, ref.name, self.name, self.parent.name, |
| 344 str(self.root))) | 344 str(self.root))) |
| 345 | 345 |
| 346 # Call LateOverride() again. | 346 # Call LateOverride() again. |
| 347 parsed_url = found_dep.LateOverride(found_dep.url) | 347 parsed_url = found_dep.LateOverride(found_dep.url) |
| 348 logging.info('%s, %s to %s' % (self.name, url, parsed_url)) | 348 logging.info( |
| 349 'LateOverride(%s, %s) -> %s (From)' % (self.name, url, parsed_url)) |
| 349 return parsed_url | 350 return parsed_url |
| 350 elif isinstance(url, basestring): | 351 |
| 352 if isinstance(url, basestring): |
| 351 parsed_url = urlparse.urlparse(url) | 353 parsed_url = urlparse.urlparse(url) |
| 352 if not parsed_url[0]: | 354 if not parsed_url[0]: |
| 353 # A relative url. Fetch the real base. | 355 # A relative url. Fetch the real base. |
| 354 path = parsed_url[2] | 356 path = parsed_url[2] |
| 355 if not path.startswith('/'): | 357 if not path.startswith('/'): |
| 356 raise gclient_utils.Error( | 358 raise gclient_utils.Error( |
| 357 'relative DEPS entry \'%s\' must begin with a slash' % url) | 359 'relative DEPS entry \'%s\' must begin with a slash' % url) |
| 358 # Create a scm just to query the full url. | 360 # Create a scm just to query the full url. |
| 359 parent_url = self.parent.parsed_url | 361 parent_url = self.parent.parsed_url |
| 360 if isinstance(parent_url, self.FileImpl): | 362 if isinstance(parent_url, self.FileImpl): |
| 361 parent_url = parent_url.file_location | 363 parent_url = parent_url.file_location |
| 362 scm = gclient_scm.CreateSCM(parent_url, self.root.root_dir, None) | 364 scm = gclient_scm.CreateSCM(parent_url, self.root.root_dir, None) |
| 363 parsed_url = scm.FullUrlForRelativeUrl(url) | 365 parsed_url = scm.FullUrlForRelativeUrl(url) |
| 364 else: | 366 else: |
| 365 parsed_url = url | 367 parsed_url = url |
| 366 logging.info('%s, %s -> %s' % (self.name, url, parsed_url)) | 368 logging.info('LateOverride(%s, %s) -> %s' % (self.name, url, parsed_url)) |
| 367 return parsed_url | 369 return parsed_url |
| 368 elif isinstance(url, self.FileImpl): | 370 |
| 369 parsed_url = url | 371 if isinstance(url, self.FileImpl): |
| 370 logging.info('%s, %s -> %s (File)' % (self.name, url, parsed_url)) | 372 logging.info('LateOverride(%s, %s) -> %s (File)' % (self.name, url, url)) |
| 371 return parsed_url | 373 return url |
| 372 elif url is None: | 374 |
| 373 return None | 375 if url is None: |
| 376 logging.info('LateOverride(%s, %s) -> %s' % (self.name, url, url)) |
| 377 return url |
| 374 else: | 378 else: |
| 375 raise gclient_utils.Error('Unkown url type') | 379 raise gclient_utils.Error('Unknown url type') |
| 376 | 380 |
| 377 def ParseDepsFile(self): | 381 def ParseDepsFile(self): |
| 378 """Parses the DEPS file for this dependency.""" | 382 """Parses the DEPS file for this dependency.""" |
| 379 assert self.processed == True | 383 assert self.processed == True |
| 380 if self.deps_parsed: | 384 if self.deps_parsed: |
| 381 logging.debug('%s was already parsed' % self.name) | 385 logging.debug('%s was already parsed' % self.name) |
| 382 return | 386 return |
| 383 # One thing is unintuitive, vars= {} must happen before Var() use. | 387 # One thing is unintuitive, vars= {} must happen before Var() use. |
| 384 local_scope = {} | 388 local_scope = {} |
| 385 var = self.VarImpl(self.custom_vars, local_scope) | 389 var = self.VarImpl(self.custom_vars, local_scope) |
| 386 global_scope = { | 390 global_scope = { |
| 387 'File': self.FileImpl, | 391 'File': self.FileImpl, |
| 388 'From': self.FromImpl, | 392 'From': self.FromImpl, |
| 389 'Var': var.Lookup, | 393 'Var': var.Lookup, |
| 390 'deps_os': {}, | 394 'deps_os': {}, |
| 391 } | 395 } |
| 392 filepath = os.path.join(self.root.root_dir, self.name, self.deps_file) | 396 filepath = os.path.join(self.root.root_dir, self.name, self.deps_file) |
| 393 if not os.path.isfile(filepath): | 397 if not os.path.isfile(filepath): |
| 394 logging.info('%s: No %s file found at %s' % (self.name, self.deps_file, | 398 logging.info( |
| 395 filepath)) | 399 'ParseDepsFile(%s): No %s file found at %s' % ( |
| 400 self.name, self.deps_file, filepath)) |
| 396 else: | 401 else: |
| 397 deps_content = gclient_utils.FileRead(filepath) | 402 deps_content = gclient_utils.FileRead(filepath) |
| 398 logging.debug(deps_content) | 403 logging.debug('ParseDepsFile(%s) read:\n%s' % (self.name, deps_content)) |
| 399 # Eval the content. | 404 # Eval the content. |
| 400 try: | 405 try: |
| 401 exec(deps_content, global_scope, local_scope) | 406 exec(deps_content, global_scope, local_scope) |
| 402 except SyntaxError, e: | 407 except SyntaxError, e: |
| 403 gclient_utils.SyntaxErrorToError(filepath, e) | 408 gclient_utils.SyntaxErrorToError(filepath, e) |
| 404 deps = local_scope.get('deps', {}) | 409 deps = local_scope.get('deps', {}) |
| 405 # load os specific dependencies if defined. these dependencies may | 410 # load os specific dependencies if defined. these dependencies may |
| 406 # override or extend the values defined by the 'deps' member. | 411 # override or extend the values defined by the 'deps' member. |
| 407 if 'deps_os' in local_scope: | 412 if 'deps_os' in local_scope: |
| 408 enforced_os = self.root.enforced_os | 413 enforced_os = self.root.enforced_os |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It | 827 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It |
| 823 # makes testing a bit too fun. | 828 # makes testing a bit too fun. |
| 824 result = 'entries = {\n' | 829 result = 'entries = {\n' |
| 825 for entry in self.root.subtree(False): | 830 for entry in self.root.subtree(False): |
| 826 # Skip over File() dependencies as we can't version them. | 831 # Skip over File() dependencies as we can't version them. |
| 827 if not isinstance(entry.parsed_url, self.FileImpl): | 832 if not isinstance(entry.parsed_url, self.FileImpl): |
| 828 result += ' %s: %s,\n' % (pprint.pformat(entry.name), | 833 result += ' %s: %s,\n' % (pprint.pformat(entry.name), |
| 829 pprint.pformat(entry.parsed_url)) | 834 pprint.pformat(entry.parsed_url)) |
| 830 result += '}\n' | 835 result += '}\n' |
| 831 file_path = os.path.join(self.root_dir, self._options.entries_filename) | 836 file_path = os.path.join(self.root_dir, self._options.entries_filename) |
| 832 logging.info(result) | 837 logging.debug(result) |
| 833 gclient_utils.FileWrite(file_path, result) | 838 gclient_utils.FileWrite(file_path, result) |
| 834 | 839 |
| 835 def _ReadEntries(self): | 840 def _ReadEntries(self): |
| 836 """Read the .gclient_entries file for the given client. | 841 """Read the .gclient_entries file for the given client. |
| 837 | 842 |
| 838 Returns: | 843 Returns: |
| 839 A sequence of solution names, which will be empty if there is the | 844 A sequence of solution names, which will be empty if there is the |
| 840 entries file hasn't been created yet. | 845 entries file hasn't been created yet. |
| 841 """ | 846 """ |
| 842 scope = {} | 847 scope = {} |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 parser.add_option('-v', '--verbose', action='count', default=0, | 1386 parser.add_option('-v', '--verbose', action='count', default=0, |
| 1382 help='Produces additional output for diagnostics. Can be ' | 1387 help='Produces additional output for diagnostics. Can be ' |
| 1383 'used up to three times for more logging info.') | 1388 'used up to three times for more logging info.') |
| 1384 parser.add_option('--gclientfile', dest='config_filename', | 1389 parser.add_option('--gclientfile', dest='config_filename', |
| 1385 default=os.environ.get('GCLIENT_FILE', '.gclient'), | 1390 default=os.environ.get('GCLIENT_FILE', '.gclient'), |
| 1386 help='Specify an alternate %default file') | 1391 help='Specify an alternate %default file') |
| 1387 # Integrate standard options processing. | 1392 # Integrate standard options processing. |
| 1388 old_parser = parser.parse_args | 1393 old_parser = parser.parse_args |
| 1389 def Parse(args): | 1394 def Parse(args): |
| 1390 (options, args) = old_parser(args) | 1395 (options, args) = old_parser(args) |
| 1391 level = None | 1396 level = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG][ |
| 1392 if options.verbose == 2: | 1397 min(options.verbose, 3)] |
| 1393 level = logging.INFO | |
| 1394 elif options.verbose > 2: | |
| 1395 level = logging.DEBUG | |
| 1396 logging.basicConfig(level=level, | 1398 logging.basicConfig(level=level, |
| 1397 format='%(module)s(%(lineno)d) %(funcName)s:%(message)s') | 1399 format='%(module)s(%(lineno)d) %(funcName)s:%(message)s') |
| 1398 options.entries_filename = options.config_filename + '_entries' | 1400 options.entries_filename = options.config_filename + '_entries' |
| 1399 if options.jobs < 1: | 1401 if options.jobs < 1: |
| 1400 parser.error('--jobs must be 1 or higher') | 1402 parser.error('--jobs must be 1 or higher') |
| 1401 | 1403 |
| 1402 # These hacks need to die. | 1404 # These hacks need to die. |
| 1403 if not hasattr(options, 'revisions'): | 1405 if not hasattr(options, 'revisions'): |
| 1404 # GClient.RunOnDeps expects it even if not applicable. | 1406 # GClient.RunOnDeps expects it even if not applicable. |
| 1405 options.revisions = [] | 1407 options.revisions = [] |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1453 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
| 1452 print >> sys.stderr, 'Error: %s' % str(e) | 1454 print >> sys.stderr, 'Error: %s' % str(e) |
| 1453 return 1 | 1455 return 1 |
| 1454 | 1456 |
| 1455 | 1457 |
| 1456 if '__main__' == __name__: | 1458 if '__main__' == __name__: |
| 1457 fix_encoding.fix_encoding() | 1459 fix_encoding.fix_encoding() |
| 1458 sys.exit(Main(sys.argv[1:])) | 1460 sys.exit(Main(sys.argv[1:])) |
| 1459 | 1461 |
| 1460 # vim: ts=2:sw=2:tw=80:et: | 1462 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |