OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 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 import getpass | 6 import getpass |
7 import optparse | 7 import optparse |
8 import os | 8 import os |
9 import subprocess | 9 import subprocess |
10 import tempfile | 10 import tempfile |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 | 65 |
66 def GetSubRepWorkingDir(sub_rep_path): | 66 def GetSubRepWorkingDir(sub_rep_path): |
67 """Computes the path to the sub repository""" | 67 """Computes the path to the sub repository""" |
68 if sub_rep_path: | 68 if sub_rep_path: |
69 root_dir = os.path.abspath(Backquote(['git', 'rev-parse', '--show-cdup'])) | 69 root_dir = os.path.abspath(Backquote(['git', 'rev-parse', '--show-cdup'])) |
70 return os.path.join(root_dir, sub_rep_path) | 70 return os.path.join(root_dir, sub_rep_path) |
71 return None | 71 return None |
72 | 72 |
73 def GetMungedDiff(branch, prefix, sub_rep_path): | 73 def GetMungedDiff(branch, prefix, sub_rep_path): |
74 """Get the diff we'll send to the try server. We munge paths to match svn. | 74 """Get the diff we'll send to the try server. We munge paths to match svn. |
75 We add the prefix that the try bot is expecting. If sub_rep_path is | 75 We add the prefix that the try bot is expecting. If sub_rep_path is |
76 provided, diff will be calculated in the sub repository.""" | 76 provided, diff will be calculated in the sub repository. |
| 77 We also return the list of files in this diff, without munged paths.""" |
77 # Make the following changes: | 78 # Make the following changes: |
78 # - Prepend "src/" (or some other prefix) to paths as svn is expecting | 79 # - Prepend "src/" (or some other prefix) to paths as svn is expecting |
79 # - In the case of added files, replace /dev/null with the path to the file | 80 # - In the case of added files, replace /dev/null with the path to the file |
80 # being added. | 81 # being added. |
81 | 82 |
82 cwd = GetSubRepWorkingDir(sub_rep_path) | 83 cwd = GetSubRepWorkingDir(sub_rep_path) |
83 | 84 |
84 output = [] | 85 output = [] |
85 if not branch: | 86 if not branch: |
86 # Try to guess the upstream branch. | 87 # Try to guess the upstream branch. |
87 branch = Backquote(['git', 'cl', 'upstream'], cwd) | 88 branch = Backquote(['git', 'cl', 'upstream'], cwd) |
88 command = ['git', 'diff-tree', '-p'] | 89 command = ['git', 'diff-tree', '-p'] |
89 | 90 |
90 new_cwd = None | 91 new_cwd = None |
91 if not sub_rep_path: | 92 if not sub_rep_path: |
92 command.extend(['--no-prefix']) | 93 command.extend(['--no-prefix']) |
93 else: | 94 else: |
94 # Append / | 95 # Append / |
95 sub_rep_path = os.path.join(sub_rep_path, '') | 96 sub_rep_path = os.path.join(sub_rep_path, '') |
96 # Add the right prefix | 97 # Add the right prefix |
97 command.extend(['--src-prefix=' + sub_rep_path]) | 98 command.extend(['--src-prefix=' + sub_rep_path]) |
98 command.extend(['--dst-prefix=' + sub_rep_path]) | 99 command.extend(['--dst-prefix=' + sub_rep_path]) |
99 | 100 |
100 command.extend([branch, 'HEAD']) | 101 command.extend([branch, 'HEAD']) |
101 | 102 |
102 # Run diff tree | 103 # Run diff tree |
103 diff = subprocess.Popen(command, | 104 diff = subprocess.Popen(command, |
104 stdout=subprocess.PIPE, | 105 stdout=subprocess.PIPE, |
105 cwd=cwd).stdout.readlines() | 106 cwd=cwd).stdout.readlines() |
106 # Replace --- /dev/null with --- <new file name> | 107 # Replace --- /dev/null with --- <new file name> |
107 for i in range(len(diff)): | 108 for i in range(len(diff)): |
108 line = diff[i] | 109 line = diff[i] |
109 if line.startswith('--- /dev/null'): | 110 if line.startswith('--- /dev/null'): |
110 line = '--- %s' % diff[i+1][4:] | 111 line = '--- %s' % diff[i+1][4:] |
111 output.append(line) | 112 output.append(line) |
112 diff = output | 113 diff = output |
113 | 114 |
114 # Add root prefix | 115 # Add root prefix |
115 output = [] | 116 output = [] |
| 117 file_set = set() |
116 for line in diff: | 118 for line in diff: |
117 if line.startswith('--- ') or line.startswith('+++ '): | 119 if line.startswith('--- ') or line.startswith('+++ '): |
118 line = line[0:4] + os.path.join(prefix,line[4:]) | 120 filename = line[4:] |
| 121 line = line[0:4] + os.path.join(prefix, filename) |
| 122 file_set.add(filename.rstrip('\r\n')) |
119 output.append(line) | 123 output.append(line) |
120 | 124 |
121 munged_diff = ''.join(output) | 125 munged_diff = ''.join(output) |
122 if len(munged_diff.strip()) == 0: | 126 if len(munged_diff.strip()) == 0: |
123 raise Exception("Patch was empty, did you give the right remote branch?") | 127 raise Exception("Patch was empty, did you give the right remote branch?") |
124 | 128 |
125 return munged_diff | 129 return (munged_diff, list(file_set)) |
126 | 130 |
127 def OneRepositoryDiff(diff_file, patch_names, branch, prefix, sub_rep_path): | 131 def OneRepositoryDiff(diff_file, patch_names, branch, prefix, sub_rep_path): |
128 """Computes a diff for one git repository at a given path against a given | 132 """Computes a diff for one git repository at a given path against a given |
129 branch. Writes the diff into diff_file and appends a name to the | 133 branch. Writes the diff into diff_file and appends a name to the |
130 patch_names list.""" | 134 patch_names list. |
131 | 135 |
132 diff = GetMungedDiff(branch, prefix, sub_rep_path) | 136 Returns the list of files in the diff.""" |
| 137 |
| 138 (diff, file_list) = GetMungedDiff(branch, prefix, sub_rep_path) |
133 | 139 |
134 # Write the diff out | 140 # Write the diff out |
135 diff_file.write(diff) | 141 diff_file.write(diff) |
136 | 142 |
137 # Add patch name to list of patches | 143 # Add patch name to list of patches |
138 patch_name = GetPatchName(GetSubRepWorkingDir(sub_rep_path)) | 144 patch_name = GetPatchName(GetSubRepWorkingDir(sub_rep_path)) |
139 patch_names.extend([patch_name]) | 145 patch_names.extend([patch_name]) |
| 146 return file_list |
140 | 147 |
141 | 148 |
142 def ValidEmail(email): | 149 def ValidEmail(email): |
143 return re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email) | 150 return re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email) |
144 | 151 |
145 | 152 |
146 def GetEmail(): | 153 def GetEmail(): |
147 email = Backquote(['git', 'config', 'user.email']) | 154 email = Backquote(['git', 'config', 'user.email']) |
148 runmsg = "Try: git config user.email <EMAIL>" | 155 runmsg = "Try: git config user.email <EMAIL>" |
149 assert ValidEmail(email), "Email '%s' is not valid. %s" % (email, runmsg) | 156 assert ValidEmail(email), "Email '%s' is not valid. %s" % (email, runmsg) |
150 return email | 157 return email |
151 | 158 |
152 | 159 |
153 def TryChange(args): | 160 def TryChange(args, file_list): |
154 """Put a patch on the try server.""" | 161 """Put a patch on the try server.""" |
155 root_dir = Backquote(['git', 'rev-parse', '--show-cdup']) | 162 trychange.TryChange(args, file_list, False) |
156 trychange.checkout_root = os.path.abspath(root_dir) | |
157 trychange.TryChange(args, None, False) | |
158 | 163 |
159 | 164 |
160 if __name__ == '__main__': | 165 if __name__ == '__main__': |
161 parser = optparse.OptionParser( | 166 parser = optparse.OptionParser( |
162 usage='git try [options] [branch]', | 167 usage='git try [options] [branch]', |
163 description='Upload the current diff of branch...HEAD to the try server.') | 168 description='Upload the current diff of branch...HEAD to the try server.') |
164 parser.add_option("-b", "--bot", | 169 parser.add_option("-b", "--bot", |
165 help="Force the use of a specific build slave (eg mac, " | 170 help="Force the use of a specific build slave (eg mac, " |
166 "win, or linux)") | 171 "win, or linux)") |
167 parser.add_option("-c", "--clobber", action="store_true", | 172 parser.add_option("-c", "--clobber", action="store_true", |
168 help="Make the try run use be a clobber build") | 173 help="Make the try run use be a clobber build") |
169 parser.add_option("-r", "--revision", | 174 parser.add_option("-r", "--revision", |
170 help="Specify the SVN base revision to use") | 175 help="Specify the SVN base revision to use") |
171 parser.add_option("--root", default="src", metavar="PATH", | 176 parser.add_option("--root", default="src", metavar="PATH", |
172 help="Specify the root prefix that is appended to paths " | 177 help="Specify the root prefix that is prepended to paths " |
173 "in the patch") | 178 "in the patch") |
174 parser.add_option("--dry_run", action="store_true", | 179 parser.add_option("--dry_run", action="store_true", |
175 help="Print the diff but don't send it to the try bots") | 180 help="Print the diff but don't send it to the try bots") |
176 parser.add_option("--sub_rep", nargs=2, action="append", default=[], | 181 parser.add_option("--sub_rep", nargs=2, action="append", default=[], |
177 metavar="PATH BRANCH", | 182 metavar="PATH BRANCH", |
178 help="Specify a path to a git sub-repository and a branch " | 183 help="Specify a path to a git sub-repository and a branch " |
179 "to diff with in order to simultanously try changes " | 184 "to diff with in order to simultanously try changes " |
180 "in multiple git repositories. Option may be " | 185 "in multiple git repositories. Option may be " |
181 "specified multiple times.") | 186 "specified multiple times.") |
182 parser.add_option("--webkit", metavar="BRANCH", | 187 parser.add_option("--webkit", metavar="BRANCH", |
183 help="Specify webkit branch. Syntactic sugar for " | 188 help="Specify webkit branch. Syntactic sugar for " |
184 "--sub_rep third_party/WebKit/ <branch>") | 189 "--sub_rep third_party/WebKit/ <branch>") |
185 | 190 |
186 (options, args) = parser.parse_args(sys.argv) | 191 (options, args) = parser.parse_args(sys.argv) |
187 | 192 |
188 if options.webkit: | 193 if options.webkit: |
189 options.sub_rep.extend([('third_party/WebKit/', options.webkit)]) | 194 options.sub_rep.extend([('third_party/WebKit/', options.webkit)]) |
190 | 195 |
191 branch = None | 196 branch = None |
192 if len(args) > 1: | 197 if len(args) > 1: |
193 branch = args[1] | 198 branch = args[1] |
194 patch_names = [] | 199 patch_names = [] |
195 | 200 |
196 # Dump all diffs into one diff file. | 201 # Dump all diffs into one diff file. |
197 diff_file = tempfile.NamedTemporaryFile() | 202 diff_file = tempfile.NamedTemporaryFile() |
198 | 203 |
199 # Calculate diff for main git repository. | 204 # Calculate diff for main git repository. |
200 OneRepositoryDiff(diff_file, patch_names, branch, options.root, None) | 205 file_list = OneRepositoryDiff(diff_file, patch_names, branch, options.root, |
201 | 206 None) |
| 207 |
202 # Calculate diff for each extra git repository. | 208 # Calculate diff for each extra git repository. |
203 for path_and_branch in options.sub_rep: | 209 for path_and_branch in options.sub_rep: |
204 OneRepositoryDiff(diff_file, | 210 file_list.extend(OneRepositoryDiff(diff_file, |
205 patch_names, | 211 patch_names, |
206 path_and_branch[1], | 212 path_and_branch[1], |
207 options.root, | 213 options.root, |
208 path_and_branch[0]) | 214 path_and_branch[0])) |
209 # Make diff file ready for reading. | 215 # Make diff file ready for reading. |
210 diff_file.flush() | 216 diff_file.flush() |
211 | 217 |
212 # Concatenate patch names | 218 # Concatenate patch names |
213 # Prepare args for TryChange | 219 # Prepare args for TryChange |
214 email = GetEmail() | 220 email = GetEmail() |
215 user = email.partition('@')[0] | 221 user = email.partition('@')[0] |
216 args = [ | 222 args = [ |
217 '-u', user, | 223 '-u', user, |
218 '-e', email, | 224 '-e', email, |
219 '-n', '-'.join(patch_names), | 225 '-n', '-'.join(patch_names), |
220 '--diff', diff_file.name, | 226 '--diff', diff_file.name, |
221 ] | 227 ] |
222 | 228 |
223 # Send to try server via HTTP if we can parse the config, otherwise | 229 # Send to try server via HTTP if we can parse the config, otherwise |
224 # upload via SVN. | 230 # upload via SVN. |
225 config = GetTryServerConfig() | 231 config = GetTryServerConfig() |
226 if config is not None: | 232 if config is not None: |
227 sendmsg = "Sending %s using HTTP..." % '-'.join(patch_names) | 233 sendmsg = "Sending %s using HTTP..." % '-'.join(patch_names) |
228 args.extend(['--use_http']) | 234 args.extend(['--use_http']) |
229 if config['try_server_http_host'] is not None: | 235 if config['try_server_http_host'] is not None: |
230 args.extend(['--host', config['try_server_http_host']]) | 236 args.extend(['--host', config['try_server_http_host']]) |
(...skipping 19 matching lines...) Expand all Loading... |
250 args.extend([ | 256 args.extend([ |
251 '--issue', GetRietveldIssueNumber(), | 257 '--issue', GetRietveldIssueNumber(), |
252 '--patchset', GetRietveldPatchsetNumber(), | 258 '--patchset', GetRietveldPatchsetNumber(), |
253 ]) | 259 ]) |
254 | 260 |
255 if options.dry_run: | 261 if options.dry_run: |
256 print open(diff_file.name, 'r').read() | 262 print open(diff_file.name, 'r').read() |
257 exit(0) | 263 exit(0) |
258 | 264 |
259 print sendmsg | 265 print sendmsg |
260 TryChange(args=args) | 266 TryChange(args, file_list) |
OLD | NEW |