OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # coding: utf-8 | 2 # coding: utf-8 |
3 # | 3 # |
4 # Copyright 2007 Google Inc. | 4 # Copyright 2007 Google Inc. |
5 # | 5 # |
6 # Licensed under the Apache License, Version 2.0 (the "License"); | 6 # Licensed under the Apache License, Version 2.0 (the "License"); |
7 # you may not use this file except in compliance with the License. | 7 # you may not use this file except in compliance with the License. |
8 # You may obtain a copy of the License at | 8 # You may obtain a copy of the License at |
9 # | 9 # |
10 # http://www.apache.org/licenses/LICENSE-2.0 | 10 # http://www.apache.org/licenses/LICENSE-2.0 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 # upload.py). | 82 # upload.py). |
83 AUTH_ACCOUNT_TYPE = "GOOGLE" | 83 AUTH_ACCOUNT_TYPE = "GOOGLE" |
84 | 84 |
85 # URL of the default review server. As for AUTH_ACCOUNT_TYPE, this line could be | 85 # URL of the default review server. As for AUTH_ACCOUNT_TYPE, this line could be |
86 # changed by the review server (see handler for upload.py). | 86 # changed by the review server (see handler for upload.py). |
87 DEFAULT_REVIEW_SERVER = "codereview.appspot.com" | 87 DEFAULT_REVIEW_SERVER = "codereview.appspot.com" |
88 | 88 |
89 # Max size of patch or base file. | 89 # Max size of patch or base file. |
90 MAX_UPLOAD_SIZE = 900 * 1024 | 90 MAX_UPLOAD_SIZE = 900 * 1024 |
91 | 91 |
92 | |
92 # Constants for version control names. Used by GuessVCSName. | 93 # Constants for version control names. Used by GuessVCSName. |
93 VCS_GIT = "Git" | 94 VCS_GIT = "Git" |
94 VCS_MERCURIAL = "Mercurial" | 95 VCS_MERCURIAL = "Mercurial" |
95 VCS_SUBVERSION = "Subversion" | 96 VCS_SUBVERSION = "Subversion" |
96 VCS_PERFORCE = "Perforce" | 97 VCS_PERFORCE = "Perforce" |
97 VCS_CVS = "CVS" | 98 VCS_CVS = "CVS" |
98 VCS_UNKNOWN = "Unknown" | 99 VCS_UNKNOWN = "Unknown" |
99 | 100 |
100 VCS_ABBREVIATIONS = { | 101 VCS = [ |
101 VCS_MERCURIAL.lower(): VCS_MERCURIAL, | 102 { |
102 "hg": VCS_MERCURIAL, | 103 'name': VCS_MERCURIAL, |
103 VCS_SUBVERSION.lower(): VCS_SUBVERSION, | 104 'aliases': ['hg', 'mercurial'], |
104 "svn": VCS_SUBVERSION, | 105 }, { |
105 VCS_PERFORCE.lower(): VCS_PERFORCE, | 106 'name': VCS_SUBVERSION, |
106 "p4": VCS_PERFORCE, | 107 'aliases': ['svn', 'subversion'], |
107 VCS_GIT.lower(): VCS_GIT, | 108 }, { |
108 VCS_CVS.lower(): VCS_CVS, | 109 'name': VCS_PERFORCE, |
109 } | 110 'aliases': ['p4', 'perforce'], |
111 }, { | |
112 'name': VCS_GIT, | |
113 'aliases': ['git'], | |
114 }, { | |
115 'name': VCS_CVS, | |
116 'aliases': ['cvs'], | |
117 }] | |
118 | |
119 VCS_SHORT_NAMES = [] # hg, svn, ... | |
120 VCS_ABBREVIATIONS = {} # alias: name, ... | |
121 for vcs in VCS: | |
122 VCS_SHORT_NAMES.append(min(vcs['aliases'], key=len)) | |
123 VCS_ABBREVIATIONS.update((alias, vcs['name']) for alias in vcs['aliases']) | |
124 | |
110 | 125 |
111 # OAuth 2.0-Related Constants | 126 # OAuth 2.0-Related Constants |
112 LOCALHOST_IP = '127.0.0.1' | 127 LOCALHOST_IP = '127.0.0.1' |
113 DEFAULT_OAUTH2_PORT = 8001 | 128 DEFAULT_OAUTH2_PORT = 8001 |
114 ACCESS_TOKEN_PARAM = 'access_token' | 129 ACCESS_TOKEN_PARAM = 'access_token' |
115 ERROR_PARAM = 'error' | 130 ERROR_PARAM = 'error' |
116 OAUTH_DEFAULT_ERROR_MESSAGE = 'OAuth 2.0 error occurred.' | 131 OAUTH_DEFAULT_ERROR_MESSAGE = 'OAuth 2.0 error occurred.' |
117 OAUTH_PATH = '/get-access-token' | 132 OAUTH_PATH = '/get-access-token' |
118 OAUTH_PATH_PORT_TEMPLATE = OAUTH_PATH + '?port=%(port)d' | 133 OAUTH_PATH_PORT_TEMPLATE = OAUTH_PATH + '?port=%(port)d' |
119 AUTH_HANDLER_RESPONSE = """\ | 134 AUTH_HANDLER_RESPONSE = """\ |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
639 "rev1:rev2 range to review already committed changeset.") | 654 "rev1:rev2 range to review already committed changeset.") |
640 group.add_option("--send_mail", action="store_true", | 655 group.add_option("--send_mail", action="store_true", |
641 dest="send_mail", default=False, | 656 dest="send_mail", default=False, |
642 help="Send notification email to reviewers.") | 657 help="Send notification email to reviewers.") |
643 group.add_option("-p", "--send_patch", action="store_true", | 658 group.add_option("-p", "--send_patch", action="store_true", |
644 dest="send_patch", default=False, | 659 dest="send_patch", default=False, |
645 help="Same as --send_mail, but include diff as an " | 660 help="Same as --send_mail, but include diff as an " |
646 "attachment, and prepend email subject with 'PATCH:'.") | 661 "attachment, and prepend email subject with 'PATCH:'.") |
647 group.add_option("--vcs", action="store", dest="vcs", | 662 group.add_option("--vcs", action="store", dest="vcs", |
648 metavar="VCS", default=None, | 663 metavar="VCS", default=None, |
649 help=("Version control system (optional, usually upload.py " | 664 help=("Explicitly specify version control system (%s)" |
650 "already guesses the right VCS).")) | 665 % ", ".join(VCS_SHORT_NAMES))) |
651 group.add_option("--emulate_svn_auto_props", action="store_true", | 666 group.add_option("--emulate_svn_auto_props", action="store_true", |
652 dest="emulate_svn_auto_props", default=False, | 667 dest="emulate_svn_auto_props", default=False, |
653 help=("Emulate Subversion's auto properties feature.")) | 668 help=("Emulate Subversion's auto properties feature.")) |
654 # Git-specific | 669 # Git-specific |
655 group = parser.add_option_group("Git-specific options") | 670 group = parser.add_option_group("Git-specific options") |
656 group.add_option("--git_similarity", action="store", dest="git_similarity", | 671 group.add_option("--git_similarity", action="store", dest="git_similarity", |
657 metavar="SIM", type="int", default=50, | 672 metavar="SIM", type="int", default=50, |
658 help=("Set the minimum similarity index for detecting renames " | 673 help=("Set the minimum similarity index for detecting renames " |
659 "and copies. See `git diff -C`. (default 50).")) | 674 "and copies. See `git diff -C`. (default 50).")) |
660 group.add_option("--git_no_find_copies", action="store_false", default=True, | 675 group.add_option("--git_no_find_copies", action="store_false", default=True, |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1590 # commands then check for an empty diff manually. | 1605 # commands then check for an empty diff manually. |
1591 if not diff: | 1606 if not diff: |
1592 ErrorExit("No output from %s" % (cmd + extra_args)) | 1607 ErrorExit("No output from %s" % (cmd + extra_args)) |
1593 return diff | 1608 return diff |
1594 | 1609 |
1595 def GetUnknownFiles(self): | 1610 def GetUnknownFiles(self): |
1596 status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], | 1611 status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], |
1597 silent_ok=True) | 1612 silent_ok=True) |
1598 return status.splitlines() | 1613 return status.splitlines() |
1599 | 1614 |
1600 def GetFileContent(self, file_hash, is_binary): | 1615 def GetFileContent(self, file_hash): |
1601 """Returns the content of a file identified by its git hash.""" | 1616 """Returns the content of a file identified by its git hash.""" |
1602 data, retcode = RunShellWithReturnCode(["git", "show", file_hash], | 1617 data, retcode = RunShellWithReturnCode(["git", "show", file_hash], |
1603 universal_newlines=not is_binary) | 1618 universal_newlines=False) |
iannucci
2013/09/19 17:25:20
isn't universal_newlines=False the default?
chrisphan
2013/09/19 17:45:09
universal_newlines is False on default for popen,
| |
1604 if retcode: | 1619 if retcode: |
1605 ErrorExit("Got error status from 'git show %s'" % file_hash) | 1620 ErrorExit("Got error status from 'git show %s'" % file_hash) |
1606 return data | 1621 return data |
1607 | 1622 |
1608 def GetBaseFile(self, filename): | 1623 def GetBaseFile(self, filename): |
1609 hash_before, hash_after = self.hashes.get(filename, (None,None)) | 1624 hash_before, hash_after = self.hashes.get(filename, (None,None)) |
1610 base_content = None | 1625 base_content = None |
1611 new_content = None | 1626 new_content = None |
1612 status = None | 1627 status = None |
1613 | 1628 |
1614 if filename in self.renames: | 1629 if filename in self.renames: |
1615 status = "A +" # Match svn attribute name for renames. | 1630 status = "A +" # Match svn attribute name for renames. |
1616 if filename not in self.hashes: | 1631 if filename not in self.hashes: |
1617 # If a rename doesn't change the content, we never get a hash. | 1632 # If a rename doesn't change the content, we never get a hash. |
1618 base_content = RunShell( | 1633 base_content = RunShell( |
1619 ["git", "show", "HEAD:" + filename], silent_ok=True) | 1634 ["git", "show", "HEAD:" + filename], silent_ok=True) |
1620 elif not hash_before: | 1635 elif not hash_before: |
1621 status = "A" | 1636 status = "A" |
1622 base_content = "" | 1637 base_content = "" |
1623 elif not hash_after: | 1638 elif not hash_after: |
1624 status = "D" | 1639 status = "D" |
1625 else: | 1640 else: |
1626 status = "M" | 1641 status = "M" |
1627 | 1642 |
1628 is_image = self.IsImage(filename) | |
1629 is_binary = self.IsBinaryData(base_content) or is_image | |
1630 | |
1631 # Grab the before/after content if we need it. | 1643 # Grab the before/after content if we need it. |
1632 # Grab the base content if we don't have it already. | 1644 # Grab the base content if we don't have it already. |
1633 if base_content is None and hash_before: | 1645 if base_content is None and hash_before: |
1634 base_content = self.GetFileContent(hash_before, is_binary) | 1646 base_content = self.GetFileContent(hash_before) |
1647 | |
1648 is_binary = self.IsImage(filename) | |
1649 if base_content: | |
1650 is_binary = is_binary or self.IsBinaryData(base_content) | |
1651 | |
1635 # Only include the "after" file if it's an image; otherwise it | 1652 # Only include the "after" file if it's an image; otherwise it |
1636 # it is reconstructed from the diff. | 1653 # it is reconstructed from the diff. |
1637 if is_image and hash_after: | 1654 if hash_after: |
1638 new_content = self.GetFileContent(hash_after, is_binary) | 1655 new_content = self.GetFileContent(hash_after) |
1639 | 1656 is_binary = is_binary or self.IsBinaryData(new_content) |
1657 if not is_binary: | |
1658 new_content = None | |
1640 return (base_content, new_content, is_binary, status) | 1659 return (base_content, new_content, is_binary, status) |
1641 | 1660 |
1642 | 1661 |
1643 class CVSVCS(VersionControlSystem): | 1662 class CVSVCS(VersionControlSystem): |
1644 """Implementation of the VersionControlSystem interface for CVS.""" | 1663 """Implementation of the VersionControlSystem interface for CVS.""" |
1645 | 1664 |
1646 def __init__(self, options): | 1665 def __init__(self, options): |
1647 super(CVSVCS, self).__init__(options) | 1666 super(CVSVCS, self).__init__(options) |
1648 | 1667 |
1649 def GetGUID(self): | 1668 def GetGUID(self): |
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2633 os.environ['LC_ALL'] = 'C' | 2652 os.environ['LC_ALL'] = 'C' |
2634 RealMain(sys.argv) | 2653 RealMain(sys.argv) |
2635 except KeyboardInterrupt: | 2654 except KeyboardInterrupt: |
2636 print | 2655 print |
2637 StatusUpdate("Interrupted.") | 2656 StatusUpdate("Interrupted.") |
2638 sys.exit(1) | 2657 sys.exit(1) |
2639 | 2658 |
2640 | 2659 |
2641 if __name__ == "__main__": | 2660 if __name__ == "__main__": |
2642 main() | 2661 main() |
OLD | NEW |