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

Side by Side Diff: gclient_scm.py

Issue 3303004: Convert all print statements to use options.stdout. (Closed)
Patch Set: 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 | « no previous file | no next file » | 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) 2010 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2010 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
11 import subprocess 11 import subprocess
12 import sys 12 import sys
13 import time 13 import time
14 14
15 import scm 15 import scm
16 import gclient_utils 16 import gclient_utils
17 17
18 18
19 class DiffFilterer(object): 19 class DiffFilterer(object):
20 """Simple class which tracks which file is being diffed and 20 """Simple class which tracks which file is being diffed and
21 replaces instances of its file name in the original and 21 replaces instances of its file name in the original and
22 working copy lines of the svn/git diff output.""" 22 working copy lines of the svn/git diff output."""
23 index_string = "Index: " 23 index_string = "Index: "
24 original_prefix = "--- " 24 original_prefix = "--- "
25 working_prefix = "+++ " 25 working_prefix = "+++ "
26 26
27 def __init__(self, relpath): 27 def __init__(self, relpath, stdout):
bradn 2010/09/01 20:15:54 Did you want this to have a default of sys.stdout
M-A Ruel 2010/09/01 23:45:35 No.
28 # Note that we always use '/' as the path separator to be 28 # Note that we always use '/' as the path separator to be
29 # consistent with svn's cygwin-style output on Windows 29 # consistent with svn's cygwin-style output on Windows
30 self._relpath = relpath.replace("\\", "/") 30 self._relpath = relpath.replace("\\", "/")
31 self._current_file = "" 31 self._current_file = ""
32 self._replacement_file = "" 32 self._replacement_file = ""
33 self._stdout = stdout
33 34
34 def SetCurrentFile(self, current_file): 35 def SetCurrentFile(self, current_file):
35 self._current_file = current_file 36 self._current_file = current_file
36 # Note that we always use '/' as the path separator to be 37 # Note that we always use '/' as the path separator to be
37 # consistent with svn's cygwin-style output on Windows 38 # consistent with svn's cygwin-style output on Windows
38 self._replacement_file = posixpath.join(self._relpath, current_file) 39 self._replacement_file = posixpath.join(self._relpath, current_file)
39 40
40 def ReplaceAndPrint(self, line): 41 def _Replace(self, line):
41 print(line.replace(self._current_file, self._replacement_file)) 42 return line.replace(self._current_file, self._replacement_file)
42 43
43 def Filter(self, line): 44 def Filter(self, line):
44 if (line.startswith(self.index_string)): 45 if (line.startswith(self.index_string)):
45 self.SetCurrentFile(line[len(self.index_string):]) 46 self.SetCurrentFile(line[len(self.index_string):])
46 self.ReplaceAndPrint(line) 47 line = self._Replace(line)
47 else: 48 else:
48 if (line.startswith(self.original_prefix) or 49 if (line.startswith(self.original_prefix) or
49 line.startswith(self.working_prefix)): 50 line.startswith(self.working_prefix)):
50 self.ReplaceAndPrint(line) 51 line = self._Replace(line)
51 else: 52 self._stdout.write(line + '\n')
52 print line
53 53
54 54
55 ### SCM abstraction layer 55 ### SCM abstraction layer
56 56
57 # Factory Method for SCM wrapper creation 57 # Factory Method for SCM wrapper creation
58 58
59 def GetScmName(url): 59 def GetScmName(url):
60 if url: 60 if url:
61 url, _ = gclient_utils.SplitUrlRevision(url) 61 url, _ = gclient_utils.SplitUrlRevision(url)
62 if (url.startswith('git://') or url.startswith('ssh://') or 62 if (url.startswith('git://') or url.startswith('ssh://') or
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 command, cwd=path, filter_fn=filterer.Filter, stdout=options.stdout) 158 command, cwd=path, filter_fn=filterer.Filter, stdout=options.stdout)
159 159
160 def update(self, options, args, file_list): 160 def update(self, options, args, file_list):
161 """Runs git to update or transparently checkout the working copy. 161 """Runs git to update or transparently checkout the working copy.
162 162
163 All updated files will be appended to file_list. 163 All updated files will be appended to file_list.
164 164
165 Raises: 165 Raises:
166 Error: if can't get URL for relative path. 166 Error: if can't get URL for relative path.
167 """ 167 """
168
169 if args: 168 if args:
170 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args)) 169 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args))
171 170
172 self._CheckMinVersion("1.6.6") 171 self._CheckMinVersion("1.6.6")
173 172
174 default_rev = "refs/heads/master" 173 default_rev = "refs/heads/master"
175 url, deps_revision = gclient_utils.SplitUrlRevision(self.url) 174 url, deps_revision = gclient_utils.SplitUrlRevision(self.url)
176 rev_str = "" 175 rev_str = ""
177 revision = deps_revision 176 revision = deps_revision
178 if options.revision: 177 if options.revision:
179 # Override the revision number. 178 # Override the revision number.
180 revision = str(options.revision) 179 revision = str(options.revision)
181 if not revision: 180 if not revision:
182 revision = default_rev 181 revision = default_rev
183 182
184 rev_str = ' at %s' % revision 183 rev_str = ' at %s' % revision
185 files = [] 184 files = []
186 185
187 printed_path = False 186 printed_path = False
188 verbose = [] 187 verbose = []
189 if options.verbose: 188 if options.verbose:
190 print("\n_____ %s%s" % (self.relpath, rev_str)) 189 options.stdout.write("\n_____ %s%s\n" % (self.relpath, rev_str))
191 verbose = ['--verbose'] 190 verbose = ['--verbose']
192 printed_path = True 191 printed_path = True
193 192
194 if revision.startswith('refs/heads/'): 193 if revision.startswith('refs/heads/'):
195 rev_type = "branch" 194 rev_type = "branch"
196 elif revision.startswith('origin/'): 195 elif revision.startswith('origin/'):
197 # For compatability with old naming, translate 'origin' to 'refs/heads' 196 # For compatability with old naming, translate 'origin' to 'refs/heads'
198 revision = revision.replace('origin/', 'refs/heads/') 197 revision = revision.replace('origin/', 'refs/heads/')
199 rev_type = "branch" 198 rev_type = "branch"
200 else: 199 else:
201 # hash is also a tag, only make a distinction at checkout 200 # hash is also a tag, only make a distinction at checkout
202 rev_type = "hash" 201 rev_type = "hash"
203 202
204 if not os.path.exists(self.checkout_path): 203 if not os.path.exists(self.checkout_path):
205 self._Clone(revision, url, options.verbose) 204 self._Clone(revision, url, options)
206 files = self._Run(['ls-files']).split() 205 files = self._Run(['ls-files']).split()
207 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 206 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
208 if not verbose: 207 if not verbose:
209 # Make the output a little prettier. It's nice to have some whitespace 208 # Make the output a little prettier. It's nice to have some whitespace
210 # between projects when cloning. 209 # between projects when cloning.
211 print "" 210 options.stdout.write('\n')
212 return 211 return
213 212
214 if not os.path.exists(os.path.join(self.checkout_path, '.git')): 213 if not os.path.exists(os.path.join(self.checkout_path, '.git')):
215 raise gclient_utils.Error('\n____ %s%s\n' 214 raise gclient_utils.Error('\n____ %s%s\n'
216 '\tPath is not a git repo. No .git dir.\n' 215 '\tPath is not a git repo. No .git dir.\n'
217 '\tTo resolve:\n' 216 '\tTo resolve:\n'
218 '\t\trm -rf %s\n' 217 '\t\trm -rf %s\n'
219 '\tAnd run gclient sync again\n' 218 '\tAnd run gclient sync again\n'
220 % (self.relpath, rev_str, self.relpath)) 219 % (self.relpath, rev_str, self.relpath))
221 220
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 try: 260 try:
262 remote_output, remote_err = scm.GIT.Capture( 261 remote_output, remote_err = scm.GIT.Capture(
263 ['remote'] + verbose + ['update'], 262 ['remote'] + verbose + ['update'],
264 self.checkout_path, 263 self.checkout_path,
265 print_error=False) 264 print_error=False)
266 break 265 break
267 except gclient_utils.CheckCallError, e: 266 except gclient_utils.CheckCallError, e:
268 # Hackish but at that point, git is known to work so just checking for 267 # Hackish but at that point, git is known to work so just checking for
269 # 502 in stderr should be fine. 268 # 502 in stderr should be fine.
270 if '502' in e.stderr: 269 if '502' in e.stderr:
271 print str(e) 270 options.stdout.write(str(e) + '\n')
272 print "Sleeping 15 seconds and retrying..." 271 options.stdout.write('Sleeping 15 seconds and retrying...\n')
273 time.sleep(15) 272 time.sleep(15)
274 continue 273 continue
275 raise 274 raise
276 275
277 if verbose: 276 if verbose:
278 print remote_output.strip() 277 options.stdout.write(remote_output.strip() + '\n')
279 # git remote update prints to stderr when used with --verbose 278 # git remote update prints to stderr when used with --verbose
280 print remote_err.strip() 279 options.stdout.write(remote_err.strip() + '\n')
281 280
282 # This is a big hammer, debatable if it should even be here... 281 # This is a big hammer, debatable if it should even be here...
283 if options.force or options.reset: 282 if options.force or options.reset:
284 self._Run(['reset', '--hard', 'HEAD'], redirect_stdout=False) 283 self._Run(['reset', '--hard', 'HEAD'], redirect_stdout=False)
285 284
286 if current_type == 'detached': 285 if current_type == 'detached':
287 # case 0 286 # case 0
288 self._CheckClean(rev_str) 287 self._CheckClean(rev_str)
289 self._CheckDetachedHead(rev_str) 288 self._CheckDetachedHead(rev_str, options)
290 self._Run(['checkout', '--quiet', '%s^0' % revision]) 289 self._Run(['checkout', '--quiet', '%s^0' % revision])
291 if not printed_path: 290 if not printed_path:
292 print("\n_____ %s%s" % (self.relpath, rev_str)) 291 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
293 elif current_type == 'hash': 292 elif current_type == 'hash':
294 # case 1 293 # case 1
295 if scm.GIT.IsGitSvn(self.checkout_path) and upstream_branch is not None: 294 if scm.GIT.IsGitSvn(self.checkout_path) and upstream_branch is not None:
296 # Our git-svn branch (upstream_branch) is our upstream 295 # Our git-svn branch (upstream_branch) is our upstream
297 self._AttemptRebase(upstream_branch, files, verbose=options.verbose, 296 self._AttemptRebase(upstream_branch, files, options,
298 newbase=revision, printed_path=printed_path) 297 newbase=revision, printed_path=printed_path)
299 printed_path = True 298 printed_path = True
300 else: 299 else:
301 # Can't find a merge-base since we don't know our upstream. That makes 300 # Can't find a merge-base since we don't know our upstream. That makes
302 # this command VERY likely to produce a rebase failure. For now we 301 # this command VERY likely to produce a rebase failure. For now we
303 # assume origin is our upstream since that's what the old behavior was. 302 # assume origin is our upstream since that's what the old behavior was.
304 upstream_branch = 'origin' 303 upstream_branch = 'origin'
305 if options.revision or deps_revision: 304 if options.revision or deps_revision:
306 upstream_branch = revision 305 upstream_branch = revision
307 self._AttemptRebase(upstream_branch, files=files, 306 self._AttemptRebase(upstream_branch, files, options,
308 verbose=options.verbose, printed_path=printed_path) 307 printed_path=printed_path)
309 printed_path = True 308 printed_path = True
310 elif rev_type == 'hash': 309 elif rev_type == 'hash':
311 # case 2 310 # case 2
312 self._AttemptRebase(upstream_branch, files, verbose=options.verbose, 311 self._AttemptRebase(upstream_branch, files, options,
313 newbase=revision, printed_path=printed_path) 312 newbase=revision, printed_path=printed_path)
314 printed_path = True 313 printed_path = True
315 elif revision.replace('heads', 'remotes/origin') != upstream_branch: 314 elif revision.replace('heads', 'remotes/origin') != upstream_branch:
316 # case 4 315 # case 4
317 new_base = revision.replace('heads', 'remotes/origin') 316 new_base = revision.replace('heads', 'remotes/origin')
318 if not printed_path: 317 if not printed_path:
319 print("\n_____ %s%s" % (self.relpath, rev_str)) 318 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
320 switch_error = ("Switching upstream branch from %s to %s\n" 319 switch_error = ("Switching upstream branch from %s to %s\n"
321 % (upstream_branch, new_base) + 320 % (upstream_branch, new_base) +
322 "Please merge or rebase manually:\n" + 321 "Please merge or rebase manually:\n" +
323 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) + 322 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) +
324 "OR git checkout -b <some new branch> %s" % new_base) 323 "OR git checkout -b <some new branch> %s" % new_base)
325 raise gclient_utils.Error(switch_error) 324 raise gclient_utils.Error(switch_error)
326 else: 325 else:
327 # case 3 - the default case 326 # case 3 - the default case
328 files = self._Run(['diff', upstream_branch, '--name-only']).split() 327 files = self._Run(['diff', upstream_branch, '--name-only']).split()
329 if verbose: 328 if verbose:
330 print "Trying fast-forward merge to branch : %s" % upstream_branch 329 options.stdout.write('Trying fast-forward merge to branch : %s\n' %
330 upstream_branch)
331 try: 331 try:
332 merge_output, merge_err = scm.GIT.Capture(['merge', '--ff-only', 332 merge_output, merge_err = scm.GIT.Capture(['merge', '--ff-only',
333 upstream_branch], 333 upstream_branch],
334 self.checkout_path, 334 self.checkout_path,
335 print_error=False) 335 print_error=False)
336 except gclient_utils.CheckCallError, e: 336 except gclient_utils.CheckCallError, e:
337 if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr): 337 if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr):
338 if not printed_path: 338 if not printed_path:
339 print("\n_____ %s%s" % (self.relpath, rev_str)) 339 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
340 printed_path = True 340 printed_path = True
341 while True: 341 while True:
342 try: 342 try:
343 # TODO(maruel): That can't work.
343 action = str(raw_input("Cannot fast-forward merge, attempt to " 344 action = str(raw_input("Cannot fast-forward merge, attempt to "
344 "rebase? (y)es / (q)uit / (s)kip : ")) 345 "rebase? (y)es / (q)uit / (s)kip : "))
345 except ValueError: 346 except ValueError:
346 gclient_utils.Error('Invalid Character') 347 gclient_utils.Error('Invalid Character')
347 continue 348 continue
348 if re.match(r'yes|y', action, re.I): 349 if re.match(r'yes|y', action, re.I):
349 self._AttemptRebase(upstream_branch, files, 350 self._AttemptRebase(upstream_branch, files, options,
350 verbose=options.verbose,
351 printed_path=printed_path) 351 printed_path=printed_path)
352 printed_path = True 352 printed_path = True
353 break 353 break
354 elif re.match(r'quit|q', action, re.I): 354 elif re.match(r'quit|q', action, re.I):
355 raise gclient_utils.Error("Can't fast-forward, please merge or " 355 raise gclient_utils.Error("Can't fast-forward, please merge or "
356 "rebase manually.\n" 356 "rebase manually.\n"
357 "cd %s && git " % self.checkout_path 357 "cd %s && git " % self.checkout_path
358 + "rebase %s" % upstream_branch) 358 + "rebase %s" % upstream_branch)
359 elif re.match(r'skip|s', action, re.I): 359 elif re.match(r'skip|s', action, re.I):
360 print "Skipping %s" % self.relpath 360 options.stdout.write('Skipping %s\n' % self.relpath)
361 return 361 return
362 else: 362 else:
363 print "Input not recognized" 363 options.stdout.write('Input not recognized\n')
364 elif re.match("error: Your local changes to '.*' would be " 364 elif re.match("error: Your local changes to '.*' would be "
365 "overwritten by merge. Aborting.\nPlease, commit your " 365 "overwritten by merge. Aborting.\nPlease, commit your "
366 "changes or stash them before you can merge.\n", 366 "changes or stash them before you can merge.\n",
367 e.stderr): 367 e.stderr):
368 if not printed_path: 368 if not printed_path:
369 print("\n_____ %s%s" % (self.relpath, rev_str)) 369 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
370 printed_path = True 370 printed_path = True
371 raise gclient_utils.Error(e.stderr) 371 raise gclient_utils.Error(e.stderr)
372 else: 372 else:
373 # Some other problem happened with the merge 373 # Some other problem happened with the merge
374 logging.error("Error during fast-forward merge in %s!" % self.relpath) 374 logging.error("Error during fast-forward merge in %s!" % self.relpath)
375 print e.stderr 375 options.stdout.write(e.stderr + '\n')
376 raise 376 raise
377 else: 377 else:
378 # Fast-forward merge was successful 378 # Fast-forward merge was successful
379 if not re.match('Already up-to-date.', merge_output) or verbose: 379 if not re.match('Already up-to-date.', merge_output) or verbose:
380 if not printed_path: 380 if not printed_path:
381 print("\n_____ %s%s" % (self.relpath, rev_str)) 381 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
382 printed_path = True 382 printed_path = True
383 print merge_output.strip() 383 print merge_output.strip()
384 if merge_err: 384 if merge_err:
385 print "Merge produced error output:\n%s" % merge_err.strip() 385 options.stdout.write('Merge produced error output:\n%s\n' %
386 merge_err.strip())
386 if not verbose: 387 if not verbose:
387 # Make the output a little prettier. It's nice to have some 388 # Make the output a little prettier. It's nice to have some
388 # whitespace between projects when syncing. 389 # whitespace between projects when syncing.
389 print "" 390 options.stdout.write('\n')
390 391
391 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 392 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
392 393
393 # If the rebase generated a conflict, abort and ask user to fix 394 # If the rebase generated a conflict, abort and ask user to fix
394 if self._IsRebasing(): 395 if self._IsRebasing():
395 raise gclient_utils.Error('\n____ %s%s\n' 396 raise gclient_utils.Error('\n____ %s%s\n'
396 '\nConflict while rebasing this branch.\n' 397 '\nConflict while rebasing this branch.\n'
397 'Fix the conflict and run gclient again.\n' 398 'Fix the conflict and run gclient again.\n'
398 'See man git-rebase for details.\n' 399 'See man git-rebase for details.\n'
399 % (self.relpath, rev_str)) 400 % (self.relpath, rev_str))
400 401
401 if verbose: 402 if verbose:
402 print "Checked out revision %s" % self.revinfo(options, (), None) 403 options.stdout.write('Checked out revision %s\n' %
404 self.revinfo(options, (), None))
403 405
404 def revert(self, options, args, file_list): 406 def revert(self, options, args, file_list):
405 """Reverts local modifications. 407 """Reverts local modifications.
406 408
407 All reverted files will be appended to file_list. 409 All reverted files will be appended to file_list.
408 """ 410 """
409 path = os.path.join(self._root_dir, self.relpath) 411 path = os.path.join(self._root_dir, self.relpath)
410 if not os.path.isdir(path): 412 if not os.path.isdir(path):
411 # revert won't work if the directory doesn't exist. It needs to 413 # revert won't work if the directory doesn't exist. It needs to
412 # checkout instead. 414 # checkout instead.
413 print("\n_____ %s is missing, synching instead" % self.relpath) 415 options.stdout.write('\n_____ %s is missing, synching instead\n' %
416 self.relpath)
414 # Don't reuse the args. 417 # Don't reuse the args.
415 return self.update(options, [], file_list) 418 return self.update(options, [], file_list)
416 419
417 default_rev = "refs/heads/master" 420 default_rev = "refs/heads/master"
418 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) 421 _, deps_revision = gclient_utils.SplitUrlRevision(self.url)
419 if not deps_revision: 422 if not deps_revision:
420 deps_revision = default_rev 423 deps_revision = default_rev
421 if deps_revision.startswith('refs/heads/'): 424 if deps_revision.startswith('refs/heads/'):
422 deps_revision = deps_revision.replace('refs/heads/', 'origin/') 425 deps_revision = deps_revision.replace('refs/heads/', 'origin/')
423 426
424 files = self._Run(['diff', deps_revision, '--name-only']).split() 427 files = self._Run(['diff', deps_revision, '--name-only']).split()
425 self._Run(['reset', '--hard', deps_revision], redirect_stdout=False) 428 self._Run(['reset', '--hard', deps_revision], redirect_stdout=False)
426 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 429 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
427 430
428 def revinfo(self, options, args, file_list): 431 def revinfo(self, options, args, file_list):
429 """Display revision""" 432 """Display revision"""
430 return self._Run(['rev-parse', 'HEAD']) 433 return self._Run(['rev-parse', 'HEAD'])
431 434
432 def runhooks(self, options, args, file_list): 435 def runhooks(self, options, args, file_list):
433 self.status(options, args, file_list) 436 self.status(options, args, file_list)
434 437
435 def status(self, options, args, file_list): 438 def status(self, options, args, file_list):
436 """Display status information.""" 439 """Display status information."""
437 if not os.path.isdir(self.checkout_path): 440 if not os.path.isdir(self.checkout_path):
438 print('\n________ couldn\'t run status in %s:\nThe directory ' 441 options.stdout.write(
439 'does not exist.' % self.checkout_path) 442 ('\n________ couldn\'t run status in %s:\nThe directory '
443 'does not exist.\n') % self.checkout_path)
440 else: 444 else:
441 merge_base = self._Run(['merge-base', 'HEAD', 'origin']) 445 merge_base = self._Run(['merge-base', 'HEAD', 'origin'])
442 self._Run(['diff', '--name-status', merge_base], redirect_stdout=False) 446 self._Run(['diff', '--name-status', merge_base], redirect_stdout=False)
443 files = self._Run(['diff', '--name-only', merge_base]).split() 447 files = self._Run(['diff', '--name-only', merge_base]).split()
444 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 448 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
445 449
446 def FullUrlForRelativeUrl(self, url): 450 def FullUrlForRelativeUrl(self, url):
447 # Strip from last '/' 451 # Strip from last '/'
448 # Equivalent to unix basename 452 # Equivalent to unix basename
449 base_url = self.url 453 base_url = self.url
450 return base_url[:base_url.rfind('/')] + url 454 return base_url[:base_url.rfind('/')] + url
451 455
452 def _Clone(self, revision, url, verbose=False): 456 def _Clone(self, revision, url, options):
453 """Clone a git repository from the given URL. 457 """Clone a git repository from the given URL.
454 458
455 Once we've cloned the repo, we checkout a working branch if the specified 459 Once we've cloned the repo, we checkout a working branch if the specified
456 revision is a branch head. If it is a tag or a specific commit, then we 460 revision is a branch head. If it is a tag or a specific commit, then we
457 leave HEAD detached as it makes future updates simpler -- in this case the 461 leave HEAD detached as it makes future updates simpler -- in this case the
458 user should first create a new branch or switch to an existing branch before 462 user should first create a new branch or switch to an existing branch before
459 making changes in the repo.""" 463 making changes in the repo."""
460 if not verbose: 464 if not options.verbose:
461 # git clone doesn't seem to insert a newline properly before printing 465 # git clone doesn't seem to insert a newline properly before printing
462 # to stdout 466 # to stdout
463 print "" 467 options.stdout.write('\n')
464 468
465 clone_cmd = ['clone'] 469 clone_cmd = ['clone']
466 if revision.startswith('refs/heads/'): 470 if revision.startswith('refs/heads/'):
467 clone_cmd.extend(['-b', revision.replace('refs/heads/', '')]) 471 clone_cmd.extend(['-b', revision.replace('refs/heads/', '')])
468 detach_head = False 472 detach_head = False
469 else: 473 else:
470 clone_cmd.append('--no-checkout') 474 clone_cmd.append('--no-checkout')
471 detach_head = True 475 detach_head = True
472 if verbose: 476 if options.verbose:
473 clone_cmd.append('--verbose') 477 clone_cmd.append('--verbose')
474 clone_cmd.extend([url, self.checkout_path]) 478 clone_cmd.extend([url, self.checkout_path])
475 479
476 for _ in range(3): 480 for _ in range(3):
477 try: 481 try:
478 self._Run(clone_cmd, cwd=self._root_dir, redirect_stdout=False) 482 self._Run(clone_cmd, cwd=self._root_dir, redirect_stdout=False)
479 break 483 break
480 except gclient_utils.Error, e: 484 except gclient_utils.Error, e:
481 # TODO(maruel): Hackish, should be fixed by moving _Run() to 485 # TODO(maruel): Hackish, should be fixed by moving _Run() to
482 # CheckCall(). 486 # CheckCall().
483 # Too bad we don't have access to the actual output. 487 # Too bad we don't have access to the actual output.
484 # We should check for "transfer closed with NNN bytes remaining to 488 # We should check for "transfer closed with NNN bytes remaining to
485 # read". In the meantime, just make sure .git exists. 489 # read". In the meantime, just make sure .git exists.
486 if (e.args[0] == 'git command clone returned 128' and 490 if (e.args[0] == 'git command clone returned 128' and
487 os.path.exists(os.path.join(self.checkout_path, '.git'))): 491 os.path.exists(os.path.join(self.checkout_path, '.git'))):
488 print str(e) 492 options.stdout.write(str(e) + '\n')
489 print "Retrying..." 493 options.stdout.write('Retrying...\n')
490 continue 494 continue
491 raise e 495 raise e
492 496
493 if detach_head: 497 if detach_head:
494 # Squelch git's very verbose detached HEAD warning and use our own 498 # Squelch git's very verbose detached HEAD warning and use our own
495 self._Run(['checkout', '--quiet', '%s^0' % revision]) 499 self._Run(['checkout', '--quiet', '%s^0' % revision])
496 print \ 500 options.stdout.write(
497 "Checked out %s to a detached HEAD. Before making any commits\n" \ 501 ('Checked out %s to a detached HEAD. Before making any commits\n'
498 "in this repo, you should use 'git checkout <branch>' to switch to\n" \ 502 'in this repo, you should use \'git checkout <branch>\' to switch to\n'
499 "an existing branch or use 'git checkout origin -b <branch>' to\n" \ 503 'an existing branch or use \'git checkout origin -b <branch>\' to\n'
500 "create a new branch for your work." % revision 504 'create a new branch for your work.') % revision)
501 505
502 def _AttemptRebase(self, upstream, files, verbose=False, newbase=None, 506 def _AttemptRebase(self, upstream, files, options, newbase=None,
503 branch=None, printed_path=False): 507 branch=None, printed_path=False):
504 """Attempt to rebase onto either upstream or, if specified, newbase.""" 508 """Attempt to rebase onto either upstream or, if specified, newbase."""
505 files.extend(self._Run(['diff', upstream, '--name-only']).split()) 509 files.extend(self._Run(['diff', upstream, '--name-only']).split())
506 revision = upstream 510 revision = upstream
507 if newbase: 511 if newbase:
508 revision = newbase 512 revision = newbase
509 if not printed_path: 513 if not printed_path:
510 print "\n_____ %s : Attempting rebase onto %s..." % (self.relpath, 514 options.stdout.write('\n_____ %s : Attempting rebase onto %s...\n' % (
511 revision) 515 self.relpath, revision))
512 printed_path = True 516 printed_path = True
513 else: 517 else:
514 print "Attempting rebase onto %s..." % revision 518 options.stdout.write('Attempting rebase onto %s...\n' % revision)
515 519
516 # Build the rebase command here using the args 520 # Build the rebase command here using the args
517 # git rebase [options] [--onto <newbase>] <upstream> [<branch>] 521 # git rebase [options] [--onto <newbase>] <upstream> [<branch>]
518 rebase_cmd = ['rebase'] 522 rebase_cmd = ['rebase']
519 if verbose: 523 if options.verbose:
520 rebase_cmd.append('--verbose') 524 rebase_cmd.append('--verbose')
521 if newbase: 525 if newbase:
522 rebase_cmd.extend(['--onto', newbase]) 526 rebase_cmd.extend(['--onto', newbase])
523 rebase_cmd.append(upstream) 527 rebase_cmd.append(upstream)
524 if branch: 528 if branch:
525 rebase_cmd.append(branch) 529 rebase_cmd.append(branch)
526 530
527 try: 531 try:
528 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd, 532 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd,
529 self.checkout_path, 533 self.checkout_path,
(...skipping 12 matching lines...) Expand all
542 self._Run(['reset', '--hard', 'HEAD'], redirect_stdout=False) 546 self._Run(['reset', '--hard', 'HEAD'], redirect_stdout=False)
543 # Should this be recursive? 547 # Should this be recursive?
544 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd, 548 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd,
545 self.checkout_path) 549 self.checkout_path)
546 break 550 break
547 elif re.match(r'quit|q', rebase_action, re.I): 551 elif re.match(r'quit|q', rebase_action, re.I):
548 raise gclient_utils.Error("Please merge or rebase manually\n" 552 raise gclient_utils.Error("Please merge or rebase manually\n"
549 "cd %s && git " % self.checkout_path 553 "cd %s && git " % self.checkout_path
550 + "%s" % ' '.join(rebase_cmd)) 554 + "%s" % ' '.join(rebase_cmd))
551 elif re.match(r'show|s', rebase_action, re.I): 555 elif re.match(r'show|s', rebase_action, re.I):
552 print "\n%s" % e.stderr.strip() 556 options.stdout.write('\n%s\n' % e.stderr.strip())
553 continue 557 continue
554 else: 558 else:
555 gclient_utils.Error("Input not recognized") 559 gclient_utils.Error("Input not recognized")
556 continue 560 continue
557 elif re.search(r'^CONFLICT', e.stdout, re.M): 561 elif re.search(r'^CONFLICT', e.stdout, re.M):
558 raise gclient_utils.Error("Conflict while rebasing this branch.\n" 562 raise gclient_utils.Error("Conflict while rebasing this branch.\n"
559 "Fix the conflict and run gclient again.\n" 563 "Fix the conflict and run gclient again.\n"
560 "See 'man git-rebase' for details.\n") 564 "See 'man git-rebase' for details.\n")
561 else: 565 else:
562 print e.stdout.strip() 566 options.stdout.write(e.stdout.strip() + '\n')
563 print "Rebase produced error output:\n%s" % e.stderr.strip() 567 options.stdout.write('Rebase produced error output:\n%s\n' %
568 e.stderr.strip())
564 raise gclient_utils.Error("Unrecognized error, please merge or rebase " 569 raise gclient_utils.Error("Unrecognized error, please merge or rebase "
565 "manually.\ncd %s && git " % 570 "manually.\ncd %s && git " %
566 self.checkout_path 571 self.checkout_path
567 + "%s" % ' '.join(rebase_cmd)) 572 + "%s" % ' '.join(rebase_cmd))
568 573
569 print rebase_output.strip() 574 print rebase_output.strip()
570 if rebase_err: 575 if rebase_err:
571 print "Rebase produced error output:\n%s" % rebase_err.strip() 576 options.stdout.write('Rebase produced error output:\n%s\n' %
572 if not verbose: 577 rebase_err.strip())
578 if not options.verbose:
573 # Make the output a little prettier. It's nice to have some 579 # Make the output a little prettier. It's nice to have some
574 # whitespace between projects when syncing. 580 # whitespace between projects when syncing.
575 print "" 581 options.stdout.write('\n')
576 582
577 @staticmethod 583 @staticmethod
578 def _CheckMinVersion(min_version): 584 def _CheckMinVersion(min_version):
579 (ok, current_version) = scm.GIT.AssertVersion(min_version) 585 (ok, current_version) = scm.GIT.AssertVersion(min_version)
580 if not ok: 586 if not ok:
581 raise gclient_utils.Error('git version %s < minimum required %s' % 587 raise gclient_utils.Error('git version %s < minimum required %s' %
582 (current_version, min_version)) 588 (current_version, min_version))
583 589
584 def _IsRebasing(self): 590 def _IsRebasing(self):
585 # Check for any of REBASE-i/REBASE-m/REBASE/AM. Unfortunately git doesn't 591 # Check for any of REBASE-i/REBASE-m/REBASE/AM. Unfortunately git doesn't
(...skipping 17 matching lines...) Expand all
603 try: 609 try:
604 scm.GIT.Capture(['diff-index', '--cached', '--name-status', '-r', 610 scm.GIT.Capture(['diff-index', '--cached', '--name-status', '-r',
605 '--ignore-submodules', 'HEAD', '--'], self.checkout_path, 611 '--ignore-submodules', 'HEAD', '--'], self.checkout_path,
606 print_error=False) 612 print_error=False)
607 except gclient_utils.CheckCallError: 613 except gclient_utils.CheckCallError:
608 raise gclient_utils.Error('\n____ %s%s\n' 614 raise gclient_utils.Error('\n____ %s%s\n'
609 '\tYour index contains uncommitted changes\n' 615 '\tYour index contains uncommitted changes\n'
610 '\tPlease commit, stash, or reset.\n' 616 '\tPlease commit, stash, or reset.\n'
611 % (self.relpath, rev_str)) 617 % (self.relpath, rev_str))
612 618
613 def _CheckDetachedHead(self, rev_str): 619 def _CheckDetachedHead(self, rev_str, options):
614 # HEAD is detached. Make sure it is safe to move away from (i.e., it is 620 # HEAD is detached. Make sure it is safe to move away from (i.e., it is
615 # reference by a commit). If not, error out -- most likely a rebase is 621 # reference by a commit). If not, error out -- most likely a rebase is
616 # in progress, try to detect so we can give a better error. 622 # in progress, try to detect so we can give a better error.
617 try: 623 try:
618 _, _ = scm.GIT.Capture( 624 _, _ = scm.GIT.Capture(
619 ['name-rev', '--no-undefined', 'HEAD'], 625 ['name-rev', '--no-undefined', 'HEAD'],
620 self.checkout_path, 626 self.checkout_path,
621 print_error=False) 627 print_error=False)
622 except gclient_utils.CheckCallError: 628 except gclient_utils.CheckCallError:
623 # Commit is not contained by any rev. See if the user is rebasing: 629 # Commit is not contained by any rev. See if the user is rebasing:
624 if self._IsRebasing(): 630 if self._IsRebasing():
625 # Punt to the user 631 # Punt to the user
626 raise gclient_utils.Error('\n____ %s%s\n' 632 raise gclient_utils.Error('\n____ %s%s\n'
627 '\tAlready in a conflict, i.e. (no branch).\n' 633 '\tAlready in a conflict, i.e. (no branch).\n'
628 '\tFix the conflict and run gclient again.\n' 634 '\tFix the conflict and run gclient again.\n'
629 '\tOr to abort run:\n\t\tgit-rebase --abort\n' 635 '\tOr to abort run:\n\t\tgit-rebase --abort\n'
630 '\tSee man git-rebase for details.\n' 636 '\tSee man git-rebase for details.\n'
631 % (self.relpath, rev_str)) 637 % (self.relpath, rev_str))
632 # Let's just save off the commit so we can proceed. 638 # Let's just save off the commit so we can proceed.
633 name = "saved-by-gclient-" + self._Run(["rev-parse", "--short", "HEAD"]) 639 name = "saved-by-gclient-" + self._Run(["rev-parse", "--short", "HEAD"])
634 self._Run(["branch", name]) 640 self._Run(["branch", name])
635 print ("\n_____ found an unreferenced commit and saved it as '%s'" % name) 641 options.stdout.write(
642 '\n_____ found an unreferenced commit and saved it as \'%s\'\n' %
643 name)
636 644
637 def _GetCurrentBranch(self): 645 def _GetCurrentBranch(self):
638 # Returns name of current branch or None for detached HEAD 646 # Returns name of current branch or None for detached HEAD
639 branch = self._Run(['rev-parse', '--abbrev-ref=strict', 'HEAD']) 647 branch = self._Run(['rev-parse', '--abbrev-ref=strict', 'HEAD'])
640 if branch == 'HEAD': 648 if branch == 'HEAD':
641 return None 649 return None
642 return branch 650 return branch
643 651
644 def _Run(self, args, cwd=None, redirect_stdout=True): 652 def _Run(self, args, cwd=None, redirect_stdout=True):
645 # TODO(maruel): Merge with Capture or better gclient_utils.CheckCall(). 653 # TODO(maruel): Merge with Capture or better gclient_utils.CheckCall().
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 700
693 def pack(self, options, args, file_list): 701 def pack(self, options, args, file_list):
694 """Generates a patch file which can be applied to the root of the 702 """Generates a patch file which can be applied to the root of the
695 repository.""" 703 repository."""
696 path = os.path.join(self._root_dir, self.relpath) 704 path = os.path.join(self._root_dir, self.relpath)
697 if not os.path.isdir(path): 705 if not os.path.isdir(path):
698 raise gclient_utils.Error('Directory %s is not present.' % path) 706 raise gclient_utils.Error('Directory %s is not present.' % path)
699 command = ['svn', 'diff', '-x', '--ignore-eol-style'] 707 command = ['svn', 'diff', '-x', '--ignore-eol-style']
700 command.extend(args) 708 command.extend(args)
701 709
702 filterer = DiffFilterer(self.relpath) 710 filterer = DiffFilterer(self.relpath, options.stdout)
703 gclient_utils.CheckCallAndFilter(command, cwd=path, always=False, 711 gclient_utils.CheckCallAndFilter(command, cwd=path, always=False,
704 print_stdout=False, filter_fn=filterer.Filter, 712 print_stdout=False, filter_fn=filterer.Filter,
705 stdout=options.stdout) 713 stdout=options.stdout)
706 714
707 def update(self, options, args, file_list): 715 def update(self, options, args, file_list):
708 """Runs svn to update or transparently checkout the working copy. 716 """Runs svn to update or transparently checkout the working copy.
709 717
710 All updated files will be appended to file_list. 718 All updated files will be appended to file_list.
711 719
712 Raises: 720 Raises:
713 Error: if can't get URL for relative path. 721 Error: if can't get URL for relative path.
714 """ 722 """
715 # Only update if git is not controlling the directory. 723 # Only update if git is not controlling the directory.
716 checkout_path = os.path.join(self._root_dir, self.relpath) 724 checkout_path = os.path.join(self._root_dir, self.relpath)
717 git_path = os.path.join(self._root_dir, self.relpath, '.git') 725 git_path = os.path.join(self._root_dir, self.relpath, '.git')
718 if os.path.exists(git_path): 726 if os.path.exists(git_path):
719 print("________ found .git directory; skipping %s" % self.relpath) 727 options.stdout.write('________ found .git directory; skipping %s\n' %
728 self.relpath)
720 return 729 return
721 730
722 if args: 731 if args:
723 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args)) 732 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args))
724 733
725 # revision is the revision to match. It is None if no revision is specified, 734 # revision is the revision to match. It is None if no revision is specified,
726 # i.e. the 'deps ain't pinned'. 735 # i.e. the 'deps ain't pinned'.
727 url, revision = gclient_utils.SplitUrlRevision(self.url) 736 url, revision = gclient_utils.SplitUrlRevision(self.url)
728 # Keep the original unpinned url for reference in case the repo is switched. 737 # Keep the original unpinned url for reference in case the repo is switched.
729 base_url = url 738 base_url = url
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 if from_info['URL'] != base_url: 778 if from_info['URL'] != base_url:
770 # The repository url changed, need to switch. 779 # The repository url changed, need to switch.
771 to_info = scm.SVN.CaptureInfo(url, '.') 780 to_info = scm.SVN.CaptureInfo(url, '.')
772 if not to_info.get('Repository Root') or not to_info.get('UUID'): 781 if not to_info.get('Repository Root') or not to_info.get('UUID'):
773 # The url is invalid or the server is not accessible, it's safer to bail 782 # The url is invalid or the server is not accessible, it's safer to bail
774 # out right now. 783 # out right now.
775 raise gclient_utils.Error('This url is unreachable: %s' % url) 784 raise gclient_utils.Error('This url is unreachable: %s' % url)
776 can_switch = ((from_info['Repository Root'] != to_info['Repository Root']) 785 can_switch = ((from_info['Repository Root'] != to_info['Repository Root'])
777 and (from_info['UUID'] == to_info['UUID'])) 786 and (from_info['UUID'] == to_info['UUID']))
778 if can_switch: 787 if can_switch:
779 print('\n_____ relocating %s to a new checkout' % self.relpath) 788 options.stdout.write('\n_____ relocating %s to a new checkout\n' %
789 self.relpath)
780 # We have different roots, so check if we can switch --relocate. 790 # We have different roots, so check if we can switch --relocate.
781 # Subversion only permits this if the repository UUIDs match. 791 # Subversion only permits this if the repository UUIDs match.
782 # Perform the switch --relocate, then rewrite the from_url 792 # Perform the switch --relocate, then rewrite the from_url
783 # to reflect where we "are now." (This is the same way that 793 # to reflect where we "are now." (This is the same way that
784 # Subversion itself handles the metadata when switch --relocate 794 # Subversion itself handles the metadata when switch --relocate
785 # is used.) This makes the checks below for whether we 795 # is used.) This makes the checks below for whether we
786 # can update to a revision or have to switch to a different 796 # can update to a revision or have to switch to a different
787 # branch work as expected. 797 # branch work as expected.
788 # TODO(maruel): TEST ME ! 798 # TODO(maruel): TEST ME !
789 command = ['switch', '--relocate', 799 command = ['switch', '--relocate',
790 from_info['Repository Root'], 800 from_info['Repository Root'],
791 to_info['Repository Root'], 801 to_info['Repository Root'],
792 self.relpath] 802 self.relpath]
793 self._Run(command, options, cwd=self._root_dir) 803 self._Run(command, options, cwd=self._root_dir)
794 from_info['URL'] = from_info['URL'].replace( 804 from_info['URL'] = from_info['URL'].replace(
795 from_info['Repository Root'], 805 from_info['Repository Root'],
796 to_info['Repository Root']) 806 to_info['Repository Root'])
797 else: 807 else:
798 if not options.force and not options.reset: 808 if not options.force and not options.reset:
799 # Look for local modifications but ignore unversioned files. 809 # Look for local modifications but ignore unversioned files.
800 for status in scm.SVN.CaptureStatus(checkout_path): 810 for status in scm.SVN.CaptureStatus(checkout_path):
801 if status[0] != '?': 811 if status[0] != '?':
802 raise gclient_utils.Error( 812 raise gclient_utils.Error(
803 ('Can\'t switch the checkout to %s; UUID don\'t match and ' 813 ('Can\'t switch the checkout to %s; UUID don\'t match and '
804 'there is local changes in %s. Delete the directory and ' 814 'there is local changes in %s. Delete the directory and '
805 'try again.') % (url, checkout_path)) 815 'try again.') % (url, checkout_path))
806 # Ok delete it. 816 # Ok delete it.
807 print('\n_____ switching %s to a new checkout' % self.relpath) 817 options.stdout.write('\n_____ switching %s to a new checkout\n' %
818 self.relpath)
808 gclient_utils.RemoveDirectory(checkout_path) 819 gclient_utils.RemoveDirectory(checkout_path)
809 # We need to checkout. 820 # We need to checkout.
810 command = ['checkout', url, checkout_path] 821 command = ['checkout', url, checkout_path]
811 command = self._AddAdditionalUpdateFlags(command, options, revision) 822 command = self._AddAdditionalUpdateFlags(command, options, revision)
812 self._RunAndGetFileList(command, options, file_list, self._root_dir) 823 self._RunAndGetFileList(command, options, file_list, self._root_dir)
813 return 824 return
814 825
815 # If the provided url has a revision number that matches the revision 826 # If the provided url has a revision number that matches the revision
816 # number of the existing directory, then we don't need to bother updating. 827 # number of the existing directory, then we don't need to bother updating.
817 if not options.force and str(from_info['Revision']) == revision: 828 if not options.force and str(from_info['Revision']) == revision:
818 if options.verbose or not forced_revision: 829 if options.verbose or not forced_revision:
819 print('\n_____ %s%s' % (self.relpath, rev_str)) 830 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
820 return 831 return
821 832
822 command = ['update', checkout_path] 833 command = ['update', checkout_path]
823 command = self._AddAdditionalUpdateFlags(command, options, revision) 834 command = self._AddAdditionalUpdateFlags(command, options, revision)
824 self._RunAndGetFileList(command, options, file_list, self._root_dir) 835 self._RunAndGetFileList(command, options, file_list, self._root_dir)
825 836
826 def updatesingle(self, options, args, file_list): 837 def updatesingle(self, options, args, file_list):
827 checkout_path = os.path.join(self._root_dir, self.relpath) 838 checkout_path = os.path.join(self._root_dir, self.relpath)
828 filename = args.pop() 839 filename = args.pop()
829 if scm.SVN.AssertVersion("1.5")[0]: 840 if scm.SVN.AssertVersion("1.5")[0]:
(...skipping 25 matching lines...) Expand all
855 def revert(self, options, args, file_list): 866 def revert(self, options, args, file_list):
856 """Reverts local modifications. Subversion specific. 867 """Reverts local modifications. Subversion specific.
857 868
858 All reverted files will be appended to file_list, even if Subversion 869 All reverted files will be appended to file_list, even if Subversion
859 doesn't know about them. 870 doesn't know about them.
860 """ 871 """
861 path = os.path.join(self._root_dir, self.relpath) 872 path = os.path.join(self._root_dir, self.relpath)
862 if not os.path.isdir(path): 873 if not os.path.isdir(path):
863 # svn revert won't work if the directory doesn't exist. It needs to 874 # svn revert won't work if the directory doesn't exist. It needs to
864 # checkout instead. 875 # checkout instead.
865 print("\n_____ %s is missing, synching instead" % self.relpath) 876 options.stdout.write('\n_____ %s is missing, synching instead\n' %
877 self.relpath)
866 # Don't reuse the args. 878 # Don't reuse the args.
867 return self.update(options, [], file_list) 879 return self.update(options, [], file_list)
868 880
869 # Do a flush of sys.stdout every 10 secs or so otherwise it may never be 881 # Do a flush of sys.stdout every 10 secs or so otherwise it may never be
870 # flushed fast enough for buildbot. 882 # flushed fast enough for buildbot.
871 last_flushed_at = time.time() 883 last_flushed_at = time.time()
872 sys.stdout.flush() 884 sys.stdout.flush()
873 885
874 for file_status in scm.SVN.CaptureStatus(path): 886 for file_status in scm.SVN.CaptureStatus(path):
875 file_path = os.path.join(path, file_status[1]) 887 file_path = os.path.join(path, file_status[1])
876 if file_status[0][0] == 'X': 888 if file_status[0][0] == 'X':
877 # Ignore externals. 889 # Ignore externals.
878 logging.info('Ignoring external %s' % file_path) 890 logging.info('Ignoring external %s' % file_path)
879 continue 891 continue
880 892
881 if logging.getLogger().isEnabledFor(logging.INFO): 893 if logging.getLogger().isEnabledFor(logging.INFO):
882 logging.info('%s%s' % (file[0], file[1])) 894 logging.info('%s%s' % (file[0], file[1]))
883 else: 895 else:
884 print(file_path) 896 options.stdout.write(file_path + '\n')
885 # Flush at least 10 seconds between line writes. We wait at least 10 897 # Flush at least 10 seconds between line writes. We wait at least 10
886 # seconds to avoid overloading the reader that called us with output, 898 # seconds to avoid overloading the reader that called us with output,
887 # which can slow busy readers down. 899 # which can slow busy readers down.
888 if (time.time() - last_flushed_at) > 10: 900 if (time.time() - last_flushed_at) > 10:
889 last_flushed_at = time.time() 901 last_flushed_at = time.time()
890 sys.stdout.flush() 902 sys.stdout.flush()
891 903
892 if file_status[0].isspace(): 904 if file_status[0].isspace():
893 logging.error('No idea what is the status of %s.\n' 905 logging.error('No idea what is the status of %s.\n'
894 'You just found a bug in gclient, please ping ' 906 'You just found a bug in gclient, please ping '
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 938
927 def runhooks(self, options, args, file_list): 939 def runhooks(self, options, args, file_list):
928 self.status(options, args, file_list) 940 self.status(options, args, file_list)
929 941
930 def status(self, options, args, file_list): 942 def status(self, options, args, file_list):
931 """Display status information.""" 943 """Display status information."""
932 path = os.path.join(self._root_dir, self.relpath) 944 path = os.path.join(self._root_dir, self.relpath)
933 command = ['status'] + args 945 command = ['status'] + args
934 if not os.path.isdir(path): 946 if not os.path.isdir(path):
935 # svn status won't work if the directory doesn't exist. 947 # svn status won't work if the directory doesn't exist.
936 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " 948 options.stdout.write(
937 "does not exist." 949 ('\n________ couldn\'t run \'%s\' in \'%s\':\nThe directory '
938 % (' '.join(command), path)) 950 'does not exist.') % (' '.join(command), path))
939 # There's no file list to retrieve. 951 # There's no file list to retrieve.
940 else: 952 else:
941 self._RunAndGetFileList(command, options, file_list) 953 self._RunAndGetFileList(command, options, file_list)
942 954
943 def FullUrlForRelativeUrl(self, url): 955 def FullUrlForRelativeUrl(self, url):
944 # Find the forth '/' and strip from there. A bit hackish. 956 # Find the forth '/' and strip from there. A bit hackish.
945 return '/'.join(self.url.split('/')[:4]) + url 957 return '/'.join(self.url.split('/')[:4]) + url
946 958
947 def _Run(self, args, options, **kwargs): 959 def _Run(self, args, options, **kwargs):
948 """Runs a commands that goes to stdout.""" 960 """Runs a commands that goes to stdout."""
(...skipping 14 matching lines...) Expand all
963 975
964 This method returns a new list to be used as a command.""" 976 This method returns a new list to be used as a command."""
965 new_command = command[:] 977 new_command = command[:]
966 if revision: 978 if revision:
967 new_command.extend(['--revision', str(revision).strip()]) 979 new_command.extend(['--revision', str(revision).strip()])
968 # --force was added to 'svn update' in svn 1.5. 980 # --force was added to 'svn update' in svn 1.5.
969 if ((options.force or options.manually_grab_svn_rev) and 981 if ((options.force or options.manually_grab_svn_rev) and
970 scm.SVN.AssertVersion("1.5")[0]): 982 scm.SVN.AssertVersion("1.5")[0]):
971 new_command.append('--force') 983 new_command.append('--force')
972 return new_command 984 return new_command
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698