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

Side by Side Diff: scm.py

Issue 3117039: Refactor SubprocessCallAndFilter() to remove positional arguments. (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 | « 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 results = [] 110 results = []
111 if status: 111 if status:
112 for statusline in status.split('\n'): 112 for statusline in status.split('\n'):
113 m = re.match('^(\w)\t(.+)$', statusline) 113 m = re.match('^(\w)\t(.+)$', statusline)
114 if not m: 114 if not m:
115 raise Exception("status currently unsupported: %s" % statusline) 115 raise Exception("status currently unsupported: %s" % statusline)
116 results.append(('%s ' % m.group(1), m.group(2))) 116 results.append(('%s ' % m.group(1), m.group(2)))
117 return results 117 return results
118 118
119 @staticmethod 119 @staticmethod
120 def RunAndFilterOutput(args, 120 def RunAndFilterOutput(args, **kwargs):
121 in_directory, 121 """Wrapper to gclient_utils.SubprocessCallAndFilter()."""
122 print_messages, 122 return gclient_utils.SubprocessCallAndFilter([GIT.COMMAND] + args, **kwargs)
123 print_stdout,
124 filter_fn,
125 stdout=None):
126 """Runs a command, optionally outputting to stdout.
127
128 stdout is passed line-by-line to the given filter_fn function. If
129 print_stdout is true, it is also printed to sys.stdout as in Run.
130
131 Args:
132 args: A sequence of command line parameters to be passed.
133 in_directory: The directory where git is to be run.
134 print_messages: Whether to print status messages to stdout about
135 which commands are being run.
136 print_stdout: Whether to forward program's output to stdout.
137 filter_fn: A function taking one argument (a string) which will be
138 passed each line (with the ending newline character removed) of
139 program's output for filtering.
140
141 Raises:
142 gclient_utils.Error: An error occurred while running the command.
143 """
144 command = [GIT.COMMAND]
145 command.extend(args)
146 gclient_utils.SubprocessCallAndFilter(command,
147 in_directory,
148 print_messages,
149 print_stdout,
150 filter_fn=filter_fn,
151 stdout=stdout)
152 123
153 @staticmethod 124 @staticmethod
154 def GetEmail(repo_root): 125 def GetEmail(repo_root):
155 """Retrieves the user email address if known.""" 126 """Retrieves the user email address if known."""
156 # We could want to look at the svn cred when it has a svn remote but it 127 # We could want to look at the svn cred when it has a svn remote but it
157 # should be fine for now, users should simply configure their git settings. 128 # should be fine for now, users should simply configure their git settings.
158 return GIT.Capture(['config', 'user.email'], 129 return GIT.Capture(['config', 'user.email'],
159 repo_root, error_ok=True)[0].strip() 130 repo_root, error_ok=True)[0].strip()
160 131
161 @staticmethod 132 @staticmethod
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 elif ver > min_ver: 309 elif ver > min_ver:
339 return (True, current_version) 310 return (True, current_version)
340 return (True, current_version) 311 return (True, current_version)
341 312
342 313
343 class SVN(object): 314 class SVN(object):
344 COMMAND = "svn" 315 COMMAND = "svn"
345 current_version = None 316 current_version = None
346 317
347 @staticmethod 318 @staticmethod
348 def Run(args, in_directory): 319 def Run(args, **kwargs):
349 """Runs svn, sending output to stdout. 320 """Wrappers to gclient_utils.SubprocessCall()."""
350 321 return gclient_utils.SubprocessCall([SVN.COMMAND] + args, **kwargs)
351 Args:
352 args: A sequence of command line parameters to be passed to svn.
353 in_directory: The directory where svn is to be run.
354
355 Raises:
356 Error: An error occurred while running the svn command.
357 """
358 c = [SVN.COMMAND]
359 c.extend(args)
360 # TODO(maruel): This is very gclient-specific.
361 gclient_utils.SubprocessCall(c, in_directory)
362 322
363 @staticmethod 323 @staticmethod
364 def Capture(args, in_directory=None, print_error=True): 324 def Capture(args, in_directory=None, print_error=True):
365 """Runs svn, capturing output sent to stdout as a string. 325 """Runs svn, capturing output sent to stdout as a string.
366 326
367 Args: 327 Args:
368 args: A sequence of command line parameters to be passed to svn. 328 args: A sequence of command line parameters to be passed to svn.
369 in_directory: The directory where svn is to be run. 329 in_directory: The directory where svn is to be run.
370 330
371 Returns: 331 Returns:
372 The output sent to stdout as a string. 332 The output sent to stdout as a string.
373 """ 333 """
374 c = [SVN.COMMAND] 334 c = [SVN.COMMAND]
375 c.extend(args) 335 c.extend(args)
376 stderr = None 336 stderr = None
377 if not print_error: 337 if not print_error:
378 stderr = subprocess.PIPE 338 stderr = subprocess.PIPE
379 return gclient_utils.Popen(c, cwd=in_directory, stdout=subprocess.PIPE, 339 return gclient_utils.Popen(c, cwd=in_directory, stdout=subprocess.PIPE,
380 stderr=stderr).communicate()[0] 340 stderr=stderr).communicate()[0]
381 341
382 @staticmethod 342 @staticmethod
383 def RunAndGetFileList(verbose, args, in_directory, file_list, stdout=None): 343 def RunAndGetFileList(verbose, args, cwd, file_list, stdout=None):
384 """Runs svn checkout, update, or status, output to stdout. 344 """Runs svn checkout, update, or status, output to stdout.
385 345
386 The first item in args must be either "checkout", "update", or "status". 346 The first item in args must be either "checkout", "update", or "status".
387 347
388 svn's stdout is parsed to collect a list of files checked out or updated. 348 svn's stdout is parsed to collect a list of files checked out or updated.
389 These files are appended to file_list. svn's stdout is also printed to 349 These files are appended to file_list. svn's stdout is also printed to
390 sys.stdout as in Run. 350 sys.stdout as in Run.
391 351
392 Args: 352 Args:
393 verbose: If True, uses verbose output 353 verbose: If True, uses verbose output
394 args: A sequence of command line parameters to be passed to svn. 354 args: A sequence of command line parameters to be passed to svn.
395 in_directory: The directory where svn is to be run. 355 cwd: The directory where svn is to be run.
396 356
397 Raises: 357 Raises:
398 Error: An error occurred while running the svn command. 358 Error: An error occurred while running the svn command.
399 """ 359 """
400 command = [SVN.COMMAND] 360 stdout = stdout or sys.stdout
401 command.extend(args)
402 361
403 # svn update and svn checkout use the same pattern: the first three columns 362 # svn update and svn checkout use the same pattern: the first three columns
404 # are for file status, property status, and lock status. This is followed 363 # are for file status, property status, and lock status. This is followed
405 # by two spaces, and then the path to the file. 364 # by two spaces, and then the path to the file.
406 update_pattern = '^... (.*)$' 365 update_pattern = '^... (.*)$'
407 366
408 # The first three columns of svn status are the same as for svn update and 367 # The first three columns of svn status are the same as for svn update and
409 # svn checkout. The next three columns indicate addition-with-history, 368 # svn checkout. The next three columns indicate addition-with-history,
410 # switch, and remote lock status. This is followed by one space, and then 369 # switch, and remote lock status. This is followed by one space, and then
411 # the path to the file. 370 # the path to the file.
(...skipping 15 matching lines...) Expand all
427 failure = [] 386 failure = []
428 387
429 def CaptureMatchingLines(line): 388 def CaptureMatchingLines(line):
430 match = compiled_pattern.search(line) 389 match = compiled_pattern.search(line)
431 if match: 390 if match:
432 file_list.append(match.group(1)) 391 file_list.append(match.group(1))
433 if line.startswith('svn: '): 392 if line.startswith('svn: '):
434 failure.append(line) 393 failure.append(line)
435 394
436 try: 395 try:
437 SVN.RunAndFilterOutput(args, 396 SVN.RunAndFilterOutput(args, cwd=cwd, print_messages=verbose,
438 in_directory, 397 print_stdout=True,
439 verbose, 398 filter_fn=CaptureMatchingLines,
440 True,
441 CaptureMatchingLines,
442 stdout=stdout) 399 stdout=stdout)
443 except gclient_utils.Error: 400 except gclient_utils.Error:
444 def IsKnownFailure(): 401 def IsKnownFailure():
445 for x in failure: 402 for x in failure:
446 if (x.startswith('svn: OPTIONS of') or 403 if (x.startswith('svn: OPTIONS of') or
447 x.startswith('svn: PROPFIND of') or 404 x.startswith('svn: PROPFIND of') or
448 x.startswith('svn: REPORT of') or 405 x.startswith('svn: REPORT of') or
449 x.startswith('svn: Unknown hostname') or 406 x.startswith('svn: Unknown hostname') or
450 x.startswith('svn: Server sent unexpected return value')): 407 x.startswith('svn: Server sent unexpected return value')):
451 return True 408 return True
(...skipping 22 matching lines...) Expand all
474 # We enforce that some progress has been made or a known failure. 431 # We enforce that some progress has been made or a known failure.
475 if len(file_list) == previous_list_len and not IsKnownFailure(): 432 if len(file_list) == previous_list_len and not IsKnownFailure():
476 # No known svn error was found and no progress, bail out. 433 # No known svn error was found and no progress, bail out.
477 raise 434 raise
478 print "Sleeping 15 seconds and retrying...." 435 print "Sleeping 15 seconds and retrying...."
479 time.sleep(15) 436 time.sleep(15)
480 continue 437 continue
481 break 438 break
482 439
483 @staticmethod 440 @staticmethod
484 def RunAndFilterOutput(args, 441 def RunAndFilterOutput(args, **kwargs):
485 in_directory, 442 """Wrapper for gclient_utils.SubprocessCallAndFilter()."""
486 print_messages, 443 return gclient_utils.SubprocessCallAndFilter([SVN.COMMAND] + args, **kwargs)
487 print_stdout,
488 filter_fn,
489 stdout=None):
490 """Runs a command, optionally outputting to stdout.
491
492 stdout is passed line-by-line to the given filter_fn function. If
493 print_stdout is true, it is also printed to sys.stdout as in Run.
494
495 Args:
496 args: A sequence of command line parameters to be passed.
497 in_directory: The directory where svn is to be run.
498 print_messages: Whether to print status messages to stdout about
499 which commands are being run.
500 print_stdout: Whether to forward program's output to stdout.
501 filter_fn: A function taking one argument (a string) which will be
502 passed each line (with the ending newline character removed) of
503 program's output for filtering.
504
505 Raises:
506 gclient_utils.Error: An error occurred while running the command.
507 """
508 command = [SVN.COMMAND]
509 command.extend(args)
510 gclient_utils.SubprocessCallAndFilter(command,
511 in_directory,
512 print_messages,
513 print_stdout,
514 filter_fn=filter_fn,
515 stdout=stdout)
516 444
517 @staticmethod 445 @staticmethod
518 def CaptureInfo(relpath, in_directory=None, print_error=True): 446 def CaptureInfo(relpath, in_directory=None, print_error=True):
519 """Returns a dictionary from the svn info output for the given file. 447 """Returns a dictionary from the svn info output for the given file.
520 448
521 Args: 449 Args:
522 relpath: The directory where the working copy resides relative to 450 relpath: The directory where the working copy resides relative to
523 the directory given by in_directory. 451 the directory given by in_directory.
524 in_directory: The directory where svn is to be run. 452 in_directory: The directory where svn is to be run.
525 """ 453 """
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 if not SVN.current_version: 862 if not SVN.current_version:
935 SVN.current_version = SVN.Capture(['--version']).split()[2] 863 SVN.current_version = SVN.Capture(['--version']).split()[2]
936 current_version_list = map(only_int, SVN.current_version.split('.')) 864 current_version_list = map(only_int, SVN.current_version.split('.'))
937 for min_ver in map(int, min_version.split('.')): 865 for min_ver in map(int, min_version.split('.')):
938 ver = current_version_list.pop(0) 866 ver = current_version_list.pop(0)
939 if ver < min_ver: 867 if ver < min_ver:
940 return (False, SVN.current_version) 868 return (False, SVN.current_version)
941 elif ver > min_ver: 869 elif ver > min_ver:
942 return (True, SVN.current_version) 870 return (True, SVN.current_version)
943 return (True, SVN.current_version) 871 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