Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Gclient-specific SCM-specific operations.""" | 5 """Gclient-specific SCM-specific operations.""" |
| 6 | 6 |
| 7 import logging | 7 import logging |
| 8 import os | 8 import os |
| 9 import posixpath | 9 import posixpath |
| 10 import re | 10 import re |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 | 78 |
| 79 def CreateSCM(url, root_dir=None, relpath=None): | 79 def CreateSCM(url, root_dir=None, relpath=None): |
| 80 SCM_MAP = { | 80 SCM_MAP = { |
| 81 'svn' : SVNWrapper, | 81 'svn' : SVNWrapper, |
| 82 'git' : GitWrapper, | 82 'git' : GitWrapper, |
| 83 } | 83 } |
| 84 | 84 |
| 85 scm_name = GetScmName(url) | 85 scm_name = GetScmName(url) |
| 86 if not scm_name in SCM_MAP: | 86 if not scm_name in SCM_MAP: |
| 87 raise gclient_utils.Error('No SCM found for url %s' % url) | 87 raise gclient_utils.Error('No SCM found for url %s' % url) |
| 88 return SCM_MAP[scm_name](url, root_dir, relpath) | 88 found_scm = SCM_MAP[scm_name](url, root_dir, relpath) |
| 89 if not found_scm.BinaryExists(): | |
| 90 raise gclient_utils.Error('%s command not found' % scm_name) | |
| 91 return found_scm | |
| 89 | 92 |
| 90 | 93 |
| 91 # SCMWrapper base class | 94 # SCMWrapper base class |
| 92 | 95 |
| 93 class SCMWrapper(object): | 96 class SCMWrapper(object): |
| 94 """Add necessary glue between all the supported SCM. | 97 """Add necessary glue between all the supported SCM. |
| 95 | 98 |
| 96 This is the abstraction layer to bind to different SCM. | 99 This is the abstraction layer to bind to different SCM. |
| 97 """ | 100 """ |
| 98 def __init__(self, url=None, root_dir=None, relpath=None): | 101 def __init__(self, url=None, root_dir=None, relpath=None): |
| 99 self.url = url | 102 self.url = url |
| 100 self._root_dir = root_dir | 103 self._root_dir = root_dir |
| 101 if self._root_dir: | 104 if self._root_dir: |
| 102 self._root_dir = self._root_dir.replace('/', os.sep) | 105 self._root_dir = self._root_dir.replace('/', os.sep) |
| 103 self.relpath = relpath | 106 self.relpath = relpath |
| 104 if self.relpath: | 107 if self.relpath: |
| 105 self.relpath = self.relpath.replace('/', os.sep) | 108 self.relpath = self.relpath.replace('/', os.sep) |
| 106 if self.relpath and self._root_dir: | 109 if self.relpath and self._root_dir: |
| 107 self.checkout_path = os.path.join(self._root_dir, self.relpath) | 110 self.checkout_path = os.path.join(self._root_dir, self.relpath) |
| 111 self._checker_command = 'help' | |
| 112 self._binary_name = None | |
| 113 | |
| 114 def BinaryExists(self): | |
|
M-A Ruel
2012/04/17 12:15:55
This function may be called over 100 times for a g
Jun Mukai
2012/04/18 02:46:36
Oh, got it. Modified to use AssertVersion.
| |
| 115 """Returns true if the command exists.""" | |
| 116 # Do not call _Run() because this we don't want to leave any messages for | |
| 117 # this check. | |
| 118 try: | |
| 119 return gclient_utils.CheckCallAndFilter( | |
| 120 [self._binary_name, self._checker_command], print_stdout=False) == 0 | |
| 121 except OSError: | |
| 122 return False | |
| 108 | 123 |
| 109 def RunCommand(self, command, options, args, file_list=None): | 124 def RunCommand(self, command, options, args, file_list=None): |
| 110 # file_list will have all files that are modified appended to it. | 125 # file_list will have all files that are modified appended to it. |
| 111 if file_list is None: | 126 if file_list is None: |
| 112 file_list = [] | 127 file_list = [] |
| 113 | 128 |
| 114 commands = ['cleanup', 'update', 'updatesingle', 'revert', | 129 commands = ['cleanup', 'update', 'updatesingle', 'revert', |
| 115 'revinfo', 'status', 'diff', 'pack', 'runhooks'] | 130 'revinfo', 'status', 'diff', 'pack', 'runhooks'] |
| 116 | 131 |
| 117 if not command in commands: | 132 if not command in commands: |
| 118 raise gclient_utils.Error('Unknown command %s' % command) | 133 raise gclient_utils.Error('Unknown command %s' % command) |
| 119 | 134 |
| 120 if not command in dir(self): | 135 if not command in dir(self): |
| 121 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( | 136 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( |
| 122 command, self.__class__.__name__)) | 137 command, self.__class__.__name__)) |
| 123 | 138 |
| 124 return getattr(self, command)(options, args, file_list) | 139 return getattr(self, command)(options, args, file_list) |
| 125 | 140 |
| 126 | 141 |
| 127 class GitWrapper(SCMWrapper): | 142 class GitWrapper(SCMWrapper): |
| 128 """Wrapper for Git""" | 143 """Wrapper for Git""" |
| 129 | 144 |
| 130 def __init__(self, url=None, root_dir=None, relpath=None): | 145 def __init__(self, url=None, root_dir=None, relpath=None): |
| 131 """Removes 'git+' fake prefix from git URL.""" | 146 """Removes 'git+' fake prefix from git URL.""" |
| 132 if url.startswith('git+http://') or url.startswith('git+https://'): | 147 if url.startswith('git+http://') or url.startswith('git+https://'): |
| 133 url = url[4:] | 148 url = url[4:] |
| 134 SCMWrapper.__init__(self, url, root_dir, relpath) | 149 SCMWrapper.__init__(self, url, root_dir, relpath) |
| 150 self._binary_name = 'git' | |
| 135 | 151 |
| 136 def GetRevisionDate(self, revision): | 152 def GetRevisionDate(self, revision): |
| 137 """Returns the given revision's date in ISO-8601 format (which contains the | 153 """Returns the given revision's date in ISO-8601 format (which contains the |
| 138 time zone).""" | 154 time zone).""" |
| 139 # TODO(floitsch): get the time-stamp of the given revision and not just the | 155 # TODO(floitsch): get the time-stamp of the given revision and not just the |
| 140 # time-stamp of the currently checked out revision. | 156 # time-stamp of the currently checked out revision. |
| 141 return self._Capture(['log', '-n', '1', '--format=%ai']) | 157 return self._Capture(['log', '-n', '1', '--format=%ai']) |
| 142 | 158 |
| 143 @staticmethod | 159 @staticmethod |
| 144 def cleanup(options, args, file_list): | 160 def cleanup(options, args, file_list): |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 752 | 768 |
| 753 def _GetCurrentBranch(self): | 769 def _GetCurrentBranch(self): |
| 754 # Returns name of current branch or None for detached HEAD | 770 # Returns name of current branch or None for detached HEAD |
| 755 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) | 771 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) |
| 756 if branch == 'HEAD': | 772 if branch == 'HEAD': |
| 757 return None | 773 return None |
| 758 return branch | 774 return branch |
| 759 | 775 |
| 760 def _Capture(self, args): | 776 def _Capture(self, args): |
| 761 return subprocess2.check_output( | 777 return subprocess2.check_output( |
| 762 ['git'] + args, | 778 [self._binary_name] + args, |
| 763 stderr=subprocess2.PIPE, | 779 stderr=subprocess2.PIPE, |
| 764 cwd=self.checkout_path).strip() | 780 cwd=self.checkout_path).strip() |
| 765 | 781 |
| 766 def _Run(self, args, options, **kwargs): | 782 def _Run(self, args, options, **kwargs): |
| 767 kwargs.setdefault('cwd', self.checkout_path) | 783 kwargs.setdefault('cwd', self.checkout_path) |
| 768 kwargs.setdefault('print_stdout', True) | 784 kwargs.setdefault('print_stdout', True) |
| 769 stdout = kwargs.get('stdout', sys.stdout) | 785 stdout = kwargs.get('stdout', sys.stdout) |
| 770 stdout.write('\n________ running \'git %s\' in \'%s\'\n' % ( | 786 stdout.write('\n________ running \'git %s\' in \'%s\'\n' % ( |
| 771 ' '.join(args), kwargs['cwd'])) | 787 ' '.join(args), kwargs['cwd'])) |
| 772 gclient_utils.CheckCallAndFilter(['git'] + args, **kwargs) | 788 gclient_utils.CheckCallAndFilter([self._binary_name] + args, **kwargs) |
| 773 | 789 |
| 774 | 790 |
| 775 class SVNWrapper(SCMWrapper): | 791 class SVNWrapper(SCMWrapper): |
| 776 """ Wrapper for SVN """ | 792 """ Wrapper for SVN """ |
| 777 | 793 |
| 794 def __init__(self, url=None, root_dir=None, relpath=None): | |
| 795 SCMWrapper.__init__(self, url, root_dir, relpath) | |
| 796 self._binary_name = 'svn' | |
| 797 | |
| 778 def GetRevisionDate(self, revision): | 798 def GetRevisionDate(self, revision): |
| 779 """Returns the given revision's date in ISO-8601 format (which contains the | 799 """Returns the given revision's date in ISO-8601 format (which contains the |
| 780 time zone).""" | 800 time zone).""" |
| 781 date = scm.SVN.Capture( | 801 date = scm.SVN.Capture( |
| 782 ['propget', '--revprop', 'svn:date', '-r', revision], | 802 ['propget', '--revprop', 'svn:date', '-r', revision], |
| 783 os.path.join(self.checkout_path, '.')) | 803 os.path.join(self.checkout_path, '.')) |
| 784 return date.strip() | 804 return date.strip() |
| 785 | 805 |
| 786 def cleanup(self, options, args, file_list): | 806 def cleanup(self, options, args, file_list): |
| 787 """Cleanup working copy.""" | 807 """Cleanup working copy.""" |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1087 'correct.') % rev) | 1107 'correct.') % rev) |
| 1088 return rev | 1108 return rev |
| 1089 | 1109 |
| 1090 def FullUrlForRelativeUrl(self, url): | 1110 def FullUrlForRelativeUrl(self, url): |
| 1091 # Find the forth '/' and strip from there. A bit hackish. | 1111 # Find the forth '/' and strip from there. A bit hackish. |
| 1092 return '/'.join(self.url.split('/')[:4]) + url | 1112 return '/'.join(self.url.split('/')[:4]) + url |
| 1093 | 1113 |
| 1094 def _Run(self, args, options, **kwargs): | 1114 def _Run(self, args, options, **kwargs): |
| 1095 """Runs a commands that goes to stdout.""" | 1115 """Runs a commands that goes to stdout.""" |
| 1096 kwargs.setdefault('cwd', self.checkout_path) | 1116 kwargs.setdefault('cwd', self.checkout_path) |
| 1097 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, | 1117 gclient_utils.CheckCallAndFilterAndHeader([self._binary_name] + args, |
| 1098 always=options.verbose, **kwargs) | 1118 always=options.verbose, **kwargs) |
| 1099 | 1119 |
| 1100 def _RunAndGetFileList(self, args, options, file_list, cwd=None): | 1120 def _RunAndGetFileList(self, args, options, file_list, cwd=None): |
| 1101 """Runs a commands that goes to stdout and grabs the file listed.""" | 1121 """Runs a commands that goes to stdout and grabs the file listed.""" |
| 1102 cwd = cwd or self.checkout_path | 1122 cwd = cwd or self.checkout_path |
| 1103 scm.SVN.RunAndGetFileList( | 1123 scm.SVN.RunAndGetFileList( |
| 1104 options.verbose, | 1124 options.verbose, |
| 1105 args + ['--ignore-externals'], | 1125 args + ['--ignore-externals'], |
| 1106 cwd=cwd, | 1126 cwd=cwd, |
| 1107 file_list=file_list) | 1127 file_list=file_list) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1129 new_command.append('--force') | 1149 new_command.append('--force') |
| 1130 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1150 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1131 new_command.extend(('--accept', 'theirs-conflict')) | 1151 new_command.extend(('--accept', 'theirs-conflict')) |
| 1132 elif options.manually_grab_svn_rev: | 1152 elif options.manually_grab_svn_rev: |
| 1133 new_command.append('--force') | 1153 new_command.append('--force') |
| 1134 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1154 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1135 new_command.extend(('--accept', 'postpone')) | 1155 new_command.extend(('--accept', 'postpone')) |
| 1136 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1156 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1137 new_command.extend(('--accept', 'postpone')) | 1157 new_command.extend(('--accept', 'postpone')) |
| 1138 return new_command | 1158 return new_command |
| OLD | NEW |