OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 # | 5 # |
6 # Wrapper script around Rietveld's upload.py that groups files into | 6 # Wrapper script around Rietveld's upload.py that groups files into |
7 # changelists. | 7 # changelists. |
8 | 8 |
9 import getpass | 9 import getpass |
10 import os | 10 import os |
(...skipping 21 matching lines...) Expand all Loading... |
32 # we store information about changelists. | 32 # we store information about changelists. |
33 repository_root = "" | 33 repository_root = "" |
34 gcl_info_dir = "" | 34 gcl_info_dir = "" |
35 | 35 |
36 # Filename where we store repository specific information for gcl. | 36 # Filename where we store repository specific information for gcl. |
37 CODEREVIEW_SETTINGS_FILE = "codereview.settings" | 37 CODEREVIEW_SETTINGS_FILE = "codereview.settings" |
38 | 38 |
39 # Warning message when the change appears to be missing tests. | 39 # Warning message when the change appears to be missing tests. |
40 MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!" | 40 MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!" |
41 | 41 |
42 # Global cache of files cached in GetInfoDir(). | 42 # Caches whether we read the codereview.settings file yet or not. |
43 FILES_CACHE = {} | 43 read_gcl_info = False |
44 | 44 |
45 | 45 |
46 def IsSVNMoved(filename): | 46 def IsSVNMoved(filename): |
47 """Determine if a file has been added through svn mv""" | 47 """Determine if a file has been added through svn mv""" |
48 info = GetSVNFileInfo(filename) | 48 info = GetSVNFileInfo(filename) |
49 return (info.get('Copied From URL') and | 49 return (info.get('Copied From URL') and |
50 info.get('Copied From Rev') and | 50 info.get('Copied From Rev') and |
51 info.get('Schedule') == 'add') | 51 info.get('Schedule') == 'add') |
52 | 52 |
53 | 53 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 | 104 |
105 | 105 |
106 def GetInfoDir(): | 106 def GetInfoDir(): |
107 """Returns the directory where gcl info files are stored.""" | 107 """Returns the directory where gcl info files are stored.""" |
108 global gcl_info_dir | 108 global gcl_info_dir |
109 if not gcl_info_dir: | 109 if not gcl_info_dir: |
110 gcl_info_dir = os.path.join(GetRepositoryRoot(), '.svn', 'gcl_info') | 110 gcl_info_dir = os.path.join(GetRepositoryRoot(), '.svn', 'gcl_info') |
111 return gcl_info_dir | 111 return gcl_info_dir |
112 | 112 |
113 | 113 |
114 def GetCachedFile(filename, max_age=60*60*24*3, use_root=False): | |
115 """Retrieves a file from the repository and caches it in GetInfoDir() for | |
116 max_age seconds. | |
117 | |
118 use_root: If False, look up the arborescence for the first match, otherwise go | |
119 directory to the root repository. | |
120 """ | |
121 global FILES_CACHE | |
122 if filename not in FILES_CACHE: | |
123 # Don't try to look up twice. | |
124 FILES_CACHE[filename] = None | |
125 # First we check if we have a cached version. | |
126 cached_file = os.path.join(GetInfoDir(), filename) | |
127 if (not os.path.exists(cached_file) or | |
128 os.stat(cached_file).st_mtime > max_age): | |
129 dir_info = GetSVNFileInfo(".") | |
130 repo_root = dir_info["Repository Root"] | |
131 if use_root: | |
132 url_path = repo_root | |
133 else: | |
134 url_path = dir_info["URL"] | |
135 content = "" | |
136 while True: | |
137 # Look for the codereview.settings file at the current level. | |
138 svn_path = url_path + "/" + filename | |
139 content, rc = RunShellWithReturnCode(["svn", "cat", svn_path]) | |
140 if not rc: | |
141 # Exit the loop if the file was found. Override content. | |
142 break | |
143 # Make sure to mark settings as empty if not found. | |
144 content = "" | |
145 if url_path == repo_root: | |
146 # Reached the root. Abandoning search. | |
147 break | |
148 # Go up one level to try again. | |
149 url_path = os.path.dirname(url_path) | |
150 # Write a cached version even if there isn't a file, so we don't try to | |
151 # fetch it each time. | |
152 WriteFile(cached_file, content) | |
153 else: | |
154 content = ReadFile(cached_settings_file) | |
155 FILES_CACHE[filename] = content | |
156 return FILES_CACHE[filename] | |
157 | |
158 | |
159 def GetCodeReviewSetting(key): | 114 def GetCodeReviewSetting(key): |
160 """Returns a value for the given key for this repository.""" | 115 """Returns a value for the given key for this repository.""" |
161 # Use '__just_initialized' as a flag to determine if the settings were | 116 global read_gcl_info |
162 # already initialized. | 117 if not read_gcl_info: |
163 if '__just_initialized' not in CODEREVIEW_SETTINGS: | 118 read_gcl_info = True |
164 for line in GetCachedFile(CODEREVIEW_SETTINGS_FILE).splitlines(): | 119 # First we check if we have a cached version. |
| 120 cached_settings_file = os.path.join(GetInfoDir(), CODEREVIEW_SETTINGS_FILE) |
| 121 if (not os.path.exists(cached_settings_file) or |
| 122 os.stat(cached_settings_file).st_mtime > 60*60*24*3): |
| 123 dir_info = GetSVNFileInfo(".") |
| 124 repo_root = dir_info["Repository Root"] |
| 125 url_path = dir_info["URL"] |
| 126 settings = "" |
| 127 while True: |
| 128 # Look for the codereview.settings file at the current level. |
| 129 svn_path = url_path + "/" + CODEREVIEW_SETTINGS_FILE |
| 130 settings, rc = RunShellWithReturnCode(["svn", "cat", svn_path]) |
| 131 if not rc: |
| 132 # Exit the loop if the file was found. |
| 133 break |
| 134 # Make sure to mark settings as empty if not found. |
| 135 settings = "" |
| 136 if url_path == repo_root: |
| 137 # Reached the root. Abandoning search. |
| 138 break; |
| 139 # Go up one level to try again. |
| 140 url_path = os.path.dirname(url_path) |
| 141 |
| 142 # Write a cached version even if there isn't a file, so we don't try to |
| 143 # fetch it each time. |
| 144 WriteFile(cached_settings_file, settings) |
| 145 |
| 146 output = ReadFile(cached_settings_file) |
| 147 for line in output.splitlines(): |
165 if not line or line.startswith("#"): | 148 if not line or line.startswith("#"): |
166 continue | 149 continue |
167 k, v = line.split(": ", 1) | 150 k, v = line.split(": ", 1) |
168 CODEREVIEW_SETTINGS[k] = v | 151 CODEREVIEW_SETTINGS[k] = v |
169 CODEREVIEW_SETTINGS.setdefault('__just_initialized', None) | |
170 return CODEREVIEW_SETTINGS.get(key, "") | 152 return CODEREVIEW_SETTINGS.get(key, "") |
171 | 153 |
172 | 154 |
173 def IsTreeOpen(): | 155 def IsTreeOpen(): |
174 """Fetches the tree status and returns either True or False.""" | 156 """Fetches the tree status and returns either True or False.""" |
175 url = GetCodeReviewSetting('STATUS') | 157 url = GetCodeReviewSetting('STATUS') |
176 status = "" | 158 status = "" |
177 if url: | 159 if url: |
178 status = urllib2.urlopen(url).read() | 160 status = urllib2.urlopen(url).read() |
179 return status.find('0') == -1 | 161 return status.find('0') == -1 |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 Basic commands: | 576 Basic commands: |
595 ----------------------------------------- | 577 ----------------------------------------- |
596 gcl change change_name | 578 gcl change change_name |
597 Add/remove files to a changelist. Only scans the current directory and | 579 Add/remove files to a changelist. Only scans the current directory and |
598 subdirectories. | 580 subdirectories. |
599 | 581 |
600 gcl upload change_name [-r reviewer1@gmail.com,reviewer2@gmail.com,...] | 582 gcl upload change_name [-r reviewer1@gmail.com,reviewer2@gmail.com,...] |
601 [--send_mail] [--no_try] [--no_presubmit] | 583 [--send_mail] [--no_try] [--no_presubmit] |
602 Uploads the changelist to the server for review. | 584 Uploads the changelist to the server for review. |
603 | 585 |
604 gcl commit change_name [--no_presubmit] [--force] | 586 gcl commit change_name [--force] |
605 Commits the changelist to the repository. | 587 Commits the changelist to the repository. |
606 | 588 |
607 gcl lint change_name | 589 gcl lint change_name |
608 Check all the files in the changelist for possible style violations. | 590 Check all the files in the changelist for possible style violations. |
609 | 591 |
610 Advanced commands: | 592 Advanced commands: |
611 ----------------------------------------- | 593 ----------------------------------------- |
612 gcl delete change_name | 594 gcl delete change_name |
613 Deletes a changelist. | 595 Deletes a changelist. |
614 | 596 |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 | 985 |
1004 | 986 |
1005 def DoPresubmitChecks(change_info, committing): | 987 def DoPresubmitChecks(change_info, committing): |
1006 """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" | 988 """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" |
1007 # Need to import here to avoid circular dependency. | 989 # Need to import here to avoid circular dependency. |
1008 import presubmit | 990 import presubmit |
1009 result = presubmit.DoPresubmitChecks(change_info, | 991 result = presubmit.DoPresubmitChecks(change_info, |
1010 committing, | 992 committing, |
1011 verbose=False, | 993 verbose=False, |
1012 output_stream=sys.stdout, | 994 output_stream=sys.stdout, |
1013 input_stream=sys.stdin, | 995 input_stream=sys.stdin) |
1014 default_presubmit= | |
1015 GetCachedFile('PRESUBMIT.py', | |
1016 use_root=True)) | |
1017 if not result: | 996 if not result: |
1018 print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" | 997 print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" |
1019 return result | 998 return result |
1020 | 999 |
1021 | 1000 |
1022 def Changes(): | 1001 def Changes(): |
1023 """Print all the changelists and their files.""" | 1002 """Print all the changelists and their files.""" |
1024 for cl in GetCLs(): | 1003 for cl in GetCLs(): |
1025 change_info = LoadChangelistInfo(cl, True, True) | 1004 change_info = LoadChangelistInfo(cl, True, True) |
1026 print "\n--- Changelist " + change_info.name + ":" | 1005 print "\n--- Changelist " + change_info.name + ":" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 # the files. This allows commands such as 'gcl diff xxx' to work. | 1092 # the files. This allows commands such as 'gcl diff xxx' to work. |
1114 args =["svn", command] | 1093 args =["svn", command] |
1115 root = GetRepositoryRoot() | 1094 root = GetRepositoryRoot() |
1116 args.extend([os.path.join(root, x) for x in change_info.FileList()]) | 1095 args.extend([os.path.join(root, x) for x in change_info.FileList()]) |
1117 RunShell(args, True) | 1096 RunShell(args, True) |
1118 return 0 | 1097 return 0 |
1119 | 1098 |
1120 | 1099 |
1121 if __name__ == "__main__": | 1100 if __name__ == "__main__": |
1122 sys.exit(main()) | 1101 sys.exit(main()) |
OLD | NEW |