Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: gclient.py

Issue 8135007: Improve logging and ease debugging. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: address review comments Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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:
OLDNEW
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698