Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright 2008 Google Inc. All Rights Reserved. | 3 # Copyright 2008 Google Inc. All Rights Reserved. |
| 4 # | 4 # |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); | 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 # you may not use this file except in compliance with the License. | 6 # you may not use this file except in compliance with the License. |
| 7 # You may obtain a copy of the License at | 7 # You may obtain a copy of the License at |
| 8 # | 8 # |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 | 9 # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 # | 10 # |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 DEFAULT_USAGE_TEXT = ( | 88 DEFAULT_USAGE_TEXT = ( |
| 89 """usage: %prog <subcommand> [options] [--] [svn options/args...] | 89 """usage: %prog <subcommand> [options] [--] [svn options/args...] |
| 90 a wrapper for managing a set of client modules in svn. | 90 a wrapper for managing a set of client modules in svn. |
| 91 Version """ + __version__ + """ | 91 Version """ + __version__ + """ |
| 92 | 92 |
| 93 subcommands: | 93 subcommands: |
| 94 cleanup | 94 cleanup |
| 95 config | 95 config |
| 96 diff | 96 diff |
| 97 export | 97 export |
| 98 pack | |
| 98 revert | 99 revert |
| 99 status | 100 status |
| 100 sync | 101 sync |
| 101 update | 102 update |
| 102 runhooks | 103 runhooks |
| 103 revinfo | 104 revinfo |
| 104 | 105 |
| 105 Options and extra arguments can be passed to invoked svn commands by | 106 Options and extra arguments can be passed to invoked svn commands by |
| 106 appending them to the command line. Note that if the first such | 107 appending them to the command line. Note that if the first such |
| 107 appended option starts with a dash (-) then the options must be | 108 appended option starts with a dash (-) then the options must be |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 gclient diff | 190 gclient diff |
| 190 simple 'svn diff' for configured client and dependences | 191 simple 'svn diff' for configured client and dependences |
| 191 gclient diff -- -x -b | 192 gclient diff -- -x -b |
| 192 use 'svn diff -x -b' to suppress whitespace-only differences | 193 use 'svn diff -x -b' to suppress whitespace-only differences |
| 193 gclient diff -- -r HEAD -x -b | 194 gclient diff -- -r HEAD -x -b |
| 194 diff versus the latest version of each module | 195 diff versus the latest version of each module |
| 195 """, | 196 """, |
| 196 "export": | 197 "export": |
| 197 """Wrapper for svn export for all managed directories | 198 """Wrapper for svn export for all managed directories |
| 198 """, | 199 """, |
| 200 "pack": | |
| 201 | |
|
sgk
2009/09/04 00:25:11
No extra newline here (consistency with other entr
| |
| 202 """Generate a patch which can be applied at the root of the tree. | |
| 203 Internally, runs 'svn diff' on each checked out module and | |
| 204 dependencies, and performs minimal postprocessing of the output. The | |
| 205 resulting patch is printed to stdout and can be applied to a freshly | |
| 206 checked out tree via 'patch -p0 < patchfile'. Additional args and | |
| 207 options to 'svn diff' can be passed after gclient options. | |
| 208 | |
| 209 usage: pack [options] [--] [svn args/options] | |
| 210 | |
| 211 Valid options: | |
| 212 --verbose : output additional diagnostics | |
| 213 | |
| 214 Examples: | |
| 215 gclient pack > patch.txt | |
| 216 generate simple patch for configured client and dependences | |
| 217 gclient pack -- -x -b > patch.txt | |
| 218 generate patch using 'svn diff -x -b' to suppress | |
| 219 whitespace-only differences | |
| 220 gclient pack -- -r HEAD -x -b > patch.txt | |
| 221 generate patch, diffing each file versus the latest version of | |
| 222 each module | |
| 223 """, | |
| 199 "revert": | 224 "revert": |
| 200 """Revert every file in every managed directory in the client view. | 225 """Revert every file in every managed directory in the client view. |
| 201 | 226 |
| 202 usage: revert | 227 usage: revert |
| 203 """, | 228 """, |
| 204 "status": | 229 "status": |
| 205 """Show the status of client and dependent modules, using 'svn diff' | 230 """Show the status of client and dependent modules, using 'svn diff' |
| 206 for each module. Additional options and args may be passed to 'svn diff'. | 231 for each module. Additional options and args may be passed to 'svn diff'. |
| 207 | 232 |
| 208 usage: status [options] [--] [svn diff args/options] | 233 usage: status [options] [--] [svn diff args/options] |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 401 if e.errno != errno.EACCES or sys.platform != 'win32': | 426 if e.errno != errno.EACCES or sys.platform != 'win32': |
| 402 raise | 427 raise |
| 403 print 'Failed to remove %s: trying again' % file_path | 428 print 'Failed to remove %s: trying again' % file_path |
| 404 time.sleep(0.1) | 429 time.sleep(0.1) |
| 405 os.rmdir(file_path) | 430 os.rmdir(file_path) |
| 406 | 431 |
| 407 | 432 |
| 408 def SubprocessCall(command, in_directory, fail_status=None): | 433 def SubprocessCall(command, in_directory, fail_status=None): |
| 409 """Runs command, a list, in directory in_directory. | 434 """Runs command, a list, in directory in_directory. |
| 410 | 435 |
| 411 This function wraps SubprocessCallAndCapture, but does not perform the | 436 This function wraps SubprocessCallAndFilter, but does not perform the |
| 412 capturing functions. See that function for a more complete usage | 437 filtering functions. See that function for a more complete usage |
| 413 description. | 438 description. |
| 414 """ | 439 """ |
| 415 # Call subprocess and capture nothing: | 440 # Call subprocess and capture nothing: |
| 416 SubprocessCallAndCapture(command, in_directory, fail_status) | 441 SubprocessCallAndFilter(command, in_directory, True, True, fail_status) |
| 417 | 442 |
| 418 | 443 |
| 419 def SubprocessCallAndCapture(command, in_directory, fail_status=None, | 444 def SubprocessCallAndFilter(command, |
| 420 pattern=None, capture_list=None): | 445 in_directory, |
| 446 print_messages, | |
| 447 print_stdout, | |
| 448 fail_status=None, filter=None): | |
| 421 """Runs command, a list, in directory in_directory. | 449 """Runs command, a list, in directory in_directory. |
| 422 | 450 |
| 423 A message indicating what is being done, as well as the command's stdout, | 451 If print_messages is true, a message indicating what is being done |
| 424 is printed to out. | 452 is printed to stdout. If print_stdout is true, the command's stdout |
| 453 is also forwarded to stdout. | |
| 425 | 454 |
| 426 If a pattern is specified, any line in the output matching pattern will have | 455 If a filter function is specified, it is expected to take a single |
| 427 its first match group appended to capture_list. | 456 string argument, and it will be called with each line of the |
| 457 subprocess's output. Each line has had the trailing newline character | |
| 458 trimmed. | |
| 428 | 459 |
| 429 If the command fails, as indicated by a nonzero exit status, gclient will | 460 If the command fails, as indicated by a nonzero exit status, gclient will |
| 430 exit with an exit status of fail_status. If fail_status is None (the | 461 exit with an exit status of fail_status. If fail_status is None (the |
| 431 default), gclient will raise an Error exception. | 462 default), gclient will raise an Error exception. |
| 432 """ | 463 """ |
| 433 | 464 |
| 434 print("\n________ running \'%s\' in \'%s\'" | 465 if print_messages: |
| 435 % (' '.join(command), in_directory)) | 466 print("\n________ running \'%s\' in \'%s\'" |
| 467 % (' '.join(command), in_directory)) | |
| 436 | 468 |
| 437 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the | 469 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for the |
| 438 # executable, but shell=True makes subprocess on Linux fail when it's called | 470 # executable, but shell=True makes subprocess on Linux fail when it's called |
| 439 # with a list because it only tries to execute the first item in the list. | 471 # with a list because it only tries to execute the first item in the list. |
| 440 kid = subprocess.Popen(command, bufsize=0, cwd=in_directory, | 472 kid = subprocess.Popen(command, bufsize=0, cwd=in_directory, |
| 441 shell=(sys.platform == 'win32'), stdout=subprocess.PIPE) | 473 shell=(sys.platform == 'win32'), stdout=subprocess.PIPE) |
| 442 | 474 |
| 443 if pattern: | |
| 444 compiled_pattern = re.compile(pattern) | |
| 445 | |
| 446 # Also, we need to forward stdout to prevent weird re-ordering of output. | 475 # Also, we need to forward stdout to prevent weird re-ordering of output. |
| 447 # This has to be done on a per byte basis to make sure it is not buffered: | 476 # This has to be done on a per byte basis to make sure it is not buffered: |
| 448 # normally buffering is done for each line, but if svn requests input, no | 477 # normally buffering is done for each line, but if svn requests input, no |
| 449 # end-of-line character is output after the prompt and it would not show up. | 478 # end-of-line character is output after the prompt and it would not show up. |
| 450 in_byte = kid.stdout.read(1) | 479 in_byte = kid.stdout.read(1) |
| 451 in_line = "" | 480 in_line = "" |
| 452 while in_byte: | 481 while in_byte: |
| 453 if in_byte != "\r": | 482 if in_byte != "\r": |
| 454 sys.stdout.write(in_byte) | 483 if print_stdout: |
| 455 in_line += in_byte | 484 sys.stdout.write(in_byte) |
| 456 if in_byte == "\n" and pattern: | 485 if in_byte != "\n": |
| 457 match = compiled_pattern.search(in_line[:-1]) | 486 in_line += in_byte |
| 458 if match: | 487 if in_byte == "\n" and filter: |
| 459 capture_list.append(match.group(1)) | 488 filter(in_line) |
|
sgk
2009/09/04 00:25:11
Good, more flexible than just the pattern.
| |
| 460 in_line = "" | 489 in_line = "" |
| 461 in_byte = kid.stdout.read(1) | 490 in_byte = kid.stdout.read(1) |
| 462 rv = kid.wait() | 491 rv = kid.wait() |
| 463 | 492 |
| 464 if rv: | 493 if rv: |
| 465 msg = "failed to run command: %s" % " ".join(command) | 494 msg = "failed to run command: %s" % " ".join(command) |
| 466 | 495 |
| 467 if fail_status != None: | 496 if fail_status != None: |
| 468 print >>sys.stderr, msg | 497 print >>sys.stderr, msg |
| 469 sys.exit(fail_status) | 498 sys.exit(fail_status) |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 # args[0] must be a supported command. This will blow up if it's something | 588 # args[0] must be a supported command. This will blow up if it's something |
| 560 # else, which is good. Note that the patterns are only effective when | 589 # else, which is good. Note that the patterns are only effective when |
| 561 # these commands are used in their ordinary forms, the patterns are invalid | 590 # these commands are used in their ordinary forms, the patterns are invalid |
| 562 # for "svn status --show-updates", for example. | 591 # for "svn status --show-updates", for example. |
| 563 pattern = { | 592 pattern = { |
| 564 'checkout': update_pattern, | 593 'checkout': update_pattern, |
| 565 'status': status_pattern, | 594 'status': status_pattern, |
| 566 'update': update_pattern, | 595 'update': update_pattern, |
| 567 }[args[0]] | 596 }[args[0]] |
| 568 | 597 |
| 569 SubprocessCallAndCapture(command, | 598 compiled_pattern = re.compile(pattern) |
| 570 in_directory, | |
| 571 pattern=pattern, | |
| 572 capture_list=file_list) | |
| 573 | 599 |
| 600 def CaptureMatchingLines(line): | |
| 601 match = compiled_pattern.search(line) | |
| 602 if match: | |
| 603 file_list.append(match.group(1)) | |
| 604 | |
| 605 RunSVNAndFilterOutput(args, | |
| 606 in_directory, | |
| 607 True, | |
| 608 True, | |
| 609 CaptureMatchingLines) | |
| 610 | |
| 611 def RunSVNAndFilterOutput(args, | |
| 612 in_directory, | |
| 613 print_messages, | |
| 614 print_stdout, | |
| 615 filter): | |
| 616 """Runs svn checkout, update, status, or diff, optionally outputting | |
| 617 to stdout. | |
| 618 | |
| 619 The first item in args must be either "checkout", "update", | |
| 620 "status", or "diff". | |
| 621 | |
| 622 svn's stdout is passed line-by-line to the given filter function. If | |
| 623 print_stdout is true, it is also printed to sys.stdout as in RunSVN. | |
| 624 | |
| 625 Args: | |
| 626 args: A sequence of command line parameters to be passed to svn. | |
| 627 in_directory: The directory where svn is to be run. | |
| 628 print_messages: Whether to print status messages to stdout about | |
| 629 which Subversion commands are being run. | |
| 630 print_stdout: Whether to forward Subversion's output to stdout. | |
| 631 filter: A function taking one argument (a string) which will be | |
| 632 passed each line (with the ending newline character removed) of | |
| 633 Subversion's output for filtering. | |
| 634 | |
| 635 Raises: | |
| 636 Error: An error occurred while running the svn command. | |
| 637 """ | |
| 638 command = [SVN_COMMAND] | |
| 639 command.extend(args) | |
| 640 | |
| 641 SubprocessCallAndFilter(command, | |
| 642 in_directory, | |
| 643 print_messages, | |
| 644 print_stdout, | |
| 645 filter=filter) | |
| 574 | 646 |
| 575 def CaptureSVNInfo(relpath, in_directory=None, print_error=True): | 647 def CaptureSVNInfo(relpath, in_directory=None, print_error=True): |
| 576 """Returns a dictionary from the svn info output for the given file. | 648 """Returns a dictionary from the svn info output for the given file. |
| 577 | 649 |
| 578 Args: | 650 Args: |
| 579 relpath: The directory where the working copy resides relative to | 651 relpath: The directory where the working copy resides relative to |
| 580 the directory given by in_directory. | 652 the directory given by in_directory. |
| 581 in_directory: The directory where svn is to be run. | 653 in_directory: The directory where svn is to be run. |
| 582 """ | 654 """ |
| 583 output = CaptureSVN(["info", "--xml", relpath], in_directory, print_error) | 655 output = CaptureSVN(["info", "--xml", relpath], in_directory, print_error) |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 if file_list == None: | 797 if file_list == None: |
| 726 file_list = [] | 798 file_list = [] |
| 727 | 799 |
| 728 commands = { | 800 commands = { |
| 729 'cleanup': self.cleanup, | 801 'cleanup': self.cleanup, |
| 730 'export': self.export, | 802 'export': self.export, |
| 731 'update': self.update, | 803 'update': self.update, |
| 732 'revert': self.revert, | 804 'revert': self.revert, |
| 733 'status': self.status, | 805 'status': self.status, |
| 734 'diff': self.diff, | 806 'diff': self.diff, |
| 807 'pack': self.pack, | |
| 735 'runhooks': self.status, | 808 'runhooks': self.status, |
| 736 } | 809 } |
| 737 | 810 |
| 738 if not command in commands: | 811 if not command in commands: |
| 739 raise Error('Unknown command %s' % command) | 812 raise Error('Unknown command %s' % command) |
| 740 | 813 |
| 741 return commands[command](options, args, file_list) | 814 return commands[command](options, args, file_list) |
| 742 | 815 |
| 743 def cleanup(self, options, args, file_list): | 816 def cleanup(self, options, args, file_list): |
| 744 """Cleanup working copy.""" | 817 """Cleanup working copy.""" |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 933 command.extend(args) | 1006 command.extend(args) |
| 934 if not os.path.isdir(path): | 1007 if not os.path.isdir(path): |
| 935 # svn status won't work if the directory doesn't exist. | 1008 # svn status won't work if the directory doesn't exist. |
| 936 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " | 1009 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " |
| 937 "does not exist." | 1010 "does not exist." |
| 938 % (' '.join(command), path)) | 1011 % (' '.join(command), path)) |
| 939 # There's no file list to retrieve. | 1012 # There's no file list to retrieve. |
| 940 else: | 1013 else: |
| 941 RunSVNAndGetFileList(command, path, file_list) | 1014 RunSVNAndGetFileList(command, path, file_list) |
| 942 | 1015 |
| 1016 def pack(self, options, args, file_list): | |
| 1017 """Generates a patch file which can be applied to the root of the | |
| 1018 repository.""" | |
| 1019 path = os.path.join(self._root_dir, self.relpath) | |
| 1020 command = ['diff'] | |
| 1021 command.extend(args) | |
| 1022 # Simple class which tracks which file is being diffed and | |
| 1023 # replaces instances of its file name in the original and | |
| 1024 # working copy lines of the svn diff output. | |
| 1025 class DiffFilterer(object): | |
| 1026 index_string = "Index: " | |
| 1027 original_prefix = "--- " | |
| 1028 working_prefix = "+++ " | |
| 1029 | |
| 1030 def __init__(self, relpath): | |
| 1031 # Note that we always use '/' as the path separator to be | |
| 1032 # consistent with svn's cygwin-style output on Windows | |
| 1033 self._relpath = relpath.replace("\\", "/") | |
| 1034 self._current_file = "" | |
| 1035 self._replacement_file = "" | |
| 1036 | |
| 1037 def SetCurrentFile(self, file): | |
| 1038 self._current_file = file | |
| 1039 # Note that we always use '/' as the path separator to be | |
| 1040 # consistent with svn's cygwin-style output on Windows | |
| 1041 self._replacement_file = self._relpath + '/' + file | |
| 1042 | |
| 1043 def ReplaceAndPrint(self, line): | |
| 1044 print(line.replace(self._current_file, self._replacement_file)) | |
| 1045 | |
| 1046 def Filter(self, line): | |
| 1047 if (line.startswith(self.index_string)): | |
| 1048 self.SetCurrentFile(line[len(self.index_string):]) | |
| 1049 self.ReplaceAndPrint(line) | |
| 1050 else: | |
| 1051 if (line.startswith(self.original_prefix) or | |
| 1052 line.startswith(self.working_prefix)): | |
| 1053 self.ReplaceAndPrint(line) | |
| 1054 else: | |
| 1055 print line | |
| 1056 | |
| 1057 filterer = DiffFilterer(self.relpath) | |
| 1058 RunSVNAndFilterOutput(command, path, False, False, filterer.Filter) | |
| 943 | 1059 |
| 944 ## GClient implementation. | 1060 ## GClient implementation. |
| 945 | 1061 |
| 946 | 1062 |
| 947 class GClient(object): | 1063 class GClient(object): |
| 948 """Object that represent a gclient checkout.""" | 1064 """Object that represent a gclient checkout.""" |
| 949 | 1065 |
| 950 supported_commands = [ | 1066 supported_commands = [ |
| 951 'cleanup', 'diff', 'export', 'revert', 'status', 'update', 'runhooks' | 1067 'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update', |
| 1068 'runhooks' | |
| 952 ] | 1069 ] |
| 953 | 1070 |
| 954 def __init__(self, root_dir, options): | 1071 def __init__(self, root_dir, options): |
| 955 self._root_dir = root_dir | 1072 self._root_dir = root_dir |
| 956 self._options = options | 1073 self._options = options |
| 957 self._config_content = None | 1074 self._config_content = None |
| 958 self._config_dict = {} | 1075 self._config_dict = {} |
| 959 self._deps_hooks = [] | 1076 self._deps_hooks = [] |
| 960 | 1077 |
| 961 def SetConfig(self, content): | 1078 def SetConfig(self, content): |
| (...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1592 | 1709 |
| 1593 Raises: | 1710 Raises: |
| 1594 Error: if the command is unknown. | 1711 Error: if the command is unknown. |
| 1595 """ | 1712 """ |
| 1596 if len(args) == 1 and args[0] in COMMAND_USAGE_TEXT: | 1713 if len(args) == 1 and args[0] in COMMAND_USAGE_TEXT: |
| 1597 print(COMMAND_USAGE_TEXT[args[0]]) | 1714 print(COMMAND_USAGE_TEXT[args[0]]) |
| 1598 else: | 1715 else: |
| 1599 raise Error("unknown subcommand '%s'; see 'gclient help'" % args[0]) | 1716 raise Error("unknown subcommand '%s'; see 'gclient help'" % args[0]) |
| 1600 | 1717 |
| 1601 | 1718 |
| 1719 def DoPack(options, args): | |
| 1720 """Handle the pack subcommand. | |
| 1721 | |
| 1722 Raises: | |
| 1723 Error: if client isn't configured properly. | |
| 1724 """ | |
| 1725 client = GClient.LoadCurrentConfig(options) | |
| 1726 if not client: | |
| 1727 raise Error("client not configured; see 'gclient config'") | |
| 1728 if options.verbose: | |
| 1729 # Print out the .gclient file. This is longer than if we just printed the | |
| 1730 # client dict, but more legible, and it might contain helpful comments. | |
| 1731 print(client.ConfigContent()) | |
| 1732 options.verbose = True | |
| 1733 return client.RunOnDeps('pack', args) | |
| 1734 | |
| 1735 | |
| 1602 def DoStatus(options, args): | 1736 def DoStatus(options, args): |
| 1603 """Handle the status subcommand. | 1737 """Handle the status subcommand. |
| 1604 | 1738 |
| 1605 Raises: | 1739 Raises: |
| 1606 Error: if client isn't configured properly. | 1740 Error: if client isn't configured properly. |
| 1607 """ | 1741 """ |
| 1608 client = GClient.LoadCurrentConfig(options) | 1742 client = GClient.LoadCurrentConfig(options) |
| 1609 if not client: | 1743 if not client: |
| 1610 raise Error("client not configured; see 'gclient config'") | 1744 raise Error("client not configured; see 'gclient config'") |
| 1611 if options.verbose: | 1745 if options.verbose: |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1711 raise Error("client not configured; see 'gclient config'") | 1845 raise Error("client not configured; see 'gclient config'") |
| 1712 client.PrintRevInfo() | 1846 client.PrintRevInfo() |
| 1713 | 1847 |
| 1714 | 1848 |
| 1715 gclient_command_map = { | 1849 gclient_command_map = { |
| 1716 "cleanup": DoCleanup, | 1850 "cleanup": DoCleanup, |
| 1717 "config": DoConfig, | 1851 "config": DoConfig, |
| 1718 "diff": DoDiff, | 1852 "diff": DoDiff, |
| 1719 "export": DoExport, | 1853 "export": DoExport, |
| 1720 "help": DoHelp, | 1854 "help": DoHelp, |
| 1855 "pack": DoPack, | |
| 1721 "status": DoStatus, | 1856 "status": DoStatus, |
| 1722 "sync": DoUpdate, | 1857 "sync": DoUpdate, |
| 1723 "update": DoUpdate, | 1858 "update": DoUpdate, |
| 1724 "revert": DoRevert, | 1859 "revert": DoRevert, |
| 1725 "runhooks": DoRunHooks, | 1860 "runhooks": DoRunHooks, |
| 1726 "revinfo" : DoRevInfo, | 1861 "revinfo" : DoRevInfo, |
| 1727 } | 1862 } |
| 1728 | 1863 |
| 1729 | 1864 |
| 1730 def DispatchCommand(command, options, args, command_map=None): | 1865 def DispatchCommand(command, options, args, command_map=None): |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1809 | 1944 |
| 1810 if "__main__" == __name__: | 1945 if "__main__" == __name__: |
| 1811 try: | 1946 try: |
| 1812 result = Main(sys.argv) | 1947 result = Main(sys.argv) |
| 1813 except Error, e: | 1948 except Error, e: |
| 1814 print >> sys.stderr, "Error: %s" % str(e) | 1949 print >> sys.stderr, "Error: %s" % str(e) |
| 1815 result = 1 | 1950 result = 1 |
| 1816 sys.exit(result) | 1951 sys.exit(result) |
| 1817 | 1952 |
| 1818 # vim: ts=2:sw=2:tw=80:et: | 1953 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |