| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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) |
| OLD | NEW |