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

Side by Side Diff: scm.py

Issue 3353018: Make gclient_scm_test much more silent (Closed)
Patch Set: gclient_scm_test can now be run Created 10 years, 3 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 | « gclient_utils.py ('k') | tests/gclient_scm_test.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 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2006-2009 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 """SCM-specific utility classes.""" 5 """SCM-specific utility classes."""
6 6
7 import cStringIO 7 import cStringIO
8 import glob 8 import glob
9 import os 9 import os
10 import re 10 import re
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 for line in file_content: 59 for line in file_content:
60 data.write('+') 60 data.write('+')
61 data.write(line) 61 data.write(line)
62 result = data.getvalue() 62 result = data.getvalue()
63 data.close() 63 data.close()
64 return result 64 return result
65 65
66 66
67 class GIT(object): 67 class GIT(object):
68 @staticmethod 68 @staticmethod
69 def Capture(args, in_directory=None, print_error=True, error_ok=False): 69 def Capture(args, **kwargs):
70 """Runs git, capturing output sent to stdout as a string. 70 return gclient_utils.CheckCall(['git'] + args, print_error=False,
71 71 **kwargs)[0]
72 Args:
73 args: A sequence of command line parameters to be passed to git.
74 in_directory: The directory where git is to be run.
75
76 Returns:
77 The output sent to stdout as a string.
78 """
79 try:
80 return gclient_utils.CheckCall(['git'] + args, in_directory, print_error)
81 except gclient_utils.CheckCallError:
82 if error_ok:
83 return ('', '')
84 raise
85 72
86 @staticmethod 73 @staticmethod
87 def CaptureStatus(files, upstream_branch=None): 74 def CaptureStatus(files, upstream_branch=None):
88 """Returns git status. 75 """Returns git status.
89 76
90 @files can be a string (one file) or a list of files. 77 @files can be a string (one file) or a list of files.
91 78
92 Returns an array of (status, file) tuples.""" 79 Returns an array of (status, file) tuples."""
93 if upstream_branch is None: 80 if upstream_branch is None:
94 upstream_branch = GIT.GetUpstreamBranch(os.getcwd()) 81 upstream_branch = GIT.GetUpstreamBranch(os.getcwd())
95 if upstream_branch is None: 82 if upstream_branch is None:
96 raise Exception("Cannot determine upstream branch") 83 raise gclient_utils.Error('Cannot determine upstream branch')
97 command = ["diff", "--name-status", "-r", "%s..." % upstream_branch] 84 command = ['diff', '--name-status', '-r', '%s...' % upstream_branch]
98 if not files: 85 if not files:
99 pass 86 pass
100 elif isinstance(files, basestring): 87 elif isinstance(files, basestring):
101 command.append(files) 88 command.append(files)
102 else: 89 else:
103 command.extend(files) 90 command.extend(files)
104 91 status = GIT.Capture(command).rstrip()
105 status = GIT.Capture(command)[0].rstrip()
106 results = [] 92 results = []
107 if status: 93 if status:
108 for statusline in status.split('\n'): 94 for statusline in status.splitlines():
109 m = re.match('^(\w)\t(.+)$', statusline) 95 m = re.match('^(\w)\t(.+)$', statusline)
110 if not m: 96 if not m:
111 raise Exception("status currently unsupported: %s" % statusline) 97 raise gclient_utils.Error(
98 'status currently unsupported: %s' % statusline)
112 results.append(('%s ' % m.group(1), m.group(2))) 99 results.append(('%s ' % m.group(1), m.group(2)))
113 return results 100 return results
114 101
115 @staticmethod 102 @staticmethod
116 def GetEmail(repo_root): 103 def GetEmail(cwd):
117 """Retrieves the user email address if known.""" 104 """Retrieves the user email address if known."""
118 # We could want to look at the svn cred when it has a svn remote but it 105 # We could want to look at the svn cred when it has a svn remote but it
119 # should be fine for now, users should simply configure their git settings. 106 # should be fine for now, users should simply configure their git settings.
120 return GIT.Capture(['config', 'user.email'], 107 try:
121 repo_root, error_ok=True)[0].strip() 108 return GIT.Capture(['config', 'user.email'], cwd=cwd).strip()
109 except gclient_utils.CheckCallError:
110 return ''
122 111
123 @staticmethod 112 @staticmethod
124 def ShortBranchName(branch): 113 def ShortBranchName(branch):
125 """Converts a name like 'refs/heads/foo' to just 'foo'.""" 114 """Converts a name like 'refs/heads/foo' to just 'foo'."""
126 return branch.replace('refs/heads/', '') 115 return branch.replace('refs/heads/', '')
127 116
128 @staticmethod 117 @staticmethod
129 def GetBranchRef(cwd): 118 def GetBranchRef(cwd):
130 """Returns the full branch reference, e.g. 'refs/heads/master'.""" 119 """Returns the full branch reference, e.g. 'refs/heads/master'."""
131 return GIT.Capture(['symbolic-ref', 'HEAD'], cwd)[0].strip() 120 return GIT.Capture(['symbolic-ref', 'HEAD'], cwd=cwd).strip()
132 121
133 @staticmethod 122 @staticmethod
134 def GetBranch(cwd): 123 def GetBranch(cwd):
135 """Returns the short branch name, e.g. 'master'.""" 124 """Returns the short branch name, e.g. 'master'."""
136 return GIT.ShortBranchName(GIT.GetBranchRef(cwd)) 125 return GIT.ShortBranchName(GIT.GetBranchRef(cwd))
137 126
138 @staticmethod 127 @staticmethod
139 def IsGitSvn(cwd): 128 def IsGitSvn(cwd):
140 """Returns true if this repo looks like it's using git-svn.""" 129 """Returns true if this repo looks like it's using git-svn."""
141 # If you have any "svn-remote.*" config keys, we think you're using svn. 130 # If you have any "svn-remote.*" config keys, we think you're using svn.
142 try: 131 try:
143 GIT.Capture(['config', '--get-regexp', r'^svn-remote\.'], cwd) 132 GIT.Capture(['config', '--get-regexp', r'^svn-remote\.'], cwd=cwd)
144 return True 133 return True
145 except gclient_utils.CheckCallError: 134 except gclient_utils.CheckCallError:
146 return False 135 return False
147 136
148 @staticmethod 137 @staticmethod
149 def GetSVNBranch(cwd): 138 def GetSVNBranch(cwd):
150 """Returns the svn branch name if found.""" 139 """Returns the svn branch name if found."""
151 # Try to figure out which remote branch we're based on. 140 # Try to figure out which remote branch we're based on.
152 # Strategy: 141 # Strategy:
153 # 1) find all git-svn branches and note their svn URLs. 142 # 1) find all git-svn branches and note their svn URLs.
154 # 2) iterate through our branch history and match up the URLs. 143 # 2) iterate through our branch history and match up the URLs.
155 144
156 # regexp matching the git-svn line that contains the URL. 145 # regexp matching the git-svn line that contains the URL.
157 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) 146 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE)
158 147
159 # Get the refname and svn url for all refs/remotes/*. 148 # Get the refname and svn url for all refs/remotes/*.
160 remotes = GIT.Capture( 149 remotes = GIT.Capture(
161 ['for-each-ref', '--format=%(refname)', 'refs/remotes'], 150 ['for-each-ref', '--format=%(refname)', 'refs/remotes'],
162 cwd)[0].splitlines() 151 cwd=cwd).splitlines()
163 svn_refs = {} 152 svn_refs = {}
164 for ref in remotes: 153 for ref in remotes:
165 match = git_svn_re.search( 154 match = git_svn_re.search(
166 GIT.Capture(['cat-file', '-p', ref], cwd)[0]) 155 GIT.Capture(['cat-file', '-p', ref], cwd=cwd))
167 # Prefer origin/HEAD over all others. 156 # Prefer origin/HEAD over all others.
168 if match and (match.group(1) not in svn_refs or 157 if match and (match.group(1) not in svn_refs or
169 ref == "refs/remotes/origin/HEAD"): 158 ref == "refs/remotes/origin/HEAD"):
170 svn_refs[match.group(1)] = ref 159 svn_refs[match.group(1)] = ref
171 160
172 svn_branch = '' 161 svn_branch = ''
173 if len(svn_refs) == 1: 162 if len(svn_refs) == 1:
174 # Only one svn branch exists -- seems like a good candidate. 163 # Only one svn branch exists -- seems like a good candidate.
175 svn_branch = svn_refs.values()[0] 164 svn_branch = svn_refs.values()[0]
176 elif len(svn_refs) > 1: 165 elif len(svn_refs) > 1:
(...skipping 14 matching lines...) Expand all
191 return svn_branch 180 return svn_branch
192 181
193 @staticmethod 182 @staticmethod
194 def FetchUpstreamTuple(cwd): 183 def FetchUpstreamTuple(cwd):
195 """Returns a tuple containg remote and remote ref, 184 """Returns a tuple containg remote and remote ref,
196 e.g. 'origin', 'refs/heads/master' 185 e.g. 'origin', 'refs/heads/master'
197 Tries to be intelligent and understand git-svn. 186 Tries to be intelligent and understand git-svn.
198 """ 187 """
199 remote = '.' 188 remote = '.'
200 branch = GIT.GetBranch(cwd) 189 branch = GIT.GetBranch(cwd)
201 upstream_branch = None 190 try:
202 upstream_branch = GIT.Capture( 191 upstream_branch = GIT.Capture(
203 ['config', 'branch.%s.merge' % branch], in_directory=cwd, 192 ['config', 'branch.%s.merge' % branch], cwd=cwd).strip()
204 error_ok=True)[0].strip() 193 except gclient_utils.Error:
194 upstream_branch = None
205 if upstream_branch: 195 if upstream_branch:
206 remote = GIT.Capture( 196 try:
207 ['config', 'branch.%s.remote' % branch], 197 remote = GIT.Capture(
208 in_directory=cwd, error_ok=True)[0].strip() 198 ['config', 'branch.%s.remote' % branch], cwd=cwd).strip()
199 except gclient_utils.Error:
200 pass
209 else: 201 else:
210 # Fall back on trying a git-svn upstream branch. 202 # Fall back on trying a git-svn upstream branch.
211 if GIT.IsGitSvn(cwd): 203 if GIT.IsGitSvn(cwd):
212 upstream_branch = GIT.GetSVNBranch(cwd) 204 upstream_branch = GIT.GetSVNBranch(cwd)
213 else: 205 else:
214 # Else, try to guess the origin remote. 206 # Else, try to guess the origin remote.
215 remote_branches = GIT.Capture( 207 remote_branches = GIT.Capture(['branch', '-r'], cwd=cwd).split()
216 ['branch', '-r'], in_directory=cwd)[0].split()
217 if 'origin/master' in remote_branches: 208 if 'origin/master' in remote_branches:
218 # Fall back on origin/master if it exits. 209 # Fall back on origin/master if it exits.
219 remote = 'origin' 210 remote = 'origin'
220 upstream_branch = 'refs/heads/master' 211 upstream_branch = 'refs/heads/master'
221 elif 'origin/trunk' in remote_branches: 212 elif 'origin/trunk' in remote_branches:
222 # Fall back on origin/trunk if it exists. Generally a shared 213 # Fall back on origin/trunk if it exists. Generally a shared
223 # git-svn clone 214 # git-svn clone
224 remote = 'origin' 215 remote = 'origin'
225 upstream_branch = 'refs/heads/trunk' 216 upstream_branch = 'refs/heads/trunk'
226 else: 217 else:
(...skipping 20 matching lines...) Expand all
247 if not branch: 238 if not branch:
248 branch = GIT.GetUpstreamBranch(cwd) 239 branch = GIT.GetUpstreamBranch(cwd)
249 command = ['diff', '-p', '--no-prefix', '--no-ext-diff', 240 command = ['diff', '-p', '--no-prefix', '--no-ext-diff',
250 branch + "..." + branch_head] 241 branch + "..." + branch_head]
251 if not full_move: 242 if not full_move:
252 command.append('-C') 243 command.append('-C')
253 # TODO(maruel): --binary support. 244 # TODO(maruel): --binary support.
254 if files: 245 if files:
255 command.append('--') 246 command.append('--')
256 command.extend(files) 247 command.extend(files)
257 diff = GIT.Capture(command, cwd)[0].splitlines(True) 248 diff = GIT.Capture(command, cwd=cwd).splitlines(True)
258 for i in range(len(diff)): 249 for i in range(len(diff)):
259 # In the case of added files, replace /dev/null with the path to the 250 # In the case of added files, replace /dev/null with the path to the
260 # file being added. 251 # file being added.
261 if diff[i].startswith('--- /dev/null'): 252 if diff[i].startswith('--- /dev/null'):
262 diff[i] = '--- %s' % diff[i+1][4:] 253 diff[i] = '--- %s' % diff[i+1][4:]
263 return ''.join(diff) 254 return ''.join(diff)
264 255
265 @staticmethod 256 @staticmethod
266 def GetDifferentFiles(cwd, branch=None, branch_head='HEAD'): 257 def GetDifferentFiles(cwd, branch=None, branch_head='HEAD'):
267 """Returns the list of modified files between two branches.""" 258 """Returns the list of modified files between two branches."""
268 if not branch: 259 if not branch:
269 branch = GIT.GetUpstreamBranch(cwd) 260 branch = GIT.GetUpstreamBranch(cwd)
270 command = ['diff', '--name-only', branch + "..." + branch_head] 261 command = ['diff', '--name-only', branch + "..." + branch_head]
271 return GIT.Capture(command, cwd)[0].splitlines(False) 262 return GIT.Capture(command, cwd=cwd).splitlines(False)
272 263
273 @staticmethod 264 @staticmethod
274 def GetPatchName(cwd): 265 def GetPatchName(cwd):
275 """Constructs a name for this patch.""" 266 """Constructs a name for this patch."""
276 short_sha = GIT.Capture(['rev-parse', '--short=4', 'HEAD'], cwd)[0].strip() 267 short_sha = GIT.Capture(['rev-parse', '--short=4', 'HEAD'], cwd=cwd).strip()
277 return "%s#%s" % (GIT.GetBranch(cwd), short_sha) 268 return "%s#%s" % (GIT.GetBranch(cwd), short_sha)
278 269
279 @staticmethod 270 @staticmethod
280 def GetCheckoutRoot(path): 271 def GetCheckoutRoot(cwd):
281 """Returns the top level directory of a git checkout as an absolute path. 272 """Returns the top level directory of a git checkout as an absolute path.
282 """ 273 """
283 root = GIT.Capture(['rev-parse', '--show-cdup'], path)[0].strip() 274 root = GIT.Capture(['rev-parse', '--show-cdup'], cwd=cwd).strip()
284 return os.path.abspath(os.path.join(path, root)) 275 return os.path.abspath(os.path.join(cwd, root))
285 276
286 @staticmethod 277 @staticmethod
287 def AssertVersion(min_version): 278 def AssertVersion(min_version):
288 """Asserts git's version is at least min_version.""" 279 """Asserts git's version is at least min_version."""
289 def only_int(val): 280 def only_int(val):
290 if val.isdigit(): 281 if val.isdigit():
291 return int(val) 282 return int(val)
292 else: 283 else:
293 return 0 284 return 0
294 current_version = GIT.Capture(['--version'])[0].split()[-1] 285 current_version = GIT.Capture(['--version']).split()[-1]
295 current_version_list = map(only_int, current_version.split('.')) 286 current_version_list = map(only_int, current_version.split('.'))
296 for min_ver in map(int, min_version.split('.')): 287 for min_ver in map(int, min_version.split('.')):
297 ver = current_version_list.pop(0) 288 ver = current_version_list.pop(0)
298 if ver < min_ver: 289 if ver < min_ver:
299 return (False, current_version) 290 return (False, current_version)
300 elif ver > min_ver: 291 elif ver > min_ver:
301 return (True, current_version) 292 return (True, current_version)
302 return (True, current_version) 293 return (True, current_version)
303 294
304 295
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 if not SVN.current_version: 813 if not SVN.current_version:
823 SVN.current_version = SVN.Capture(['--version']).split()[2] 814 SVN.current_version = SVN.Capture(['--version']).split()[2]
824 current_version_list = map(only_int, SVN.current_version.split('.')) 815 current_version_list = map(only_int, SVN.current_version.split('.'))
825 for min_ver in map(int, min_version.split('.')): 816 for min_ver in map(int, min_version.split('.')):
826 ver = current_version_list.pop(0) 817 ver = current_version_list.pop(0)
827 if ver < min_ver: 818 if ver < min_ver:
828 return (False, SVN.current_version) 819 return (False, SVN.current_version)
829 elif ver > min_ver: 820 elif ver > min_ver:
830 return (True, SVN.current_version) 821 return (True, SVN.current_version)
831 return (True, SVN.current_version) 822 return (True, SVN.current_version)
OLDNEW
« no previous file with comments | « gclient_utils.py ('k') | tests/gclient_scm_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698