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

Side by Side Diff: gclient.py

Issue 2836042: Mixed bag of nits. (Closed)
Patch Set: quotes Created 10 years, 5 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
« no previous file with comments | « no previous file | tests/gclient_smoketest.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/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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 out.append('') 395 out.append('')
396 return '\n'.join(out) 396 return '\n'.join(out)
397 397
398 def __repr__(self): 398 def __repr__(self):
399 return '%s: %s' % (self.name, self.url) 399 return '%s: %s' % (self.name, self.url)
400 400
401 401
402 class GClient(Dependency): 402 class GClient(Dependency):
403 """Object that represent a gclient checkout. A tree of Dependency(), one per 403 """Object that represent a gclient checkout. A tree of Dependency(), one per
404 solution or DEPS entry.""" 404 solution or DEPS entry."""
405 SUPPORTED_COMMANDS = [
406 'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update',
407 'runhooks'
408 ]
409 405
410 DEPS_OS_CHOICES = { 406 DEPS_OS_CHOICES = {
411 "win32": "win", 407 "win32": "win",
412 "win": "win", 408 "win": "win",
413 "cygwin": "win", 409 "cygwin": "win",
414 "darwin": "mac", 410 "darwin": "mac",
415 "mac": "mac", 411 "mac": "mac",
416 "unix": "unix", 412 "unix": "unix",
417 "linux": "unix", 413 "linux": "unix",
418 "linux2": "unix", 414 "linux2": "unix",
419 } 415 }
420 416
421 DEFAULT_CLIENT_FILE_TEXT = ("""\ 417 DEFAULT_CLIENT_FILE_TEXT = ("""\
422 solutions = [ 418 solutions = [
423 { "name" : "%(solution_name)s", 419 { "name" : "%(solution_name)s",
424 "url" : "%(solution_url)s", 420 "url" : "%(solution_url)s",
425 "custom_deps" : { 421 "custom_deps" : {
426 }, 422 },
427 "safesync_url": "%(safesync_url)s" 423 "safesync_url": "%(safesync_url)s",
428 }, 424 },
429 ] 425 ]
430 """) 426 """)
431 427
432 DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\ 428 DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\
433 { "name" : "%(solution_name)s", 429 { "name" : "%(solution_name)s",
434 "url" : "%(solution_url)s", 430 "url" : "%(solution_url)s",
435 "custom_deps" : { 431 "custom_deps" : {
436 %(solution_deps)s, 432 %(solution_deps)s },
437 }, 433 "safesync_url": "%(safesync_url)s",
438 "safesync_url": "%(safesync_url)s"
439 }, 434 },
440 """) 435 """)
441 436
442 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ 437 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\
443 # Snapshot generated with gclient revinfo --snapshot 438 # Snapshot generated with gclient revinfo --snapshot
444 solutions = [ 439 solutions = [
445 %(solution_list)s 440 %(solution_list)s]
446 ]
447 """) 441 """)
448 442
449 def __init__(self, root_dir, options): 443 def __init__(self, root_dir, options):
450 Dependency.__init__(self, None, None, None) 444 Dependency.__init__(self, None, None, None)
451 self._options = options 445 self._options = options
452 if options.deps_os: 446 if options.deps_os:
453 enforced_os = options.deps_os.split(',') 447 enforced_os = options.deps_os.split(',')
454 else: 448 else:
455 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] 449 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')]
456 if 'all' in enforced_os: 450 if 'all' in enforced_os:
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 self.SetConfig(self.DEFAULT_CLIENT_FILE_TEXT % { 509 self.SetConfig(self.DEFAULT_CLIENT_FILE_TEXT % {
516 'solution_name': solution_name, 510 'solution_name': solution_name,
517 'solution_url': solution_url, 511 'solution_url': solution_url,
518 'safesync_url' : safesync_url, 512 'safesync_url' : safesync_url,
519 }) 513 })
520 514
521 def _SaveEntries(self, entries): 515 def _SaveEntries(self, entries):
522 """Creates a .gclient_entries file to record the list of unique checkouts. 516 """Creates a .gclient_entries file to record the list of unique checkouts.
523 517
524 The .gclient_entries file lives in the same directory as .gclient. 518 The .gclient_entries file lives in the same directory as .gclient.
525
526 Args:
527 entries: A sequence of solution names.
528 """ 519 """
529 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It 520 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It
530 # makes testing a bit too fun. 521 # makes testing a bit too fun.
531 result = pprint.pformat(entries, 2) 522 result = pprint.pformat(entries, 2)
532 if result.startswith('{\''): 523 if result.startswith('{\''):
533 result = '{ \'' + result[2:] 524 result = '{ \'' + result[2:]
534 text = "entries = \\\n" + result + '\n' 525 text = 'entries = \\\n' + result + '\n'
535 file_path = os.path.join(self.root_dir(), self._options.entries_filename) 526 file_path = os.path.join(self.root_dir(), self._options.entries_filename)
536 gclient_utils.FileWrite(file_path, text) 527 gclient_utils.FileWrite(file_path, text)
537 528
538 def _ReadEntries(self): 529 def _ReadEntries(self):
539 """Read the .gclient_entries file for the given client. 530 """Read the .gclient_entries file for the given client.
540 531
541 Returns: 532 Returns:
542 A sequence of solution names, which will be empty if there is the 533 A sequence of solution names, which will be empty if there is the
543 entries file hasn't been created yet. 534 entries file hasn't been created yet.
544 """ 535 """
545 scope = {} 536 scope = {}
546 filename = os.path.join(self.root_dir(), self._options.entries_filename) 537 filename = os.path.join(self.root_dir(), self._options.entries_filename)
547 if not os.path.exists(filename): 538 if not os.path.exists(filename):
548 return [] 539 return {}
549 exec(gclient_utils.FileRead(filename), scope) 540 exec(gclient_utils.FileRead(filename), scope)
550 return scope['entries'] 541 return scope['entries']
551 542
552 def _EnforceRevisions(self): 543 def _EnforceRevisions(self):
553 """Checks for revision overrides.""" 544 """Checks for revision overrides."""
554 revision_overrides = {} 545 revision_overrides = {}
555 if self._options.head: 546 if self._options.head:
556 return revision_overrides 547 return revision_overrides
557 for s in self.dependencies: 548 for s in self.dependencies:
558 if not s.safesync_url: 549 if not s.safesync_url:
(...skipping 22 matching lines...) Expand all
581 index += 1 572 index += 1
582 return revision_overrides 573 return revision_overrides
583 574
584 def RunOnDeps(self, command, args): 575 def RunOnDeps(self, command, args):
585 """Runs a command on each dependency in a client and its dependencies. 576 """Runs a command on each dependency in a client and its dependencies.
586 577
587 Args: 578 Args:
588 command: The command to use (e.g., 'status' or 'diff') 579 command: The command to use (e.g., 'status' or 'diff')
589 args: list of str - extra arguments to add to the command line. 580 args: list of str - extra arguments to add to the command line.
590 """ 581 """
591 if not command in self.SUPPORTED_COMMANDS:
592 raise gclient_utils.Error("'%s' is an unsupported command" % command)
593
594 if not self.dependencies: 582 if not self.dependencies:
595 raise gclient_utils.Error("No solution specified") 583 raise gclient_utils.Error('No solution specified')
596 revision_overrides = self._EnforceRevisions() 584 revision_overrides = self._EnforceRevisions()
597 585
598 # When running runhooks --force, there's no need to consult the SCM. 586 # When running runhooks --force, there's no need to consult the SCM.
599 # All known hooks are expected to run unconditionally regardless of working 587 # All known hooks are expected to run unconditionally regardless of working
600 # copy state, so skip the SCM status check. 588 # copy state, so skip the SCM status check.
601 run_scm = not (command == 'runhooks' and self._options.force) 589 run_scm = not (command == 'runhooks' and self._options.force)
602 590
603 entries = {} 591 entries = {}
604 file_list = [] 592 file_list = []
605 # Run on the base solutions first. 593 # Run on the base solutions first.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 scm.status(self._options, [], file_list) 692 scm.status(self._options, [], file_list)
705 modified_files = file_list != [] 693 modified_files = file_list != []
706 if not self._options.delete_unversioned_trees or modified_files: 694 if not self._options.delete_unversioned_trees or modified_files:
707 # There are modified files in this entry. Keep warning until 695 # There are modified files in this entry. Keep warning until
708 # removed. 696 # removed.
709 print(('\nWARNING: \'%s\' is no longer part of this client. ' 697 print(('\nWARNING: \'%s\' is no longer part of this client. '
710 'It is recommended that you manually remove it.\n') % 698 'It is recommended that you manually remove it.\n') %
711 entry_fixed) 699 entry_fixed)
712 else: 700 else:
713 # Delete the entry 701 # Delete the entry
714 print('\n________ deleting \'%s\' ' + 702 print('\n________ deleting \'%s\' in \'%s\'' % (
715 'in \'%s\'') % (entry_fixed, self.root_dir()) 703 entry_fixed, self.root_dir()))
716 gclient_utils.RemoveDirectory(e_dir) 704 gclient_utils.RemoveDirectory(e_dir)
717 # record the current list of entries for next time 705 # record the current list of entries for next time
718 self._SaveEntries(entries) 706 self._SaveEntries(entries)
719 return 0 707 return 0
720 708
721 def PrintRevInfo(self): 709 def PrintRevInfo(self):
722 """Output revision info mapping for the client and its dependencies. 710 """Output revision info mapping for the client and its dependencies.
723 711
724 This allows the capture of an overall "revision" for the source tree that 712 This allows the capture of an overall "revision" for the source tree that
725 can be used to reproduce the same tree in the future. It is only useful for 713 can be used to reproduce the same tree in the future. It is only useful for
726 "unpinned dependencies", i.e. DEPS/deps references without a svn revision 714 "unpinned dependencies", i.e. DEPS/deps references without a svn revision
727 number or a git hash. A git branch name isn't "pinned" since the actual 715 number or a git hash. A git branch name isn't "pinned" since the actual
728 commit can change. 716 commit can change.
729 717
730 The --snapshot option allows creating a .gclient file to reproduce the tree. 718 The --snapshot option allows creating a .gclient file to reproduce the tree.
731 """ 719 """
732 if not self.dependencies: 720 if not self.dependencies:
733 raise gclient_utils.Error("No solution specified") 721 raise gclient_utils.Error('No solution specified')
734 722
735 # Inner helper to generate base url and rev tuple 723 # Inner helper to generate base url and rev tuple
736 def GetURLAndRev(name, original_url): 724 def GetURLAndRev(name, original_url):
737 url, _ = gclient_utils.SplitUrlRevision(original_url) 725 url, _ = gclient_utils.SplitUrlRevision(original_url)
738 scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name) 726 scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name)
739 return (url, scm.revinfo(self._options, [], None)) 727 return (url, scm.revinfo(self._options, [], None))
740 728
741 # text of the snapshot gclient file 729 # text of the snapshot gclient file
742 new_gclient = "" 730 new_gclient = ""
743 # Dictionary of { path : SCM url } to ensure no duplicate solutions 731 # Dictionary of { path : SCM url } to ensure no duplicate solutions
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 sub_deps_base_url = deps[deps[d].module_name] 763 sub_deps_base_url = deps[deps[d].module_name]
776 sub_deps = Dependency(self, deps[d].module_name, sub_deps_base_url 764 sub_deps = Dependency(self, deps[d].module_name, sub_deps_base_url
777 ).ParseDepsFile(False) 765 ).ParseDepsFile(False)
778 url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps) 766 url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps)
779 (url, rev) = GetURLAndRev(d, url) 767 (url, rev) = GetURLAndRev(d, url)
780 entries[d] = "%s@%s" % (url, rev) 768 entries[d] = "%s@%s" % (url, rev)
781 769
782 # Build the snapshot configuration string 770 # Build the snapshot configuration string
783 if self._options.snapshot: 771 if self._options.snapshot:
784 url = entries.pop(name) 772 url = entries.pop(name)
785 custom_deps = ",\n ".join(["\"%s\": \"%s\"" % (x, entries[x]) 773 custom_deps = ''.join([' \"%s\": \"%s\",\n' % (x, entries[x])
786 for x in sorted(entries.keys())]) 774 for x in sorted(entries.keys())])
787 775
788 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { 776 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % {
789 'solution_name': name, 777 'solution_name': name,
790 'solution_url': url, 778 'solution_url': url,
791 'safesync_url' : "", 779 'safesync_url' : '',
792 'solution_deps': custom_deps, 780 'solution_deps': custom_deps,
793 } 781 }
794 else: 782 else:
795 print(";\n".join(["%s: %s" % (x, entries[x]) 783 print(';\n'.join(['%s: %s' % (x, entries[x])
796 for x in sorted(entries.keys())])) 784 for x in sorted(entries.keys())]))
797 785
798 # Print the snapshot configuration file 786 # Print the snapshot configuration file
799 if self._options.snapshot: 787 if self._options.snapshot:
800 config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient} 788 config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}
801 snapclient = GClient(self.root_dir(), self._options) 789 snapclient = GClient(self.root_dir(), self._options)
802 snapclient.SetConfig(config) 790 snapclient.SetConfig(config)
803 print(snapclient.config_content) 791 print(snapclient.config_content)
804 792
805 def ParseDepsFile(self, direct_reference): 793 def ParseDepsFile(self, direct_reference):
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 return CMDhelp(parser, argv) 1166 return CMDhelp(parser, argv)
1179 except gclient_utils.Error, e: 1167 except gclient_utils.Error, e:
1180 print >> sys.stderr, 'Error: %s' % str(e) 1168 print >> sys.stderr, 'Error: %s' % str(e)
1181 return 1 1169 return 1
1182 1170
1183 1171
1184 if '__main__' == __name__: 1172 if '__main__' == __name__:
1185 sys.exit(Main(sys.argv[1:])) 1173 sys.exit(Main(sys.argv[1:]))
1186 1174
1187 # vim: ts=2:sw=2:tw=80:et: 1175 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | tests/gclient_smoketest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698