OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright 2008 Google Inc. All Rights Reserved. | 3 # Copyright 2008 Google Inc. All Rights Reserved. |
4 # | 4 # |
5 # Licensed under the Apache License, Version 2.0 (the "License"); | 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
6 # you may not use this file except in compliance with the License. | 6 # you may not use this file except in compliance with the License. |
7 # You may obtain a copy of the License at | 7 # You may obtain a copy of the License at |
8 # | 8 # |
9 # http://www.apache.org/licenses/LICENSE-2.0 | 9 # http://www.apache.org/licenses/LICENSE-2.0 |
10 # | 10 # |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 |entries| is a list of paths to check.""" | 468 |entries| is a list of paths to check.""" |
469 for path in paths: | 469 for path in paths: |
470 if os.path.exists(os.path.join(root, path, '.git')): | 470 if os.path.exists(os.path.join(root, path, '.git')): |
471 return True | 471 return True |
472 return False | 472 return False |
473 | 473 |
474 # ----------------------------------------------------------------------------- | 474 # ----------------------------------------------------------------------------- |
475 # SVN utils: | 475 # SVN utils: |
476 | 476 |
477 | 477 |
478 def RunSVN(options, args, in_directory): | 478 def RunSVN(args, in_directory): |
479 """Runs svn, sending output to stdout. | 479 """Runs svn, sending output to stdout. |
480 | 480 |
481 Args: | 481 Args: |
482 args: A sequence of command line parameters to be passed to svn. | 482 args: A sequence of command line parameters to be passed to svn. |
483 in_directory: The directory where svn is to be run. | 483 in_directory: The directory where svn is to be run. |
484 | 484 |
485 Raises: | 485 Raises: |
486 Error: An error occurred while running the svn command. | 486 Error: An error occurred while running the svn command. |
487 """ | 487 """ |
488 c = [SVN_COMMAND] | 488 c = [SVN_COMMAND] |
489 c.extend(args) | 489 c.extend(args) |
490 | 490 |
491 SubprocessCall(c, in_directory, options.stdout) | 491 SubprocessCall(c, in_directory, options.stdout) |
492 | 492 |
493 | 493 |
494 def CaptureSVN(options, args, in_directory): | 494 def CaptureSVN(args, in_directory=None, print_error=True): |
495 """Runs svn, capturing output sent to stdout as a string. | 495 """Runs svn, capturing output sent to stdout as a string. |
496 | 496 |
497 Args: | 497 Args: |
498 args: A sequence of command line parameters to be passed to svn. | 498 args: A sequence of command line parameters to be passed to svn. |
499 in_directory: The directory where svn is to be run. | 499 in_directory: The directory where svn is to be run. |
500 | 500 |
501 Returns: | 501 Returns: |
502 The output sent to stdout as a string. | 502 The output sent to stdout as a string. |
503 """ | 503 """ |
504 c = [SVN_COMMAND] | 504 c = [SVN_COMMAND] |
505 c.extend(args) | 505 c.extend(args) |
506 | 506 |
507 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for | 507 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for |
508 # the svn.exe executable, but shell=True makes subprocess on Linux fail | 508 # the svn.exe executable, but shell=True makes subprocess on Linux fail |
509 # when it's called with a list because it only tries to execute the | 509 # when it's called with a list because it only tries to execute the |
510 # first string ("svn"). | 510 # first string ("svn"). |
511 return subprocess.Popen(c, cwd=in_directory, shell=(sys.platform == 'win32'), | 511 stderr = None |
512 stdout=subprocess.PIPE).communicate()[0] | 512 if print_error: |
| 513 stderr = subprocess.PIPE |
| 514 return subprocess.Popen(c, |
| 515 cwd=in_directory, |
| 516 shell=(sys.platform == 'win32'), |
| 517 stdout=subprocess.PIPE, |
| 518 stderr=stderr).communicate()[0] |
513 | 519 |
514 | 520 |
515 def RunSVNAndGetFileList(options, args, in_directory, file_list): | 521 def RunSVNAndGetFileList(options, args, in_directory, file_list): |
516 """Runs svn checkout, update, or status, output to stdout. | 522 """Runs svn checkout, update, or status, output to stdout. |
517 | 523 |
518 The first item in args must be either "checkout", "update", or "status". | 524 The first item in args must be either "checkout", "update", or "status". |
519 | 525 |
520 svn's stdout is parsed to collect a list of files checked out or updated. | 526 svn's stdout is parsed to collect a list of files checked out or updated. |
521 These files are appended to file_list. svn's stdout is also printed to | 527 These files are appended to file_list. svn's stdout is also printed to |
522 sys.stdout as in RunSVN. | 528 sys.stdout as in RunSVN. |
(...skipping 26 matching lines...) Expand all Loading... |
549 pattern = { | 555 pattern = { |
550 'checkout': update_pattern, | 556 'checkout': update_pattern, |
551 'status': status_pattern, | 557 'status': status_pattern, |
552 'update': update_pattern, | 558 'update': update_pattern, |
553 }[args[0]] | 559 }[args[0]] |
554 | 560 |
555 SubprocessCallAndCapture(command, in_directory, options.stdout, | 561 SubprocessCallAndCapture(command, in_directory, options.stdout, |
556 pattern=pattern, capture_list=file_list) | 562 pattern=pattern, capture_list=file_list) |
557 | 563 |
558 | 564 |
559 def CaptureSVNInfo(options, relpath, in_directory): | 565 def CaptureSVNInfo(relpath, in_directory=None, print_error=True): |
560 """Returns a dictionary from the svn info output for the given file. | 566 """Returns a dictionary from the svn info output for the given file. |
561 | 567 |
562 Args: | 568 Args: |
563 relpath: The directory where the working copy resides relative to | 569 relpath: The directory where the working copy resides relative to |
564 the directory given by in_directory. | 570 the directory given by in_directory. |
565 in_directory: The directory where svn is to be run. | 571 in_directory: The directory where svn is to be run. |
566 """ | 572 """ |
567 dom = ParseXML(CaptureSVN(options, ["info", "--xml", relpath], in_directory)) | 573 output = CaptureSVN(["info", "--xml", relpath], in_directory, print_error) |
| 574 dom = ParseXML(output) |
568 result = {} | 575 result = {} |
569 if dom: | 576 if dom: |
570 def C(item, f): | 577 def C(item, f): |
571 if item is not None: return f(item) | 578 if item is not None: return f(item) |
572 # /info/entry/ | 579 # /info/entry/ |
573 # url | 580 # url |
574 # reposityory/(root|uuid) | 581 # reposityory/(root|uuid) |
575 # wc-info/(schedule|depth) | 582 # wc-info/(schedule|depth) |
576 # commit/(author|date) | 583 # commit/(author|date) |
577 # str() the results because they may be returned as Unicode, which | 584 # str() the results because they may be returned as Unicode, which |
578 # interferes with the higher layers matching up things in the deps | 585 # interferes with the higher layers matching up things in the deps |
579 # dictionary. | 586 # dictionary. |
580 # TODO(maruel): Fix at higher level instead (!) | 587 # TODO(maruel): Fix at higher level instead (!) |
581 result['Repository Root'] = C(GetNamedNodeText(dom, 'root'), str) | 588 result['Repository Root'] = C(GetNamedNodeText(dom, 'root'), str) |
582 result['URL'] = C(GetNamedNodeText(dom, 'url'), str) | 589 result['URL'] = C(GetNamedNodeText(dom, 'url'), str) |
583 result['UUID'] = C(GetNamedNodeText(dom, 'uuid'), str) | 590 result['UUID'] = C(GetNamedNodeText(dom, 'uuid'), str) |
584 result['Revision'] = C(GetNodeNamedAttributeText(dom, 'entry', 'revision'), | 591 result['Revision'] = C(GetNodeNamedAttributeText(dom, 'entry', 'revision'), |
585 int) | 592 int) |
586 result['Node Kind'] = C(GetNodeNamedAttributeText(dom, 'entry', 'kind'), | 593 result['Node Kind'] = C(GetNodeNamedAttributeText(dom, 'entry', 'kind'), |
587 str) | 594 str) |
588 result['Schedule'] = C(GetNamedNodeText(dom, 'schedule'), str) | 595 result['Schedule'] = C(GetNamedNodeText(dom, 'schedule'), str) |
589 result['Path'] = C(GetNodeNamedAttributeText(dom, 'entry', 'path'), str) | 596 result['Path'] = C(GetNodeNamedAttributeText(dom, 'entry', 'path'), str) |
590 result['Copied From URL'] = C(GetNamedNodeText(dom, 'copy-from-url'), str) | 597 result['Copied From URL'] = C(GetNamedNodeText(dom, 'copy-from-url'), str) |
591 result['Copied From Rev'] = C(GetNamedNodeText(dom, 'copy-from-rev'), str) | 598 result['Copied From Rev'] = C(GetNamedNodeText(dom, 'copy-from-rev'), str) |
592 return result | 599 return result |
593 | 600 |
594 | 601 |
595 def CaptureSVNHeadRevision(options, url): | 602 def CaptureSVNHeadRevision(url): |
596 """Get the head revision of a SVN repository. | 603 """Get the head revision of a SVN repository. |
597 | 604 |
598 Returns: | 605 Returns: |
599 Int head revision | 606 Int head revision |
600 """ | 607 """ |
601 info = CaptureSVN(options, ["info", "--xml", url], os.getcwd()) | 608 info = CaptureSVN(["info", "--xml", url], os.getcwd()) |
602 dom = xml.dom.minidom.parseString(info) | 609 dom = xml.dom.minidom.parseString(info) |
603 return int(dom.getElementsByTagName('entry')[0].getAttribute('revision')) | 610 return int(dom.getElementsByTagName('entry')[0].getAttribute('revision')) |
604 | 611 |
605 | 612 |
606 class FileStatus: | 613 class FileStatus: |
607 def __init__(self, path, text_status, props, lock, history): | 614 def __init__(self, path, text_status, props, lock, history): |
608 self.path = path | 615 self.path = path |
609 self.text_status = text_status | 616 self.text_status = text_status |
610 self.props = props | 617 self.props = props |
611 self.lock = lock | 618 self.lock = lock |
612 self.history = history | 619 self.history = history |
613 | 620 |
614 def __str__(self): | 621 def __str__(self): |
615 # Emulate svn status 1.5 output. | 622 # Emulate svn status 1.5 output. |
616 return (self.text_status + self.props + self.lock + self.history + ' ' + | 623 return (self.text_status + self.props + self.lock + self.history + ' ' + |
617 self.path) | 624 self.path) |
618 | 625 |
619 | 626 |
620 def CaptureSVNStatus(options, path): | 627 def CaptureSVNStatus(path): |
621 """Runs 'svn status' on an existing path. | 628 """Runs 'svn status' on an existing path. |
622 | 629 |
623 Args: | 630 Args: |
624 path: The directory to run svn status. | 631 path: The directory to run svn status. |
625 | 632 |
626 Returns: | 633 Returns: |
627 An array of FileStatus corresponding to the emulated output of 'svn status' | 634 An array of FileStatus corresponding to the emulated output of 'svn status' |
628 version 1.5.""" | 635 version 1.5.""" |
629 dom = ParseXML(CaptureSVN(options, ["status", "--xml"], path)) | 636 dom = ParseXML(CaptureSVN(["status", "--xml"], path)) |
630 results = [] | 637 results = [] |
631 if dom: | 638 if dom: |
632 # /status/target/entry/(wc-status|commit|author|date) | 639 # /status/target/entry/(wc-status|commit|author|date) |
633 for target in dom.getElementsByTagName('target'): | 640 for target in dom.getElementsByTagName('target'): |
634 base_path = target.getAttribute('path') | 641 base_path = target.getAttribute('path') |
635 for entry in target.getElementsByTagName('entry'): | 642 for entry in target.getElementsByTagName('entry'): |
636 file = entry.getAttribute('path') | 643 file = entry.getAttribute('path') |
637 wc_status = entry.getElementsByTagName('wc-status') | 644 wc_status = entry.getElementsByTagName('wc-status') |
638 assert len(wc_status) == 1 | 645 assert len(wc_status) == 1 |
639 # Emulate svn 1.5 status ouput... | 646 # Emulate svn 1.5 status ouput... |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 | 728 |
722 if not command in commands: | 729 if not command in commands: |
723 raise Error('Unknown command %s' % command) | 730 raise Error('Unknown command %s' % command) |
724 | 731 |
725 return commands[command](options, args, file_list) | 732 return commands[command](options, args, file_list) |
726 | 733 |
727 def cleanup(self, options, args, file_list): | 734 def cleanup(self, options, args, file_list): |
728 """Cleanup working copy.""" | 735 """Cleanup working copy.""" |
729 command = ['cleanup'] | 736 command = ['cleanup'] |
730 command.extend(args) | 737 command.extend(args) |
731 RunSVN(options, command, os.path.join(self._root_dir, self.relpath)) | 738 RunSVN(command, os.path.join(self._root_dir, self.relpath)) |
732 | 739 |
733 def diff(self, options, args, file_list): | 740 def diff(self, options, args, file_list): |
734 # NOTE: This function does not currently modify file_list. | 741 # NOTE: This function does not currently modify file_list. |
735 command = ['diff'] | 742 command = ['diff'] |
736 command.extend(args) | 743 command.extend(args) |
737 RunSVN(options, command, os.path.join(self._root_dir, self.relpath)) | 744 RunSVN(command, os.path.join(self._root_dir, self.relpath)) |
738 | 745 |
739 def update(self, options, args, file_list): | 746 def update(self, options, args, file_list): |
740 """Runs SCM to update or transparently checkout the working copy. | 747 """Runs SCM to update or transparently checkout the working copy. |
741 | 748 |
742 All updated files will be appended to file_list. | 749 All updated files will be appended to file_list. |
743 | 750 |
744 Raises: | 751 Raises: |
745 Error: if can't get URL for relative path. | 752 Error: if can't get URL for relative path. |
746 """ | 753 """ |
747 # Only update if git is not controlling the directory. | 754 # Only update if git is not controlling the directory. |
(...skipping 25 matching lines...) Expand all Loading... |
773 | 780 |
774 if not options.path_exists(os.path.join(self._root_dir, self.relpath)): | 781 if not options.path_exists(os.path.join(self._root_dir, self.relpath)): |
775 # We need to checkout. | 782 # We need to checkout. |
776 command = ['checkout', url, os.path.join(self._root_dir, self.relpath)] | 783 command = ['checkout', url, os.path.join(self._root_dir, self.relpath)] |
777 if revision: | 784 if revision: |
778 command.extend(['--revision', str(revision)]) | 785 command.extend(['--revision', str(revision)]) |
779 RunSVNAndGetFileList(options, command, self._root_dir, file_list) | 786 RunSVNAndGetFileList(options, command, self._root_dir, file_list) |
780 return | 787 return |
781 | 788 |
782 # Get the existing scm url and the revision number of the current checkout. | 789 # Get the existing scm url and the revision number of the current checkout. |
783 from_info = CaptureSVNInfo(options, | 790 from_info = CaptureSVNInfo(os.path.join(self._root_dir, self.relpath, '.'), |
784 os.path.join(self._root_dir, self.relpath, '.'), | |
785 '.') | 791 '.') |
786 | 792 |
787 if options.manually_grab_svn_rev: | 793 if options.manually_grab_svn_rev: |
788 # Retrieve the current HEAD version because svn is slow at null updates. | 794 # Retrieve the current HEAD version because svn is slow at null updates. |
789 if not revision: | 795 if not revision: |
790 from_info_live = CaptureSVNInfo(options, from_info['URL'], '.') | 796 from_info_live = CaptureSVNInfo(from_info['URL'], '.') |
791 revision = int(from_info_live['Revision']) | 797 revision = int(from_info_live['Revision']) |
792 rev_str = ' at %d' % revision | 798 rev_str = ' at %d' % revision |
793 | 799 |
794 if from_info['URL'] != components[0]: | 800 if from_info['URL'] != components[0]: |
795 to_info = CaptureSVNInfo(options, url, '.') | 801 to_info = CaptureSVNInfo(url, '.') |
796 if from_info['Repository Root'] != to_info['Repository Root']: | 802 if from_info['Repository Root'] != to_info['Repository Root']: |
797 # We have different roots, so check if we can switch --relocate. | 803 # We have different roots, so check if we can switch --relocate. |
798 # Subversion only permits this if the repository UUIDs match. | 804 # Subversion only permits this if the repository UUIDs match. |
799 if from_info['UUID'] != to_info['UUID']: | 805 if from_info['UUID'] != to_info['UUID']: |
800 raise Error("Can't switch the checkout to %s; UUID don't match. That " | 806 raise Error("Can't switch the checkout to %s; UUID don't match. That " |
801 "simply means in theory, gclient should verify you don't " | 807 "simply means in theory, gclient should verify you don't " |
802 "have a local change, remove the old checkout and do a " | 808 "have a local change, remove the old checkout and do a " |
803 "fresh new checkout of the new repo. Contributions are " | 809 "fresh new checkout of the new repo. Contributions are " |
804 "welcome." % url) | 810 "welcome." % url) |
805 | 811 |
806 # Perform the switch --relocate, then rewrite the from_url | 812 # Perform the switch --relocate, then rewrite the from_url |
807 # to reflect where we "are now." (This is the same way that | 813 # to reflect where we "are now." (This is the same way that |
808 # Subversion itself handles the metadata when switch --relocate | 814 # Subversion itself handles the metadata when switch --relocate |
809 # is used.) This makes the checks below for whether we | 815 # is used.) This makes the checks below for whether we |
810 # can update to a revision or have to switch to a different | 816 # can update to a revision or have to switch to a different |
811 # branch work as expected. | 817 # branch work as expected. |
812 # TODO(maruel): TEST ME ! | 818 # TODO(maruel): TEST ME ! |
813 command = ["switch", "--relocate", | 819 command = ["switch", "--relocate", |
814 from_info['Repository Root'], | 820 from_info['Repository Root'], |
815 to_info['Repository Root'], | 821 to_info['Repository Root'], |
816 self.relpath] | 822 self.relpath] |
817 RunSVN(options, command, self._root_dir) | 823 RunSVN(command, self._root_dir) |
818 from_info['URL'] = from_info['URL'].replace( | 824 from_info['URL'] = from_info['URL'].replace( |
819 from_info['Repository Root'], | 825 from_info['Repository Root'], |
820 to_info['Repository Root']) | 826 to_info['Repository Root']) |
821 | 827 |
822 # If the provided url has a revision number that matches the revision | 828 # If the provided url has a revision number that matches the revision |
823 # number of the existing directory, then we don't need to bother updating. | 829 # number of the existing directory, then we don't need to bother updating. |
824 if not options.force and from_info['Revision'] == revision: | 830 if not options.force and from_info['Revision'] == revision: |
825 if options.verbose or not forced_revision: | 831 if options.verbose or not forced_revision: |
826 print >>options.stdout, ("\n_____ %s%s" % ( | 832 print >>options.stdout, ("\n_____ %s%s" % ( |
827 self.relpath, rev_str)) | 833 self.relpath, rev_str)) |
(...skipping 12 matching lines...) Expand all Loading... |
840 """ | 846 """ |
841 path = os.path.join(self._root_dir, self.relpath) | 847 path = os.path.join(self._root_dir, self.relpath) |
842 if not os.path.isdir(path): | 848 if not os.path.isdir(path): |
843 # svn revert won't work if the directory doesn't exist. It needs to | 849 # svn revert won't work if the directory doesn't exist. It needs to |
844 # checkout instead. | 850 # checkout instead. |
845 print >>options.stdout, ("\n_____ %s is missing, synching instead" % | 851 print >>options.stdout, ("\n_____ %s is missing, synching instead" % |
846 self.relpath) | 852 self.relpath) |
847 # Don't reuse the args. | 853 # Don't reuse the args. |
848 return self.update(options, [], file_list) | 854 return self.update(options, [], file_list) |
849 | 855 |
850 files = CaptureSVNStatus(options, path) | 856 files = CaptureSVNStatus(path) |
851 # Batch the command. | 857 # Batch the command. |
852 files_to_revert = [] | 858 files_to_revert = [] |
853 for file in files: | 859 for file in files: |
854 file_path = os.path.join(path, file.path) | 860 file_path = os.path.join(path, file.path) |
855 print >>options.stdout, file_path | 861 print >>options.stdout, file_path |
856 # Unversioned file or unexpected unversioned file. | 862 # Unversioned file or unexpected unversioned file. |
857 if file.text_status in ('?', '~'): | 863 if file.text_status in ('?', '~'): |
858 # Remove extraneous file. Also remove unexpected unversioned | 864 # Remove extraneous file. Also remove unexpected unversioned |
859 # directories. svn won't touch them but we want to delete these. | 865 # directories. svn won't touch them but we want to delete these. |
860 file_list.append(file_path) | 866 file_list.append(file_path) |
861 try: | 867 try: |
862 os.remove(file_path) | 868 os.remove(file_path) |
863 except EnvironmentError: | 869 except EnvironmentError: |
864 RemoveDirectory(file_path) | 870 RemoveDirectory(file_path) |
865 | 871 |
866 if file.text_status != '?': | 872 if file.text_status != '?': |
867 # For any other status, svn revert will work. | 873 # For any other status, svn revert will work. |
868 file_list.append(file_path) | 874 file_list.append(file_path) |
869 files_to_revert.append(file.path) | 875 files_to_revert.append(file.path) |
870 | 876 |
871 # Revert them all at once. | 877 # Revert them all at once. |
872 if files_to_revert: | 878 if files_to_revert: |
873 accumulated_paths = [] | 879 accumulated_paths = [] |
874 accumulated_length = 0 | 880 accumulated_length = 0 |
875 command = ['revert'] | 881 command = ['revert'] |
876 for p in files_to_revert: | 882 for p in files_to_revert: |
877 # Some shell have issues with command lines too long. | 883 # Some shell have issues with command lines too long. |
878 if accumulated_length and accumulated_length + len(p) > 3072: | 884 if accumulated_length and accumulated_length + len(p) > 3072: |
879 RunSVN(options, command + accumulated_paths, | 885 RunSVN(command + accumulated_paths, |
880 os.path.join(self._root_dir, self.relpath)) | 886 os.path.join(self._root_dir, self.relpath)) |
881 accumulated_paths = [] | 887 accumulated_paths = [] |
882 accumulated_length = 0 | 888 accumulated_length = 0 |
883 else: | 889 else: |
884 accumulated_paths.append(p) | 890 accumulated_paths.append(p) |
885 accumulated_length += len(p) | 891 accumulated_length += len(p) |
886 if accumulated_paths: | 892 if accumulated_paths: |
887 RunSVN(options, command + accumulated_paths, | 893 RunSVN(command + accumulated_paths, |
888 os.path.join(self._root_dir, self.relpath)) | 894 os.path.join(self._root_dir, self.relpath)) |
889 | 895 |
890 def status(self, options, args, file_list): | 896 def status(self, options, args, file_list): |
891 """Display status information.""" | 897 """Display status information.""" |
892 path = os.path.join(self._root_dir, self.relpath) | 898 path = os.path.join(self._root_dir, self.relpath) |
893 command = ['status'] | 899 command = ['status'] |
894 command.extend(args) | 900 command.extend(args) |
895 if not os.path.isdir(path): | 901 if not os.path.isdir(path): |
896 # svn status won't work if the directory doesn't exist. | 902 # svn status won't work if the directory doesn't exist. |
897 print >> options.stdout, ( | 903 print >> options.stdout, ( |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 self._RunHooks(command, file_list, is_using_git) | 1324 self._RunHooks(command, file_list, is_using_git) |
1319 | 1325 |
1320 if command == 'update': | 1326 if command == 'update': |
1321 # notify the user if there is an orphaned entry in their working copy. | 1327 # notify the user if there is an orphaned entry in their working copy. |
1322 # TODO(darin): we should delete this directory manually if it doesn't | 1328 # TODO(darin): we should delete this directory manually if it doesn't |
1323 # have any changes in it. | 1329 # have any changes in it. |
1324 prev_entries = self._ReadEntries() | 1330 prev_entries = self._ReadEntries() |
1325 for entry in prev_entries: | 1331 for entry in prev_entries: |
1326 e_dir = os.path.join(self._root_dir, entry) | 1332 e_dir = os.path.join(self._root_dir, entry) |
1327 if entry not in entries and self._options.path_exists(e_dir): | 1333 if entry not in entries and self._options.path_exists(e_dir): |
1328 if CaptureSVNStatus(self._options, e_dir): | 1334 if CaptureSVNStatus(e_dir): |
1329 # There are modified files in this entry | 1335 # There are modified files in this entry |
1330 entries[entry] = None # Keep warning until removed. | 1336 entries[entry] = None # Keep warning until removed. |
1331 print >> self._options.stdout, ( | 1337 print >> self._options.stdout, ( |
1332 "\nWARNING: \"%s\" is no longer part of this client. " | 1338 "\nWARNING: \"%s\" is no longer part of this client. " |
1333 "It is recommended that you manually remove it.\n") % entry | 1339 "It is recommended that you manually remove it.\n") % entry |
1334 else: | 1340 else: |
1335 # Delete the entry | 1341 # Delete the entry |
1336 print >> self._options.stdout, ("\n________ deleting \'%s\' " + | 1342 print >> self._options.stdout, ("\n________ deleting \'%s\' " + |
1337 "in \'%s\'") % (entry, self._root_dir) | 1343 "in \'%s\'") % (entry, self._root_dir) |
1338 RemoveDirectory(e_dir) | 1344 RemoveDirectory(e_dir) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1376 entries_deps_content = {} | 1382 entries_deps_content = {} |
1377 | 1383 |
1378 # Inner helper to generate base url and rev tuple (including honoring | 1384 # Inner helper to generate base url and rev tuple (including honoring |
1379 # |revision_overrides|) | 1385 # |revision_overrides|) |
1380 def GetURLAndRev(name, original_url): | 1386 def GetURLAndRev(name, original_url): |
1381 if original_url.find("@") < 0: | 1387 if original_url.find("@") < 0: |
1382 if revision_overrides.has_key(name): | 1388 if revision_overrides.has_key(name): |
1383 return (original_url, int(revision_overrides[name])) | 1389 return (original_url, int(revision_overrides[name])) |
1384 else: | 1390 else: |
1385 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) | 1391 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) |
1386 return (original_url, CaptureSVNHeadRevision(self._options, | 1392 return (original_url, CaptureSVNHeadRevision(original_url)) |
1387 original_url)) | |
1388 else: | 1393 else: |
1389 url_components = original_url.split("@") | 1394 url_components = original_url.split("@") |
1390 if revision_overrides.has_key(name): | 1395 if revision_overrides.has_key(name): |
1391 return (url_components[0], int(revision_overrides[name])) | 1396 return (url_components[0], int(revision_overrides[name])) |
1392 else: | 1397 else: |
1393 return (url_components[0], int(url_components[1])) | 1398 return (url_components[0], int(url_components[1])) |
1394 | 1399 |
1395 # Run on the base solutions first. | 1400 # Run on the base solutions first. |
1396 for solution in solutions: | 1401 for solution in solutions: |
1397 name = solution["name"] | 1402 name = solution["name"] |
1398 if name in entries: | 1403 if name in entries: |
1399 raise Error("solution %s specified more than once" % name) | 1404 raise Error("solution %s specified more than once" % name) |
1400 (url, rev) = GetURLAndRev(name, solution["url"]) | 1405 (url, rev) = GetURLAndRev(name, solution["url"]) |
1401 entries[name] = "%s@%d" % (url, rev) | 1406 entries[name] = "%s@%d" % (url, rev) |
1402 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) | 1407 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) |
1403 entries_deps_content[name] = CaptureSVN( | 1408 entries_deps_content[name] = CaptureSVN( |
1404 self._options, | |
1405 ["cat", | 1409 ["cat", |
1406 "%s/%s@%d" % (url, | 1410 "%s/%s@%d" % (url, |
1407 self._options.deps_file, | 1411 self._options.deps_file, |
1408 rev)], | 1412 rev)], |
1409 os.getcwd()) | 1413 os.getcwd()) |
1410 | 1414 |
1411 # Process the dependencies next (sort alphanumerically to ensure that | 1415 # Process the dependencies next (sort alphanumerically to ensure that |
1412 # containing directories get populated first and for readability) | 1416 # containing directories get populated first and for readability) |
1413 deps = self._ParseAllDeps(entries, entries_deps_content) | 1417 deps = self._ParseAllDeps(entries, entries_deps_content) |
1414 deps_to_process = deps.keys() | 1418 deps_to_process = deps.keys() |
1415 deps_to_process.sort() | 1419 deps_to_process.sort() |
1416 | 1420 |
1417 # First pass for direct dependencies. | 1421 # First pass for direct dependencies. |
1418 for d in deps_to_process: | 1422 for d in deps_to_process: |
1419 if type(deps[d]) == str: | 1423 if type(deps[d]) == str: |
1420 (url, rev) = GetURLAndRev(d, deps[d]) | 1424 (url, rev) = GetURLAndRev(d, deps[d]) |
1421 entries[d] = "%s@%d" % (url, rev) | 1425 entries[d] = "%s@%d" % (url, rev) |
1422 | 1426 |
1423 # Second pass for inherited deps (via the From keyword) | 1427 # Second pass for inherited deps (via the From keyword) |
1424 for d in deps_to_process: | 1428 for d in deps_to_process: |
1425 if type(deps[d]) != str: | 1429 if type(deps[d]) != str: |
1426 deps_parent_url = entries[deps[d].module_name] | 1430 deps_parent_url = entries[deps[d].module_name] |
1427 if deps_parent_url.find("@") < 0: | 1431 if deps_parent_url.find("@") < 0: |
1428 raise Error("From %s missing revisioned url" % deps[d].module_name) | 1432 raise Error("From %s missing revisioned url" % deps[d].module_name) |
1429 deps_parent_url_components = deps_parent_url.split("@") | 1433 deps_parent_url_components = deps_parent_url.split("@") |
1430 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) | 1434 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) |
1431 deps_parent_content = CaptureSVN( | 1435 deps_parent_content = CaptureSVN( |
1432 self._options, | |
1433 ["cat", | 1436 ["cat", |
1434 "%s/%s@%s" % (deps_parent_url_components[0], | 1437 "%s/%s@%s" % (deps_parent_url_components[0], |
1435 self._options.deps_file, | 1438 self._options.deps_file, |
1436 deps_parent_url_components[1])], | 1439 deps_parent_url_components[1])], |
1437 os.getcwd()) | 1440 os.getcwd()) |
1438 sub_deps = self._ParseSolutionDeps( | 1441 sub_deps = self._ParseSolutionDeps( |
1439 deps[d].module_name, | 1442 deps[d].module_name, |
1440 FileRead(os.path.join(self._root_dir, | 1443 FileRead(os.path.join(self._root_dir, |
1441 deps[d].module_name, | 1444 deps[d].module_name, |
1442 self._options.deps_file)), | 1445 self._options.deps_file)), |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1716 | 1719 |
1717 if "__main__" == __name__: | 1720 if "__main__" == __name__: |
1718 try: | 1721 try: |
1719 result = Main(sys.argv) | 1722 result = Main(sys.argv) |
1720 except Error, e: | 1723 except Error, e: |
1721 print "Error: %s" % str(e) | 1724 print "Error: %s" % str(e) |
1722 result = 1 | 1725 result = 1 |
1723 sys.exit(result) | 1726 sys.exit(result) |
1724 | 1727 |
1725 # vim: ts=2:sw=2:tw=80:et: | 1728 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |